From f5cf2534a6295e1348fb46e3b9320e9359e72f6b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 30 Oct 2026 23:10:54 +0000 Subject: [PATCH 1/3] =?UTF-8?q?Web=200.13.37:=20Bereich=20=E2=80=9EProgram?= =?UTF-8?q?mieren=E2=80=9C=20hei=C3=9Ft=20=E2=80=9ECode=E2=80=9C,=20Farben?= =?UTF-8?q?=20f=C3=BCr=20Struktogramm=20und=20Code,=20=C3=9Cbungen=20mit?= =?UTF-8?q?=20bereich:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Ugz28WsFncnVqF96ZZJzbu --- CHANGELOG.md | 1 + web/README.md | 2 +- web/lessons/README.md | 3 +- web/lessons/de/02-der-editor.md | 4 +- web/lessons/de/04-variablen-und-datentypen.md | 8 +- web/lessons/de/05-sequenz.md | 6 +- web/lessons/de/06-eingabe-und-ausgabe.md | 2 +- .../de/07-simulation-und-schreibtischtest.md | 8 +- web/lessons/de/08-verzweigung.md | 4 +- web/lessons/de/09-bedingungen-verknuepfen.md | 2 +- web/lessons/de/10-fallauswahl.md | 2 +- web/lessons/de/12-do-while-schleife.md | 2 +- web/lessons/de/13-for-schleife.md | 2 +- web/lessons/de/14-verschachteln.md | 4 +- web/lessons/de/15-arrays.md | 2 +- web/lessons/de/16-zweidimensionale-arrays.md | 2 +- web/lessons/de/17-zeichenketten.md | 2 +- web/lessons/de/18-aufruf-und-aussprung.md | 6 +- web/lessons/de/19-suchen-und-sortieren.md | 2 +- web/lessons/de/20-java.md | 24 +- web/lessons/de/22-try-und-catch.md | 10 +- web/lessons/de/28-erstes-fenster.md | 12 +- web/lessons/de/34-notenrechner.md | 2 +- web/lessons/de/36-zahlenraten.md | 2 +- web/lessons/de/visubot/06-abstand.md | 2 +- web/lessons/de/visubot/22-eigene-methoden.md | 2 +- web/lessons/en/02-der-editor.md | 4 +- web/lessons/en/04-variablen-und-datentypen.md | 8 +- web/lessons/en/05-sequenz.md | 6 +- web/lessons/en/06-eingabe-und-ausgabe.md | 2 +- .../en/07-simulation-und-schreibtischtest.md | 8 +- web/lessons/en/08-verzweigung.md | 4 +- web/lessons/en/09-bedingungen-verknuepfen.md | 2 +- web/lessons/en/10-fallauswahl.md | 2 +- web/lessons/en/12-do-while-schleife.md | 2 +- web/lessons/en/13-for-schleife.md | 2 +- web/lessons/en/14-verschachteln.md | 4 +- web/lessons/en/15-arrays.md | 2 +- web/lessons/en/16-zweidimensionale-arrays.md | 2 +- web/lessons/en/17-zeichenketten.md | 2 +- web/lessons/en/18-aufruf-und-aussprung.md | 6 +- web/lessons/en/19-suchen-und-sortieren.md | 2 +- web/lessons/en/20-java.md | 24 +- web/lessons/en/22-try-und-catch.md | 10 +- web/lessons/en/28-erstes-fenster.md | 12 +- web/lessons/en/34-notenrechner.md | 2 +- web/lessons/en/36-zahlenraten.md | 2 +- web/lessons/en/visubot/06-abstand.md | 2 +- web/lessons/en/visubot/22-eigene-methoden.md | 2 +- web/lessons/pt/02-der-editor.md | 4 +- web/lessons/pt/04-variablen-und-datentypen.md | 8 +- web/lessons/pt/05-sequenz.md | 6 +- web/lessons/pt/06-eingabe-und-ausgabe.md | 2 +- .../pt/07-simulation-und-schreibtischtest.md | 8 +- web/lessons/pt/08-verzweigung.md | 4 +- web/lessons/pt/09-bedingungen-verknuepfen.md | 2 +- web/lessons/pt/10-fallauswahl.md | 2 +- web/lessons/pt/12-do-while-schleife.md | 2 +- web/lessons/pt/13-for-schleife.md | 2 +- web/lessons/pt/14-verschachteln.md | 4 +- web/lessons/pt/15-arrays.md | 2 +- web/lessons/pt/16-zweidimensionale-arrays.md | 2 +- web/lessons/pt/17-zeichenketten.md | 2 +- web/lessons/pt/18-aufruf-und-aussprung.md | 6 +- web/lessons/pt/19-suchen-und-sortieren.md | 2 +- web/lessons/pt/20-java.md | 24 +- web/lessons/pt/22-try-und-catch.md | 10 +- web/lessons/pt/28-erstes-fenster.md | 12 +- web/lessons/pt/34-notenrechner.md | 2 +- web/lessons/pt/36-zahlenraten.md | 2 +- web/package-lock.json | 4 +- web/package.json | 2 +- web/src/i18n/de.strings | 19 +- web/src/i18n/en.strings | 15 +- web/src/i18n/pt-PT.strings | 15 +- web/src/learn/lessonFormat.ts | 17 +- web/src/ui/app.ts | 16 +- web/src/ui/learnPanel.ts | 38 +- web/src/ui/robotPreview.ts | 2 +- web/src/ui/styles.css | 37 +- web/src/ui/termTips.ts | 6 +- web/test/lessons.test.ts | 15 +- .../assets/{de-B05MOgXv.js => de-DS9kn30Y.js} | 19 +- .../assets/{en-OfXp05Y3.js => en-Mt2ryoik.js} | 15 +- website/app/assets/index-3atjocI4.css | 1 - .../{index-CqnqsqSP.js => index-CBJVdWXq.js} | 2736 +++++++++-------- website/app/assets/index-Dn-t64wp.css | 1 + ...tApp-fPb85kNH.js => objectApp-BAiNGNpM.js} | 8 +- ...Zip-d7JtxgDL.js => projectZip-UnR2rfE2.js} | 2 +- .../{pt-PT-DYKlzJlW.js => pt-PT-ClEeb4rA.js} | 15 +- ...obot3d-F7Of_tVr.js => robot3d-CCjHhNM_.js} | 2 +- website/app/index.html | 4 +- 92 files changed, 1712 insertions(+), 1615 deletions(-) rename website/app/assets/{de-B05MOgXv.js => de-DS9kn30Y.js} (98%) rename website/app/assets/{en-OfXp05Y3.js => en-Mt2ryoik.js} (99%) delete mode 100644 website/app/assets/index-3atjocI4.css rename website/app/assets/{index-CqnqsqSP.js => index-CBJVdWXq.js} (94%) create mode 100644 website/app/assets/index-Dn-t64wp.css rename website/app/assets/{objectApp-fPb85kNH.js => objectApp-BAiNGNpM.js} (99%) rename website/app/assets/{projectZip-d7JtxgDL.js => projectZip-UnR2rfE2.js} (99%) rename website/app/assets/{pt-PT-DYKlzJlW.js => pt-PT-ClEeb4rA.js} (99%) rename website/app/assets/{robot3d-F7Of_tVr.js => robot3d-CCjHhNM_.js} (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 766ca7cf..a6afd045 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is loosely inspired by Keep a Changelog. ### Added +- **Web 0.13.37, area „Code“ and area colours:** the area „Programmieren“ is now called „Code“ (en „Code“, pt „Código“) in the app, all lessons, VisuBot lessons, tasks and glossary. Struktogramm and Code each have a colour (blue #007aff, violet #7c3aed): a coloured top edge, the slim strip when collapsed, and the area names on the exercise card („Löse diese Übung im Struktogramm und im Code.“). New exercise key `bereich: struktogramm | code | beide`: the card names the area(s) and „Im Editor öffnen“ opens exactly those (nothing is closed). Lesson 20 „Countdown“ and „Fakultät aus Java“ use `beide` (de/en/pt). - **Web 0.13.36, sequence diagram in lesson 5:** step „Schritt für Schritt“ now shows a sequence as a structure chart: four boxes one below the other (`laenge`, `breite`, `flaeche = laenge * breite`, output 15) with a short caption that each box runs exactly once from top to bottom (de/en/pt). - **Web 0.13.35, open Java examples in the editor:** a Java example in a lesson can now carry the button „Im Editor öffnen“. It opens the example in a new tab with Programmieren set to Java, so students can run it, change values and try again; the structure chart builds itself from the code. Lesson 4 step „Text in Java“ (Mia, 14, 1.62) uses it and says how to try it (de/en/pt). For authors: write ```` ```java editor ```` instead of ```` ```java ````; a test checks that every such example parses without errors. - **Web 0.13.32, every exercise says where to solve it:** below the title of each exercise card a small label names the area: „Löse diese Übung im Struktogramm.“ or, for `code: java` exercises, „Löse diese Übung in Programmieren.“ The area names are taken from the on-screen headings, so they always match (de/en/pt; applies to all VisuStruct, VisuBot and task-area exercises). diff --git a/web/README.md b/web/README.md index 7c080ddc..90218847 100644 --- a/web/README.md +++ b/web/README.md @@ -90,7 +90,7 @@ Verschieben vorhandener Elemente mit dem Finger. ## VisuObject (Welt `?visuobject`) Dritte Welt neben VisuStruct und VisuBot, für Objektorientierung ab Klasse 12 (Plan: `docs/visuobject/PLAN.md`). -`src/ui/objectApp.ts` zeigt links den Java-Code (CodeMirror wie in „Programmieren“) und rechts das Klassendiagramm. +`src/ui/objectApp.ts` zeigt links den Java-Code (CodeMirror wie in „Code“) und rechts das Klassendiagramm. `src/core/classModel.ts` liest Klassen, Attribute, Methoden-Köpfe, `extends` und `implements` aus dem Code und schreibt Änderungen im Diagramm an genau diese Stelle zurück (Rümpfe, Startwerte und Kommentare bleiben). Tests: `test/classModel.test.ts`. Ein Projekt hat mehrere Dateien in Packages (`src/core/javaProject.ts`, eine Datei pro Klasse, die Zeile `package …;` folgt diff --git a/web/lessons/README.md b/web/lessons/README.md index 19ab0d8a..c11737eb 100644 --- a/web/lessons/README.md +++ b/web/lessons/README.md @@ -77,7 +77,8 @@ lösung: l2-hallo-loesung.visustruct - `unterprogramm:` (optional) Unterprogramme zur Musterlösung, durch Komma getrennt. Ihr Titel ist der Name im Aufruf. Beim Prüfen findet VisuStruct Unterprogramme in den anderen offenen Reitern. - `datei:` (optional, nach einem `test:`) Diese Datei soll das Programm in diesem Test speichern, zum Beispiel `datei: einkauf-neu.txt -> Heu | Äpfel | Kuchen`. Verglichen wird Zeile für Zeile wie bei den Ausgaben. -- `code: java` (optional) Die Übung wird im Bereich Programmieren in Java gelöst. „Im Editor öffnen“ öffnet die Spalte gleich mit und stellt sie auf Java. Geprüft wird wie sonst das Struktogramm, das beim Tippen entsteht. Eine Musterlösung ist Pflicht, der Test tippt sie als Java und prüft sie. +- `code: java` (optional) Die Übung wird im Bereich Code in Java gelöst. „Im Editor öffnen“ öffnet die Spalte gleich mit und stellt sie auf Java. Geprüft wird wie sonst das Struktogramm, das beim Tippen entsteht. Eine Musterlösung ist Pflicht, der Test tippt sie als Java und prüft sie. +- `bereich: struktogramm | code | beide` (optional) Wo man die Übung löst. Die Karte zeigt es farbig an (Struktogramm blau, Code violett), und „Im Editor öffnen“ öffnet genau diese Bereiche (geschlossen wird nichts). Ohne Angabe gilt `code` bei `code: java`, sonst `struktogramm`. Für Übungen, bei denen man Code tippt und das Struktogramm liest (oder umgekehrt), `beide` nehmen. - Die Kennung (`l2-hallo`) muss überall eindeutig sein, denn unter ihr wird der Fortschritt gespeichert. Eine Checkliste zum Abhaken: diff --git a/web/lessons/de/02-der-editor.md b/web/lessons/de/02-der-editor.md index e4c31d10..b15503b1 100644 --- a/web/lessons/de/02-der-editor.md +++ b/web/lessons/de/02-der-editor.md @@ -14,7 +14,7 @@ kurz: Elemente einfügen, Text eingeben, verschieben und löschen. ## Die Oberfläche -VisuStruct hat zwei Editoren: den [Struktogramm-Editor](#zeige-editor), um den es in dieser Lektion geht, und rechts den Bereich [Programmieren](#zeige-codelive) für Java-Code (ab Lektion 4). Ist der Struktogramm-Editor eingeklappt, öffnet ihn diese Lektion von selbst. Die blauen Wörter zeigen dir die Bereiche, auch wenn sie gerade eingeklappt sind: Fährst du mit der Maus darüber, öffnet sich der Bereich neben dem Lernbereich und leuchtet auf. Klickst du darauf (oder tippst es an), bleibt er offen. +VisuStruct hat zwei Editoren: den [Struktogramm-Editor](#zeige-editor), um den es in dieser Lektion geht, und rechts den Bereich [Code](#zeige-codelive) für Java-Code (ab Lektion 4). Ist der Struktogramm-Editor eingeklappt, öffnet ihn diese Lektion von selbst. Die blauen Wörter zeigen dir die Bereiche, auch wenn sie gerade eingeklappt sind: Fährst du mit der Maus darüber, öffnet sich der Bereich neben dem Lernbereich und leuchtet auf. Klickst du darauf (oder tippst es an), bleibt er offen. Der Struktogramm-Editor besteht aus mehreren Bereichen. Fahre mit der Maus über ein blaues Wort oder tippe es an, dann leuchtet der Bereich im Editor auf, eingeklappte Bereiche wie die Elemente öffnen sich dabei. @@ -24,7 +24,7 @@ Der Struktogramm-Editor besteht aus mehreren Bereichen. Fahre mit der Maus über - **In der Mitte das [Struktogramm](#zeige-struktogramm):** Ein neues Diagramm enthält nur einen leeren Platzhalter, erkennbar an **ø**. - **Unten der [Objektinspektor](#zeige-objektinspektor):** Hier bearbeitest du den Text des ausgewählten Elements. -> Diesen Lernbereich kannst du jederzeit mit dem [Seitenleisten-Symbol](#zeige-lernen) oben in diesem Bereich einklappen. Dann bleibt links nur die schmale Leiste „🎓 Lernen“, ein Klick darauf öffnet ihn wieder. Er bleibt neben dem Editor offen, damit du gleich ausprobieren kannst, was du liest. Genauso gibt es links die Spalte [📁 Dateien](#zeige-dateien) für deine gespeicherten Programme (Lektion 3) und rechts den Bereich [Programmieren](#zeige-codelive) für Java (ab Lektion 4). +> Diesen Lernbereich kannst du jederzeit mit dem [Seitenleisten-Symbol](#zeige-lernen) oben in diesem Bereich einklappen. Dann bleibt links nur die schmale Leiste „🎓 Lernen“, ein Klick darauf öffnet ihn wieder. Er bleibt neben dem Editor offen, damit du gleich ausprobieren kannst, was du liest. Genauso gibt es links die Spalte [📁 Dateien](#zeige-dateien) für deine gespeicherten Programme (Lektion 3) und rechts den Bereich [Code](#zeige-codelive) für Java (ab Lektion 4). ## Ein Element einfügen diff --git a/web/lessons/de/04-variablen-und-datentypen.md b/web/lessons/de/04-variablen-und-datentypen.md index 5e4502fc..ab063782 100644 --- a/web/lessons/de/04-variablen-und-datentypen.md +++ b/web/lessons/de/04-variablen-und-datentypen.md @@ -196,14 +196,14 @@ System.out.println("Größe: " + groesse + " m"); - `String` schreibst du groß, `int`, `double` und `boolean` klein. Java unterscheidet das. - Mit `+` hängst du Text und Zahlen aneinander. -Java tippst du im Bereich [Programmieren](#zeige-codelive). Das Struktogramm entsteht dabei von selbst. „Im Editor öffnen“ holt das Beispiel in den Bereich Programmieren. Klicke dort auf „Ausführen“, ändere dann Name, Alter oder Größe und probiere es noch einmal. +Java tippst du im Bereich [Code](#zeige-codelive). Das Struktogramm entsteht dabei von selbst. „Im Editor öffnen“ holt das Beispiel in den Bereich Code. Klicke dort auf „Ausführen“, ändere dann Name, Alter oder Größe und probiere es noch einmal. ::: übung l04-java-steckbrief titel: Steckbrief in Java code: java auftrag: Schreibe einen Steckbrief für Ludwig den Geißbock. Lege drei Variablen an: den Namen **Ludwig**, das Alter **7** und die Größe **1.2**. Gib dann diese zwei Zeilen aus: **Ludwig ist 7 Jahre alt.** und **Größe: 1.2 m** - „Im Editor öffnen“ öffnet rechts auch den Bereich Programmieren. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. + „Im Editor öffnen“ öffnet rechts auch den Bereich Code. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. test: - -> Ludwig ist 7 Jahre alt. | Größe: 1.2 m braucht: anweisung tipp: Du brauchst einen `String`, einen `int` und einen `double`. Jede Zeile endet mit einem Semikolon. @@ -227,7 +227,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 Programmieren 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 „Java“. ::: ## Fehler finden: Sekunden @@ -236,7 +236,7 @@ erklärung: Ganze Zahlen sind `int`, Kommazahlen `double`, Texte `String` (groß titel: Sekunden reparieren code: java auftrag: Das Programm soll 200 Sekunden in Minuten und Sekunden umrechnen und **3 min 20 s** ausgeben. Es gibt aber **20 min 3 s** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l04-java-fehler-start.visustruct test: - -> 3 min 20 s braucht: anweisung diff --git a/web/lessons/de/05-sequenz.md b/web/lessons/de/05-sequenz.md index bffb39ce..fde24fc1 100644 --- a/web/lessons/de/05-sequenz.md +++ b/web/lessons/de/05-sequenz.md @@ -100,13 +100,13 @@ System.out.println("b = " + b); - Am Ende jeder Anweisung steht ein **Semikolon** `;`. - Eine Ausgabe heißt in Java `System.out.println(…)`. Achte auf das große S bei `System`, Java unterscheidet Groß- und Kleinbuchstaben. -Java tippst du im Bereich [Programmieren](#zeige-codelive) rechts neben dem Struktogramm. Während du tippst, baut VisuStruct das Struktogramm mit. So siehst du sofort, welcher Kasten zu welcher Zeile gehört. +Java tippst du im Bereich [Code](#zeige-codelive) rechts neben dem Struktogramm. Während du tippst, baut VisuStruct das Struktogramm mit. So siehst du sofort, welcher Kasten zu welcher Zeile gehört. ::: übung l05-java-kino titel: Kinokarten in Java code: java auftrag: Eine Kinokarte kostet 9 Euro. Schreibe ein Java-Programm, das den Preis für 3 Karten ausrechnet und **Gesamt: 27** ausgibt. - „Im Editor öffnen“ öffnet rechts auch den Bereich Programmieren. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. + „Im Editor öffnen“ öffnet rechts auch den Bereich Code. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. test: - -> Gesamt: 27 braucht: anweisung tipp: Du brauchst drei Variablen: den Preis, die Anzahl und das Ergebnis. Jede Zeile endet mit einem Semikolon. @@ -136,7 +136,7 @@ erklärung: Erst rettest du `a` in die Hilfsvariable, dann bekommt `a` den Wert titel: Guthaben reparieren code: java auftrag: Auf der Mensakarte sind 20 Euro. Ein Essen kostet 7 Euro. Das Programm soll das Guthaben **nach** dem Bezahlen ausgeben, also **Übrig: 13**. Es gibt aber **Übrig: 20** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l05-java-fehler-start.visustruct test: - -> Übrig: 13 braucht: anweisung diff --git a/web/lessons/de/06-eingabe-und-ausgabe.md b/web/lessons/de/06-eingabe-und-ausgabe.md index eac891af..1346665a 100644 --- a/web/lessons/de/06-eingabe-und-ausgabe.md +++ b/web/lessons/de/06-eingabe-und-ausgabe.md @@ -192,7 +192,7 @@ erklärung: `scanner.next()` liest ein Wort, `scanner.nextInt()` eine ganze Zahl titel: Summe reparieren code: java auftrag: Das Programm liest zwei Zahlen ein und soll ihre Summe ausgeben. Bei 3 und 4 erscheint aber **Summe: 34** statt **Summe: 7**. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l06-java-fehler-start.visustruct test: 3, 4 -> Summe: 7 test: 10, 5 -> Summe: 15 diff --git a/web/lessons/de/07-simulation-und-schreibtischtest.md b/web/lessons/de/07-simulation-und-schreibtischtest.md index 9b8c6bf1..0bf5a1df 100644 --- a/web/lessons/de/07-simulation-und-schreibtischtest.md +++ b/web/lessons/de/07-simulation-und-schreibtischtest.md @@ -41,7 +41,7 @@ Die Werte von a und b werden vertauscht. Die Variable hilf merkt sich dabei eine - **Variablen:** Alle Variablen mit ihren aktuellen Werten. - **Ausgabe:** Alles, was mit `output:` ausgegeben wurde. -Ist rechts der Bereich [Programmieren](#zeige-codelive) geöffnet, läuft dort zusätzlich die [Konsole](#zeige-konsole) mit. Sie wird beim Start geleert und zeigt dann die Ausgaben und Eingaben so, wie sie auch beim echten Programm erscheinen würden. +Ist rechts der Bereich [Code](#zeige-codelive) geöffnet, läuft dort zusätzlich die [Konsole](#zeige-konsole) mit. Sie wird beim Start geleert und zeigt dann die Ausgaben und Eingaben so, wie sie auch beim echten Programm erscheinen würden. Am Ende erscheint **Simulation beendet**. Geht etwas schief, bleibt die Simulation auf dem fehlerhaften Kasten stehen und zeigt eine Meldung, z. B. **Unbekannte Variable: gesamt**. @@ -122,7 +122,7 @@ lösung: sim-kino-loesung.visustruct ## Jetzt in Java -Auch Java-Code kannst du Schritt für Schritt ausführen. Im Bereich [Programmieren](#zeige-codelive) heißt das Werkzeug dafür **Debugger**: +Auch Java-Code kannst du Schritt für Schritt ausführen. Im Bereich [Code](#zeige-codelive) heißt das Werkzeug dafür **Debugger**: - Klicke links auf eine Zeilennummer. Ein roter Punkt erscheint, das ist ein **Haltepunkt**. [▶︎ Ausführen](#zeige-ausfuehren) hält vor dieser Zeile an. - Der Knopf [Einzelschritt](#zeige-einzelschritt) führt genau eine Zeile aus, wie **Schritt** in der Simulation. @@ -154,7 +154,7 @@ b = a * 2; // b ist jetzt [[14]] a = b - a; // a ist jetzt [[7]] System.out.println(a + b); // Ausgabe: [[21]] ``` -erklärung: Jede Zeile rechnet mit den Werten, die gerade in den Variablen stehen: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, Ausgabe 7 + 14 = 21. Mit dem Einzelschritt im Bereich Programmieren kannst du es nachprüfen. +erklärung: Jede Zeile rechnet mit den Werten, die gerade in den Variablen stehen: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, Ausgabe 7 + 14 = 21. Mit dem Einzelschritt im Bereich Code kannst du es nachprüfen. ::: ## Fehler finden: Spielstand @@ -286,7 +286,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] summe ist zu groß. - [ ] Das Struktogramm hat zu viele Kästen. -? Was macht ein roter Punkt vor einer Zeilennummer im Bereich Programmieren? +? Was macht ein roter Punkt vor einer Zeilennummer im Bereich Code? → Jetzt in Java - [ ] Er markiert einen Fehler. - [x] Das Programm hält vor dieser Zeile an. diff --git a/web/lessons/de/08-verzweigung.md b/web/lessons/de/08-verzweigung.md index 34487f58..48372c79 100644 --- a/web/lessons/de/08-verzweigung.md +++ b/web/lessons/de/08-verzweigung.md @@ -130,7 +130,7 @@ Java hat auch ein Maskottchen: **Duke**, ein kleiner schwarz-weißer Kerl mit gr titel: Bestanden in Java code: java auftrag: Schreibe ein Java-Programm, das nach der Punktzahl fragt. Ab 50 Punkten gibt es **bestanden** aus, sonst **nicht bestanden**. - Tippe den Code im Bereich Programmieren und klicke dann auf Prüfen. + Tippe den Code im Bereich Code und klicke dann auf Prüfen. test: 50 -> bestanden test: 49 -> nicht bestanden test: 100 -> bestanden @@ -167,7 +167,7 @@ erklärung: `zahl % 2` ist der Rest beim Teilen durch 2. Ist er 0, ist die Zahl titel: Eintritt reparieren code: java auftrag: Im Zoo haben Kinder **unter** 6 Jahren freien Eintritt, alle anderen zahlen 4 Euro. Das Programm lässt aber auch Sechsjährige umsonst hinein. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l08-java-fehler-start.visustruct test: 5 -> Eintritt frei test: 6 -> 4 Euro diff --git a/web/lessons/de/09-bedingungen-verknuepfen.md b/web/lessons/de/09-bedingungen-verknuepfen.md index f986ad78..42063c79 100644 --- a/web/lessons/de/09-bedingungen-verknuepfen.md +++ b/web/lessons/de/09-bedingungen-verknuepfen.md @@ -247,7 +247,7 @@ erklärung: Eine Note ist gültig, wenn **beide** Bedingungen stimmen, also `&&` titel: Schulfrei reparieren code: java auftrag: Das Programm soll bei Tag 6 (Samstag) und Tag 7 (Sonntag) **schulfrei** ausgeben, sonst **Schule**. Es gibt aber immer **Schule** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l09-java-fehler-start.visustruct test: 6 -> schulfrei test: 7 -> schulfrei diff --git a/web/lessons/de/10-fallauswahl.md b/web/lessons/de/10-fallauswahl.md index d69bfe7a..51d586a2 100644 --- a/web/lessons/de/10-fallauswahl.md +++ b/web/lessons/de/10-fallauswahl.md @@ -171,7 +171,7 @@ erklärung: Nach `switch` steht die Variable in runden Klammern. Jeder Fall begi titel: Rechner reparieren code: java auftrag: Der Rechner liest zwei Zahlen und eine Wahl ein: 1 plus, 2 minus, 3 mal. Bei 7, 3 und Wahl 2 soll **4** herauskommen, er rechnet aber **-4**. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l10-java-fehler-start.visustruct test: 7, 3, 2 -> 4 test: 7, 3, 1 -> 10 diff --git a/web/lessons/de/12-do-while-schleife.md b/web/lessons/de/12-do-while-schleife.md index b1e321e1..caa58d4e 100644 --- a/web/lessons/de/12-do-while-schleife.md +++ b/web/lessons/de/12-do-while-schleife.md @@ -132,7 +132,7 @@ erklärung: Der Rumpf steht zwischen `do {` und `}`, die Bedingung erst danach. titel: Halbieren reparieren code: java auftrag: Das Programm liest eine Startzahl ein und teilt sie mit einer Do-while-Schleife immer wieder ganzzahlig durch 2. Jedes Ergebnis wird ausgegeben, bis **0** erreicht ist. Bei 10 also 5, 2, 1 und 0. Die 0 fehlt aber. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l12-java-fehler-start.visustruct test: 10 -> 5 | 2 | 1 | 0 test: 1 -> 0 diff --git a/web/lessons/de/13-for-schleife.md b/web/lessons/de/13-for-schleife.md index fa9aea4a..5332d8fc 100644 --- a/web/lessons/de/13-for-schleife.md +++ b/web/lessons/de/13-for-schleife.md @@ -169,7 +169,7 @@ erklärung: In den runden Klammern stehen Startwert, Bedingung und Schritt, getr titel: Einmaleins reparieren code: java auftrag: Das Programm fragt nach einer Reihe und soll sie vom 1-fachen bis zum 10-fachen ausgeben, bei 7 also 7, 14, … bis 70. Die 70 fehlt aber. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l13-java-fehler-start.visustruct test: 7 -> 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 test: 3 -> 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 diff --git a/web/lessons/de/14-verschachteln.md b/web/lessons/de/14-verschachteln.md index 3673f13c..b25ebcd0 100644 --- a/web/lessons/de/14-verschachteln.md +++ b/web/lessons/de/14-verschachteln.md @@ -102,7 +102,7 @@ for (int i = 1; i <= n; i++) { System.out.println(anzahl); ``` -Was im Struktogramm ineinander steckt, steht in Java in geschweiften Klammern ineinander. Jede Ebene ist vier Leerzeichen weiter eingerückt. Ist dein Code durcheinander, hilft der Knopf **Einrücken** oben im Bereich Programmieren. +Was im Struktogramm ineinander steckt, steht in Java in geschweiften Klammern ineinander. Jede Ebene ist vier Leerzeichen weiter eingerückt. Ist dein Code durcheinander, hilft der Knopf **Einrücken** oben im Bereich Code. `anzahl++` ist die Kurzform von `anzahl = anzahl + 1`. @@ -142,7 +142,7 @@ erklärung: Die innere Schleife baut eine Zeile aus 4 Sternchen, die äußere wi titel: Zählen reparieren code: java auftrag: Das Programm soll zählen, wie viele Zahlen von 1 bis `n` durch 3 teilbar sind, und **einmal** das Ergebnis ausgeben. Bei 10 also nur **Anzahl: 3**. Es gibt aber viel zu viele Zeilen aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l14-java-fehler-start.visustruct test: 10 -> Anzahl: 3 test: 3 -> Anzahl: 1 diff --git a/web/lessons/de/15-arrays.md b/web/lessons/de/15-arrays.md index a0cd0635..b30c60da 100644 --- a/web/lessons/de/15-arrays.md +++ b/web/lessons/de/15-arrays.md @@ -191,7 +191,7 @@ erklärung: `int[]` ist ein Array aus ganzen Zahlen, `werte.length` seine Länge titel: Höchste Temperatur reparieren code: java auftrag: Im Januar wurden die Temperaturen -5, -2, -8 und -3 Grad gemessen. Das Programm soll die höchste ausgeben, also **Höchste Temperatur: -2**. Es behauptet aber 0 Grad, obwohl es so warm nie war. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l15-java-fehler-start.visustruct test: - -> Höchste Temperatur: -2 braucht: forSchleife, verzweigung diff --git a/web/lessons/de/16-zweidimensionale-arrays.md b/web/lessons/de/16-zweidimensionale-arrays.md index cd9a8ad4..a5bd3caa 100644 --- a/web/lessons/de/16-zweidimensionale-arrays.md +++ b/web/lessons/de/16-zweidimensionale-arrays.md @@ -169,7 +169,7 @@ erklärung: `int[][]` ist eine Tabelle. `feld.length` ist die Zahl der Reihen (2 titel: Spieler 2 reparieren code: java auftrag: In der Tabelle `punkte` steht jede Reihe für einen Spieler. Das Programm soll die Punkte von Spieler 2 (Reihe 1) zusammenzählen, also **Spieler 2: 11**. Stattdessen meldet es einen Fehler. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l16-java-fehler-start.visustruct test: - -> Spieler 2: 11 braucht: forSchleife diff --git a/web/lessons/de/17-zeichenketten.md b/web/lessons/de/17-zeichenketten.md index 77808825..2e869f7b 100644 --- a/web/lessons/de/17-zeichenketten.md +++ b/web/lessons/de/17-zeichenketten.md @@ -222,7 +222,7 @@ erklärung: `length()` zählt die Zeichen, `toUpperCase()` macht alles groß, `c titel: Initialen reparieren code: java auftrag: Das Programm liest Vor- und Nachnamen ein und soll die Initialen ausgeben. Bei Ludwig Geißbock also **L. G.** Es gibt aber **u. e.** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l17-java-fehler-start.visustruct test: Ludwig, Geißbock -> L. G. test: Mia, Meyer -> M. M. diff --git a/web/lessons/de/18-aufruf-und-aussprung.md b/web/lessons/de/18-aufruf-und-aussprung.md index 46f07827..1fca1042 100644 --- a/web/lessons/de/18-aufruf-und-aussprung.md +++ b/web/lessons/de/18-aufruf-und-aussprung.md @@ -228,7 +228,7 @@ System.out.println("Das Quadrat ist " + q); - In der Kopfzeile steht vor dem Namen, was die Methode zurückgibt (`int`). Gibt sie nichts zurück, steht dort `void`. - Die Parameter stehen mit Datentyp in den runden Klammern: `(int x)`. Mehrere trennst du mit Komma. -- Im Bereich Programmieren schreibst du jede Methode in einen eigenen Reiter, so wie jedes Unterprogramm ein eigenes Struktogramm hat. +- Im Bereich Code schreibst du jede Methode in einen eigenen Reiter, so wie jedes Unterprogramm ein eigenes Struktogramm hat. - Der Aussprung heißt in Java `break`. Mit `while (true)` baust du eine Schleife, die nur durch `break` endet. ::: übung l18-java-kasse @@ -249,7 +249,7 @@ lösung: l18-java-kasse-loesung.visustruct ::: lückentext titel: Methode und Aussprung -auftrag: Ergänze die fehlenden Wörter. Oben steht die Methode, die ein Quadrat ausrechnet. Darunter steht das Hauptprogramm, das sie aufruft. Im Bereich Programmieren stehen beide in eigenen Reitern. +auftrag: Ergänze die fehlenden Wörter. Oben steht die Methode, die ein Quadrat ausrechnet. Darunter steht das Hauptprogramm, das sie aufruft. Im Bereich Code stehen beide in eigenen Reitern. ```java public static [[int]] quadrat(int x) { [[return]] x * x; @@ -275,7 +275,7 @@ erklärung: `int` vor dem Methodennamen heißt: Die Methode gibt eine ganze Zahl titel: Versuche zählen reparieren code: java auftrag: Beim Zahlenraten ist die gesuchte Zahl 7. Das Programm fragt so lange nach einem Tipp, bis die 7 kommt, und gibt dann die Zahl der Versuche aus. Bei 3, 5 und 7 waren es 3 Versuche, das Programm sagt aber **Versuche: 2**. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l18-java-fehler-start.visustruct test: 3, 5, 7 -> Versuche: 3 test: 7 -> Versuche: 1 diff --git a/web/lessons/de/19-suchen-und-sortieren.md b/web/lessons/de/19-suchen-und-sortieren.md index 71f9e0e8..cfa54aae 100644 --- a/web/lessons/de/19-suchen-und-sortieren.md +++ b/web/lessons/de/19-suchen-und-sortieren.md @@ -189,7 +189,7 @@ erklärung: Ist eine Karte größer als ihre rechte Nachbarin, werden die beiden titel: Lineare Suche reparieren code: java auftrag: Die Karten {8, 4, 11, 4, 6} liegen in einem Array. Das Programm soll die **erste** Position der gesuchten Karte ausgeben, bei 4 also **Position: 1**. Es gibt aber **Position: 3** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l19-java-fehler-start.visustruct test: 4 -> Position: 1 test: 6 -> Position: 4 diff --git a/web/lessons/de/20-java.md b/web/lessons/de/20-java.md index 7184a51d..951b54f7 100644 --- a/web/lessons/de/20-java.md +++ b/web/lessons/de/20-java.md @@ -1,7 +1,7 @@ --- titel: Struktogramm und Code bereich: Vom Struktogramm zum Code -kurz: Alle Elemente in Java auf einen Blick, Code erzeugen, im Bereich Programmieren Java schreiben, ausführen und Fehler suchen. +kurz: Alle Elemente in Java auf einen Blick, Code erzeugen, im Bereich Code Java schreiben, ausführen und Fehler suchen. --- ## Diese Kompetenzen erwerbe ich jetzt @@ -11,7 +11,7 @@ kurz: Alle Elemente in Java auf einen Blick, Code erzeugen, im Bereich Programmi - Ausgabe, Eingabe, Verzweigung und Schleifen in Java erkennen - den Unterschied zwischen Snippet und Class erklären - ein kurzes Java-Programm als Struktogramm nachbauen -- im Bereich Programmieren Java tippen und das entstehende Struktogramm lesen +- im Bereich Code Java tippen und das entstehende Struktogramm lesen - ein Programm mit ▶︎ ausführen und Ein- und Ausgaben in der Konsole nutzen - Haltepunkte setzen und ein Programm im Einzelschritt verfolgen ::: @@ -118,25 +118,25 @@ Das hilft dir, die Kästen und die Java-Befehle einander zuzuordnen. Dein Diagra ## Java direkt schreiben -Bisher hast du zuerst das Struktogramm gezeichnet und dann den Code angesehen. Im Bereich [Programmieren](#zeige-codelive) geht es auch andersherum. Klicke rechts auf die schmale Leiste **Programmieren**. Neben dem Struktogramm erscheint eine Spalte, in die du Java selbst tippst. +Bisher hast du zuerst das Struktogramm gezeichnet und dann den Code angesehen. Im Bereich [Code](#zeige-codelive) geht es auch andersherum. Klicke rechts auf die schmale Leiste **Code**. Neben dem Struktogramm erscheint eine Spalte, in die du Java selbst tippst. - **Struktogramm zu Code:** Änderst du etwas im Struktogramm, ändert sich der Java-Code sofort mit. - **Code zu Struktogramm:** Tippst du Java, baut VisuStruct beim Tippen das Struktogramm dazu. Fehlt noch etwas, zum Beispiel eine schließende Klammer `}`, steht unter dem Code ein Hinweis. - **Vorschläge:** Beim Tippen schlägt VisuStruct Vorlagen vor, etwa für `if`, `for` oder `while`. Mit der Eingabetaste übernimmst du eine Vorlage. Grau geschriebene Platzhalter ersetzt du einfach durch deinen Text. -- **Einrücken:** Ist dein Code durcheinandergeraten, klicke oben im Bereich Programmieren auf den Knopf **Einrücken**. Jede Ebene steht dann vier Leerzeichen tiefer, wie in Eclipse oder IntelliJ. Hast du Zeilen markiert, rückt VisuStruct nur diese ein. +- **Einrücken:** Ist dein Code durcheinandergeraten, klicke oben im Bereich Code auf den Knopf **Einrücken**. Jede Ebene steht dann vier Leerzeichen tiefer, wie in Eclipse oder IntelliJ. Hast du Zeilen markiert, rückt VisuStruct nur diese ein. So kannst du beide Wege ausprobieren. Erst das Struktogramm zeichnen ist gut, um einen Ablauf zu planen. Direkt Code schreiben ist schneller, wenn du schon weißt, was du willst. Das Struktogramm hilft dir dann, deinen Code zu kontrollieren. ## Das Programm ausführen -Oben im Bereich Programmieren startet [▶︎ Ausführen](#zeige-ausfuehren) dein Programm, **■ Stopp** bricht es ab, zum Beispiel bei einer Endlosschleife. Was dein Programm ausgibt, erscheint unten in der [Konsole](#zeige-konsole). Fragt es nach einer Eingabe, tippst du sie dort ein und drückst die Eingabetaste. +Oben im Bereich Code startet [▶︎ Ausführen](#zeige-ausfuehren) dein Programm, **■ Stopp** bricht es ab, zum Beispiel bei einer Endlosschleife. Was dein Programm ausgibt, erscheint unten in der [Konsole](#zeige-konsole). Fragt es nach einer Eingabe, tippst du sie dort ein und drückst die Eingabetaste. Die Grenze zwischen Code und Konsole kannst du mit der Maus nach oben oder unten ziehen. -> Der Bereich Programmieren versteht die Java-Befehle, die es auch als Kasten im Struktogramm gibt. Eigene Klassen und Objekte kennt es noch nicht. Fenster mit Swing gehen trotzdem: Schalte dafür im Zahnrad **Echtes Java (mit Swing)** ein (Lektion „Dein erstes Fenster“). +> Der Bereich Code versteht die Java-Befehle, die es auch als Kasten im Struktogramm gibt. Eigene Klassen und Objekte kennt es noch nicht. Fenster mit Swing gehen trotzdem: Schalte dafür im Zahnrad **Echtes Java (mit Swing)** ein (Lektion „Dein erstes Fenster“). ::: angeberwissen -Profis nennen ein Programm, in dem man Code schreibt, ausführt und Fehler sucht, eine **IDE** (Integrated Development Environment). Mit dem Bereich Programmieren ist VisuStruct eine kleine IDE mit eingebautem Struktogramm. +Profis nennen ein Programm, in dem man Code schreibt, ausführt und Fehler sucht, eine **IDE** (Integrated Development Environment). Mit dem Bereich Code ist VisuStruct eine kleine IDE mit eingebautem Struktogramm. ::: ## Fehler suchen mit dem Debugger @@ -165,7 +165,7 @@ Das ist ein Schreibtischtest, nur dass der Computer für dich mitschreibt. Über ## Übung: Erst Code, dann Struktogramm -Diesmal zeichnest du nicht. Öffne den Bereich Programmieren und tippe diesen Java-Code ab: +Diesmal zeichnest du nicht. Öffne den Bereich Code und tippe diesen Java-Code ab: ``` System.out.println("Startzahl?"); @@ -179,13 +179,14 @@ System.out.println("Start!"); ::: übung l20-countdown titel: Countdown -auftrag: Tippe den Java-Code oben im Bereich Programmieren ab. Führe ihn mit ▶︎ aus und gib in der Konsole eine Startzahl ein. +bereich: beide +auftrag: Tippe den Java-Code oben im Bereich Code ab. Führe ihn mit ▶︎ aus und gib in der Konsole eine Startzahl ein. Sieh dir dann das Struktogramm an, das dabei entstanden ist, und klicke auf Prüfen. test: 3 -> 3 | 2 | 1 | Start! test: 1 -> 1 | Start! test: 0 -> Start! braucht: whileSchleife -tipp: Öffne den Bereich Programmieren mit der schmalen Leiste ganz rechts und tippe einfach los. +tipp: Öffne den Bereich Code mit der schmalen Leiste ganz rechts und tippe einfach los. tipp: Achte auf das Semikolon am Ende jeder Anweisung und auf die geschweiften Klammern der While-Schleife. Unter dem Code steht ein Hinweis, wenn noch etwas fehlt. lösung: l20-countdown-loesung.visustruct ::: @@ -206,6 +207,7 @@ System.out.println(fakultaet); ::: übung l17-fakultaet titel: Fakultät aus Java +bereich: beide auftrag: Baue den Java-Code oben als Struktogramm nach. Das Programm liest eine Zahl n ein und gibt das Produkt 1 · 2 · … · n aus. Kontrolliere am Ende in der Code-Ansicht, ob dein Java-Code genauso aussieht. test: 3 -> 6 @@ -325,7 +327,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann Ausgabe, Eingabe, Verzweigung und Schleifen in Java erkennen. → Die Elemente in Java - Ich kann den Unterschied zwischen Snippet und Class erklären. → Snippet oder Class - Ich kann ein kurzes Java-Programm als Struktogramm nachbauen. → Übung: Java als Struktogramm -- Ich kann im Bereich Programmieren Java tippen und das entstehende Struktogramm lesen. → Java direkt schreiben +- Ich kann im Bereich Code Java tippen und das entstehende Struktogramm lesen. → Java direkt schreiben - Ich kann ein Programm mit ▶︎ ausführen und Ein- und Ausgaben in der Konsole nutzen. → Das Programm ausführen - Ich kann Haltepunkte setzen und ein Programm im Einzelschritt verfolgen. → Fehler suchen mit dem Debugger ::: diff --git a/web/lessons/de/22-try-und-catch.md b/web/lessons/de/22-try-und-catch.md index 892edcd3..88b6b4d0 100644 --- a/web/lessons/de/22-try-und-catch.md +++ b/web/lessons/de/22-try-und-catch.md @@ -7,7 +7,7 @@ kurz: Mit echtem Java Fehlermeldungen lesen und Abstürze mit try und catch abfa ## Diese Kompetenzen erwerbe ich jetzt ::: kompetenzen -- echtes Java im Bereich Programmieren einschalten +- echtes Java im Bereich Code einschalten - aus einer Fehlermeldung die Exception und die Zeile ablesen - eine Exception mit try und catch auffangen - Text mit Integer.parseInt in eine Zahl umwandeln und die NumberFormatException abfangen @@ -16,7 +16,7 @@ kurz: Mit echtem Java Fehlermeldungen lesen und Abstürze mit try und catch abfa ## Abgestürzt! -Dieses Programm soll drei Noten ausgeben. Tippe es im Bereich [Programmieren](#zeige-codelive) ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): +Dieses Programm soll drei Noten ausgeben. Tippe es im Bereich [Code](#zeige-codelive) ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): ```java int[] noten = {2, 3, 1}; @@ -37,7 +37,7 @@ Ist dir das auch schon passiert? Ein kleiner Fehler, und das ganze Programm ist ## Echtes Java einschalten -Der Bereich Programmieren rechnet normalerweise mit derselben Simulation wie das Struktogramm. Die hält bei einem Fehler einfach an. Um zu sehen, was echtes Java macht, schaltest du echtes Java ein: +Der Bereich Code rechnet normalerweise mit derselben Simulation wie das Struktogramm. Die hält bei einem Fehler einfach an. Um zu sehen, was echtes Java macht, schaltest du echtes Java ein: 1. Klicke oben rechts auf das [Zahnrad](#zeige-einstellungen) und wähle als **Programmiersprache** Java. 2. Setze im Abschnitt Java den Haken bei **Echtes Java (mit Swing)**. @@ -80,7 +80,7 @@ So eine Meldung sieht erst einmal erschreckend aus. Sie verrät dir aber genau, So einen Fehler zur Laufzeit nennt Java eine **Exception** (englisch für Ausnahme). Man sagt: Java *wirft* eine Exception. Fängt sie niemand auf, bricht das Programm ab. Deshalb erscheint „Fertig!“ nicht. ::: ludwig -Lies Fehlermeldungen immer von oben: Erst der Name der Exception, dann die Zeilennummer. Die Zeilennummern stehen im Bereich Programmieren links neben dem Code. +Lies Fehlermeldungen immer von oben: Erst der Name der Exception, dann die Zeilennummer. Die Zeilennummern stehen im Bereich Code links neben dem Code. ::: ## try und catch @@ -245,7 +245,7 @@ Die Exception heißt `ArithmeticException`. Schreib in den `try`-Block nur die Z 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. ::: checkliste -- Ich kann echtes Java im Bereich Programmieren einschalten. → Echtes Java einschalten +- Ich kann echtes Java im Bereich Code einschalten. → Echtes Java einschalten - Ich kann aus einer Fehlermeldung die Exception und die Zeile ablesen. → Die Fehlermeldung lesen - Ich kann eine Exception mit try und catch auffangen. → try und catch - Ich kann Text mit Integer.parseInt in eine Zahl umwandeln und die NumberFormatException abfangen. → Text in eine Zahl umwandeln diff --git a/web/lessons/de/28-erstes-fenster.md b/web/lessons/de/28-erstes-fenster.md index fb0e98e6..b7047614 100644 --- a/web/lessons/de/28-erstes-fenster.md +++ b/web/lessons/de/28-erstes-fenster.md @@ -7,7 +7,7 @@ kurz: Mit Java und Swing ein eigenes Fenster öffnen, Zeile für Zeile erklärt. ## Diese Kompetenzen erwerbe ich jetzt ::: kompetenzen -- im Bereich Programmieren „Echtes Java“ einschalten +- im Bereich Code „Echtes Java“ einschalten - ein Fenster mit Titel und Größe öffnen - erklären, was jede Zeile des Fensterprogramms macht - erklären, warum setVisible(true) am Ende steht @@ -19,11 +19,11 @@ Bisher haben deine Programme Text in die Konsole geschrieben. Die meisten Progra Java bringt dafür einen Werkzeugkasten mit: **Swing**. In VisuStruct schaltest du ihn so ein: -1. Öffne rechts den Bereich [Programmieren](#zeige-codelive). +1. Öffne rechts den Bereich [Code](#zeige-codelive). 2. Klicke oben rechts auf das [Zahnrad](#zeige-einstellungen) und wähle als **Programmiersprache** Java. 3. Setze darunter im Abschnitt Java den Haken bei **Echtes Java (mit Swing)**. -Beim ersten [▶︎ Ausführen](#zeige-ausfuehren) lädt VisuStruct einmalig etwa 40 MB, das dauert einen Moment. Danach läuft dein Code als echtes Java, und deine Fenster erscheinen im Bereich Programmieren im Feld **Java-Fenster** über der Konsole. +Beim ersten [▶︎ Ausführen](#zeige-ausfuehren) lädt VisuStruct einmalig etwa 40 MB, das dauert einen Moment. Danach läuft dein Code als echtes Java, und deine Fenster erscheinen im Bereich Code im Feld **Java-Fenster** über der Konsole. > Mit „Echtes Java“ funktionieren Eingaben über die Konsole (`Scanner`) noch nicht. Für Programme mit Eingabe schaltest du den Haken wieder aus. @@ -33,7 +33,7 @@ Swing gibt es seit 1998. Davor hatte Java nur das ältere AWT mit einer Klasse ` ## Das ganze Programm -So sieht das kleinste Programm aus, das ein Fenster öffnet. Tippe es im Bereich Programmieren ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): +So sieht das kleinste Programm aus, das ein Fenster öffnet. Tippe es im Bereich Code ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): ```java import javax.swing.*; @@ -177,7 +177,7 @@ frage: Was siehst du? Führe es aus und prüfe alle drei Punkte. ::: ludwig -Du willst nicht so viel tippen? Mit „Echtes Java“ darfst du im Bereich Programmieren auch nur die vier Zeilen aus `main` schreiben. VisuStruct packt sie dann selbst in eine Klasse und ergänzt die `import`-Zeilen. In einer richtigen Java-Entwicklungsumgebung brauchst du aber das ganze Programm. +Du willst nicht so viel tippen? Mit „Echtes Java“ darfst du im Bereich Code auch nur die vier Zeilen aus `main` schreiben. VisuStruct packt sie dann selbst in eine Klasse und ergänzt die `import`-Zeilen. In einer richtigen Java-Entwicklungsumgebung brauchst du aber das ganze Programm. ::: ## Checkliste @@ -185,7 +185,7 @@ Du willst nicht so viel tippen? Mit „Echtes Java“ darfst du im Bereich Progr 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. ::: checkliste -- Ich kann im Bereich Programmieren „Echtes Java“ einschalten. → Programme mit Fenstern +- Ich kann im Bereich Code „Echtes Java“ einschalten. → Programme mit Fenstern - Ich kann ein Fenster mit Titel und Größe öffnen. → Das ganze Programm - Ich kann erklären, was jede Zeile des Fensterprogramms macht. → Zeile für Zeile - Ich kann erklären, warum setVisible(true) am Ende steht. → Warum setVisible am Ende steht diff --git a/web/lessons/de/34-notenrechner.md b/web/lessons/de/34-notenrechner.md index 7c78aa2d..bdb29296 100644 --- a/web/lessons/de/34-notenrechner.md +++ b/web/lessons/de/34-notenrechner.md @@ -57,7 +57,7 @@ if (punkte >= 92) { Bei 85 Punkten ist `punkte >= 92` falsch, aber `punkte >= 81` wahr. Also Note 2, und die restlichen Bedingungen werden gar nicht mehr geprüft. Deshalb reicht jeweils die untere Grenze. ::: -Du kannst diesen Teil ohne Fenster im Bereich [Programmieren](#zeige-codelive) ausprobieren. Schreib `int punkte = 85;` davor und `System.out.println("Note: " + note);` dahinter. Das Struktogramm zeigt dir die verschachtelten Verzweigungen. +Du kannst diesen Teil ohne Fenster im Bereich [Code](#zeige-codelive) ausprobieren. Schreib `int punkte = 85;` davor und `System.out.println("Note: " + note);` dahinter. Das Struktogramm zeigt dir die verschachtelten Verzweigungen. ## Das Fenster diff --git a/web/lessons/de/36-zahlenraten.md b/web/lessons/de/36-zahlenraten.md index 94511766..1becd0aa 100644 --- a/web/lessons/de/36-zahlenraten.md +++ b/web/lessons/de/36-zahlenraten.md @@ -38,7 +38,7 @@ int geheim = (int) (Math.random() * 100) + 1; Ohne `+ 1` käme 0 bis 99 heraus. -Probiere es im Bereich [Programmieren](#zeige-codelive) aus: `int geheim = (int) (Math.random() * 100) + 1;` und `System.out.println(geheim);`. Jedes Ausführen liefert eine andere Zahl. +Probiere es im Bereich [Code](#zeige-codelive) aus: `int geheim = (int) (Math.random() * 100) + 1;` und `System.out.println(geheim);`. Jedes Ausführen liefert eine andere Zahl. ::: angeberwissen Computer können eigentlich gar nicht würfeln. `Math.random()` rechnet mit einer Formel eine lange Folge von Zahlen aus, die nur zufällig **aussehen**. Man nennt sie Pseudozufallszahlen. Für Spiele reicht das völlig. diff --git a/web/lessons/de/visubot/06-abstand.md b/web/lessons/de/visubot/06-abstand.md index 09537450..ffaec603 100644 --- a/web/lessons/de/visubot/06-abstand.md +++ b/web/lessons/de/visubot/06-abstand.md @@ -49,7 +49,7 @@ lösung: vb-abstand-halten-loesung.visustruct ## Jetzt in Java -Im Bereich [Programmieren](#zeige-codelive) siehst du dein Struktogramm schon als Java-Code. Eine Verzweigung heißt dort `if`, der Nein-Zweig `else`: +Im Bereich [Code](#zeige-codelive) siehst du dein Struktogramm schon als Java-Code. Eine Verzweigung heißt dort `if`, der Nein-Zweig `else`: ```java if (mbot.getDistance() < 10) { diff --git a/web/lessons/de/visubot/22-eigene-methoden.md b/web/lessons/de/visubot/22-eigene-methoden.md index acb5f2f0..254ef227 100644 --- a/web/lessons/de/visubot/22-eigene-methoden.md +++ b/web/lessons/de/visubot/22-eigene-methoden.md @@ -53,7 +53,7 @@ public class Quadrate { } ``` -Im Bereich [Programmieren](#zeige-codelive) siehst du jede Methode in ihrem eigenen Reiter, so wie im Struktogramm. +Im Bereich [Code](#zeige-codelive) siehst du jede Methode in ihrem eigenen Reiter, so wie im Struktogramm. ::: quiz ? Was bedeutet `void` in `void quadrat(int seite)`? diff --git a/web/lessons/en/02-der-editor.md b/web/lessons/en/02-der-editor.md index 96c44cf5..3f5da15a 100644 --- a/web/lessons/en/02-der-editor.md +++ b/web/lessons/en/02-der-editor.md @@ -14,7 +14,7 @@ kurz: Insert elements, type text, move and delete. ## The screen -VisuStruct has two editors: the [structure chart editor](#zeige-editor), which this lesson is about, and on the right the [Programming](#zeige-codelive) area for Java code (from lesson 4). If the structure chart editor is collapsed, this lesson opens it for you. The blue words show you the areas, even when they are collapsed: move the mouse over one, and the area opens next to the learning area and lights up. Click it (or tap it), and it stays open. +VisuStruct has two editors: the [structure chart editor](#zeige-editor), which this lesson is about, and on the right the [Code](#zeige-codelive) area for Java code (from lesson 4). If the structure chart editor is collapsed, this lesson opens it for you. The blue words show you the areas, even when they are collapsed: move the mouse over one, and the area opens next to the learning area and lights up. Click it (or tap it), and it stays open. The structure chart editor has several areas. Move the mouse over a blue word or tap it, and that area lights up in the editor; collapsed areas such as Elements open. @@ -24,7 +24,7 @@ The structure chart editor has several areas. Move the mouse over a blue word or - **In the middle, the [structure chart](#zeige-struktogramm):** A new diagram contains only an empty placeholder, marked with **ø**. - **At the bottom, the [Object Inspector](#zeige-objektinspektor):** Here you edit the text of the selected element. -> You can collapse this learning area at any time with the [sidebar icon](#zeige-lernen) at the top of this area. Then only the slim “🎓 Learn” strip stays on the left; click it to open the area again. It stays open next to the editor so you can try out right away what you read. In the same way there is the [📁 Files](#zeige-dateien) column on the left for your saved programs (lesson 3) and the [Programming](#zeige-codelive) area on the right for Java (from lesson 4). +> You can collapse this learning area at any time with the [sidebar icon](#zeige-lernen) at the top of this area. Then only the slim “🎓 Learn” strip stays on the left; click it to open the area again. It stays open next to the editor so you can try out right away what you read. In the same way there is the [📁 Files](#zeige-dateien) column on the left for your saved programs (lesson 3) and the [Code](#zeige-codelive) area on the right for Java (from lesson 4). ## Insert an element diff --git a/web/lessons/en/04-variablen-und-datentypen.md b/web/lessons/en/04-variablen-und-datentypen.md index 396f90be..75b821dd 100644 --- a/web/lessons/en/04-variablen-und-datentypen.md +++ b/web/lessons/en/04-variablen-und-datentypen.md @@ -196,14 +196,14 @@ System.out.println("Height: " + height + " m"); - You write `String` with a capital letter, `int`, `double` and `boolean` in lowercase. Java tells them apart. - With `+` you join text and numbers together. -You type Java in the [Programming](#zeige-codelive) area. The structure chart builds itself as you type. “Open in editor” brings the example into the Programming area. Click “Run” there, then change the name, age or height and try again. +You type Java in the [Code](#zeige-codelive) area. The structure chart builds itself as you type. “Open in editor” brings the example into the Code area. Click “Run” there, then change the name, age or height and try again. ::: übung l04-java-steckbrief titel: Profile in Java code: java auftrag: Write a profile of Ludwig the billy goat. Create three variables: the name **Ludwig**, the age **7** and the height **1.2**. Then output these two lines: **Ludwig is 7 years old.** and **Height: 1.2 m** - “Open in editor” also opens the Programming area on the right. Type your code there; the structure chart builds itself. Then click Check. + “Open in editor” also opens the Code area on the right. Type your code there; the structure chart builds itself. Then click Check. test: - -> Ludwig is 7 years old. | Height: 1.2 m braucht: anweisung tipp: You need a `String`, an `int` and a `double`. Every line ends with a semicolon. @@ -227,7 +227,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 Programming 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 “Java”. ::: ## Find the bug: seconds @@ -236,7 +236,7 @@ erklärung: Whole numbers are `int`, decimal numbers `double`, texts `String` (w titel: Fix the seconds code: java auftrag: The program should convert 200 seconds into minutes and seconds and output **3 min 20 s**. But it outputs **20 min 3 s**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l04-java-fehler-start.visustruct test: - -> 3 min 20 s braucht: anweisung diff --git a/web/lessons/en/05-sequenz.md b/web/lessons/en/05-sequenz.md index fe1a1b9b..dcaa6b88 100644 --- a/web/lessons/en/05-sequenz.md +++ b/web/lessons/en/05-sequenz.md @@ -100,13 +100,13 @@ System.out.println("b = " + b); - Every statement ends with a **semicolon** `;`. - An output is called `System.out.println(…)` in Java. Mind the capital S in `System`: Java tells upper and lower case apart. -You type Java in the [Programming](#zeige-codelive) area to the right of the structure chart. While you type, VisuStruct builds the structure chart along with it. So you see straight away which box belongs to which line. +You type Java in the [Code](#zeige-codelive) area to the right of the structure chart. While you type, VisuStruct builds the structure chart along with it. So you see straight away which box belongs to which line. ::: übung l05-java-kino titel: Cinema tickets in Java code: java auftrag: A cinema ticket costs 9 euros. Write a Java program that calculates the price of 3 tickets and outputs **Total: 27**. - “Open in editor” also opens the Programming area on the right. Type your code there; the structure chart builds itself. Then click Check. + “Open in editor” also opens the Code area on the right. Type your code there; the structure chart builds itself. Then click Check. test: - -> Total: 27 braucht: anweisung tipp: You need three variables: the price, the number of tickets and the result. Every line ends with a semicolon. @@ -136,7 +136,7 @@ erklärung: First you save `a` in the helper variable, then `a` gets the value o titel: Fix the credit code: java auftrag: The canteen card holds 20 euros. A meal costs 7 euros. The program should output the credit **after** paying, so **Left: 13**. But it outputs **Left: 20**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l05-java-fehler-start.visustruct test: - -> Left: 13 braucht: anweisung diff --git a/web/lessons/en/06-eingabe-und-ausgabe.md b/web/lessons/en/06-eingabe-und-ausgabe.md index f6107c4f..964325c9 100644 --- a/web/lessons/en/06-eingabe-und-ausgabe.md +++ b/web/lessons/en/06-eingabe-und-ausgabe.md @@ -192,7 +192,7 @@ erklärung: `scanner.next()` reads a word, `scanner.nextInt()` a whole number. T titel: Fix the sum code: java auftrag: The program reads two numbers and should output their sum. For 3 and 4, however, it shows **Sum: 34** instead of **Sum: 7**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l06-java-fehler-start.visustruct test: 3, 4 -> Sum: 7 test: 10, 5 -> Sum: 15 diff --git a/web/lessons/en/07-simulation-und-schreibtischtest.md b/web/lessons/en/07-simulation-und-schreibtischtest.md index 038e3d1d..c59b7e8d 100644 --- a/web/lessons/en/07-simulation-und-schreibtischtest.md +++ b/web/lessons/en/07-simulation-und-schreibtischtest.md @@ -41,7 +41,7 @@ The values of a and b are swapped. The variable temp keeps one value meanwhile. - **Variables:** All variables with their current values. - **Output:** Everything that was output with `output:`. -If the [Programming](#zeige-codelive) area is open on the right, the [console](#zeige-konsole) runs along there as well. It is cleared at the start and then shows output and input just as they would appear in the real program. +If the [Code](#zeige-codelive) area is open on the right, the [console](#zeige-konsole) runs along there as well. It is cleared at the start and then shows output and input just as they would appear in the real program. At the end, **Simulation finished.** appears. If something goes wrong, the simulation stops on the faulty box and shows a message, e.g. **Unknown variable: total**. @@ -122,7 +122,7 @@ lösung: sim-kino-loesung.visustruct ## Now in Java -You can run Java code step by step too. In the [Programming](#zeige-codelive) area the tool for this is called the **debugger**: +You can run Java code step by step too. In the [Code](#zeige-codelive) area the tool for this is called the **debugger**: - Click a line number on the left. A red dot appears: that is a **breakpoint**. [▶︎ Run](#zeige-ausfuehren) pauses before this line. - The [Step](#zeige-einzelschritt) button runs exactly one line, like **Step** in the simulation. @@ -154,7 +154,7 @@ b = a * 2; // b is now [[14]] a = b - a; // a is now [[7]] System.out.println(a + b); // output: [[21]] ``` -erklärung: Each line calculates with the values that are in the variables right now: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, output 7 + 14 = 21. You can check it with Step in the Programming area. +erklärung: Each line calculates with the values that are in the variables right now: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, output 7 + 14 = 21. You can check it with Step in the Code area. ::: ## Find the bug: score @@ -286,7 +286,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] sum is too big. - [ ] The structure chart has too many boxes. -? What does a red dot in front of a line number in the Programming area do? +? What does a red dot in front of a line number in the Code area do? → Now in Java - [ ] It marks an error. - [x] The program pauses before this line. diff --git a/web/lessons/en/08-verzweigung.md b/web/lessons/en/08-verzweigung.md index dd000036..c267866a 100644 --- a/web/lessons/en/08-verzweigung.md +++ b/web/lessons/en/08-verzweigung.md @@ -130,7 +130,7 @@ Java has a mascot too: **Duke**, a little black-and-white fellow with a big red titel: Passed in Java code: java auftrag: Write a Java program that asks for the number of points. From 50 points on it outputs **passed**, otherwise **not passed**. - Type the code in the Programming area and then click Check. + Type the code in the Code area and then click Check. test: 50 -> passed test: 49 -> not passed test: 100 -> passed @@ -167,7 +167,7 @@ erklärung: `number % 2` is the remainder when dividing by 2. If it is 0, the nu titel: Fix the admission code: java auftrag: At the zoo, children **under** 6 get in for free, everyone else pays 4 euros. But the program also lets six-year-olds in for free. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l08-java-fehler-start.visustruct test: 5 -> Free entry test: 6 -> 4 euros diff --git a/web/lessons/en/09-bedingungen-verknuepfen.md b/web/lessons/en/09-bedingungen-verknuepfen.md index e5c5f398..3d26f13c 100644 --- a/web/lessons/en/09-bedingungen-verknuepfen.md +++ b/web/lessons/en/09-bedingungen-verknuepfen.md @@ -247,7 +247,7 @@ erklärung: A grade is valid when **both** conditions are true, so `&&`. It is t titel: Fix the day off code: java auftrag: The program should output **no school** for day 6 (Saturday) and day 7 (Sunday), otherwise **school**. But it always outputs **school**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l09-java-fehler-start.visustruct test: 6 -> no school test: 7 -> no school diff --git a/web/lessons/en/10-fallauswahl.md b/web/lessons/en/10-fallauswahl.md index cf79d8a0..143aa8a2 100644 --- a/web/lessons/en/10-fallauswahl.md +++ b/web/lessons/en/10-fallauswahl.md @@ -171,7 +171,7 @@ erklärung: After `switch` the variable is in round brackets. Each case starts w titel: Fix the calculator code: java auftrag: The calculator reads two numbers and a choice: 1 plus, 2 minus, 3 times. For 7, 3 and choice 2 the result should be **4**, but it calculates **-4**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l10-java-fehler-start.visustruct test: 7, 3, 2 -> 4 test: 7, 3, 1 -> 10 diff --git a/web/lessons/en/12-do-while-schleife.md b/web/lessons/en/12-do-while-schleife.md index d24e2d77..65a92ce9 100644 --- a/web/lessons/en/12-do-while-schleife.md +++ b/web/lessons/en/12-do-while-schleife.md @@ -132,7 +132,7 @@ erklärung: The body is between `do {` and `}`, the condition only comes afterwa titel: Fix the halving code: java auftrag: The program reads a start number and keeps dividing it by 2 (whole-number division) with a do-while loop. Every result is output until **0** is reached. For 10 that is 5, 2, 1 and 0. But the 0 is missing. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l12-java-fehler-start.visustruct test: 10 -> 5 | 2 | 1 | 0 test: 1 -> 0 diff --git a/web/lessons/en/13-for-schleife.md b/web/lessons/en/13-for-schleife.md index fa392026..070ce673 100644 --- a/web/lessons/en/13-for-schleife.md +++ b/web/lessons/en/13-for-schleife.md @@ -169,7 +169,7 @@ erklärung: The round brackets hold the start value, the condition and the step, titel: Fix the times table code: java auftrag: The program asks for a times table and should output it from 1 times to 10 times, for 7 that is 7, 14, … up to 70. But the 70 is missing. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l13-java-fehler-start.visustruct test: 7 -> 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 test: 3 -> 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 diff --git a/web/lessons/en/14-verschachteln.md b/web/lessons/en/14-verschachteln.md index 132459b0..87e795fb 100644 --- a/web/lessons/en/14-verschachteln.md +++ b/web/lessons/en/14-verschachteln.md @@ -102,7 +102,7 @@ for (int i = 1; i <= n; i++) { System.out.println(count); ``` -What is nested in the structure chart is nested in curly brackets in Java. Every level is indented four spaces further. If your code gets messy, the **Indent** button at the top of the Programming area helps. +What is nested in the structure chart is nested in curly brackets in Java. Every level is indented four spaces further. If your code gets messy, the **Indent** button at the top of the Code area helps. `count++` is short for `count = count + 1`. @@ -142,7 +142,7 @@ erklärung: The inner loop builds one line of 4 stars, the outer loop repeats th titel: Fix the counting code: java auftrag: The program should count how many numbers from 1 to `n` are divisible by 3 and output the result **once**. For 10 that is just **Count: 3**. But it outputs far too many lines. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l14-java-fehler-start.visustruct test: 10 -> Count: 3 test: 3 -> Count: 1 diff --git a/web/lessons/en/15-arrays.md b/web/lessons/en/15-arrays.md index eeec184f..f01e9828 100644 --- a/web/lessons/en/15-arrays.md +++ b/web/lessons/en/15-arrays.md @@ -191,7 +191,7 @@ erklärung: `int[]` is an array of whole numbers, `values.length` is its length. titel: Fix the highest temperature code: java auftrag: In January the temperatures -5, -2, -8 and -3 degrees were measured. The program should output the highest, so **Highest temperature: -2**. But it claims 0 degrees, although it was never that warm. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l15-java-fehler-start.visustruct test: - -> Highest temperature: -2 braucht: forSchleife, verzweigung diff --git a/web/lessons/en/16-zweidimensionale-arrays.md b/web/lessons/en/16-zweidimensionale-arrays.md index 680380e8..0924c003 100644 --- a/web/lessons/en/16-zweidimensionale-arrays.md +++ b/web/lessons/en/16-zweidimensionale-arrays.md @@ -169,7 +169,7 @@ erklärung: `int[][]` is a table. `grid.length` is the number of rows (2), `grid titel: Fix player 2 code: java auftrag: In the table `points` each row stands for one player. The program should add up the points of player 2 (row 1), so **Player 2: 11**. Instead it reports an error. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l16-java-fehler-start.visustruct test: - -> Player 2: 11 braucht: forSchleife diff --git a/web/lessons/en/17-zeichenketten.md b/web/lessons/en/17-zeichenketten.md index 4a99a9e3..29df9d20 100644 --- a/web/lessons/en/17-zeichenketten.md +++ b/web/lessons/en/17-zeichenketten.md @@ -222,7 +222,7 @@ erklärung: `length()` counts the characters, `toUpperCase()` makes everything u titel: Fix the initials code: java auftrag: The program reads a first name and a last name and should output the initials. For Ludwig Geißbock that is **L. G.** But it outputs **u. e.** - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l17-java-fehler-start.visustruct test: Ludwig, Geißbock -> L. G. test: Mia, Meyer -> M. M. diff --git a/web/lessons/en/18-aufruf-und-aussprung.md b/web/lessons/en/18-aufruf-und-aussprung.md index c04425b0..9b977298 100644 --- a/web/lessons/en/18-aufruf-und-aussprung.md +++ b/web/lessons/en/18-aufruf-und-aussprung.md @@ -228,7 +228,7 @@ System.out.println("The square is " + q); - In the header, what the method returns (`int`) comes before the name. If it returns nothing, it says `void`. - The parameters go in the round brackets with their data type: `(int x)`. You separate several with commas. -- In the Programming area you write every method in its own tab, just as every subprogram has its own structure chart. +- In the Code area you write every method in its own tab, just as every subprogram has its own structure chart. - In Java the exit is called `break`. With `while (true)` you build a loop that only ends through `break`. ::: übung l18-java-kasse @@ -249,7 +249,7 @@ lösung: l18-java-kasse-loesung.visustruct ::: lückentext titel: Method and exit -auftrag: Fill in the missing words. At the top is the method that calculates a square. Below is the main program that calls it. In the Programming area both are in tabs of their own. +auftrag: Fill in the missing words. At the top is the method that calculates a square. Below is the main program that calls it. In the Code area both are in tabs of their own. ```java public static [[int]] square(int x) { [[return]] x * x; @@ -275,7 +275,7 @@ erklärung: `int` before the method name means: the method returns a whole numbe titel: Fix the try counter code: java auftrag: In this guessing game the secret number is 7. The program keeps asking for a guess until 7 comes, then it outputs the number of tries. For 3, 5 and 7 that was 3 tries, but the program says **Tries: 2**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l18-java-fehler-start.visustruct test: 3, 5, 7 -> Tries: 3 test: 7 -> Tries: 1 diff --git a/web/lessons/en/19-suchen-und-sortieren.md b/web/lessons/en/19-suchen-und-sortieren.md index 1fd651bd..a8b1ea3b 100644 --- a/web/lessons/en/19-suchen-und-sortieren.md +++ b/web/lessons/en/19-suchen-und-sortieren.md @@ -189,7 +189,7 @@ erklärung: If a card is larger than its right neighbour, the two are swapped, w titel: Fix the linear search code: java auftrag: The cards {8, 4, 11, 4, 6} are in an array. The program should output the **first** position of the card you are looking for, so for 4 **Position: 1**. But it outputs **Position: 3**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l19-java-fehler-start.visustruct test: 4 -> Position: 1 test: 6 -> Position: 4 diff --git a/web/lessons/en/20-java.md b/web/lessons/en/20-java.md index 656106a9..b7a1bd3c 100644 --- a/web/lessons/en/20-java.md +++ b/web/lessons/en/20-java.md @@ -1,7 +1,7 @@ --- titel: Structure chart and code bereich: From structure chart to code -kurz: All elements in Java at a glance, generate code, write Java in the Programming area, run it and find mistakes. +kurz: All elements in Java at a glance, generate code, write Java in the Code area, run it and find mistakes. --- ## Skills I will gain now @@ -11,7 +11,7 @@ kurz: All elements in Java at a glance, generate code, write Java in the Program - recognise output, input, branches and loops in Java - explain the difference between Snippet and Class - rebuild a short Java program as a structure chart -- type Java in the Programming area and read the structure chart that is built +- type Java in the Code area and read the structure chart that is built - run a program with ▶︎ and use input and output in the console - set breakpoints and follow a program step by step ::: @@ -118,25 +118,25 @@ This helps you match the boxes to the Java commands. Your diagram itself stays u ## Write Java directly -So far you drew the structure chart first and then looked at the code. In the [Programming](#zeige-codelive) area it also works the other way round. Click the slim **Programming** strip on the right. Next to the structure chart a column appears where you type Java yourself. +So far you drew the structure chart first and then looked at the code. In the [Code](#zeige-codelive) area it also works the other way round. Click the slim **Code** strip on the right. Next to the structure chart a column appears where you type Java yourself. - **Structure chart to code:** When you change something in the structure chart, the Java code changes right away. - **Code to structure chart:** When you type Java, VisuStruct builds the structure chart as you type. If something is still missing, for example a closing bracket `}`, a hint appears below the code. - **Suggestions:** While you type, VisuStruct suggests templates, for example for `if`, `for` or `while`. Press Enter to accept a template. Simply replace the grey placeholders with your own text. -- **Indent:** If your code has got messy, click the **Indent** button at the top of the Programming area. Every level then sits four spaces deeper, as in Eclipse or IntelliJ. If you have selected lines, VisuStruct only indents those. +- **Indent:** If your code has got messy, click the **Indent** button at the top of the Code area. Every level then sits four spaces deeper, as in Eclipse or IntelliJ. If you have selected lines, VisuStruct only indents those. So you can try both ways. Drawing the structure chart first is good for planning a process. Writing code directly is faster when you already know what you want. The structure chart then helps you check your code. ## Run the program -At the top of the Programming area, [▶︎ Run](#zeige-ausfuehren) starts your program and **■ Stop** ends it, for example in an endless loop. What your program outputs appears below in the [console](#zeige-konsole). If it asks for input, type it there and press Enter. +At the top of the Code area, [▶︎ Run](#zeige-ausfuehren) starts your program and **■ Stop** ends it, for example in an endless loop. What your program outputs appears below in the [console](#zeige-konsole). If it asks for input, type it there and press Enter. You can drag the border between code and console up or down with the mouse. -> The Programming area understands the Java commands that also exist as boxes in the structure chart. It does not know your own classes and objects yet. Windows with Swing work anyway: turn on **Real Java (with Swing)** under the gear (lesson “Your first window”). +> The Code area understands the Java commands that also exist as boxes in the structure chart. It does not know your own classes and objects yet. Windows with Swing work anyway: turn on **Real Java (with Swing)** under the gear (lesson “Your first window”). ::: angeberwissen -Professionals call a program where you write code, run it and look for mistakes an **IDE** (Integrated Development Environment). With the Programming area, VisuStruct is a small IDE with a built-in structure chart. +Professionals call a program where you write code, run it and look for mistakes an **IDE** (Integrated Development Environment). With the Code area, VisuStruct is a small IDE with a built-in structure chart. ::: ## Find mistakes with the debugger @@ -165,7 +165,7 @@ This is a desk check, except the computer takes the notes for you. Before each s ## Exercise: Code first, then the structure chart -This time you don't draw. Open the Programming area and type in this Java code: +This time you don't draw. Open the Code area and type in this Java code: ``` System.out.println("Start number?"); @@ -179,13 +179,14 @@ System.out.println("Start!"); ::: übung l20-countdown titel: Countdown -auftrag: Type the Java code above into the Programming area. Run it with ▶︎ and enter a start number in the console. +bereich: beide +auftrag: Type the Java code above into the Code area. Run it with ▶︎ and enter a start number in the console. Then look at the structure chart that was built and click Check. test: 3 -> 3 | 2 | 1 | Start! test: 1 -> 1 | Start! test: 0 -> Start! braucht: whileSchleife -tipp: Open the Programming area with the slim strip on the far right and just start typing. +tipp: Open the Code area with the slim strip on the far right and just start typing. tipp: Watch out for the semicolon at the end of every statement and the curly brackets of the while loop. A hint below the code tells you when something is still missing. lösung: l20-countdown-loesung.visustruct ::: @@ -206,6 +207,7 @@ System.out.println(factorial); ::: übung l17-fakultaet titel: Factorial from Java +bereich: beide auftrag: Rebuild the Java code above as a structure chart. The program reads in a number n and outputs the product 1 · 2 · … · n. At the end, check in the code view whether your Java code looks the same. test: 3 -> 6 @@ -325,7 +327,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can recognise output, input, branches and loops in Java. → The elements in Java - I can explain the difference between Snippet and Class. → Snippet or Class - I can rebuild a short Java program as a structure chart. → Exercise: Java as a structure chart -- I can type Java in the Programming area and read the structure chart that is built. → Write Java directly +- I can type Java in the Code area and read the structure chart that is built. → Write Java directly - I can run a program with ▶︎ and use input and output in the console. → Run the program - I can set breakpoints and follow a program step by step. → Find mistakes with the debugger ::: diff --git a/web/lessons/en/22-try-und-catch.md b/web/lessons/en/22-try-und-catch.md index c4e1463b..ca890987 100644 --- a/web/lessons/en/22-try-und-catch.md +++ b/web/lessons/en/22-try-und-catch.md @@ -7,7 +7,7 @@ kurz: Use real Java to read error messages and catch crashes with try and catch. ## Skills I will gain now ::: kompetenzen -- switch on real Java in the Programming area +- switch on real Java in the Code area - read the exception and the line from an error message - catch an exception with try and catch - turn text into a number with Integer.parseInt and catch the NumberFormatException @@ -16,7 +16,7 @@ kurz: Use real Java to read error messages and catch crashes with try and catch. ## Crashed! -This program should print three grades. Type it into the [Programming](#zeige-codelive) area and click [▶︎ Run](#zeige-ausfuehren): +This program should print three grades. Type it into the [Code](#zeige-codelive) area and click [▶︎ Run](#zeige-ausfuehren): ```java int[] grades = {2, 3, 1}; @@ -37,7 +37,7 @@ In 1947 Grace Hopper's team found a moth in the Mark II computer at Harvard Univ ## Switching on real Java -The Programming area normally calculates with the same simulation as the structure chart. It simply stops when there is an error. To see what real Java does, switch on real Java: +The Code area normally calculates with the same simulation as the structure chart. It simply stops when there is an error. To see what real Java does, switch on real Java: 1. Click the [gear](#zeige-einstellungen) at the top right and choose Java as the **Programming language**. 2. In the Java section, tick **Real Java (with Swing)**. @@ -80,7 +80,7 @@ A message like this looks scary at first. But it tells you exactly what is going Java calls an error like this, at run time, an **exception**. We say: Java *throws* an exception. If nobody catches it, the program stops. That is why “Done!” does not appear. ::: ludwig -Always read error messages from the top: first the name of the exception, then the line number. In the Programming area the line numbers are on the left next to the code. +Always read error messages from the top: first the name of the exception, then the line number. In the Code area the line numbers are on the left next to the code. ::: ## try and catch @@ -245,7 +245,7 @@ The exception is called `ArithmeticException`. Only put the line that can crash 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. ::: checkliste -- I can switch on real Java in the Programming area. → Switching on real Java +- I can switch on real Java in the Code area. → Switching on real Java - I can read the exception and the line from an error message. → Reading the error message - I can catch an exception with try and catch. → try and catch - I can turn text into a number with Integer.parseInt and catch the NumberFormatException. → Turning text into a number diff --git a/web/lessons/en/28-erstes-fenster.md b/web/lessons/en/28-erstes-fenster.md index 42bde29a..f877ebfa 100644 --- a/web/lessons/en/28-erstes-fenster.md +++ b/web/lessons/en/28-erstes-fenster.md @@ -7,7 +7,7 @@ kurz: Open your own window with Java and Swing, explained line by line. ## Skills I will gain now ::: kompetenzen -- switch on “Real Java” in the Programming area +- switch on “Real Java” in the Code area - open a window with a title and a size - explain what each line of the window program does - explain why setVisible(true) comes last @@ -19,11 +19,11 @@ So far your programs have written text to the console. Most programs you know, h Java comes with a toolbox for this: **Swing**. In VisuStruct you switch it on like this: -1. Open the [Programming](#zeige-codelive) area on the right. +1. Open the [Code](#zeige-codelive) area on the right. 2. Click the [gear](#zeige-einstellungen) at the top right and choose Java as the **Programming language**. 3. Below that, in the Java section, tick **Real Java (with Swing)**. -The first time you click [▶︎ Run](#zeige-ausfuehren), VisuStruct downloads about 40 MB once, which takes a moment. After that your code runs as real Java, and your windows appear in the Programming area in the **Java windows** box above the console. +The first time you click [▶︎ Run](#zeige-ausfuehren), VisuStruct downloads about 40 MB once, which takes a moment. After that your code runs as real Java, and your windows appear in the Code area in the **Java windows** box above the console. > With “Real Java”, input from the console (`Scanner`) does not work yet. For programs with input, untick the box again. @@ -33,7 +33,7 @@ Swing has been around since 1998. Before that, Java only had the older AWT with ## The whole program -This is the smallest program that opens a window. Type it into the Programming area and click [▶︎ Run](#zeige-ausfuehren): +This is the smallest program that opens a window. Type it into the Code area and click [▶︎ Run](#zeige-ausfuehren): ```java import javax.swing.*; @@ -177,7 +177,7 @@ Change the program so that Run it and check all three points. ::: ludwig -Don't feel like typing so much? With “Real Java” you may type just the four lines from `main` into the Programming area. VisuStruct then wraps them in a class itself and adds the `import` lines. In a real Java development environment, though, you need the whole program. +Don't feel like typing so much? With “Real Java” you may type just the four lines from `main` into the Code area. VisuStruct then wraps them in a class itself and adds the `import` lines. In a real Java development environment, though, you need the whole program. ::: ## Checklist @@ -185,7 +185,7 @@ Don't feel like typing so much? With “Real Java” you may type just the four 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. ::: checkliste -- I can switch on “Real Java” in the Programming area. → Programs with windows +- I can switch on “Real Java” in the Code area. → Programs with windows - I can open a window with a title and a size. → The whole program - I can explain what each line of the window program does. → Line by line - I can explain why setVisible(true) comes last. → Why setVisible comes last diff --git a/web/lessons/en/34-notenrechner.md b/web/lessons/en/34-notenrechner.md index 4c7aa453..933473c5 100644 --- a/web/lessons/en/34-notenrechner.md +++ b/web/lessons/en/34-notenrechner.md @@ -54,7 +54,7 @@ if (points >= 90) { With 85 points, `points >= 90` is false, but `points >= 80` is true. So grade B, and the remaining conditions are not checked at all. That is why the lower limit is enough each time. ::: -You can try this part without a window in the [Programming](#zeige-codelive) area. Put `int points = 85;` in front of it and `System.out.println("Grade: " + grade);` after it. The structure chart shows you the nested branches. +You can try this part without a window in the [Code](#zeige-codelive) area. Put `int points = 85;` in front of it and `System.out.println("Grade: " + grade);` after it. The structure chart shows you the nested branches. ## The window diff --git a/web/lessons/en/36-zahlenraten.md b/web/lessons/en/36-zahlenraten.md index bb0f79e3..0574bf3c 100644 --- a/web/lessons/en/36-zahlenraten.md +++ b/web/lessons/en/36-zahlenraten.md @@ -38,7 +38,7 @@ int secret = (int) (Math.random() * 100) + 1; Without `+ 1` you would get 0 to 99. -Try it in the [Programming](#zeige-codelive) area: `int secret = (int) (Math.random() * 100) + 1;` and `System.out.println(secret);`. Every run gives a different number. +Try it in the [Code](#zeige-codelive) area: `int secret = (int) (Math.random() * 100) + 1;` and `System.out.println(secret);`. Every run gives a different number. ::: angeberwissen Computers can't actually roll dice. `Math.random()` uses a formula to calculate a long sequence of numbers that only **look** random. They are called pseudo-random numbers. For games that is perfectly fine. diff --git a/web/lessons/en/visubot/06-abstand.md b/web/lessons/en/visubot/06-abstand.md index 73f9c005..571987f7 100644 --- a/web/lessons/en/visubot/06-abstand.md +++ b/web/lessons/en/visubot/06-abstand.md @@ -49,7 +49,7 @@ lösung: vb-abstand-halten-loesung.visustruct ## Now in Java -In the [Programming](#zeige-codelive) area you already see your structure chart as Java code. A branch is called `if` there, the No branch is `else`: +In the [Code](#zeige-codelive) area you already see your structure chart as Java code. A branch is called `if` there, the No branch is `else`: ```java if (mbot.getDistance() < 10) { diff --git a/web/lessons/en/visubot/22-eigene-methoden.md b/web/lessons/en/visubot/22-eigene-methoden.md index a7a9b512..02d9c4a6 100644 --- a/web/lessons/en/visubot/22-eigene-methoden.md +++ b/web/lessons/en/visubot/22-eigene-methoden.md @@ -53,7 +53,7 @@ public class Squares { } ``` -In [Programming](#zeige-codelive) you see each method in its own tab, just like in the structogram. +In [Code](#zeige-codelive) you see each method in its own tab, just like in the structogram. ::: quiz ? What does `void` mean in `void square(int side)`? diff --git a/web/lessons/pt/02-der-editor.md b/web/lessons/pt/02-der-editor.md index e3ae1fda..affdfaaf 100644 --- a/web/lessons/pt/02-der-editor.md +++ b/web/lessons/pt/02-der-editor.md @@ -14,7 +14,7 @@ kurz: Inserir elementos, escrever texto, mover e eliminar. ## O ecrã -O VisuStruct tem dois editores: o [editor de estrutogramas](#zeige-editor), de que trata esta lição, e à direita a área [Programação](#zeige-codelive) para código Java (a partir da lição 4). Se o editor de estrutogramas estiver recolhido, esta lição abre-o sozinha. As palavras azuis mostram-te as áreas, mesmo que estejam recolhidas: passa o rato por cima de uma, e a área abre-se ao lado da área de aprendizagem e acende-se. Se clicares nela (ou tocares nela), fica aberta. +O VisuStruct tem dois editores: o [editor de estrutogramas](#zeige-editor), de que trata esta lição, e à direita a área [Código](#zeige-codelive) para código Java (a partir da lição 4). Se o editor de estrutogramas estiver recolhido, esta lição abre-o sozinha. As palavras azuis mostram-te as áreas, mesmo que estejam recolhidas: passa o rato por cima de uma, e a área abre-se ao lado da área de aprendizagem e acende-se. Se clicares nela (ou tocares nela), fica aberta. O editor de estrutogramas tem várias áreas. Passa o rato por cima de uma palavra azul ou toca nela, e essa área acende-se no editor; as áreas recolhidas, como os Elementos, abrem-se. @@ -24,7 +24,7 @@ O editor de estrutogramas tem várias áreas. Passa o rato por cima de uma palav - **Ao meio, o [estrutograma](#zeige-struktogramm):** Um diagrama novo contém apenas um marcador vazio, assinalado com **ø**. - **Em baixo, o [Inspetor de objetos](#zeige-objektinspektor):** Aqui editas o texto do elemento selecionado. -> Podes recolher esta área de aprendizagem a qualquer momento com o [ícone da barra lateral](#zeige-lernen) no topo desta área. Fica só a barra estreita “🎓 Aprender” à esquerda; um clique abre-a de novo. Ela fica aberta ao lado do editor, para poderes experimentar logo o que lês. Da mesma forma, há à esquerda a coluna [📁 Ficheiros](#zeige-dateien) para os teus programas guardados (lição 3) e à direita a área [Programação](#zeige-codelive) para Java (a partir da lição 4). +> Podes recolher esta área de aprendizagem a qualquer momento com o [ícone da barra lateral](#zeige-lernen) no topo desta área. Fica só a barra estreita “🎓 Aprender” à esquerda; um clique abre-a de novo. Ela fica aberta ao lado do editor, para poderes experimentar logo o que lês. Da mesma forma, há à esquerda a coluna [📁 Ficheiros](#zeige-dateien) para os teus programas guardados (lição 3) e à direita a área [Código](#zeige-codelive) para Java (a partir da lição 4). ## Inserir um elemento diff --git a/web/lessons/pt/04-variablen-und-datentypen.md b/web/lessons/pt/04-variablen-und-datentypen.md index 46edd54c..25a13847 100644 --- a/web/lessons/pt/04-variablen-und-datentypen.md +++ b/web/lessons/pt/04-variablen-und-datentypen.md @@ -196,14 +196,14 @@ System.out.println("Altura: " + altura + " m"); - `String` escreve-se com maiúscula, `int`, `double` e `boolean` com minúscula. O Java distingue-os. - Com `+` juntas texto e números. -Escreves Java na área [Programação](#zeige-codelive). O estrutograma constrói-se sozinho enquanto escreves. “Abrir no editor” leva o exemplo para a área Programação. Clica aí em “Executar”, depois muda o nome, a idade ou a altura e experimenta outra vez. +Escreves Java na área [Código](#zeige-codelive). O estrutograma constrói-se sozinho enquanto escreves. “Abrir no editor” leva o exemplo para a área Código. Clica aí em “Executar”, depois muda o nome, a idade ou a altura e experimenta outra vez. ::: übung l04-java-steckbrief titel: Ficha em Java code: java auftrag: Escreve a ficha do Ludwig, o bode. Cria três variáveis: o nome **Ludwig**, a idade **7** e a altura **1.2**. Depois mostra estas duas linhas: **Ludwig tem 7 anos.** e **Altura: 1.2 m** - “Abrir no editor” abre também a área Programação à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. + “Abrir no editor” abre também a área Código à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. test: - -> Ludwig tem 7 anos. | Altura: 1.2 m braucht: anweisung tipp: Precisas de uma `String`, um `int` e um `double`. Cada linha termina com ponto e vírgula. @@ -227,7 +227,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 Programação 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 “Java”. ::: ## Encontra o erro: segundos @@ -236,7 +236,7 @@ erklärung: Números inteiros são `int`, números decimais `double`, textos `St titel: Corrigir os segundos code: java auftrag: O programa deve converter 200 segundos em minutos e segundos e mostrar **3 min 20 s**. Mas mostra **20 min 3 s**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l04-java-fehler-start.visustruct test: - -> 3 min 20 s braucht: anweisung diff --git a/web/lessons/pt/05-sequenz.md b/web/lessons/pt/05-sequenz.md index 9b2d392e..2d89b5c9 100644 --- a/web/lessons/pt/05-sequenz.md +++ b/web/lessons/pt/05-sequenz.md @@ -100,13 +100,13 @@ System.out.println("b = " + b); - No fim de cada instrução há um **ponto e vírgula** `;`. - Uma saída chama-se `System.out.println(…)` em Java. Atenção ao S maiúsculo de `System`: o Java distingue maiúsculas de minúsculas. -Escreves Java na área [Programação](#zeige-codelive), à direita do estrutograma. Enquanto escreves, o VisuStruct constrói o estrutograma ao mesmo tempo. Assim vês logo que bloco pertence a que linha. +Escreves Java na área [Código](#zeige-codelive), à direita do estrutograma. Enquanto escreves, o VisuStruct constrói o estrutograma ao mesmo tempo. Assim vês logo que bloco pertence a que linha. ::: übung l05-java-kino titel: Bilhetes de cinema em Java code: java auftrag: Um bilhete de cinema custa 9 euros. Escreve um programa em Java que calcula o preço de 3 bilhetes e mostra **Total: 27**. - “Abrir no editor” abre também a área Programação à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. + “Abrir no editor” abre também a área Código à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. test: - -> Total: 27 braucht: anweisung tipp: Precisas de três variáveis: o preço, a quantidade e o resultado. Cada linha termina com ponto e vírgula. @@ -136,7 +136,7 @@ erklärung: Primeiro guardas `a` na variável auxiliar, depois `a` recebe o valo titel: Corrigir o saldo code: java auftrag: O cartão da cantina tem 20 euros. Uma refeição custa 7 euros. O programa deve mostrar o saldo **depois** de pagar, ou seja, **Resta: 13**. Mas mostra **Resta: 20**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l05-java-fehler-start.visustruct test: - -> Resta: 13 braucht: anweisung diff --git a/web/lessons/pt/06-eingabe-und-ausgabe.md b/web/lessons/pt/06-eingabe-und-ausgabe.md index 998c0dde..b7abc0cb 100644 --- a/web/lessons/pt/06-eingabe-und-ausgabe.md +++ b/web/lessons/pt/06-eingabe-und-ausgabe.md @@ -192,7 +192,7 @@ erklärung: `scanner.next()` lê uma palavra, `scanner.nextInt()` um número int titel: Corrigir a soma code: java auftrag: O programa lê dois números e deve mostrar a soma. Mas com 3 e 4 aparece **Soma: 34** em vez de **Soma: 7**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l06-java-fehler-start.visustruct test: 3, 4 -> Soma: 7 test: 10, 5 -> Soma: 15 diff --git a/web/lessons/pt/07-simulation-und-schreibtischtest.md b/web/lessons/pt/07-simulation-und-schreibtischtest.md index 1f46ea4e..e7bb327d 100644 --- a/web/lessons/pt/07-simulation-und-schreibtischtest.md +++ b/web/lessons/pt/07-simulation-und-schreibtischtest.md @@ -41,7 +41,7 @@ Os valores de a e b são trocados. A variável aux guarda um dos valores entreta - **Variáveis:** Todas as variáveis com os seus valores atuais. - **Saída:** Tudo o que foi mostrado com `output:`. -Se a área [Programação](#zeige-codelive) estiver aberta à direita, a [consola](#zeige-konsole) também acompanha lá. É limpa no início e depois mostra as saídas e entradas tal como apareceriam no programa real. +Se a área [Código](#zeige-codelive) estiver aberta à direita, a [consola](#zeige-konsole) também acompanha lá. É limpa no início e depois mostra as saídas e entradas tal como apareceriam no programa real. No fim aparece **Simulação terminada.** Se algo correr mal, a simulação para no bloco com erro e mostra uma mensagem, p. ex. **Variável desconhecida: total**. @@ -122,7 +122,7 @@ lösung: sim-kino-loesung.visustruct ## Agora em Java -Também podes executar código Java passo a passo. Na área [Programação](#zeige-codelive), a ferramenta para isso chama-se **depurador** (debugger): +Também podes executar código Java passo a passo. Na área [Código](#zeige-codelive), a ferramenta para isso chama-se **depurador** (debugger): - Clica num número de linha à esquerda. Aparece um ponto vermelho: é um **ponto de paragem**. [▶︎ Executar](#zeige-ausfuehren) para antes dessa linha. - O botão [Passo a passo](#zeige-einzelschritt) executa exatamente uma linha, como **Passo** na simulação. @@ -154,7 +154,7 @@ b = a * 2; // b vale agora [[14]] a = b - a; // a vale agora [[7]] System.out.println(a + b); // saída: [[21]] ``` -erklärung: Cada linha calcula com os valores que estão nesse momento nas variáveis: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, saída 7 + 14 = 21. Podes confirmar com Passo a passo na área Programação. +erklärung: Cada linha calcula com os valores que estão nesse momento nas variáveis: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, saída 7 + 14 = 21. Podes confirmar com Passo a passo na área Código. ::: ## Encontra o erro: pontuação @@ -286,7 +286,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] soma é demasiado grande. - [ ] O estrutograma tem demasiados blocos. -? O que faz um ponto vermelho antes de um número de linha na área Programação? +? O que faz um ponto vermelho antes de um número de linha na área Código? → Agora em Java - [ ] Marca um erro. - [x] O programa para antes dessa linha. diff --git a/web/lessons/pt/08-verzweigung.md b/web/lessons/pt/08-verzweigung.md index dfd5c3fc..4a882877 100644 --- a/web/lessons/pt/08-verzweigung.md +++ b/web/lessons/pt/08-verzweigung.md @@ -130,7 +130,7 @@ O Java também tem uma mascote: o **Duke**, um bonequinho preto e branco com um titel: Aprovado em Java code: java auftrag: Escreve um programa em Java que pergunta pela pontuação. A partir de 50 pontos mostra **aprovado**, senão **reprovado**. - Escreve o código na área Programação e depois clica em Verificar. + Escreve o código na área Código e depois clica em Verificar. test: 50 -> aprovado test: 49 -> reprovado test: 100 -> aprovado @@ -167,7 +167,7 @@ erklärung: `numero % 2` é o resto da divisão por 2. Se for 0, o número é pa titel: Corrigir a entrada code: java auftrag: No jardim zoológico, as crianças com **menos** de 6 anos entram de graça, todos os outros pagam 4 euros. Mas o programa também deixa entrar de graça as crianças de seis anos. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l08-java-fehler-start.visustruct test: 5 -> Entrada gratuita test: 6 -> 4 euros diff --git a/web/lessons/pt/09-bedingungen-verknuepfen.md b/web/lessons/pt/09-bedingungen-verknuepfen.md index ed73ba74..805c52ba 100644 --- a/web/lessons/pt/09-bedingungen-verknuepfen.md +++ b/web/lessons/pt/09-bedingungen-verknuepfen.md @@ -247,7 +247,7 @@ erklärung: Uma nota é válida quando **as duas** condições são verdadeiras, titel: Corrigir o dia sem escola code: java auftrag: O programa deve mostrar **sem escola** para o dia 6 (sábado) e o dia 7 (domingo), e **escola** nos outros dias. Mas mostra sempre **escola**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l09-java-fehler-start.visustruct test: 6 -> sem escola test: 7 -> sem escola diff --git a/web/lessons/pt/10-fallauswahl.md b/web/lessons/pt/10-fallauswahl.md index a3377061..a8e277d8 100644 --- a/web/lessons/pt/10-fallauswahl.md +++ b/web/lessons/pt/10-fallauswahl.md @@ -171,7 +171,7 @@ erklärung: Depois de `switch` vem a variável entre parênteses. Cada caso come titel: Corrigir a calculadora code: java auftrag: A calculadora lê dois números e uma opção: 1 mais, 2 menos, 3 vezes. Com 7, 3 e a opção 2 devia dar **4**, mas dá **-4**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l10-java-fehler-start.visustruct test: 7, 3, 2 -> 4 test: 7, 3, 1 -> 10 diff --git a/web/lessons/pt/12-do-while-schleife.md b/web/lessons/pt/12-do-while-schleife.md index e2570ad2..a29848e8 100644 --- a/web/lessons/pt/12-do-while-schleife.md +++ b/web/lessons/pt/12-do-while-schleife.md @@ -132,7 +132,7 @@ erklärung: O corpo fica entre `do {` e `}`, a condição só vem depois. No cic titel: Corrigir a divisão ao meio code: java auftrag: O programa lê um número inicial e, com um ciclo do-while, divide-o repetidamente por 2 (divisão inteira). Cada resultado é mostrado até chegar a **0**. Para 10 são 5, 2, 1 e 0. Mas falta o 0. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l12-java-fehler-start.visustruct test: 10 -> 5 | 2 | 1 | 0 test: 1 -> 0 diff --git a/web/lessons/pt/13-for-schleife.md b/web/lessons/pt/13-for-schleife.md index 63c6e997..03d01f0a 100644 --- a/web/lessons/pt/13-for-schleife.md +++ b/web/lessons/pt/13-for-schleife.md @@ -169,7 +169,7 @@ erklärung: Entre os parênteses ficam o valor inicial, a condição e o passo, titel: Corrigir a tabuada code: java auftrag: O programa pergunta que tabuada queres e deve mostrá-la de 1 vez até 10 vezes, para o 7 são 7, 14, … até 70. Mas falta o 70. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l13-java-fehler-start.visustruct test: 7 -> 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 test: 3 -> 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 diff --git a/web/lessons/pt/14-verschachteln.md b/web/lessons/pt/14-verschachteln.md index 883ca724..2009e21d 100644 --- a/web/lessons/pt/14-verschachteln.md +++ b/web/lessons/pt/14-verschachteln.md @@ -102,7 +102,7 @@ for (int i = 1; i <= n; i++) { System.out.println(quantidade); ``` -O que no estrutograma está encaixado, em Java está encaixado entre chavetas. Cada nível fica quatro espaços mais para dentro. Se o teu código ficar desarrumado, ajuda o botão **Indentar** em cima na área Programação. +O que no estrutograma está encaixado, em Java está encaixado entre chavetas. Cada nível fica quatro espaços mais para dentro. Se o teu código ficar desarrumado, ajuda o botão **Indentar** em cima na área Código. `quantidade++` é a forma curta de `quantidade = quantidade + 1`. @@ -142,7 +142,7 @@ erklärung: O ciclo de dentro constrói uma linha de 4 estrelas, o de fora repet titel: Corrigir a contagem code: java auftrag: O programa deve contar quantos números de 1 a `n` são divisíveis por 3 e mostrar o resultado **uma vez**. Para 10 é só **Quantidade: 3**. Mas mostra linhas a mais. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l14-java-fehler-start.visustruct test: 10 -> Quantidade: 3 test: 3 -> Quantidade: 1 diff --git a/web/lessons/pt/15-arrays.md b/web/lessons/pt/15-arrays.md index 84f7fc2a..5f97bc59 100644 --- a/web/lessons/pt/15-arrays.md +++ b/web/lessons/pt/15-arrays.md @@ -191,7 +191,7 @@ erklärung: `int[]` é um array de números inteiros, `valores.length` é o seu titel: Corrigir a temperatura mais alta code: java auftrag: Em janeiro mediram-se as temperaturas -5, -2, -8 e -3 graus. O programa deve mostrar a mais alta, ou seja, **Temperatura mais alta: -2**. Mas diz 0 graus, embora nunca tenha estado tão quente. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l15-java-fehler-start.visustruct test: - -> Temperatura mais alta: -2 braucht: forSchleife, verzweigung diff --git a/web/lessons/pt/16-zweidimensionale-arrays.md b/web/lessons/pt/16-zweidimensionale-arrays.md index a3ab27b8..77bb28a0 100644 --- a/web/lessons/pt/16-zweidimensionale-arrays.md +++ b/web/lessons/pt/16-zweidimensionale-arrays.md @@ -169,7 +169,7 @@ erklärung: `int[][]` é uma tabela. `campo.length` é o número de linhas (2), titel: Corrigir o jogador 2 code: java auftrag: Na tabela `pontos`, cada linha corresponde a um jogador. O programa deve somar os pontos do jogador 2 (linha 1), ou seja, **Jogador 2: 11**. Em vez disso, dá um erro. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l16-java-fehler-start.visustruct test: - -> Jogador 2: 11 braucht: forSchleife diff --git a/web/lessons/pt/17-zeichenketten.md b/web/lessons/pt/17-zeichenketten.md index b5f0b675..627890f8 100644 --- a/web/lessons/pt/17-zeichenketten.md +++ b/web/lessons/pt/17-zeichenketten.md @@ -222,7 +222,7 @@ erklärung: `length()` conta os carateres, `toUpperCase()` põe tudo em maiúscu titel: Corrigir as iniciais code: java auftrag: O programa lê o nome próprio e o apelido e deve mostrar as iniciais. Para Ludwig Geißbock é **L. G.** Mas mostra **u. e.** - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l17-java-fehler-start.visustruct test: Ludwig, Geißbock -> L. G. test: Mia, Meyer -> M. M. diff --git a/web/lessons/pt/18-aufruf-und-aussprung.md b/web/lessons/pt/18-aufruf-und-aussprung.md index e89f5c69..aa65552e 100644 --- a/web/lessons/pt/18-aufruf-und-aussprung.md +++ b/web/lessons/pt/18-aufruf-und-aussprung.md @@ -228,7 +228,7 @@ System.out.println("O quadrado é " + q); - No cabeçalho, antes do nome, fica o que o método devolve (`int`). Se não devolver nada, fica `void`. - Os parâmetros ficam entre parênteses curvos, com o tipo de dados: `(int x)`. Separas vários com vírgulas. -- Na área Programação escreves cada método no seu próprio separador, tal como cada subprograma tem o seu próprio estrutograma. +- Na área Código escreves cada método no seu próprio separador, tal como cada subprograma tem o seu próprio estrutograma. - Em Java, a saída chama-se `break`. Com `while (true)` constróis um ciclo que só termina com `break`. ::: übung l18-java-kasse @@ -249,7 +249,7 @@ lösung: l18-java-kasse-loesung.visustruct ::: lückentext titel: Método e saída -auftrag: Preenche as palavras que faltam. Em cima está o método que calcula um quadrado. Por baixo está o programa principal, que o chama. Na área Programação, cada um fica no seu separador. +auftrag: Preenche as palavras que faltam. Em cima está o método que calcula um quadrado. Por baixo está o programa principal, que o chama. Na área Código, cada um fica no seu separador. ```java public static [[int]] quadrado(int x) { [[return]] x * x; @@ -275,7 +275,7 @@ erklärung: `int` antes do nome do método quer dizer que o método devolve um n titel: Corrigir a contagem de tentativas code: java auftrag: Neste jogo de adivinhar, o número secreto é 7. O programa pede um palpite até aparecer o 7 e depois mostra o número de tentativas. Com 3, 5 e 7 foram 3 tentativas, mas o programa diz **Tentativas: 2**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l18-java-fehler-start.visustruct test: 3, 5, 7 -> Tentativas: 3 test: 7 -> Tentativas: 1 diff --git a/web/lessons/pt/19-suchen-und-sortieren.md b/web/lessons/pt/19-suchen-und-sortieren.md index 2ba93747..28652e6e 100644 --- a/web/lessons/pt/19-suchen-und-sortieren.md +++ b/web/lessons/pt/19-suchen-und-sortieren.md @@ -189,7 +189,7 @@ erklärung: Se uma carta for maior do que a vizinha da direita, as duas trocam d titel: Corrigir a pesquisa linear code: java auftrag: As cartas {8, 4, 11, 4, 6} estão num array. O programa deve mostrar a **primeira** posição da carta procurada, para o 4 é **Posição: 1**. Mas mostra **Posição: 3**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l19-java-fehler-start.visustruct test: 4 -> Posição: 1 test: 6 -> Posição: 4 diff --git a/web/lessons/pt/20-java.md b/web/lessons/pt/20-java.md index aef8b872..f64e29d1 100644 --- a/web/lessons/pt/20-java.md +++ b/web/lessons/pt/20-java.md @@ -1,7 +1,7 @@ --- titel: Estrutograma e código bereich: Do estrutograma ao código -kurz: Todos os elementos em Java num relance, gerar código, escrever Java na área Programação, executá-lo e procurar erros. +kurz: Todos os elementos em Java num relance, gerar código, escrever Java na área Código, executá-lo e procurar erros. --- ## Competências que vou adquirir agora @@ -11,7 +11,7 @@ kurz: Todos os elementos em Java num relance, gerar código, escrever Java na á - reconhecer em Java a saída, a entrada, as decisões e os ciclos - explicar a diferença entre Excerto e Classe - reconstruir um programa Java curto como estrutograma -- escrever Java na área Programação e ler o estrutograma que é construído +- escrever Java na área Código e ler o estrutograma que é construído - executar um programa com ▶︎ e usar entradas e saídas na consola - pôr pontos de paragem e seguir um programa passo a passo ::: @@ -118,25 +118,25 @@ Isto ajuda-te a associar os blocos aos comandos Java. O teu diagrama em si fica ## Escrever Java diretamente -Até agora desenhaste primeiro o estrutograma e depois viste o código. Na área [Programação](#zeige-codelive) também funciona ao contrário. Clica na barra estreita **Programação** à direita. Ao lado do estrutograma aparece uma coluna onde escreves tu mesmo o Java. +Até agora desenhaste primeiro o estrutograma e depois viste o código. Na área [Código](#zeige-codelive) também funciona ao contrário. Clica na barra estreita **Código** à direita. Ao lado do estrutograma aparece uma coluna onde escreves tu mesmo o Java. - **Do estrutograma para o código:** Quando alteras alguma coisa no estrutograma, o código Java muda logo. - **Do código para o estrutograma:** Quando escreves Java, o VisuStruct constrói o estrutograma enquanto escreves. Se ainda faltar alguma coisa, por exemplo uma chaveta de fecho `}`, aparece uma indicação por baixo do código. - **Sugestões:** Enquanto escreves, o VisuStruct sugere modelos, por exemplo para `if`, `for` ou `while`. Com Enter aceitas um modelo. Substitui simplesmente os marcadores cinzentos pelo teu texto. -- **Indentar:** Se o teu código ficou desarrumado, clica no botão **Indentar** em cima na área Programação. Cada nível fica então quatro espaços mais para dentro, como no Eclipse ou no IntelliJ. Se tiveres linhas selecionadas, o VisuStruct só indenta essas. +- **Indentar:** Se o teu código ficou desarrumado, clica no botão **Indentar** em cima na área Código. Cada nível fica então quatro espaços mais para dentro, como no Eclipse ou no IntelliJ. Se tiveres linhas selecionadas, o VisuStruct só indenta essas. Assim podes experimentar os dois caminhos. Desenhar primeiro o estrutograma é bom para planear um processo. Escrever o código diretamente é mais rápido quando já sabes o que queres. O estrutograma ajuda-te depois a verificar o teu código. ## Executar o programa -Em cima, na área Programação, [▶︎ Executar](#zeige-ausfuehren) inicia o teu programa e **■ Parar** termina-o, por exemplo num ciclo infinito. O que o teu programa mostra aparece em baixo na [consola](#zeige-konsole). Se pedir uma entrada, escreve-a lá e carrega em Enter. +Em cima, na área Código, [▶︎ Executar](#zeige-ausfuehren) inicia o teu programa e **■ Parar** termina-o, por exemplo num ciclo infinito. O que o teu programa mostra aparece em baixo na [consola](#zeige-konsole). Se pedir uma entrada, escreve-a lá e carrega em Enter. Podes arrastar com o rato a fronteira entre o código e a consola para cima ou para baixo. -> A área Programação entende os comandos Java que também existem como blocos no estrutograma. Ainda não conhece classes próprias nem objetos. Janelas com Swing funcionam na mesma: liga o **Java verdadeiro (com Swing)** na roda dentada (lição “A tua primeira janela”). +> A área Código entende os comandos Java que também existem como blocos no estrutograma. Ainda não conhece classes próprias nem objetos. Janelas com Swing funcionam na mesma: liga o **Java verdadeiro (com Swing)** na roda dentada (lição “A tua primeira janela”). ::: angeberwissen -Os profissionais chamam **IDE** (Integrated Development Environment) a um programa onde se escreve código, se executa e se procuram erros. Com a área Programação, o VisuStruct é um pequeno IDE com estrutograma incluído. +Os profissionais chamam **IDE** (Integrated Development Environment) a um programa onde se escreve código, se executa e se procuram erros. Com a área Código, o VisuStruct é um pequeno IDE com estrutograma incluído. ::: ## Encontrar erros com o depurador @@ -165,7 +165,7 @@ System.out.println("Soma: " + soma); ## Exercício: Primeiro o código, depois o estrutograma -Desta vez não desenhas. Abre a área Programação e escreve este código Java: +Desta vez não desenhas. Abre a área Código e escreve este código Java: ``` System.out.println("Número inicial?"); @@ -179,13 +179,14 @@ System.out.println("Start!"); ::: übung l20-countdown titel: Contagem decrescente -auftrag: Escreve o código Java acima na área Programação. Executa-o com ▶︎ e introduz um número inicial na consola. +bereich: beide +auftrag: Escreve o código Java acima na área Código. Executa-o com ▶︎ e introduz um número inicial na consola. Depois observa o estrutograma que foi construído e clica em Verificar. test: 3 -> 3 | 2 | 1 | Start! test: 1 -> 1 | Start! test: 0 -> Start! braucht: whileSchleife -tipp: Abre a área Programação com a barra estreita mais à direita e começa simplesmente a escrever. +tipp: Abre a área Código com a barra estreita mais à direita e começa simplesmente a escrever. tipp: Atenção ao ponto e vírgula no fim de cada instrução e às chavetas do ciclo while. Por baixo do código aparece uma indicação quando ainda falta alguma coisa. lösung: l20-countdown-loesung.visustruct ::: @@ -206,6 +207,7 @@ System.out.println(fatorial); ::: übung l17-fakultaet titel: Fatorial a partir de Java +bereich: beide auftrag: Reconstrói o código Java de cima como estrutograma. O programa lê um número n e mostra o produto 1 · 2 · … · n. No fim, confirma na vista de código se o teu código Java fica igual. test: 3 -> 6 @@ -325,7 +327,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - Consigo reconhecer em Java a saída, a entrada, as decisões e os ciclos. → Os elementos em Java - Consigo explicar a diferença entre Excerto e Classe. → Excerto ou Classe - Consigo reconstruir um programa Java curto como estrutograma. → Exercício: Java como estrutograma -- Consigo escrever Java na área Programação e ler o estrutograma que é construído. → Escrever Java diretamente +- Consigo escrever Java na área Código e ler o estrutograma que é construído. → Escrever Java diretamente - Consigo executar um programa com ▶︎ e usar entradas e saídas na consola. → Executar o programa - Consigo pôr pontos de paragem e seguir um programa passo a passo. → Encontrar erros com o depurador ::: diff --git a/web/lessons/pt/22-try-und-catch.md b/web/lessons/pt/22-try-und-catch.md index cb2ae934..21f18e13 100644 --- a/web/lessons/pt/22-try-und-catch.md +++ b/web/lessons/pt/22-try-und-catch.md @@ -7,7 +7,7 @@ kurz: Ler mensagens de erro com Java verdadeiro e apanhar falhas com try e catch ## Competências que vou adquirir agora ::: kompetenzen -- ligar o Java verdadeiro na área Programação +- ligar o Java verdadeiro na área Código - ler numa mensagem de erro a exceção e a linha - apanhar uma exceção com try e catch - transformar texto num número com Integer.parseInt e apanhar a NumberFormatException @@ -16,7 +16,7 @@ kurz: Ler mensagens de erro com Java verdadeiro e apanhar falhas com try e catch ## Falhou! -Este programa deve escrever três notas. Escreve-o na área [Programação](#zeige-codelive) e clica em [▶︎ Executar](#zeige-ausfuehren): +Este programa deve escrever três notas. Escreve-o na área [Código](#zeige-codelive) e clica em [▶︎ Executar](#zeige-ausfuehren): ```java int[] notas = {2, 3, 1}; @@ -37,7 +37,7 @@ Em 1947, a equipa de Grace Hopper encontrou no computador Mark II da Universidad ## Ligar o Java verdadeiro -Normalmente a área Programação calcula com a mesma simulação que o estrutograma. Quando há um erro, ela simplesmente para. Para veres o que faz o Java verdadeiro, liga o Java verdadeiro: +Normalmente a área Código calcula com a mesma simulação que o estrutograma. Quando há um erro, ela simplesmente para. Para veres o que faz o Java verdadeiro, liga o Java verdadeiro: 1. Clica na [roda dentada](#zeige-einstellungen) em cima à direita e escolhe Java como **Linguagem de programação**. 2. Na secção Java, marca **Java verdadeiro (com Swing)**. @@ -80,7 +80,7 @@ Uma mensagem destas assusta à primeira vista. Mas diz-te exatamente o que se pa O Java chama a um erro destes, durante a execução, uma **exceção** (em inglês *exception*). Diz-se: o Java *lança* uma exceção. Se ninguém a apanhar, o programa para. É por isso que “Pronto!” não aparece. ::: ludwig -Lê as mensagens de erro sempre de cima: primeiro o nome da exceção, depois o número da linha. Na área Programação, os números das linhas estão à esquerda do código. +Lê as mensagens de erro sempre de cima: primeiro o nome da exceção, depois o número da linha. Na área Código, os números das linhas estão à esquerda do código. ::: ## try e catch @@ -245,7 +245,7 @@ A exceção chama-se `ArithmeticException`. Põe no bloco `try` só a linha que 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. ::: checkliste -- Consigo ligar o Java verdadeiro na área Programação. → Ligar o Java verdadeiro +- Consigo ligar o Java verdadeiro na área Código. → Ligar o Java verdadeiro - Consigo ler numa mensagem de erro a exceção e a linha. → Ler a mensagem de erro - Consigo apanhar uma exceção com try e catch. → try e catch - Consigo transformar texto num número com Integer.parseInt e apanhar a NumberFormatException. → Transformar texto num número diff --git a/web/lessons/pt/28-erstes-fenster.md b/web/lessons/pt/28-erstes-fenster.md index 893edb77..0104b322 100644 --- a/web/lessons/pt/28-erstes-fenster.md +++ b/web/lessons/pt/28-erstes-fenster.md @@ -7,7 +7,7 @@ kurz: Abrir uma janela tua com Java e Swing, explicado linha a linha. ## Competências que vou adquirir agora ::: kompetenzen -- ligar o “Java verdadeiro” na área Programação +- ligar o “Java verdadeiro” na área Código - abrir uma janela com título e tamanho - explicar o que faz cada linha do programa com janela - explicar porque é que setVisible(true) fica no fim @@ -19,11 +19,11 @@ Até agora os teus programas escreviam texto na consola. Mas a maioria dos progr O Java traz uma caixa de ferramentas para isso: o **Swing**. No VisuStruct ligas o Swing assim: -1. Abre à direita a área [Programação](#zeige-codelive). +1. Abre à direita a área [Código](#zeige-codelive). 2. Clica na [roda dentada](#zeige-einstellungen) em cima à direita e escolhe Java como **Linguagem de programação**. 3. Por baixo, na secção Java, marca **Java verdadeiro (com Swing)**. -Na primeira vez que clicas em [▶︎ Executar](#zeige-ausfuehren), o VisuStruct descarrega uma única vez cerca de 40 MB, o que demora um pouco. Depois disso o teu código corre como Java verdadeiro, e as tuas janelas aparecem na área Programação na área **Janelas Java**, por cima da consola. +Na primeira vez que clicas em [▶︎ Executar](#zeige-ausfuehren), o VisuStruct descarrega uma única vez cerca de 40 MB, o que demora um pouco. Depois disso o teu código corre como Java verdadeiro, e as tuas janelas aparecem na área Código na área **Janelas Java**, por cima da consola. > Com o “Java verdadeiro”, as entradas pela consola (`Scanner`) ainda não funcionam. Para programas com entradas, desliga outra vez a opção. @@ -33,7 +33,7 @@ O Swing existe desde 1998. Antes disso, o Java só tinha o AWT, mais antigo, com ## O programa completo -Este é o programa mais pequeno que abre uma janela. Escreve-o na área Programação e clica em [▶︎ Executar](#zeige-ausfuehren): +Este é o programa mais pequeno que abre uma janela. Escreve-o na área Código e clica em [▶︎ Executar](#zeige-ausfuehren): ```java import javax.swing.*; @@ -177,7 +177,7 @@ Altera o programa de forma que Executa-o e verifica os três pontos. ::: ludwig -Não te apetece escrever tanto? Com o “Java verdadeiro” podes escrever na área Programação só as quatro linhas de `main`. O VisuStruct põe-nas sozinho dentro de uma classe e acrescenta as linhas `import`. Num ambiente de desenvolvimento Java a sério precisas, no entanto, do programa completo. +Não te apetece escrever tanto? Com o “Java verdadeiro” podes escrever na área Código só as quatro linhas de `main`. O VisuStruct põe-nas sozinho dentro de uma classe e acrescenta as linhas `import`. Num ambiente de desenvolvimento Java a sério precisas, no entanto, do programa completo. ::: ## Lista de verificação @@ -185,7 +185,7 @@ Não te apetece escrever tanto? Com o “Java verdadeiro” podes escrever na á 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. ::: checkliste -- Consigo ligar o “Java verdadeiro” na área Programação. → Programas com janelas +- Consigo ligar o “Java verdadeiro” na área Código. → Programas com janelas - Consigo abrir uma janela com título e tamanho. → O programa completo - Consigo explicar o que faz cada linha do programa com janela. → Linha a linha - Consigo explicar porque é que setVisible(true) fica no fim. → Porque é que setVisible fica no fim diff --git a/web/lessons/pt/34-notenrechner.md b/web/lessons/pt/34-notenrechner.md index 46ff70c8..8b1db8e9 100644 --- a/web/lessons/pt/34-notenrechner.md +++ b/web/lessons/pt/34-notenrechner.md @@ -54,7 +54,7 @@ if (percentagem >= 90) { Com 75 %, `percentagem >= 90` é falso, mas `percentagem >= 70` é verdadeiro. Portanto nível 4, e as restantes condições já nem são verificadas. É por isso que basta sempre o limite de baixo. ::: -Podes experimentar esta parte sem janela na área [Programação](#zeige-codelive). Escreve `int percentagem = 75;` antes e `System.out.println("Nível: " + nivel);` depois. O estrutograma mostra-te as decisões encaixadas. +Podes experimentar esta parte sem janela na área [Código](#zeige-codelive). Escreve `int percentagem = 75;` antes e `System.out.println("Nível: " + nivel);` depois. O estrutograma mostra-te as decisões encaixadas. ## A janela diff --git a/web/lessons/pt/36-zahlenraten.md b/web/lessons/pt/36-zahlenraten.md index 276ddee1..ba08d834 100644 --- a/web/lessons/pt/36-zahlenraten.md +++ b/web/lessons/pt/36-zahlenraten.md @@ -38,7 +38,7 @@ int secreto = (int) (Math.random() * 100) + 1; Sem o `+ 1` sairia de 0 a 99. -Experimenta na área [Programação](#zeige-codelive): `int secreto = (int) (Math.random() * 100) + 1;` e `System.out.println(secreto);`. Cada execução dá um número diferente. +Experimenta na área [Código](#zeige-codelive): `int secreto = (int) (Math.random() * 100) + 1;` e `System.out.println(secreto);`. Cada execução dá um número diferente. ::: angeberwissen Na verdade, os computadores não sabem lançar dados. O `Math.random()` calcula com uma fórmula uma longa sequência de números que só **parecem** aleatórios. Chamam-se números pseudoaleatórios. Para jogos chega perfeitamente. diff --git a/web/package-lock.json b/web/package-lock.json index 40bb0e42..c674dc9f 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "visustruct-web", - "version": "0.13.36", + "version": "0.13.37", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "visustruct-web", - "version": "0.13.36", + "version": "0.13.37", "dependencies": { "@codemirror/autocomplete": "^6.20.4", "@codemirror/commands": "^6.11.1", diff --git a/web/package.json b/web/package.json index 901842c9..89aee5db 100644 --- a/web/package.json +++ b/web/package.json @@ -1,7 +1,7 @@ { "name": "visustruct-web", "private": true, - "version": "0.13.36", + "version": "0.13.37", "type": "module", "scripts": { "dev": "vite", diff --git a/web/src/i18n/de.strings b/web/src/i18n/de.strings index c1394cd7..05af11b0 100644 --- a/web/src/i18n/de.strings +++ b/web/src/i18n/de.strings @@ -69,7 +69,8 @@ "web_learn_solved" = "geschafft"; "web_learn_open_exercise" = "Im Editor öffnen"; "web_learn_solve_in_editor" = "Löse diese Übung im %@."; -"web_learn_solve_in_code" = "Löse diese Übung in %@."; +"web_learn_solve_in_code" = "Löse diese Übung im %@."; +"web_learn_solve_in_both" = "Löse diese Übung im %1$@ und im %2$@."; "web_learn_open_in_editor" = "Im Editor öffnen"; "web_learn_graphic_labels" = "👆 Klick aufs Bild: Beschriftung ein oder aus"; "web_learn_check" = "Prüfen"; @@ -140,14 +141,14 @@ "web_site_imprint" = "Impressum"; "web_site_privacy" = "Datenschutz"; -/* Programmieren (früher „Code live“) */ -"web_live_title" = "Programmieren"; -"web_live_hide" = "Programmieren ausblenden"; +/* Code (früher „Code live“, dann „Programmieren“) */ +"web_live_title" = "Code"; +"web_live_hide" = "Code ausblenden"; "web_scale_canvas" = "Textgröße Struktogramm"; -"web_scale_code" = "Textgröße Programmieren"; +"web_scale_code" = "Textgröße Code"; "web_live_indent" = "Einrücken"; "web_live_indent_title" = "Code einrücken: jede Ebene vier Leerzeichen tiefer (markierte Zeilen, sonst alles)"; -"web_live_show" = "Programmieren aufklappen"; +"web_live_show" = "Code aufklappen"; "web_live_resize" = "Breite des Codebereichs ändern (Doppelklick: zurücksetzen)"; "web_live_hint" = "Der Code wächst mit deinem Struktogramm. Grau = Platzhalter: Schreib im Objektinspektor, dann steht dort dein Text. Klick auf eine Zeile markiert das Element."; "web_live_ph_selector" = "Variable"; @@ -405,7 +406,7 @@ "web_visubot_preview_hide" = "mBot2 live einklappen"; "web_visubot_preview_show" = "mBot2 live zeigen"; "web_visubot_preview_resize" = "Größe von mBot2 live ändern"; -"web_visubot_preview_stack" = "Unter den Code in Programmieren"; +"web_visubot_preview_stack" = "Unter den Code im Bereich Code"; "web_visubot_preview_side" = "Als eigene Spalte"; "web_visubot_preview_distance_fmt" = "Strecke: %d cm"; "web_visubot_preview_input" = "braucht eine Eingabe, dafür die Simulation starten"; @@ -422,8 +423,8 @@ "web_visubot_group_light" = "Licht und Lautstärke"; "web_visubot_group_tilt" = "Neigung und Schütteln"; "web_visubot_group_timer" = "Stoppuhr und Akku"; -"web_swap_to_code" = "Programmieren groß, Struktogramm schmal"; -"web_swap_to_editor" = "Struktogramm groß, Programmieren schmal"; +"web_swap_to_code" = "Code groß, Struktogramm schmal"; +"web_swap_to_editor" = "Struktogramm groß, Code schmal"; "web_editor_resize" = "Breite des Struktogramms ändern"; "web_palette_resize" = "Breite der Elemente ändern (Doppelklick: zurücksetzen)"; "web_palette_hide" = "Elemente einklappen"; diff --git a/web/src/i18n/en.strings b/web/src/i18n/en.strings index d236e435..3be0e8f7 100644 --- a/web/src/i18n/en.strings +++ b/web/src/i18n/en.strings @@ -70,6 +70,7 @@ "web_learn_open_exercise" = "Open in editor"; "web_learn_solve_in_editor" = "Solve this exercise in the %@ area."; "web_learn_solve_in_code" = "Solve this exercise in the %@ area."; +"web_learn_solve_in_both" = "Solve this exercise in the %1$@ and %2$@ areas."; "web_learn_open_in_editor" = "Open in editor"; "web_learn_graphic_labels" = "👆 Click the picture to show or hide the labels"; "web_learn_check" = "Check"; @@ -141,13 +142,13 @@ "web_site_privacy" = "Privacy"; /* Programmieren (früher „Code live“) */ -"web_live_title" = "Programming"; -"web_live_hide" = "Hide programming"; +"web_live_title" = "Code"; +"web_live_hide" = "Hide code"; "web_scale_canvas" = "Text size: structure chart"; -"web_scale_code" = "Text size: Programming"; +"web_scale_code" = "Text size: Code"; "web_live_indent" = "Indent"; "web_live_indent_title" = "Indent the code: four spaces per level (selected lines, otherwise everything)"; -"web_live_show" = "Show programming"; +"web_live_show" = "Show code"; "web_live_resize" = "Change width of the code area (double-click: reset)"; "web_live_hint" = "The code grows with your diagram. Grey = placeholder: type in the object inspector and your text appears there. Click a line to select its element."; "web_live_ph_selector" = "variable"; @@ -405,7 +406,7 @@ "web_visubot_preview_hide" = "Collapse mBot2 live"; "web_visubot_preview_show" = "Show mBot2 live"; "web_visubot_preview_resize" = "Resize mBot2 live"; -"web_visubot_preview_stack" = "Below the code in Programming"; +"web_visubot_preview_stack" = "Below the code in the Code area"; "web_visubot_preview_side" = "As a column of its own"; "web_visubot_preview_distance_fmt" = "Distance: %d cm"; "web_visubot_preview_input" = "needs an input, start the simulation for that"; @@ -422,8 +423,8 @@ "web_visubot_group_light" = "Light and loudness"; "web_visubot_group_tilt" = "Tilt and shaking"; "web_visubot_group_timer" = "Stopwatch and battery"; -"web_swap_to_code" = "Programming large, structogram narrow"; -"web_swap_to_editor" = "Structogram large, programming narrow"; +"web_swap_to_code" = "Code large, structogram narrow"; +"web_swap_to_editor" = "Structogram large, code narrow"; "web_editor_resize" = "Resize the structogram"; "web_palette_resize" = "Resize the elements (double-click: reset)"; "web_palette_hide" = "Hide elements"; diff --git a/web/src/i18n/pt-PT.strings b/web/src/i18n/pt-PT.strings index b1c66454..a5849cac 100644 --- a/web/src/i18n/pt-PT.strings +++ b/web/src/i18n/pt-PT.strings @@ -68,6 +68,7 @@ "web_learn_open_exercise" = "Abrir no editor"; "web_learn_solve_in_editor" = "Resolve este exercício na área %@."; "web_learn_solve_in_code" = "Resolve este exercício na área %@."; +"web_learn_solve_in_both" = "Resolve este exercício nas áreas %1$@ e %2$@."; "web_learn_open_in_editor" = "Abrir no editor"; "web_learn_graphic_labels" = "👆 Clica na imagem para mostrar ou esconder as legendas"; "web_learn_check" = "Verificar"; @@ -139,13 +140,13 @@ "web_site_privacy" = "Privacidade"; /* Programmieren (früher „Code live“) */ -"web_live_title" = "Programação"; -"web_live_hide" = "Ocultar programação"; +"web_live_title" = "Código"; +"web_live_hide" = "Ocultar código"; "web_scale_canvas" = "Tamanho do texto: estrutograma"; -"web_scale_code" = "Tamanho do texto: Programação"; +"web_scale_code" = "Tamanho do texto: Código"; "web_live_indent" = "Indentar"; "web_live_indent_title" = "Indentar o código: quatro espaços por nível (linhas selecionadas, senão tudo)"; -"web_live_show" = "Mostrar programação"; +"web_live_show" = "Mostrar código"; "web_live_resize" = "Alterar a largura da área de código (duplo clique: repor)"; "web_live_hint" = "O código cresce com o teu diagrama. Cinzento = marcador: escreve no inspetor de objetos e o teu texto aparece aí. Clica numa linha para selecionar o elemento."; "web_live_ph_selector" = "variável"; @@ -403,7 +404,7 @@ "web_visubot_preview_hide" = "Recolher mBot2 ao vivo"; "web_visubot_preview_show" = "Mostrar mBot2 ao vivo"; "web_visubot_preview_resize" = "Alterar o tamanho de mBot2 ao vivo"; -"web_visubot_preview_stack" = "Por baixo do código em Programação"; +"web_visubot_preview_stack" = "Por baixo do código na área Código"; "web_visubot_preview_side" = "Como coluna própria"; "web_visubot_preview_distance_fmt" = "Percurso: %d cm"; "web_visubot_preview_input" = "precisa de uma entrada, inicia a simulação para isso"; @@ -420,8 +421,8 @@ "web_visubot_group_light" = "Luz e volume"; "web_visubot_group_tilt" = "Inclinação e abanar"; "web_visubot_group_timer" = "Cronómetro e bateria"; -"web_swap_to_code" = "Programação grande, diagrama estreito"; -"web_swap_to_editor" = "Diagrama grande, programação estreita"; +"web_swap_to_code" = "Código grande, diagrama estreito"; +"web_swap_to_editor" = "Diagrama grande, código estreito"; "web_editor_resize" = "Alterar a largura do diagrama"; "web_palette_resize" = "Alterar a largura dos elementos (duplo clique: repor)"; "web_palette_hide" = "Ocultar elementos"; diff --git a/web/src/learn/lessonFormat.ts b/web/src/learn/lessonFormat.ts index 305f69f9..4f9e5ab8 100644 --- a/web/src/learn/lessonFormat.ts +++ b/web/src/learn/lessonFormat.ts @@ -56,10 +56,19 @@ export interface Exercise { subprograms: string[] /** `code: java`: Die Übung wird in Code live auf Java gelöst; „Übung öffnen“ öffnet die Spalte gleich mit. */ code?: 'java' + /** `bereich: struktogramm | code | beide`: wo man die Übung löst; „Im Editor öffnen“ öffnet genau diese Bereiche. Ohne Angabe: `code` bei `code: java`, sonst `struktogramm`. */ + area?: ExerciseArea /** VisuBot: Schleifen müssen mindestens so tief ineinander stecken (`schleifentiefe: 2`). */ loopDepth?: number } +export type ExerciseArea = 'struktogramm' | 'code' | 'beide' + +/** Bereich, in dem man die Übung löst (siehe `bereich:`). */ +export function exerciseArea(ex: Pick): ExerciseArea { + return ex.area ?? (ex.code === 'java' ? 'code' : 'struktogramm') +} + export interface ChecklistItem { text: string /** Titel des Schritts, in dem der Punkt erklärt wird (`- Text → Schritt`). */ @@ -170,7 +179,7 @@ function parseExercise(id: string, lines: string[], file: string): Exercise { const ex: Exercise = { id, title: '', task: '', tests: [], requires: [], hints: [], subprograms: [] } let last: 'task' | 'hint' | undefined for (const raw of lines) { - const kv = /^(titel|auftrag|start|test|datei|fahrt|befehle|welt|messwerte|schleifentiefe|braucht|tipp|lösung|loesung|unterprogramm|code):\s*(.*)$/i.exec(raw.trim()) + const kv = /^(titel|auftrag|start|test|datei|fahrt|befehle|welt|messwerte|schleifentiefe|braucht|tipp|lösung|loesung|unterprogramm|code|bereich):\s*(.*)$/i.exec(raw.trim()) if (kv) { const [, key, value] = kv last = undefined @@ -243,6 +252,12 @@ function parseExercise(id: string, lines: string[], file: string): Exercise { if (value.trim().toLowerCase() !== 'java') throw new FormatError(`${file}: Übung „${id}“: „code:“ kennt nur „java“.`) ex.code = 'java' break + case 'bereich': { + const area = value.trim().toLowerCase() + if (area !== 'struktogramm' && area !== 'code' && area !== 'beide') throw new FormatError(`${file}: Übung „${id}“: „bereich:“ kennt nur „struktogramm“, „code“ oder „beide“.`) + ex.area = area + break + } } } else if (last && raw.trim() !== '') { // Fortsetzungszeilen für Auftrag und Tipp diff --git a/web/src/ui/app.ts b/web/src/ui/app.ts index c2af27b1..bb44aff1 100644 --- a/web/src/ui/app.ts +++ b/web/src/ui/app.ts @@ -37,7 +37,7 @@ import { LiveCodePanel } from './liveCodePanel' import { RobotPreviewPanel } from './robotPreview' import { codeScopes, setCodeScopes } from './javaEditor' import type { LiveTarget } from '../core/codeGenerator' -import type { Exercise } from '../learn/lessonFormat' +import { exerciseArea, type Exercise } from '../learn/lessonFormat' import { progress } from '../learn/progress' import { codeKeywords, currentLanguage, offeredLanguages, setCodeKeywords, setLanguage, t, type LanguageCode } from './i18n' import * as Export from './exporter' @@ -1225,9 +1225,11 @@ export class App { }, reveal: (areas) => this.revealAreas(areas), openExercise: (ex: Exercise, doc: VSDocument) => { - // Java-Übungen tippt man in „Programmieren“. Geschlossen wird nichts, so wächst das Struktogramm sichtbar mit. - if (ex.code === 'java') this.openJavaColumn() - else this.setEditorHidden(false) + // Die Übung sagt, wo man sie löst (`bereich:`), und genau diese Bereiche gehen auf. + // Geschlossen wird nichts, so wächst das Struktogramm beim Tippen sichtbar mit. + const area = exerciseArea(ex) + if (area !== 'code') this.setEditorHidden(false) + if (area !== 'struktogramm') this.openJavaColumn() const existing = this.tabs.findIndex((tab) => tab.exerciseId === ex.id) if (existing >= 0) { this.switchTab(existing) @@ -1622,7 +1624,7 @@ export class App { // MARK: - Code live - /** Übungen mit `code: java`: Spalte Programmieren öffnen und auf Java stellen, wie über das Zahnrad. */ + /** Übungen mit `code: java`: Spalte Code öffnen und auf Java stellen, wie über das Zahnrad. */ private openJavaColumn() { if (this.live.language !== 'java') { const sel = '[data-action=live-language]' @@ -1670,7 +1672,7 @@ export class App { this.preview.onToggleStacked = () => { this.previewStacked = !this.previewStacked storeValue(previewStackedKey, this.previewStacked ? '1' : '0') - // Unter dem Code geht nur mit offener Spalte „Programmieren“. + // Unter dem Code geht nur mit offener Spalte „Code“. if (this.previewStacked && !this.liveCoding) this.setLiveCoding(true) this.placePreview() } @@ -1734,7 +1736,7 @@ export class App { if (!inPreview) robot?.restoreViewport() } - /** Eigene Spalte ganz rechts oder unten in „Programmieren“ (nur wenn diese Spalte offen ist). */ + /** Eigene Spalte ganz rechts oder unten in „Code“ (nur wenn diese Spalte offen ist). */ private placePreview() { const stacked = this.previewStacked && this.liveCoding this.preview.setStacked(this.previewStacked) diff --git a/web/src/ui/learnPanel.ts b/web/src/ui/learnPanel.ts index 1e8fe3d4..561b6ace 100644 --- a/web/src/ui/learnPanel.ts +++ b/web/src/ui/learnPanel.ts @@ -6,7 +6,7 @@ import type { SubprogramResolver } from '../core/simulation' import { decodeDocument } from '../core/xmlCodec' import { explain, makeRound, usedValues, type BoolGame } from '../learn/boolGame' import { contentLanguageFor, diagram, glossary, image, lessons, reference, tasks, useContentLanguage, world } from '../learn/content' -import type { Block, ChecklistItem, Exercise, Lesson, QuizQuestion, Task } from '../learn/lessonFormat' +import { exerciseArea, type Block, type ChecklistItem, type Exercise, type Lesson, type QuizQuestion, type Task } from '../learn/lessonFormat' import { inline, markdownToHTML } from '../learn/markdown' import ludwigURL from './ludwig.webp' import { progress, type Rating } from '../learn/progress' @@ -30,7 +30,7 @@ import { attachPointers, attachTermTips, markPointers, markTerms, pointsIntoEdit export interface LearnHost { /** Übung im Editor öffnen (vorhandenen Reiter wählen oder neuen anlegen). */ openExercise(exercise: Exercise, doc: VSDocument): void - /** Java-Beispiel aus dem Text in einem neuen Reiter öffnen, Spalte „Programmieren“ auf Java. */ + /** Java-Beispiel aus dem Text in einem neuen Reiter öffnen, Spalte „Code“ auf Java. */ openJavaCode(java: string): void /** Beispieldiagramm in einem neuen Reiter öffnen. */ openDiagram(doc: VSDocument, fileName: string): void @@ -40,9 +40,9 @@ export interface LearnHost { subprogramsFor(id: string): SubprogramResolver /** Eingeklappte Struktogramm-Spalte wieder zeigen. */ showEditor(): void - /** Spalte „Programmieren“ öffnen. */ + /** Spalte „Code“ öffnen. */ showLiveCode(): void - /** Spalte „Programmieren“ auf Java öffnen (der Struktogramm-Editor bleibt, wie er ist). */ + /** Spalte „Code“ auf Java öffnen (der Struktogramm-Editor bleibt, wie er ist). */ showJava(): void /** Spalte Dateien öffnen (die anderen Spalten bleiben, wie sie sind). */ showFiles(): void @@ -200,7 +200,7 @@ export class LearnPanel { } } - /** Reiter „Nachschlagen“ zeigen, z. B. vom Knopf in „Programmieren“ aus. */ + /** Reiter „Nachschlagen“ zeigen, z. B. vom Knopf in „Code“ aus. */ showReference() { this.tab = 'reference' this.persist() @@ -342,9 +342,9 @@ export class LearnPanel { else if (pointsIntoFiles(this.body)) this.host.showFiles() // Eine Struktogramm-Übung braucht den Struktogramm-Editor. else if (exercises.some((ex) => ex.code !== 'java')) this.host.showEditor() - // Java (Beispiel als ```java oder Übung mit `code: java`) braucht die Spalte „Programmieren“. + // Java (Beispiel als ```java oder Übung mit `code: java`) braucht die Spalte „Code“. else if (exercises.length > 0 || this.body.querySelector('.lesson-code[data-lang=java]')) this.host.showJava() - // Dasselbe für Ausführen, Konsole und Einzelschritt in der Spalte „Programmieren“. + // Dasselbe für Ausführen, Konsole und Einzelschritt in der Spalte „Code“. if (pointsIntoLiveCode(this.body)) this.host.showLiveCode() } @@ -607,11 +607,9 @@ export class LearnPanel { const state = () => progress.exercise(ex.id) const badge = h('span', { class: 'learn-badge' }, `✓ ${t('web_learn_solved')}`) badge.hidden = !state().done - // Jede Übung sagt, in welchem Bereich man sie löst, mit dem Namen, der dort als Überschrift steht. - const where = ex.code === 'java' ? t('web_learn_solve_in_code', t('web_live_title')) : t('web_learn_solve_in_editor', t('web_editor_title')) card.append( h('h4', {}, `${t('web_learn_exercise')}: ${ex.title}`, badge), - h('p', { class: 'learn-where' }, where), + solveWhere(ex), html('div', { class: 'learn-text' }, markdownToHTML(ex.task)), ) @@ -1005,3 +1003,23 @@ export class LearnPanel { function matchOrder(q: QuizQuestion): string[] { return (q.pairs ?? []).map((p) => p.right).sort((a, b) => a.localeCompare(b, 'de')) } + +/** + * Schild „Löse diese Übung im Struktogramm/im Code“. Die Bereichsnamen sind die Überschriften auf dem Bildschirm + * und stehen in der Farbe ihres Bereichs (Struktogramm blau, Code violett). + */ +function solveWhere(ex: Exercise): HTMLElement { + const area = exerciseArea(ex) + const key = area === 'beide' ? 'web_learn_solve_in_both' : area === 'code' ? 'web_learn_solve_in_code' : 'web_learn_solve_in_editor' + const names = { editor: t('web_editor_title'), code: t('web_live_title') } + const args = area === 'beide' ? ['\u0001editor', '\u0001code'] : [area === 'code' ? '\u0001code' : '\u0001editor'] + const p = h('p', { class: `learn-where learn-where-${area}` }) + for (const part of t(key, ...args).split(/(\u0001(?:editor|code))/)) { + if (part === '\u0001editor' || part === '\u0001code') { + const which = part.slice(1) as 'editor' | 'code' + p.append(h('span', { class: `area-name area-${which}` }, names[which])) + } else if (part) p.append(part) + } + return p +} + diff --git a/web/src/ui/robotPreview.ts b/web/src/ui/robotPreview.ts index 60aacd0f..343cbdc5 100644 --- a/web/src/ui/robotPreview.ts +++ b/web/src/ui/robotPreview.ts @@ -17,7 +17,7 @@ const frameMs = 300 /** * VisuBot: „mBot2 live“ neben dem Bearbeiten. Nach jeder Änderung rechnet es das Programm im Hintergrund durch * und zeigt, wo der mBot2 am Ende steht und welche Spur er fährt; ▶ spielt die Fahrt ab. - * Steht als eigene Spalte oder unter dem Code in „Programmieren“ (`stacked`). + * Steht als eigene Spalte oder unter dem Code in „Code“ (`stacked`). */ export class RobotPreviewPanel { readonly element: HTMLElement diff --git a/web/src/ui/styles.css b/web/src/ui/styles.css index 59f44693..8fe6d23d 100644 --- a/web/src/ui/styles.css +++ b/web/src/ui/styles.css @@ -8,6 +8,9 @@ --accent-soft: rgba(0, 122, 255, 0.18); --accent-faint: rgba(0, 122, 255, 0.08); --accent-glow: rgba(0, 122, 255, 0.35); + /* Farben der Bereiche (auch in VisuBot gleich): Überschrift, Leiste und Schild „Löse diese Übung im …“ */ + --area-editor: #007aff; + --area-code: #7c3aed; color-scheme: light; } @@ -2165,13 +2168,39 @@ button.danger-text:not(:disabled) { } .learn-where { margin: 0; - justify-self: start; font-size: 13px; font-weight: 600; - color: var(--accent); - border: 1px solid var(--accent); + color: var(--muted); +} +.area-name { + display: inline-block; + color: #fff; border-radius: 10px; - padding: 1px 8px; + padding: 0 8px; +} +.area-name.area-editor { + background: var(--area-editor); +} +.area-name.area-code { + background: var(--area-code); +} +/* Jeder Bereich zeigt seine Farbe: oben ein farbiger Rand, eingeklappt die Leiste. */ +.columns > .app { + border-top: 3px solid var(--area-editor); +} +.livecode { + border-top: 3px solid var(--area-code); +} +.livecode-head h2, +.live-rail span { + color: var(--area-code); +} +.editor-rail span { + color: var(--area-editor); +} +.live-rail, +.editor-rail { + font-weight: 600; } .learn-exercise .learn-text p:last-child { margin-bottom: 0; diff --git a/web/src/ui/termTips.ts b/web/src/ui/termTips.ts index 9ba0d5af..21fa05b4 100644 --- a/web/src/ui/termTips.ts +++ b/web/src/ui/termTips.ts @@ -159,14 +159,14 @@ export const uiTargets: Record = { /** Zeiger auf diese Bereiche brauchen die Struktogramm-Spalte. */ const editorTargets = new Set(['editor', 'werkzeuge', 'elemente', 'struktogramm', 'objektinspektor', 'reiter', 'titel', 'rueckgaengig', 'loeschen', 'exportieren', 'code', 'simulation']) -/** Zeiger auf diese Bereiche brauchen die offene Spalte „Programmieren“ (die schmale Leiste allein reicht nicht). */ +/** Zeiger auf diese Bereiche brauchen die offene Spalte „Code“ (die schmale Leiste allein reicht nicht). */ const liveCodeTargets = new Set(['ausfuehren', 'konsole', 'einzelschritt']) function pointsInto(root: HTMLElement, targets: Set): boolean { return [...root.querySelectorAll('.ui-pointer')].some((p) => targets.has(p.dataset.target ?? '')) } -/** Eingeklappte Bereiche, die ein Zeiger öffnen kann: Struktogramm-Editor, Elemente, „Programmieren“, Dateien. */ +/** Eingeklappte Bereiche, die ein Zeiger öffnen kann: Struktogramm-Editor, Elemente, „Code“, Dateien. */ export type UiArea = 'editor' | 'palette' | 'livecode' | 'files' /** Was offen sein muss, damit man den Bereich des Zeigers sieht (die Elemente liegen im Struktogramm-Editor). */ @@ -193,7 +193,7 @@ export function pointsIntoEditor(root: HTMLElement): boolean { return pointsInto(root, editorTargets) } -/** Zeigt der Text auf einen Bereich der Spalte „Programmieren“? */ +/** Zeigt der Text auf einen Bereich der Spalte „Code“? */ export function pointsIntoLiveCode(root: HTMLElement): boolean { return pointsInto(root, liveCodeTargets) } diff --git a/web/test/lessons.test.ts b/web/test/lessons.test.ts index 4dc8cd31..2d82e608 100644 --- a/web/test/lessons.test.ts +++ b/web/test/lessons.test.ts @@ -6,7 +6,7 @@ import { documentFromJava, plainLiveJava } from '../src/core/liveSource' import { ElementType, makeElement, type VSElement } from '../src/core/model' import { subprogramName } from '../src/core/simulation' import { contentLanguages, diagram, image, lessons, reference, tasks, useContentLanguage } from '../src/learn/content' -import { parseBlocks, parseLesson, parseTest, type Block } from '../src/learn/lessonFormat' +import { exerciseArea, parseBlocks, parseLesson, parseTest, type Block } from '../src/learn/lessonFormat' import { markdownToHTML } from '../src/learn/markdown' import { clozeAnswerRight, clozeGaps, type Cloze } from '../src/learn/cloze' import { papFits, papLayout, parsePap } from '../src/learn/pap' @@ -194,6 +194,19 @@ describe('Lernbereich: Format', () => { expect(() => parseBlocks('::: quiz\n? Ordne zu.\n= a b\n:::', 'x.md')).toThrow(/links -> rechts/) }) + it('liest bereich: und leitet den Bereich sonst aus code: ab', () => { + const ex = (extra: string) => { + const block = parseBlocks(`::: übung x\ntitel: T\nauftrag: A\ntest: - -> 1\n${extra}:::`, 'x.md')[0] + if (block.kind !== 'exercise') throw new Error('keine Übung') + return exerciseArea(block.exercise) + } + expect(ex('')).toBe('struktogramm') + expect(ex('code: java\n')).toBe('code') + expect(ex('bereich: beide\n')).toBe('beide') + expect(ex('code: java\nbereich: Beide\n')).toBe('beide') + expect(() => ex('bereich: links\n')).toThrow(/bereich:/) + }) + it('löst Checklisten-Verweise auf und meldet unbekannte Schritte', () => { const source = (ref: string) => `---\ntitel: T\n---\n## Erster Schritt\nText\n## Checkliste\n::: checkliste\n- Ich kann es. → ${ref}\n- Ohne Verweis\n:::\n` const block = parseLesson(source('erster schritt'), '01-t.md').steps[1].blocks[0] diff --git a/website/app/assets/de-B05MOgXv.js b/website/app/assets/de-DS9kn30Y.js similarity index 98% rename from website/app/assets/de-B05MOgXv.js rename to website/app/assets/de-DS9kn30Y.js index bbe0f72f..69b6e8fa 100644 --- a/website/app/assets/de-B05MOgXv.js +++ b/website/app/assets/de-DS9kn30Y.js @@ -69,7 +69,8 @@ const e=`/* Texte, die es nur in der Web-Version gibt. Alle anderen kommen aus d "web_learn_solved" = "geschafft"; "web_learn_open_exercise" = "Im Editor öffnen"; "web_learn_solve_in_editor" = "Löse diese Übung im %@."; -"web_learn_solve_in_code" = "Löse diese Übung in %@."; +"web_learn_solve_in_code" = "Löse diese Übung im %@."; +"web_learn_solve_in_both" = "Löse diese Übung im %1$@ und im %2$@."; "web_learn_open_in_editor" = "Im Editor öffnen"; "web_learn_graphic_labels" = "👆 Klick aufs Bild: Beschriftung ein oder aus"; "web_learn_check" = "Prüfen"; @@ -140,14 +141,14 @@ const e=`/* Texte, die es nur in der Web-Version gibt. Alle anderen kommen aus d "web_site_imprint" = "Impressum"; "web_site_privacy" = "Datenschutz"; -/* Programmieren (früher „Code live“) */ -"web_live_title" = "Programmieren"; -"web_live_hide" = "Programmieren ausblenden"; +/* Code (früher „Code live“, dann „Programmieren“) */ +"web_live_title" = "Code"; +"web_live_hide" = "Code ausblenden"; "web_scale_canvas" = "Textgröße Struktogramm"; -"web_scale_code" = "Textgröße Programmieren"; +"web_scale_code" = "Textgröße Code"; "web_live_indent" = "Einrücken"; "web_live_indent_title" = "Code einrücken: jede Ebene vier Leerzeichen tiefer (markierte Zeilen, sonst alles)"; -"web_live_show" = "Programmieren aufklappen"; +"web_live_show" = "Code aufklappen"; "web_live_resize" = "Breite des Codebereichs ändern (Doppelklick: zurücksetzen)"; "web_live_hint" = "Der Code wächst mit deinem Struktogramm. Grau = Platzhalter: Schreib im Objektinspektor, dann steht dort dein Text. Klick auf eine Zeile markiert das Element."; "web_live_ph_selector" = "Variable"; @@ -405,7 +406,7 @@ const e=`/* Texte, die es nur in der Web-Version gibt. Alle anderen kommen aus d "web_visubot_preview_hide" = "mBot2 live einklappen"; "web_visubot_preview_show" = "mBot2 live zeigen"; "web_visubot_preview_resize" = "Größe von mBot2 live ändern"; -"web_visubot_preview_stack" = "Unter den Code in Programmieren"; +"web_visubot_preview_stack" = "Unter den Code im Bereich Code"; "web_visubot_preview_side" = "Als eigene Spalte"; "web_visubot_preview_distance_fmt" = "Strecke: %d cm"; "web_visubot_preview_input" = "braucht eine Eingabe, dafür die Simulation starten"; @@ -422,8 +423,8 @@ const e=`/* Texte, die es nur in der Web-Version gibt. Alle anderen kommen aus d "web_visubot_group_light" = "Licht und Lautstärke"; "web_visubot_group_tilt" = "Neigung und Schütteln"; "web_visubot_group_timer" = "Stoppuhr und Akku"; -"web_swap_to_code" = "Programmieren groß, Struktogramm schmal"; -"web_swap_to_editor" = "Struktogramm groß, Programmieren schmal"; +"web_swap_to_code" = "Code groß, Struktogramm schmal"; +"web_swap_to_editor" = "Struktogramm groß, Code schmal"; "web_editor_resize" = "Breite des Struktogramms ändern"; "web_palette_resize" = "Breite der Elemente ändern (Doppelklick: zurücksetzen)"; "web_palette_hide" = "Elemente einklappen"; diff --git a/website/app/assets/en-OfXp05Y3.js b/website/app/assets/en-Mt2ryoik.js similarity index 99% rename from website/app/assets/en-OfXp05Y3.js rename to website/app/assets/en-Mt2ryoik.js index 4ddfa9e4..3ac4ea39 100644 --- a/website/app/assets/en-OfXp05Y3.js +++ b/website/app/assets/en-Mt2ryoik.js @@ -70,6 +70,7 @@ const e=`/* Texts that exist only in the web version. Everything else comes from "web_learn_open_exercise" = "Open in editor"; "web_learn_solve_in_editor" = "Solve this exercise in the %@ area."; "web_learn_solve_in_code" = "Solve this exercise in the %@ area."; +"web_learn_solve_in_both" = "Solve this exercise in the %1$@ and %2$@ areas."; "web_learn_open_in_editor" = "Open in editor"; "web_learn_graphic_labels" = "👆 Click the picture to show or hide the labels"; "web_learn_check" = "Check"; @@ -141,13 +142,13 @@ const e=`/* Texts that exist only in the web version. Everything else comes from "web_site_privacy" = "Privacy"; /* Programmieren (früher „Code live“) */ -"web_live_title" = "Programming"; -"web_live_hide" = "Hide programming"; +"web_live_title" = "Code"; +"web_live_hide" = "Hide code"; "web_scale_canvas" = "Text size: structure chart"; -"web_scale_code" = "Text size: Programming"; +"web_scale_code" = "Text size: Code"; "web_live_indent" = "Indent"; "web_live_indent_title" = "Indent the code: four spaces per level (selected lines, otherwise everything)"; -"web_live_show" = "Show programming"; +"web_live_show" = "Show code"; "web_live_resize" = "Change width of the code area (double-click: reset)"; "web_live_hint" = "The code grows with your diagram. Grey = placeholder: type in the object inspector and your text appears there. Click a line to select its element."; "web_live_ph_selector" = "variable"; @@ -405,7 +406,7 @@ const e=`/* Texts that exist only in the web version. Everything else comes from "web_visubot_preview_hide" = "Collapse mBot2 live"; "web_visubot_preview_show" = "Show mBot2 live"; "web_visubot_preview_resize" = "Resize mBot2 live"; -"web_visubot_preview_stack" = "Below the code in Programming"; +"web_visubot_preview_stack" = "Below the code in the Code area"; "web_visubot_preview_side" = "As a column of its own"; "web_visubot_preview_distance_fmt" = "Distance: %d cm"; "web_visubot_preview_input" = "needs an input, start the simulation for that"; @@ -422,8 +423,8 @@ const e=`/* Texts that exist only in the web version. Everything else comes from "web_visubot_group_light" = "Light and loudness"; "web_visubot_group_tilt" = "Tilt and shaking"; "web_visubot_group_timer" = "Stopwatch and battery"; -"web_swap_to_code" = "Programming large, structogram narrow"; -"web_swap_to_editor" = "Structogram large, programming narrow"; +"web_swap_to_code" = "Code large, structogram narrow"; +"web_swap_to_editor" = "Structogram large, code narrow"; "web_editor_resize" = "Resize the structogram"; "web_palette_resize" = "Resize the elements (double-click: reset)"; "web_palette_hide" = "Hide elements"; diff --git a/website/app/assets/index-3atjocI4.css b/website/app/assets/index-3atjocI4.css deleted file mode 100644 index ad2976e4..00000000 --- a/website/app/assets/index-3atjocI4.css +++ /dev/null @@ -1 +0,0 @@ -:root{--bg: #f2f2f7;--panel: #ffffff;--text: #1c1c1e;--muted: #6e6e73;--border: #d1d1d6;--accent: #007aff;--accent-soft: rgba(0, 122, 255, .18);--accent-faint: rgba(0, 122, 255, .08);--accent-glow: rgba(0, 122, 255, .35);color-scheme:light}:root.visubot-theme{--bg: #f1f0f8;--text: #2f3454;--muted: #6a6890;--border: #d6d3e8;--accent: #e07000;--accent-soft: rgba(253, 161, 21, .24);--accent-faint: rgba(253, 161, 21, .1);--accent-glow: rgba(224, 112, 0, .35)}:root.visubot-theme .selection-frame{stroke:#e07000e6}*{box-sizing:border-box}html,body{margin:0;height:100%;background:var(--bg);color:var(--text);font:14px/1.4 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.app{display:grid;grid-template:"tools tools" auto "pal work" 1fr "pal insp" auto / var(--palette-width, 210px) minmax(0,1fr);height:100%;flex:1;min-width:0}.shell{display:flex;flex-direction:column;height:100vh;height:100dvh}.columns{display:flex;flex:1;min-height:0}.columns>.app{min-width:240px}.toolbar{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;padding:8px 12px;background:var(--panel);border-bottom:1px solid var(--border)}button.icon{display:inline-flex;align-items:center;justify-content:center;min-width:34px;height:32px;padding:0 7px}button.icon svg{display:block}.tooltip{position:fixed;z-index:1000;max-width:260px;padding:4px 8px;border-radius:6px;background:#1c1c1e;color:#fff;font-size:12px;line-height:1.35;pointer-events:none;box-shadow:0 2px 8px #0003}.tooltip[hidden]{display:none}.diagram-tools{grid-area:tools;display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:5px 8px;background:var(--panel);border-bottom:1px solid var(--border)}.diagram-tools button.icon{min-width:30px;height:30px;padding:0 5px}.diagram-tools .sim-toggle{margin-inline-start:auto;display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 10px;white-space:nowrap}.diagram-tools{container-type:inline-size}@container (max-width: 520px){.diagram-tools .sim-toggle span{display:none}}.diagram-tools .sep{width:1px;height:20px;margin-inline:3px;background:var(--border)}.menu-host{position:relative}.export-menu{position:absolute;top:calc(100% + 4px);inset-inline-end:0;z-index:30;display:grid;min-width:180px;padding:4px;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #00000026}.export-menu[hidden]{display:none}.export-menu button{border:none;background:none;text-align:start;padding:7px 10px;border-radius:6px}.export-menu button:hover,.export-menu button:focus-visible{background:var(--accent-soft)}.settings{position:relative;margin-inline-start:auto}.settings>button{display:inline-flex;align-items:center;padding:6px 8px}.settings-menu{position:absolute;top:calc(100% + 6px);inset-inline-end:0;z-index:30;display:grid;width:290px;max-width:calc(100vw - 24px);max-height:calc(100dvh - 80px);overflow-y:auto;padding:4px 0;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #00000026}.settings-menu[hidden]{display:none}.settings-menu section,.settings-menu footer{display:grid;gap:10px;padding:10px 14px 12px}.settings-menu section+section,.settings-menu footer{border-top:1px solid var(--border)}.settings-menu footer{display:flex;align-items:center;justify-content:space-between;gap:10px}.settings-version{font-size:12px;color:var(--muted)}.settings-menu section[hidden]{display:none}.settings-menu h3{margin:0;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}.settings-menu label{display:grid;gap:4px;font-size:13px;font-weight:600;color:var(--muted)}.settings-menu select{width:100%;max-width:none}.settings-menu label.check{grid-template-columns:auto 1fr;align-items:start;gap:8px;font-weight:500;color:var(--text);cursor:pointer}.settings-menu label.check input{margin:2px 0 0}.settings-menu label small,.settings-menu label.check small{display:block;font-weight:400;color:var(--muted)}.settings-menu .about-button{justify-self:start;padding:6px 10px;font-size:13px}dialog.about{width:min(560px,calc(100vw - 32px));max-height:calc(100dvh - 48px);padding:0;color:var(--text);background:var(--panel);border:1px solid var(--border);border-radius:12px;box-shadow:0 12px 40px #00000040}dialog.about::backdrop{background:#00000059}dialog.about header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;border-bottom:1px solid var(--border)}dialog.about h2{margin:0;font-size:16px}.about-body{padding:20px 24px 24px;font-size:14px;line-height:1.5}.about-body p{margin:0 0 8px;color:var(--muted)}.about-head{display:flex;gap:16px;padding-bottom:16px;margin-bottom:8px;border-bottom:1px solid var(--border)}.about-head .logo{flex:none;width:40px;height:40px;color:var(--accent)}.about-head h3{margin:0 0 6px;font-size:20px}.about-head h3 small{font-weight:400;color:var(--muted)}.about-body .about-version{font-variant-numeric:tabular-nums}.about-body .about-author{color:var(--text);font-weight:600}.about-link{margin:0 0 2px}.about-body h4{margin:16px 0 6px;font-size:15px}.about-body code{font-weight:600;color:var(--text)}.about-body .about-copy{margin-top:16px}.brand{font-weight:700;font-size:16px;display:flex;align-items:center;gap:8px}.visubot-logo{width:auto;height:30px;margin:-4px 0}.visubot-bot{color:#f08a00;margin-left:-8px}.brand small{font-weight:500;color:var(--muted);font-size:12px}.logo{width:20px;height:20px;border:2px solid currentColor;background:linear-gradient(to bottom right,transparent 47%,currentColor 47% 53%,transparent 53%) left / 50% 60% no-repeat,linear-gradient(to bottom left,transparent 47%,currentColor 47% 53%,transparent 53%) right / 50% 60% no-repeat}.group{display:flex;flex-wrap:wrap;gap:6px}button,select{font:inherit;padding:6px 12px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);cursor:pointer;min-height:34px}select{max-width:180px}button:hover:not(:disabled),select:hover{border-color:var(--accent)}button:disabled{opacity:.4;cursor:default}.palette,.inspector{background:var(--panel);padding:12px;overflow-y:auto}.palette{grid-area:pal;border-inline-end:1px solid var(--border)}.inspector{grid-area:insp;border-top:1px solid var(--border);max-height:34vh}h2{font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:0 0 4px}.hint{color:var(--muted);font-size:12px;margin:0 0 10px}.palette ul{list-style:none;margin:0;padding:0;display:grid;gap:6px}.palette-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--border);border-radius:8px;cursor:grab;line-height:1.25;user-select:none;-webkit-user-select:none;touch-action:none}.palette-item:hover,.palette-item:focus-visible{border-color:var(--accent);outline:none}.palette-item .icon{flex:none;color:var(--text)}.workspace{grid-area:work;display:flex;flex-direction:column;min-width:0;min-height:0}.caption{font:600 18px system-ui,-apple-system,sans-serif;border:none;border-bottom:1px solid var(--border);padding:10px 16px;background:var(--panel);outline:none}.canvas{flex:1;overflow:auto;scrollbar-gutter:stable;background:#fafafa}.canvas svg{display:block;user-select:none;-webkit-user-select:none}.dragging,.dragging *{cursor:grabbing!important}.drop-line{fill:var(--accent)}.drop-replace{fill:var(--accent-soft);stroke:var(--accent);stroke-width:3}.drag-ghost{position:fixed;left:0;top:0;z-index:10;pointer-events:none;padding:6px 10px;border-radius:8px;background:var(--accent);color:#fff;font-weight:600;box-shadow:0 4px 14px #0003;white-space:nowrap;max-width:260px;overflow:hidden;text-overflow:ellipsis}.inspector label{display:block;font-weight:600;margin:8px 0 4px}.inspector textarea{width:100%;font:14px ui-monospace,SF Mono,Menlo,Consolas,monospace;padding:8px;border:1px solid var(--border);border-radius:8px;resize:vertical}.statusbar{display:flex;flex-wrap:wrap;gap:2px 16px;align-items:baseline;padding:4px 12px;font-size:12px;color:var(--muted);background:var(--panel);border-top:1px solid var(--border)}.status{flex:1 1 auto;min-width:0}.site-links{display:flex;gap:12px;margin-inline-start:auto}.site-links a{color:inherit}.site-links a:hover,.site-links a:focus-visible{color:var(--accent)}a.brand{color:inherit;text-decoration:none}.file-drag .canvas{outline:3px dashed var(--accent);outline-offset:-8px}@media(min-width:821px){.app.compact-palette{--palette-width: 100px}.app.compact-palette .palette{padding:8px 6px}.app.compact-palette .palette h2{font-size:10px;letter-spacing:0;text-align:center}.app.compact-palette .palette .hint{display:none}.app.compact-palette .palette-item{flex-direction:column;gap:3px;padding:6px 2px;font-size:10.5px;line-height:1.15;text-align:center;overflow-wrap:break-word}}@media(max-width:820px){.app{grid-template:"tools" auto "pal" auto "work" 1fr "insp" auto / minmax(0,1fr)}.palette,.inspector{min-width:0}.palette{border-inline-end:none;border-bottom:1px solid var(--border);padding:8px}.palette .hint,.palette h2{display:none}.palette ul{display:flex;overflow-x:auto;overflow-y:hidden}.palette-item{white-space:nowrap}.inspector{max-height:30vh}}.status.message{color:var(--text);font-weight:600}.confirm{position:fixed;top:0;right:0;bottom:0;left:0;z-index:20;display:grid;place-items:center;background:#00000040;padding:16px}.confirm-card{background:var(--panel);border-radius:12px;padding:16px 18px;max-width:360px;box-shadow:0 10px 30px #0003}.confirm-card p{margin:0 0 8px}.confirm-card .group{justify-content:flex-end;margin-top:12px}.files-ask{width:min(360px,100%)}.files-ask input{width:100%;box-sizing:border-box;margin-top:4px}.files-choices{display:flex;flex-wrap:wrap;gap:6px;margin:4px 0 10px}.files-choice{display:inline-flex;align-items:center;gap:6px}.files-choice svg{width:16px;height:16px}button.danger{background:#d70015;border-color:#d70015;color:#fff}.simpanel{display:none;grid-area:insp;background:var(--panel);border-inline-start:1px solid var(--border);padding:12px;overflow-y:auto}.app.simulating{grid-template:"tools tools" auto "work insp" 1fr / minmax(0,1fr) 320px}.app.simulating.visubot-mode{grid-template:"tools tools" auto "work insp" 1fr / minmax(0,1fr) min(440px,45%)}.app.simulating .palette,.app.simulating .inspector{display:none}.app.simulating .simpanel{display:block}.app.simulating .caption{cursor:default}button.sim-toggle{font-weight:600}button.sim-toggle{background:var(--accent);border-color:var(--accent);color:#fff}.simpanel section{margin-bottom:14px}.sim-buttons{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:6px 0 10px}.sim-option{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px;font-size:13px}.mono,.sim-vars td{font:13px/1.5 ui-monospace,SF Mono,Menlo,Consolas,monospace}.sim-trace,.sim-output,.sim-vars{background:var(--bg);border-radius:8px;padding:8px 10px;overflow-wrap:anywhere}.sim-output{max-height:220px;overflow-y:auto;white-space:pre-wrap}.sim-vars table{border-collapse:collapse;width:100%}.sim-vars td{padding:2px 0;vertical-align:top}.sim-vars td:first-child{color:var(--muted);padding-inline-end:12px;width:1%;white-space:nowrap}.sim-vars table.sim-grid{width:auto}.sim-vars .sim-grid td,.sim-vars .sim-grid td:first-child{border:1px solid var(--border);color:inherit;font-size:11px;padding:0 4px;text-align:center;width:auto}.sim-vars .sim-grid td.sim-grid-true{font-weight:700}.simpanel .placeholder{color:var(--muted);font:13px system-ui,-apple-system,sans-serif;margin:0}.sim-notice{margin:0 0 14px;padding:8px 10px;border-radius:8px;background:#34c75926;font-weight:600}.sim-edit{width:100%;margin:-6px 0 14px}.sim-notice.error{background:#ff3b3026;color:#b0000f}.sim-input.active{padding:8px 10px;margin-left:-10px;margin-right:-10px;border-radius:10px;background:var(--accent-faint);outline:2px solid var(--accent)}.sim-prompt{margin:4px 0 6px;font-weight:600}.sim-input-row{display:flex;gap:6px}.sim-input-row input{flex:1;min-width:0;font:inherit;padding:6px 10px;border:1px solid var(--border);border-radius:8px}.sim-input-error{color:#b0000f;margin:6px 0 0;font-size:13px}@media(max-width:820px){.app.simulating{grid-template:"tools" auto "work" minmax(200px,1fr) "insp" auto / minmax(0,1fr)}.simpanel{border-inline-start:none;border-top:1px solid var(--border);max-height:48vh}}.codepanel{display:none;grid-area:code;background:var(--panel);border-inline-start:1px solid var(--border);padding:12px;overflow-y:auto;min-height:0}.app.coding{grid-template:"tools tools tools" auto "pal work code" 1fr "pal insp code" auto / var(--palette-width, 210px) minmax(0,1fr) 400px}.app.coding .codepanel{display:block}.app.coding .inspector{max-height:34vh}button[data-action=code][aria-pressed=true]{border-color:var(--accent);background:var(--accent-soft)}.code-head,.runner-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.code-close{min-height:28px;padding:2px 10px}.segmented{display:flex;margin-bottom:8px}.segmented button{flex:1;border-radius:0;min-height:30px;padding:4px 8px}.segmented button:first-child{border-radius:8px 0 0 8px}.segmented button:last-child{border-radius:0 8px 8px 0}.segmented button+button{border-inline-start:none}.segmented button[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:#fff}.segmented[hidden]{display:none}.check{display:flex;gap:8px;align-items:center;font-size:13px;margin-bottom:4px}.code-actions{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}.code-actions [hidden]{display:none}button.primary{background:var(--accent);border-color:var(--accent);color:#fff}.code-view,.runner-out{margin:0;padding:10px 12px;border-radius:10px;background:var(--bg);font:13px/1.5 ui-monospace,SF Mono,Menlo,Consolas,monospace;overflow:auto;white-space:pre;-moz-tab-size:4;tab-size:4}.runner{margin:12px 0}.runner-out{background:#0b1220;color:#e5e7eb;min-height:3em;max-height:240px;white-space:pre-wrap}.runner-out.error{outline:2px solid #ff453a}.runner-input{margin-top:8px}.runner-input label{display:block;font-weight:600;margin-bottom:4px}@media(max-width:820px){.app.coding{grid-template:"tools" auto "pal" auto "work" minmax(240px,1fr) "insp" auto "code" auto / minmax(0,1fr)}.codepanel{border-inline-start:none;border-top:1px solid var(--border);max-height:50vh}}.tabs{display:flex;align-items:flex-end;gap:2px;padding:6px 8px 0;background:var(--bg);border-bottom:1px solid var(--border);overflow-x:auto;overflow-y:hidden;scrollbar-width:thin}.tab{display:flex;align-items:center;max-width:220px;border:1px solid var(--border);border-bottom:none;border-radius:8px 8px 0 0;background:#ffffff80}.tab.active{background:var(--panel);margin-bottom:-1px;padding-bottom:1px}.tab button{border:none;background:none;min-height:30px;border-radius:8px 8px 0 0}.tab-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:4px 6px 4px 12px}.tab.active .tab-label{font-weight:600}.tab-close{padding:2px 8px;color:var(--muted);font-size:11px}.tab-close:hover{color:var(--text)}.tab-dot,.tab-close.unsaved .tab-x{display:none}.tab-close.unsaved .tab-dot{display:inline;color:var(--text);font-size:10px}.tab-close.unsaved:hover .tab-dot{display:none}button.tab-close.unsaved:hover .tab-x{display:inline}span.tab-close{padding:2px 10px 2px 4px}.tab-add{min-height:28px;padding:2px 10px;margin:0 0 3px 4px;border-radius:8px}.inspector .segmented{margin:6px 0 4px;max-width:420px}.mono-hint{font:11px/1.45 ui-monospace,SF Mono,Menlo,Consolas,monospace;overflow-wrap:anywhere}.editor-row{display:flex;gap:8px;align-items:flex-start}.editor-row textarea{flex:1;min-width:0}.fixed-prefix{font:14px ui-monospace,SF Mono,Menlo,Consolas,monospace;color:var(--muted);padding-top:9px}.inspector input:not([type]){width:100%;font:14px ui-monospace,SF Mono,Menlo,Consolas,monospace;padding:7px 8px;border:1px solid var(--border);border-radius:8px}.for-fields{display:grid;gap:4px}.for-fields label,.case-controls label{margin:4px 0 0;font-size:12px;color:var(--muted);font-weight:600}.case-controls{margin-top:12px;padding-top:10px;border-top:1px solid var(--border)}.case-controls .group{margin-top:8px}button.danger-text:not(:disabled){color:#d70015}.print-sheet{display:none}.files{display:none;flex:0 1 auto;flex-direction:column;width:260px;min-width:200px;min-height:0;background:var(--panel);border-inline-end:1px solid var(--border)}.shell.files-open .files{display:flex}.shell.files-open .files-rail{display:none}.files-head{display:flex;align-items:center;gap:4px;margin:10px 12px 6px}.files-head h2{flex:1;margin:0;font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.files-head button.icon{min-width:30px;height:30px;padding:0 5px}.files-head [hidden]{display:none}.files-body{flex:1;min-height:0;overflow:auto;padding:0 8px 12px;font-size:14px}.files-where{margin:0 4px 6px;font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.files-hint,.files-empty{margin:8px 4px;font-size:13px;color:var(--muted)}.start-ask .files-start{margin-bottom:2px}.start-ask .hint{font-size:13px;color:var(--muted)}.start-without{display:block;margin:12px auto 0;border:none;background:none;color:var(--accent);text-decoration:underline}.start-without+.hint{text-align:center}.files-start{display:flex;align-items:center;gap:6px;width:100%;margin:8px 0;justify-content:center}.files-row{display:flex;align-items:center;border-radius:6px}.files-row:hover,.files-row:focus-within{background:var(--accent-soft)}.files-row.current>.files-name{font-weight:600}.files-name{flex:1;min-width:0;display:flex;align-items:center;gap:6px;padding:4px 6px 4px calc(6px + var(--depth) * 16px);border:none;background:none;text-align:start;font:inherit;color:var(--text);cursor:pointer}.files-name:disabled{cursor:default;color:var(--muted)}.files-name svg{flex:none;width:16px;height:16px;color:var(--muted)}.files-name span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.files-name small{margin-inline-start:auto;padding:0 6px;border-radius:6px;background:var(--accent);color:#fff;font-size:11px;font-weight:600}.files-row .files-delete{visibility:hidden;min-width:26px;height:26px;padding:0 4px;border:none;background:none;color:var(--muted)}.files-row:hover .files-delete,.files-row:focus-within .files-delete{visibility:visible}.files-error{color:#c62828}.files-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.shell.files-open .files-resizer{display:block}.files-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px}.files-resizer:hover:after,.files-resizer:focus-visible:after{background:var(--accent)}.learn{display:none;flex:0 1 auto;width:400px;min-width:280px;flex-direction:column;background:var(--panel);border-inline-end:1px solid var(--border);min-height:0}.shell.learning .learn{display:flex}.learn-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.shell.learning .learn-resizer{display:block}.learn-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.learn-resizer:hover:after,.learn-resizer:focus-visible:after,.shell.resizing .learn-resizer:after{background:var(--accent)}.learn-resizer:focus-visible{outline:none}.shell.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.learn-head{display:flex;align-items:flex-start;gap:6px;margin:10px 12px 0}.learn-tabs{flex:1;min-width:0}.learn-hide{flex:none;min-height:30px;padding:4px 7px;display:inline-flex;align-items:center;color:var(--muted)}.learn-rail{flex:none;display:flex;flex-direction:column;align-items:center;gap:10px;width:36px;padding:10px 0;border:none;border-radius:0;border-inline-end:1px solid var(--border);background:var(--panel);cursor:pointer}.learn-rail:hover{background:var(--accent-soft)}.learn-rail span{writing-mode:vertical-rl;white-space:nowrap}.shell.learning .learn-rail:not(.live-rail):not(.editor-rail):not(.files-rail):not(.robotpreview-rail):not(.palette-rail){display:none}.live-rail{border-inline-end:none;border-inline-start:1px solid var(--border)}.live-rail svg{transform:scaleX(-1)}.shell.live .live-rail{display:none}.editor-rail{display:none;border-inline-start:1px solid var(--border)}.shell.editor-hidden .editor-rail{display:flex}.shell.editor-hidden .app,.shell.editor-hidden .live-resizer,.shell.editor-hidden:not(.live) .learn-resizer{display:none}.shell.editor-hidden .livecode,.shell.editor-hidden:not(.live) .learn{flex:1 1 0;width:auto!important;min-width:0}.learn-body{overflow-y:auto;scrollbar-gutter:stable;padding:4px 16px 24px;flex:1;min-height:0;line-height:1.5}.learn-body h2.learn-title{display:flex;align-items:center;gap:8px;font-size:20px;text-transform:none;letter-spacing:0;color:var(--text);margin:2px 0 10px}.learn-section{font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:18px 0 6px}.learn-list{list-style:none;padding:0;margin:0;display:grid;gap:6px}.learn-item{display:flex;align-items:center;gap:10px;width:100%;text-align:start;padding:8px 10px}.learn-item.done{border-color:#34c759}.learn-num{flex:none;min-width:28px;height:28px;border-radius:14px;background:var(--accent-soft);color:var(--accent);display:grid;place-items:center;font-weight:700;font-size:12px;padding:0 6px}.learn-item.done .learn-num{background:#34c7592e;color:#248a3d}.learn-item-text{flex:1;display:grid;min-width:0}.learn-item-text small{color:var(--muted)}.learn-status{flex:none;color:var(--muted);font-size:12px}.learn-item.done .learn-status{color:#248a3d;font-weight:700}.learn-back,.link-button{border:none;background:none;padding:6px 0;min-height:0;color:var(--accent)}.link-button{padding:0;text-align:start}.learn-lesson-head{position:sticky;top:-4px;z-index:3;margin:-4px -16px 10px;padding:4px 16px 8px;background:var(--panel);border-bottom:1px solid var(--border)}.learn-lesson-head .learn-progress{margin-bottom:8px}.learn-lesson-head .learn-step-title{margin:0}.learn-head-row{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}.learn-nav.learn-nav-top{margin-top:0;gap:6px}.learn-nav-top button{padding:3px 10px;min-height:0;font-size:13px}.learn-kicker{margin:4px 0 0;color:var(--muted);font-size:12px}.learn-progress{display:flex;gap:4px;margin-bottom:14px}.learn-progress button{flex:1 1 0;min-width:0;padding:3px 0;font-size:13px;font-variant-numeric:tabular-nums;border-radius:6px}.learn-progress button.past{border-color:var(--accent);color:var(--accent)}.learn-progress button.current{border-color:var(--accent);background:var(--accent);color:#fff;font-weight:600}.learn-progress button.robot-step:not(.current){border-color:#0fa3c6;background:#0fa3c61f}.learn-progress button.robot-step.current{border-color:#0fa3c6;background:#0fa3c6}.learn-step-title{font-size:16px;margin:0 0 6px}.learn-text p,.learn-text ul,.learn-text ol{margin:0 0 10px}.learn-text ul,.learn-text ol{padding-inline-start:22px}.learn-text code,.learn-tests code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;background:var(--bg);border-radius:4px;padding:1px 4px}.learn-text h3{font-size:15px;margin:18px 0 4px}.reference-group{border:1px solid var(--border);border-radius:8px;margin:0 0 8px;padding:0 12px}.reference-group summary{cursor:pointer;font-weight:600;padding:9px 0}.reference-group[open] summary{border-bottom:1px solid var(--border)}.reference-group>h3:first-of-type{margin-top:10px}.lesson-code{background:var(--bg);border-radius:8px;padding:8px 10px;margin:0 0 10px;overflow-x:auto;overflow-y:hidden;font-size:12.5px}.learn-open-code{display:block;margin:-4px 0 12px}.lesson-code code{background:none;padding:0}.lesson-note{border-inline-start:3px solid var(--accent);background:var(--accent-soft);border-radius:6px;padding:8px 10px;margin:0 0 10px}.lesson-note p:last-child{margin-bottom:0}.learn-images{display:flex;gap:8px;flex-wrap:wrap}.learn-images img{width:150px;height:200px;object-fit:cover;border-radius:8px}.learn-file{margin:0 0 14px;border:1px solid var(--border);border-radius:10px;overflow:hidden;background:var(--panel)}.learn-file figcaption{display:flex;align-items:center;gap:6px;padding:6px 10px;background:var(--bg);border-bottom:1px solid var(--border);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;font-weight:600}.learn-file-text{margin:0;padding:8px 10px;overflow-x:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;line-height:1.5;white-space:pre}.learn-file.written{margin:8px 0;border-color:#15803d}.learn-file.written figcaption{background:#dcfce7}.learn-file-text .ln{display:inline-block;min-width:2ch;margin-inline-end:10px;color:var(--muted);text-align:end;-webkit-user-select:none;user-select:none}.learn-brag{display:grid;grid-template-columns:48px minmax(0,1fr);gap:10px;align-items:start;border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin:0 0 14px;background:var(--accent-soft)}.learn-brag img{width:48px;height:48px;border-radius:50%}.learn-brag-title{margin:0 0 4px;font-weight:700}.learn-brag .learn-text p:last-child{margin-bottom:0}.learn-game{border:2px solid var(--accent);border-radius:12px;padding:12px 14px;margin:0 0 14px}.learn-game-head{display:flex;align-items:center;gap:10px;font-size:1.05em}.learn-game-head img{width:40px;height:40px;border-radius:50%}.learn-game-status{margin:6px 0;color:var(--muted);font-size:.9em}.learn-game-values{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.learn-game-values code{background:var(--accent-soft);border-radius:6px;padding:2px 8px}.learn-game-condition{font-size:1.15em;font-weight:600;padding:10px 12px;border-radius:8px;background:var(--bg, #f2f2f7);margin-bottom:10px;overflow-wrap:anywhere}.learn-game-answers button{flex:1;font-weight:600;padding-block:10px}.learn-game-true:not(:disabled){border-color:#15803d;color:#15803d}.learn-game-false:not(:disabled){border-color:#b91c1c;color:#b91c1c}.learn-game-feedback:empty{display:none}.learn-game-feedback{margin-top:10px;padding:10px 12px;border-radius:8px}.learn-game-feedback.right{background:#dcfce7}.learn-game-feedback.wrong{background:#fee2e2}.learn-game-feedback p{margin:0 0 6px;font-weight:700}.learn-game-steps{margin-bottom:10px;line-height:1.6}.learn-game-result{font-size:1.2em;font-weight:700}.learn-game-question{font-weight:600;margin:10px 0 8px}.learn-game-code{margin:0 0 8px;padding:8px 0;border-radius:8px;background:var(--bg, #f2f2f7);font-size:13px;line-height:1.5;overflow-x:auto}.learn-game-code .ln{padding:0 10px 0 calc(10px + 2ch);text-indent:-2ch;border-inline-start:3px solid transparent;white-space:pre-wrap;overflow-wrap:anywhere;transition:background .2s}.learn-game-code .ln.hit{background:#fef3c7;border-inline-start-color:#d97706}.learn-bomb{display:flex;align-items:center;gap:10px;margin-bottom:6px;font-weight:700}.learn-bomb-icon{font-size:28px;line-height:1}.learn-bomb.hurry .learn-bomb-icon{animation:learn-bomb-shake .25s infinite alternate}.learn-bomb.boom .learn-bomb-icon{animation:learn-bomb-boom .5s ease-out}@keyframes learn-bomb-shake{0%{transform:rotate(-8deg)}to{transform:rotate(8deg)}}@keyframes learn-bomb-boom{0%{transform:scale(.6)}60%{transform:scale(1.5)}to{transform:scale(1)}}.learn-bomb-time{min-width:7ch;font-variant-numeric:tabular-nums}.learn-bomb-fuse{flex:1;height:8px;border-radius:4px;background:#e5e7eb;overflow:hidden}.learn-bomb-fuse span{display:block;height:100%;background:#f59e0b;transition:width .2s linear}.learn-bomb.hurry .learn-bomb-fuse span{background:#dc2626}.learn-bomb.defused .learn-bomb-fuse span{background:#15803d}.learn-bomb-code .ln{display:block;width:100%;margin:0;border-radius:0;border-block:0;border-inline-end:0;background:none;color:inherit;font:inherit;line-height:inherit;min-height:0;height:auto;padding-block:1px;text-align:start;cursor:pointer}.learn-bomb-code .ln:not(:disabled):hover{background:#fef3c7}.learn-bomb-code .ln:disabled{cursor:default;opacity:1}.learn-bomb-code .ln.right,.learn-bomb-code .ln.right:hover{background:#dcfce7;border-inline-start-color:#15803d}.learn-bomb-code .ln.wrong,.learn-bomb-code .ln.wrong:hover{background:#fee2e2;border-inline-start-color:#b91c1c}.learn-bomb-fix code{white-space:pre-wrap}.learn-game-options{display:grid;gap:6px}.learn-game-options button{text-align:start;padding:8px 12px}.learn-game-options.pictures{grid-template-columns:repeat(auto-fill,minmax(130px,1fr))}.learn-game-options.pictures button{padding:6px}.learn-game-options button.right{border-color:#15803d;background:#dcfce7;color:inherit;opacity:1}.learn-game-options button.wrong{border-color:#b91c1c;background:#fee2e2;color:inherit;opacity:1}.learn-order-hint{margin:0 0 6px;font-size:13px;opacity:.75}.learn-order button{display:flex;align-items:center;gap:10px}.learn-order-badge{flex:none;display:inline-grid;place-items:center;width:24px;height:24px;border-radius:50%;border:1.5px solid currentColor;font-size:13px;font-weight:700;opacity:.5}.learn-order button.right .learn-order-badge,.learn-order button:disabled .learn-order-badge:not(:empty){opacity:1}.learn-game-file{margin:0;padding:2px 0;font-size:13px;line-height:1.45;white-space:pre;background:none}.learn-game-explain{margin-bottom:10px}.learn-swing-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px;align-items:start}.learn-swing-window{border:1px solid var(--border);border-radius:8px;overflow:hidden;background:#fff;color:#1c1c1e}.learn-swing-title{padding:3px 8px;font-size:12px;text-align:center;background:#e5e5ea;border-bottom:1px solid #d1d1d6;min-height:1.4em}.learn-swing-body{display:grid;gap:6px;padding:10px}.learn-swing-label{padding:4px 2px;min-height:1.4em}.learn-swing-label.changed,.learn-swing-button.changed{animation:swing-changed 1s ease-out}@keyframes swing-changed{0%{background:#ffd60acc}}.learn-swing-button{padding:6px 10px;background:#fff;color:#1c1c1e;border:1px solid #a1a1aa;border-radius:6px}.learn-swing-button:disabled{opacity:1;cursor:default}.learn-swing-button.pressed{background:var(--accent);border-color:var(--accent);color:#fff;transform:scale(.96)}.learn-swing-event{margin:0;padding:0 10px 8px;font-size:12px;min-height:1.4em}.learn-swing-event.heard{color:#b45309;font-weight:600}.learn-swing-event.nobody{color:#6b7280;font-style:italic}.learn-swing-console{margin:0 10px 10px;padding:6px 8px;border-radius:6px;background:#1c1c1e;color:#f2f2f7;font-size:12px}.learn-swing-console[hidden]{display:none}.learn-swing-clicks{margin:8px 0 0}.learn-swing-try{font-weight:400!important;font-style:italic}.learn-layout-window{width:100%;border:1px solid #a1a1aa;border-radius:6px;overflow:hidden;background:#fff;color:#1c1c1e}.learn-layout-title{height:10px;background:#e5e5ea;border-bottom:1px solid #d1d1d6}.learn-layout-body{height:80px;padding:3px;gap:3px;font-size:12px}.learn-layout-body.grid{display:grid;grid-auto-rows:1fr}.learn-layout-body.flow{display:flex;flex-direction:column;gap:3px}.learn-layout-row{display:flex;justify-content:center;gap:3px}.learn-layout-body.border{display:grid;grid-template:"N N N" auto "W C E" 1fr "S S S" auto / auto 1fr auto}.learn-layout-cell{display:flex;align-items:center;justify-content:center;min-width:22px;padding:2px 6px;border:1px solid #a1a1aa;border-radius:4px;background:#f4f4f5;font-weight:600}.learn-figure{margin:0 0 14px;display:grid;gap:6px;justify-items:start}.learn-preview{width:100%;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:#fafafa}.learn-preview>svg{display:block;width:100%;margin:0 auto;height:auto}.learn-figure figcaption{color:var(--muted);font-size:13px}.learn-exercise{border:1px solid var(--accent);border-radius:10px;padding:10px 12px;margin:0 0 14px;display:grid;gap:8px}.learn-exercise h4{margin:0;font-size:15px;display:flex;gap:8px;align-items:center}.learn-badge{font-size:12px;color:#248a3d;background:#34c7592e;border-radius:10px;padding:1px 8px}.learn-where{margin:0;justify-self:start;font-size:13px;font-weight:600;color:var(--accent);border:1px solid var(--accent);border-radius:10px;padding:1px 8px}.learn-exercise .learn-text p:last-child{margin-bottom:0}.learn-result:empty{display:none}.learn-result{border-radius:8px;padding:8px 10px}.learn-result.ok{background:#34c75924}.learn-result.fail{background:#ff950024}.learn-result.info{background:var(--bg)}.learn-result-head{margin:0 0 6px;font-weight:600}.learn-tests{list-style:none;padding:0;margin:0;display:grid;gap:6px}.learn-test-detail{display:grid;padding-inline-start:16px;font-size:13px}.learn-error{color:#c4291c}.learn-solution summary{cursor:pointer;color:var(--accent)}.learn-solution[open]{display:grid;gap:6px;justify-items:start}.learn-checklist{list-style:none;padding:0;margin:0 0 14px;display:grid;gap:6px}.learn-checklist li{display:flex;gap:8px;align-items:baseline;justify-content:space-between}.learn-checklist li{align-items:center;justify-content:flex-start;padding:4px 6px;border-radius:8px}.learn-check-text{flex:1}.learn-checklist li[data-rating=sun]{background:color-mix(in srgb,#f5b800 14%,transparent)}.learn-checklist li[data-rating=cloud]{background:color-mix(in srgb,#8a97a8 14%,transparent)}.learn-checklist li[data-rating=umbrella]{background:color-mix(in srgb,#3b82f6 12%,transparent)}.learn-rating{display:inline-flex;gap:2px;flex:none}.learn-rating-button{min-width:34px;min-height:34px;padding:2px;font-size:1.15em;line-height:1;border-radius:8px;opacity:.45;filter:grayscale(.7)}.learn-rating-button[aria-pressed=true]{opacity:1;filter:none;border-color:var(--accent);background:var(--accent-soft)}.learn-rating-legend{display:flex;flex-wrap:wrap;gap:4px 14px;margin:0 0 8px;font-size:.9em;color:var(--muted, inherit)}.learn-review{margin:12px 0 0}.learn-review:empty{display:none}.learn-review-title{margin:0 0 4px;font-weight:700}.learn-review-icon{flex:none;width:1.6em;text-align:center}.learn-checklist li.learn-review-deviation{border:1px solid var(--accent);background:var(--accent-soft)}.learn-competences{border:1px solid var(--accent);border-radius:10px;padding:10px 12px;margin:0 0 14px;background:var(--accent-soft)}.learn-competences-title{margin:0 0 4px;font-weight:700}.learn-competences ul{margin:0;padding-left:1.3em}.learn-return{width:100%;margin:0 0 12px;border-color:var(--accent);background:var(--accent-soft)}.learn-nav+.learn-return{margin:12px 0 0}.learn-check-link{flex:none;font-size:13px}.learn-quiz fieldset{border:1px solid var(--border);border-radius:10px;padding:8px 12px 10px;margin:0 0 10px;display:grid;gap:6px}.learn-quiz legend{font-weight:600;padding:0 4px}.learn-option{text-align:start}.learn-option.right{border-color:#34c759;background:#34c75924}.learn-option.wrong{border-color:#ff3b30;background:#ff3b301a}.learn-match{display:grid;gap:6px}.learn-match-left{display:grid;grid-template-columns:8.5em minmax(0,1fr);align-items:center;gap:8px}.learn-match-select{min-width:0;width:100%;max-width:none}.learn-match-select.right{border-color:#34c759;background:#34c75924}.learn-match-select.wrong{border-color:#ff3b30;background:#ff3b301a}.learn-explanation{margin:0;color:var(--muted);font-size:13px}.learn-score{font-weight:600}.learn-nav{display:flex;justify-content:space-between;gap:8px;margin-top:18px}@media(max-width:1100px){.learn{width:340px}}@media(max-width:900px){.learn{width:300px}}.livecode{display:none;flex:0 1 auto;width:420px;min-width:200px;flex-direction:column;gap:6px;padding:10px 12px 12px;background:var(--panel);border-inline-start:1px solid var(--border);min-height:0}.shell.live .livecode{display:flex}.livecode-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px}.livecode-head h2{margin:0;font-size:16px}.livecode-lang{margin-inline-start:auto;padding:2px 8px;border-radius:6px;background:var(--accent-soft);color:var(--accent);font-size:12px;font-weight:600}.livecode .learn-hide svg{transform:scaleX(-1)}.livecode .hint{margin:0}.livecode-view{flex:1;min-height:0;padding:10px 0;font-size:var(--code-size, 14px)}.livecode-view .ln{padding:0 12px;min-height:1.5em;border-inline-start:3px solid transparent}.livecode-view.selectable .ln{cursor:pointer}.livecode-view .ln.sel{background:var(--accent-soft);border-inline-start-color:var(--accent)}.livecode-view .ph{color:var(--muted);font-style:italic}.livecode-editor{flex:1;min-height:0;padding:0;font-size:var(--code-size, 14px);white-space:normal;overflow:hidden;--syn-keyword: #7f0055;--syn-string: #2a00ff;--syn-number: #986801;--syn-comment: #3f7f5f}.livecode-editor[hidden],.livecode-view[hidden],.livecode-problem[hidden]{display:none}.livecode-editor .cm-editor{height:100%;background:transparent}.livecode-editor .cm-editor.cm-focused{outline:2px solid var(--accent-soft);outline-offset:-2px;border-radius:10px}.livecode-editor .cm-scroller{font:inherit;font-family:ui-monospace,SF Mono,Menlo,Consolas,monospace;line-height:1.5}.livecode-editor .cm-gutters{background:transparent;border-inline-end:1px solid var(--border);color:var(--muted)}.livecode-editor .cm-lineNumbers .cm-gutterElement{padding:0 8px 0 10px;min-width:2ch}.livecode-editor .cm-activeLineGutter{background:transparent;color:var(--text)}.livecode-editor .cm-content{padding:10px 0;caret-color:var(--text)}.livecode-editor .cm-line{padding:0 12px;border-inline-start:3px solid transparent}.livecode-editor .cm-scopeLayer .cm-scope{border:1px solid color-mix(in srgb,var(--scope) 28%,transparent);border-left:3px solid var(--scope);border-radius:8px;background:color-mix(in srgb,var(--scope) 9%,#fff)}.livecode-editor .cm-scopeLayer .cm-scope-class{--scope: #34c47c}.livecode-editor .cm-scopeLayer .cm-scope-method{--scope: #f2b100}.livecode-editor .cm-scopeLayer .cm-scope-loop{--scope: #ec5fa6}.livecode-editor .cm-scopeLayer .cm-scope-if{--scope: #3b9cf0}.livecode-editor .cm-scopeLayer .cm-scope-try{--scope: #9a7cf0}:root.no-code-scopes .livecode-editor .cm-scopeLayer .cm-scope:not(.cm-scope-sel){display:none}:root:not(.no-code-scopes) .ns-scope-method{fill:color-mix(in srgb,#f2b100 14%,#fff)}:root:not(.no-code-scopes) .ns-scope-loop{fill:color-mix(in srgb,#ec5fa6 14%,#fff)}:root:not(.no-code-scopes) .ns-scope-if{fill:color-mix(in srgb,#3b9cf0 14%,#fff)}:root:not(.no-code-scopes) .palette-item[data-scope=method]{background:color-mix(in srgb,#f2b100 14%,#fff)}:root:not(.no-code-scopes) .palette-item[data-scope=loop]{background:color-mix(in srgb,#ec5fa6 14%,#fff)}:root:not(.no-code-scopes) .palette-item[data-scope=if]{background:color-mix(in srgb,#3b9cf0 14%,#fff)}.livecode-editor .cm-scopeLayer .cm-scope-sel{background:transparent;border:2px solid var(--accent);box-shadow:0 0 0 3px var(--accent-faint)}.livecode-editor .cm-line.cm-debug-line{background:#ffd60a59;border-inline-start-color:#e0a800}.livecode-editor .cm-breakpoint-gutter .cm-gutterElement,.livecode-editor .cm-lineNumbers .cm-gutterElement{cursor:pointer}.livecode-editor .cm-breakpoint-gutter .cm-gutterElement{display:flex;align-items:center;justify-content:center;width:14px;padding-inline-start:4px}.livecode-editor .cm-breakpoint{display:inline-block;width:10px;height:10px;border-radius:50%;background:#d33}.livecode-editor .cm-breakpoint-gutter .cm-gutterElement:not(:has(.cm-breakpoint)):hover:before{content:"";width:10px;height:10px;border-radius:50%;background:#dd33334d}.livecode-debug{flex:none;max-height:30%;overflow-y:auto}.livecode-debug[hidden]{display:none}.livecode-debug h2{margin:0 0 4px;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.livecode-vars tr.changed td{animation:var-changed 1.6s ease-out;font-weight:700}@keyframes var-changed{0%{background:#ffd60ab3}to{background:transparent}}.livecode-editor .cm-ph,.livecode-editor .cm-ph *{color:var(--muted)!important;font-style:italic;font-weight:400!important}.livecode-editor .cm-err{text-decoration:underline wavy #d33;text-decoration-skip-ink:none;text-underline-offset:3px}.livecode-editor .cm-selectionBackground,.livecode-editor .cm-focused .cm-selectionBackground{background:color-mix(in srgb,var(--accent) 25%,transparent)!important}.livecode-editor .cm-matchingBracket{background:color-mix(in srgb,var(--accent) 20%,transparent);outline:1px solid color-mix(in srgb,var(--accent) 50%,transparent)}.cm-tooltip.cm-tooltip-autocomplete{border:1px solid var(--border);border-radius:8px;background:var(--panel);box-shadow:0 4px 16px #0000001f;overflow:hidden}.cm-tooltip.cm-tooltip-autocomplete>ul{font:14px/1.4 ui-monospace,SF Mono,Menlo,Consolas,monospace;max-height:16em}.cm-tooltip.cm-tooltip-autocomplete>ul>li{padding:4px 10px}.cm-tooltip.cm-tooltip-autocomplete>ul>li[aria-selected]{background:var(--accent);color:#fff}.cm-tooltip-autocomplete .cm-completionDetail{margin-inline-start:12px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-style:normal;color:var(--muted)}.cm-tooltip-autocomplete li[aria-selected] .cm-completionDetail{color:#ffffffd9}.livecode-run{padding:3px 10px;font-size:13px;margin-inline-start:6px}.console{display:flex;flex:none;flex-direction:column;gap:6px;height:180px;min-height:80px;padding:6px 10px 8px;background:var(--bg);border:1px solid var(--border);border-radius:8px}.console[hidden],.console-resizer[hidden]{display:none}.console-head{display:flex;align-items:center;gap:8px}.console-head h2{margin:0;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.console-hide{margin-inline-start:auto;padding:0 8px;font-size:14px}.console-resizer{flex:none;height:10px;margin-block:-5px;cursor:row-resize;touch-action:none;position:relative}.console-resizer:after{content:"";position:absolute;inset-inline:0;top:4px;height:2px}.console-resizer:hover:after,.console-resizer:focus-visible:after,.console-resizer.dragging:after{background:var(--accent)}.console-resizer:focus-visible{outline:none}.livecode-console-lines{flex:1;min-height:0;overflow:auto;font-size:var(--code-size, 14px);white-space:pre-wrap}.livecode-console-lines .typed{color:var(--accent)}.livecode-console-lines .pending:after{content:"▌";color:var(--accent);animation:blink 1s steps(1) infinite}@keyframes blink{50%{opacity:0}}.livecode-console-input{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.livecode-console-input[hidden]{display:none}.livecode-console-input label{display:flex;flex:1;align-items:center;gap:6px;min-width:0;font-size:var(--code-size, 14px)}.livecode-console-input input{flex:1;min-width:60px;padding:4px 8px;font:inherit}.livecode-console-error,.livecode-console-notice{margin:0;font-size:13px;color:var(--muted)}.livecode-console-error{flex-basis:100%;color:#c62828}.livecode-console-notice.error{color:#c62828}.livecode-problem{margin:0;min-height:1.4em;font-size:13px;color:#c62828}.live-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.shell.live .live-resizer{display:block}.live-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.live-resizer:hover:after,.live-resizer:focus-visible:after,.shell.resizing .live-resizer:after{background:var(--accent)}.live-resizer:focus-visible{outline:none}@media(max-width:1100px){.livecode{width:340px}}@media(max-width:700px){.shell.learning .learn-resizer,.shell.live .live-resizer,.shell.files-open .files-resizer{display:none}.shell .files{width:auto!important;max-height:40vh;border-inline-end:none;border-bottom:1px solid var(--border)}.shell .learn,.shell .livecode,.columns>.app{width:auto!important;min-width:0}.livecode{height:40vh;height:40dvh;border-inline-start:none;border-top:1px solid var(--border)}.learn-rail{flex-direction:row;justify-content:center;width:auto;padding:4px 0;border-inline-end:none;border-bottom:1px solid var(--border)}.learn-rail span{writing-mode:horizontal-tb}.live-rail{border-inline-start:none;border-bottom:none;border-top:1px solid var(--border)}.columns{flex-direction:column}.editor-rail{border-inline-start:none;border-bottom:1px solid var(--border)}.learn{width:auto;height:45vh;height:45dvh;border-inline-end:none;border-bottom:1px solid var(--border)}.columns>.app,.shell.editor-hidden .livecode{flex:1;min-height:0;height:auto}}@media print{@page{margin:12mm}body>*:not(.print-sheet){display:none!important}body{background:#fff!important}.print-sheet{display:block}.print-sheet svg{display:block;width:100%;height:auto;max-height:100vh}}.learn .term{text-decoration:underline dotted var(--accent);text-decoration-thickness:2px;text-underline-offset:3px;cursor:help;border-radius:3px}.learn .term:focus-visible,.learn .term[aria-expanded=true]{outline:none;background:var(--accent-soft)}.term-tip{position:fixed;z-index:1000;max-width:min(300px,calc(100vw - 16px));padding:8px 10px;background:var(--panel);color:var(--text);border:1px solid var(--border);border-radius:8px;box-shadow:0 4px 16px #0000002e;font-size:14px;line-height:1.4}.term-tip[hidden]{display:none}.learn .ui-pointer{color:var(--accent);font-weight:600;border-bottom:2px solid var(--accent-soft);cursor:pointer;border-radius:3px}.learn .ui-pointer:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.ui-spot{outline:3px solid var(--accent)!important;outline-offset:-3px;box-shadow:inset 0 0 0 9999px var(--accent-faint);animation:ui-spot-pulse 1.2s ease-in-out infinite}@keyframes ui-spot-pulse{50%{outline-color:var(--accent-glow)}}@media(prefers-reduced-motion:reduce){.ui-spot{animation:none}}.learn-graphic{display:block;width:100%;max-width:440px;height:auto;margin:0 auto;border-radius:8px;border:1px solid var(--border)}.learn-graphic-toggle{display:block;width:100%;padding:0;border:0;background:none;cursor:zoom-in}.learn-graphic-toggle[aria-pressed=true]{cursor:zoom-out}.learn-graphic-hint{margin:4px 0 0;text-align:center;font-size:.85em;color:var(--muted)}.lesson-table{overflow-x:auto;margin:8px 0}.lesson-table table{border-collapse:collapse;font-size:13px;font-variant-numeric:tabular-nums}.lesson-table th,.lesson-table td{border:1px solid var(--border);padding:3px 8px;text-align:start;white-space:nowrap}.lesson-table th{background:var(--bg)}.learn-hints .lesson-note{margin-top:8px}.learn-teacher{margin-top:24px;border-top:1px solid var(--border);padding-top:12px}.learn-teacher summary{cursor:pointer;color:var(--muted)}.learn-teacher input{flex:1;min-width:0}.shell.editor-hidden:not(.live):not(.learning) .files{flex:1 1 0;width:auto!important}.livecode-swing{height:380px}.livecode-swing[hidden]{display:none}.livecode-swing-display{position:relative;flex:1;min-height:0;overflow:hidden;border-radius:6px;background:#e9ecf0}.learn-caesar-stage{display:flex;flex-direction:column;align-items:center;gap:8px}.learn-caesar-disc{width:min(100%,320px);touch-action:none;user-select:none;-webkit-user-select:none}.learn-caesar-disc text{font:600 19px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.learn-caesar-disc .outer-disc{fill:#f3e6c8;stroke:#8a6d3b;stroke-width:3}.learn-caesar-disc .outer-letters text{fill:#3d2f14;cursor:pointer}.learn-caesar-disc .inner{cursor:grab;transition:transform .25s ease}.learn-caesar-disc .inner.dragging{cursor:grabbing;transition:none}.learn-caesar-disc .inner-disc{fill:#6b4f2a;stroke:#3d2f14;stroke-width:2}.learn-caesar-disc .inner-letters text{fill:#fff8e8}.learn-caesar-disc .tick{stroke:#8a6d3b;stroke-width:1;opacity:.6}.learn-caesar-disc .hub{fill:#f3e6c8;stroke:#3d2f14;stroke-width:2}.learn-caesar-disc .window{fill:var(--accent-soft);stroke:var(--accent);stroke-width:2.5}.learn-caesar-disc .marked text{fill:var(--accent);font-size:23px}.learn-caesar-disc .inner-letters .marked text{fill:#ffd54a}.learn-caesar-disc .key{font-size:40px;font-weight:700;fill:#3d2f14}.learn-caesar-disc .key-label{font-size:15px;fill:#6e5a33}.learn-caesar-controls,.learn-caesar-mode{display:flex;justify-content:center;gap:8px}.learn-caesar-controls button{min-width:56px;font-size:1.05em}.learn-caesar-mode{margin:10px 0 6px}.learn-caesar-mode button.active{background:var(--accent);border-color:var(--accent);color:#fff}.learn-caesar-fields{display:grid;gap:8px}.learn-caesar-fields label,.learn-caesar-fields>div{display:grid;gap:3px;color:var(--muted);font-size:.9em}.learn-caesar-fields input,.learn-caesar-output{font:600 1.15em ui-monospace,Menlo,Consolas,monospace;letter-spacing:.08em;padding:6px 8px;border:1px solid var(--border);border-radius:8px;color:var(--text);background:var(--panel);overflow-wrap:anywhere}.learn-caesar-output{background:var(--bg)}.learn-rescue-path{display:flex;align-items:center;gap:6px;margin:8px 0 2px}.learn-rescue-ludwig{width:32px;height:32px;border-radius:50%;flex:none}.learn-rescue-dot{flex:1;height:6px;max-width:48px;border-radius:3px;background:var(--border);transition:background .3s}.learn-rescue-dot.done{background:#15803d}.learn-rescue-tower{position:relative;font-size:34px;line-height:1;margin-inline-start:auto}.learn-rescue-zora,.learn-rescue-fox{position:absolute;font-size:15px}.learn-rescue-zora{top:-4px;left:50%;transform:translate(-50%)}.learn-rescue-fox{bottom:-2px;right:-12px;transition:transform .8s,opacity .8s}.learn-rescue.freed .learn-rescue-fox{transform:translate(60px);opacity:0}.learn-rescue.freed .learn-rescue-zora{display:none}.learn-rescue-free{font-size:24px;line-height:1;animation:learn-rescue-jump .6s ease-out 3}@keyframes learn-rescue-jump{50%{transform:translateY(-12px)}}.learn-rescue-answer{display:flex;gap:8px;align-items:center}.learn-rescue-number{width:6ch;font-size:1.1em;padding:6px 8px;text-align:center}.learn-rescue-label{margin:14px 0 4px;color:var(--muted);font-size:.9em}.learn-rescue-alphabet{display:flex;flex-wrap:wrap;gap:2px;margin-bottom:12px}.learn-rescue-letter{display:inline-flex;flex-direction:column;align-items:center;min-width:22px;padding:2px 0;border-radius:4px;background:var(--bg)}.learn-rescue-letter small{font-size:10px;color:var(--muted)}.learn-rescue-letter.hit{background:#fde68a;outline:2px solid #d97706}.learn-rescue-charat{font-weight:600}.learn-rescue-moved{font-weight:400!important}.learn-rescue-word{font:inherit;padding:1px 4px;border:1px solid var(--accent);border-radius:4px}.learn-rescue-gate{padding:8px 0;margin-bottom:8px}.learn-cw{--cw-cell: 30px;display:flex;flex-wrap:wrap;gap:12px 20px;margin-bottom:10px}.learn-cw-grid{display:grid;gap:2px}.learn-cw-cell{position:relative;width:var(--cw-cell);height:var(--cw-cell)}.learn-cw-cell input{width:100%;height:100%;box-sizing:border-box;padding:0;border:1px solid #6e6e73;border-radius:3px;background:#fff;color:#1c1c1e;text-align:center;font:600 16px/1 ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase}.learn-cw-cell input:disabled{opacity:1;-webkit-text-fill-color:#1c1c1e}.learn-cw-cell.key input{background:#fde68a}.learn-cw-cell.given input{color:#1d4ed8;-webkit-text-fill-color:#1d4ed8}.learn-cw-cell.arrived input{animation:learn-cw-arrive .6s ease-out}.learn-cw-cell input.wrong{border-color:#b91c1c;background:#fee2e2}@keyframes learn-cw-arrive{0%{transform:scale(1.6)}}.learn-cw-number,.learn-cw-keyindex{position:absolute;font-size:8px;line-height:1;pointer-events:none;color:#6e6e73;z-index:1}.learn-cw-number{top:2px;left:2px}.learn-cw-keyindex{bottom:2px;right:2px;color:#b45309}.learn-cw-keyword{margin:8px 0 0;font-weight:600}.learn-cw-keybox{display:inline-block;width:22px;height:24px;margin-inline-end:2px;border-bottom:2px solid #d97706;background:#fef3c7;text-align:center;line-height:24px;white-space:pre}.learn-cw-cluebox{flex:1;min-width:200px}.learn-cw-clues{margin:4px 0 10px;padding-inline-start:24px}.learn-cw-clues li{cursor:pointer}@media(max-width:380px){.learn-cw{--cw-cell: 28px}}.learn-cloze{border:2px solid var(--accent);border-radius:12px;padding:12px 14px;margin:0 0 14px}.learn-cloze-title{display:block;font-size:1.05em;margin-bottom:4px}.learn-cloze p{margin:0 0 8px}.learn-cloze-hint{color:var(--muted);font-size:.9em}.learn-cloze-code{margin:0 0 10px;padding:8px 10px;border-radius:8px;background:var(--bg, #f2f2f7);font-size:13px;line-height:1.9;overflow-x:auto}.learn-cloze-code .ln{white-space:pre;min-height:1.9em}.learn-cloze-gap{font-size:13px;padding:1px 3px;margin:0 1px;min-width:0;max-width:none;border:1px solid #8e8e93;border-bottom-width:2px;border-radius:4px;background:#fff;color:#1c1c1e;text-align:center}.learn-cloze-gap.right{border-color:#34c759;background:#34c75924}.learn-cloze-gap.wrong{border-color:#ff3b30;background:#ff3b301a}.learn-cloze-gap.shown{border-color:#d97706;background:#fef3c7}.learn-cloze-gap:disabled{opacity:1;-webkit-text-fill-color:currentColor}.learn-cloze-actions{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.learn-cloze-check{font-weight:600}.learn-cloze-status:empty{display:none}.learn-cloze-status{padding:8px 12px;border-radius:8px;font-weight:600}.learn-cloze-status.right{background:#dcfce7}.learn-cloze-status.wrong{background:#fee2e2}.learn-pap{border:2px solid var(--accent);border-radius:12px;padding:12px 14px;margin:0 0 14px}.learn-pap-title{display:block;font-size:1.05em;margin-bottom:4px}.learn-pap p{margin:0 0 8px}.learn-pap-hint{color:var(--muted);font-size:.9em}.learn-pap-plan{display:block;width:100%;max-width:420px;margin:0 auto 10px;background:#fff;border-radius:8px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;fill:#1c1c1e}.learn-pap-slot{cursor:pointer;outline:none}.learn-pap-slot .learn-pap-shape{stroke:#8e8e93;stroke-width:2}.learn-pap-slot:focus-visible .learn-pap-shape,.learn-pap-slot.over .learn-pap-shape{stroke:var(--accent);stroke-width:3}.learn-pap-slot.right .learn-pap-shape{stroke:#34c759;stroke-width:3}.learn-pap-slot.wrong .learn-pap-shape{stroke:#ff3b30;stroke-width:3}.learn-pap-slot.shown .learn-pap-shape{stroke:#d97706}.learn-pap-legend{display:grid;grid-template-columns:auto 1fr;gap:4px 10px;align-items:center;max-width:420px;margin:0 auto 12px;padding:8px 10px;border-radius:8px;background:var(--bg, #f2f2f7);font-size:.9em}.learn-pap-legend dt{line-height:0}.learn-pap-legend dd{margin:0}.learn-pap-work{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);gap:8px;align-items:start;margin-bottom:10px}.learn-pap-work.done{grid-template-columns:minmax(0,1fr)}.learn-pap-left .learn-pap-plan{margin-bottom:8px}.learn-pap-tray{position:sticky;top:0;display:flex;flex-direction:column;align-items:center;gap:4px;max-height:100vh;overflow-y:auto;padding:6px 2px;border-radius:8px;background:var(--bg, #f2f2f7)}.learn-pap-tray:empty,.learn-pap-tray:not(:has(.learn-pap-card:not([hidden]))){display:none}.learn-pap-card svg{max-width:100%;height:auto}.learn-pap-card{padding:2px;max-width:100%;border:2px solid transparent;border-radius:10px;background:none;line-height:0;touch-action:none;cursor:grab;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;fill:#1c1c1e}.learn-pap-card.selected{border-color:var(--accent);background:var(--accent-soft)}.learn-pap-card.dragging{opacity:.3}.learn-pap-ghost{position:fixed;z-index:1000;pointer-events:none;transform:translate(-50%,-50%);opacity:.9}.learn-pap-actions{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.learn-pap-check{font-weight:600}.learn-pap-status:empty{display:none}.learn-pap-status{padding:8px 12px;border-radius:8px;font-weight:600}.learn-pap-status.right{background:#dcfce7}.learn-pap-status.wrong{background:#fee2e2}.learn-mark{color:inherit;padding:0 3px;border-radius:3px}.learn-mark.blau{background:#e4f1fd}.learn-mark.orange{background:#ffedd5}.learn-mark.gruen{background:#dcfce7}.learn-mark.gelb{background:#fdf4db}.learn-mark.rosa{background:#fce9f2}.startup-error{max-width:520px;margin:15vh auto 0;padding:0 16px;font:16px/1.5 system-ui,-apple-system,sans-serif;color:var(--text)}.startup-error h1{font-size:22px}.startup-error button{font-size:16px;padding:8px 16px}.startup-error pre{margin-top:24px;color:var(--muted);font-size:12px;white-space:pre-wrap}.visubot-stage{position:relative;height:280px;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:linear-gradient(#dfe9f3,#f6f3ec)}.visubot-live{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 8px;font-size:12px;color:var(--muted)}.visubot-live:empty{display:none}.visubot-live.connected{color:#0f8a5f;font-weight:600}.visubot-worlds{display:flex;gap:6px;margin:0 0 6px}.visubot-worlds button.active{background:var(--accent);border-color:var(--accent);color:#fff}.visubot-canvas{display:block;width:100%;height:100%;touch-action:none}.visubot-status{font-size:12px;color:var(--muted);margin:6px 0 0}.visubot-controls{margin-top:8px;font-size:13px}.visubot-controls summary{cursor:pointer;font-weight:600}.visubot-controls .hint{color:var(--muted);font-size:12px;margin:4px 0 6px}.visubot-controls label{display:grid;grid-template-columns:9.5em 1fr 2.5em;align-items:center;gap:6px;margin:2px 0}.visubot-controls output{text-align:end;font-variant-numeric:tabular-nums}.visubot-presses{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}.visubot-presses button{min-width:2.2em}.visubot-presses button.pressed{background:var(--accent);border-color:var(--accent);color:#fff}.visubot-check{margin-top:8px;font-size:13px}.visubot-check summary{cursor:pointer;font-weight:600}.visubot-check .hint{color:var(--muted);font-size:12px;margin:4px 0 6px}.visubot-check-sensors{margin-top:8px;border-collapse:collapse;font-variant-numeric:tabular-nums}.visubot-check-sensors th{text-align:start;font-weight:400;padding:1px 12px 1px 0}.palette-visubot-title{font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:14px 0 6px}.palette-sensor{display:flex;flex-direction:column;align-items:flex-start;gap:2px;border-style:dashed}.palette-sensor code{font-size:12px;color:var(--muted)}.palette-visubot .palette-item{border-color:#a7a0d3;background:color-mix(in srgb,#a7a0d3 16%,transparent)}.visubot-model{margin:12px 0}.visubot-model .visubot-stage{height:300px}.visubot-model-hint{font-size:13px;margin:4px 0 0}.visubot-part-label{position:absolute;pointer-events:none;padding:2px 8px;border-radius:6px;background:#14181ed9;color:#fff;font-size:13px;white-space:nowrap;z-index:1}.robot-part-link{text-decoration:underline 2px #f2b705;text-underline-offset:3px;cursor:pointer}.robot-part-link:hover,.robot-part-link:focus-visible{background:color-mix(in srgb,#f2b705 25%,transparent);outline:none}.visubot-quiz-question{font-size:15px;margin:12px 0 6px}.visubot-quiz-question.done{color:var(--success, #2f9e44)}.visubot-quiz-feedback{min-height:1.4em;margin:6px 0}.visubot-quiz-feedback.right{color:var(--success, #2f9e44)}.visubot-quiz-feedback.wrong{color:var(--danger, #c92a2a)}.diagram-tools .mbot-link{margin-inline-start:auto;height:30px;padding:0 10px;white-space:nowrap}.diagram-tools .mbot-link:not([hidden])+.sim-toggle,.diagram-tools .mbot-upload:not([hidden])+.sim-toggle{margin-inline-start:6px}.diagram-tools .mbot-upload{margin-inline-start:6px;height:30px;padding:0 10px;white-space:nowrap}.mbot-upload-steps{margin:0 0 12px;padding-inline-start:22px;line-height:1.5}.mbot-upload progress{width:100%;height:10px}.mbot-upload-status.done{color:var(--success, #2f9e44);font-weight:600}.settings-mbot-link{display:grid;gap:4px;margin-top:8px}.settings-mbot-link small{font-size:12px;color:var(--muted)}.world-chooser{margin-bottom:4px}.world-hint{display:block;font-size:12px;color:var(--muted);margin-bottom:8px}.start-world{margin-bottom:14px}.robotpreview,.robotpreview-rail,.preview-resizer{display:none}.shell.robot-world.preview .robotpreview{display:flex}.shell.robot-world:not(.preview) .robotpreview-rail{display:flex;border-inline-end:none;border-inline-start:1px solid var(--border)}.robotpreview-rail svg{transform:scaleX(-1)}.shell.robot-world.preview:not(.preview-stacked) .preview-resizer{display:block}.robotpreview{flex:0 1 auto;width:360px;min-width:220px;flex-direction:column;gap:6px;padding:10px 12px 12px;background:var(--panel);border-inline-start:1px solid var(--border);min-height:0;overflow-y:auto}.robotpreview .hint{margin:0;font-size:.85em;color:var(--muted, inherit)}.robotpreview .robotpreview-stage{flex:1 1 auto;height:auto;min-height:160px}.robotpreview .robotpreview-status{margin:0;min-height:1.3em}.robotpreview-height{display:none}.robotpreview.simulation>.visubot-worlds,.robotpreview.simulation>.robotpreview-stage,.robotpreview.simulation>.robotpreview-status,.robotpreview.simulation .robotpreview-play{display:none}.robotpreview .visubot-viewport{display:flex;flex:1 1 auto;flex-direction:column;min-height:0}.robotpreview .visubot-viewport .visubot-stage{flex:1 1 auto;height:auto;min-height:160px}.visubot-elsewhere{display:none;margin:0 0 8px;font-size:12px;color:var(--muted)}.visubot:not(:has(>.visubot-viewport)) .visubot-elsewhere{display:block}.shell.preview-stacked .robotpreview{flex:0 0 auto;width:auto!important;height:320px;min-width:0;margin:4px -12px -12px;padding-top:0;border-inline-start:none;border-top:1px solid var(--border);overflow:visible}.shell.preview-stacked .robotpreview-height{display:block;height:10px;margin:-5px 0 0;cursor:row-resize;touch-action:none;position:relative}.robotpreview-height:after{content:"";position:absolute;inset-inline:0;top:4px;height:2px;background:transparent;transition:background .15s}.robotpreview-height:hover:after,.robotpreview-height:focus-visible:after,.shell.resizing .robotpreview-height:after{background:var(--accent)}.robotpreview-height:focus-visible{outline:none}.preview-resizer{flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.preview-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.preview-resizer:hover:after,.preview-resizer:focus-visible:after,.shell.resizing .preview-resizer:after{background:var(--accent)}.preview-resizer:focus-visible{outline:none}.palette-group{grid-column:1 / -1}.palette-group button{display:flex;align-items:center;gap:6px;width:100%;margin-top:4px;padding:2px 0;border:none;background:none;color:var(--muted);font-size:12px;font-weight:600;text-align:start;cursor:pointer}.palette-group button:before{content:"▾";transition:transform .15s}.palette-group button[aria-expanded=false]:before{transform:rotate(-90deg)}.palette-item[hidden]{display:none}.editor-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.editor-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.editor-resizer:hover:after,.editor-resizer:focus-visible:after,.shell.resizing .editor-resizer:after{background:var(--accent)}.editor-resizer:focus-visible{outline:none}.shell.code-main.live:not(.editor-hidden) .editor-resizer{display:block}.shell.code-main.live:not(.editor-hidden) .live-resizer{display:none}.shell.code-main.live:not(.editor-hidden) .app{flex:0 1 auto;width:460px;min-width:300px}.shell.code-main.live:not(.editor-hidden) .livecode{flex:1 1 0;width:auto!important;min-width:0}.shell.code-main.live:not(.editor-hidden) .livecode{order:1}.shell.code-main.live:not(.editor-hidden) .editor-resizer{order:2}.shell.code-main.live:not(.editor-hidden) .app{order:3;border-inline-start:1px solid var(--border)}.shell.code-main.live:not(.editor-hidden) .live-rail,.shell.code-main.live:not(.editor-hidden) .preview-resizer,.shell.code-main.live:not(.editor-hidden) .robotpreview,.shell.code-main.live:not(.editor-hidden) .robotpreview-rail{order:4}[data-action=swap-main]{font-size:16px;line-height:1}[data-action=swap-main][aria-pressed=true]{color:var(--accent)}.palette-resizer{grid-area:pal;justify-self:end;width:10px;margin-inline-end:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.palette-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.palette-resizer:hover:after,.palette-resizer:focus-visible:after,.shell.resizing .palette-resizer:after{background:var(--accent)}.palette-resizer:focus-visible{outline:none}.app.simulating .palette-resizer{display:none}:root.visuobject-theme{--bg: #edf4f6;--text: #17292e;--muted: #566a70;--border: #cddde1;--accent: #0e7c86;--accent-soft: rgba(14, 124, 134, .2);--accent-faint: rgba(14, 124, 134, .08);--accent-glow: rgba(14, 124, 134, .35)}.visuobject-obj,.visuobject .brand .logo{color:var(--accent)}.shell.visuobject button.text-button{padding:5px 10px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);font:inherit;cursor:pointer}.shell.visuobject button.text-button:hover{border-color:var(--accent);color:var(--accent)}:root.visuobject-theme{--vo-bar: #e3edf0}.vo-columns{display:grid;grid-template-columns:var(--vo-cols, 260px 1px minmax(0, 45fr) 1px minmax(0, 55fr));flex:1;min-height:0;border-top:1px solid var(--border)}.vo-columns.vo-resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.vo-pane{display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--panel)}.vo-pane.collapsed>:not(.vo-strip){display:none}.vo-strip{display:none;flex:1;align-items:center;justify-content:center;padding:12px 0;border:0;background:var(--vo-bar);color:var(--muted);font:600 14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;writing-mode:vertical-rl;cursor:pointer}.vo-pane.collapsed>.vo-strip{display:flex}.vo-strip:hover,.vo-strip:focus-visible{color:var(--accent);background:var(--accent-faint);outline:none}.vo-splitter{position:relative;z-index:4;background:var(--border);cursor:col-resize;touch-action:none;outline:none}.vo-splitter:after{content:"";position:absolute;top:0;right:-4px;bottom:0;left:-4px}.vo-splitter:hover,.vo-splitter:focus-visible,.vo-resizing .vo-splitter{background:var(--accent)}.vo-splitter.fixed{cursor:default;background:var(--border)}.vo-bar{display:flex;flex-wrap:wrap;align-items:stretch;min-height:40px;background:var(--vo-bar);border-bottom:1px solid var(--border);font-size:14px}.vo-bar-title{display:flex;flex:1;align-items:center;margin:0;text-transform:none;letter-spacing:normal;padding:0 12px;font-size:14px;font-weight:600;color:var(--text)}.vo-bar-actions{display:flex;flex:0 1 auto;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px;padding:4px 4px 4px 0}.shell.visuobject .vo-bar button.text-button{padding:2px 8px;border-radius:6px}.vo-collapse{padding:0 12px;border:0;background:none;color:var(--muted);font-size:16px;font-weight:700;cursor:pointer}.vo-collapse:hover,.vo-collapse:focus-visible{color:var(--accent)}.vo-tabs{display:flex;flex:1;min-width:0;overflow-x:auto}.vo-tab{display:flex;align-items:stretch;border-right:1px solid var(--border);border-bottom:3px solid transparent}.vo-tab.active{background:var(--panel);border-bottom-color:var(--accent)}.vo-tab [role=tab]{padding:0 4px 0 14px;border:0;background:none;color:var(--text);font:13px ui-monospace,SF Mono,Menlo,Consolas,monospace;white-space:nowrap;cursor:pointer}.vo-tab.active [role=tab]{font-weight:700}.vo-tab [role=tab]:hover{color:var(--accent)}.vo-tab-close{padding:0 10px 0 6px;border:0;background:none;color:var(--muted);font-size:15px;cursor:pointer;visibility:hidden}.vo-tab.active .vo-tab-close,.vo-tab:hover .vo-tab-close{visibility:visible}.vo-tab-close:hover{color:var(--accent)}.vo-tab-close .vo-dot,.vo-tab-close.unsaved .vo-x{display:none}.vo-tab-close.unsaved{visibility:visible;color:var(--text)}.vo-tab-close.unsaved .vo-dot{display:inline;font-size:11px}.vo-tab-close.unsaved:hover .vo-dot{display:none}.vo-tab-close.unsaved:hover .vo-x{display:inline}.vo-no-file{display:flex;align-items:center;padding:0 12px;color:var(--muted)}.vo-editor{flex:1;min-height:0;overflow:auto;font-size:14px}.vo-foot{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;padding:6px 12px;border-top:1px solid var(--border);background:var(--vo-bar)}.vo-hint{color:var(--muted);flex:1 1 260px}.vo-canvas{position:relative;flex:1;min-height:0;overflow:auto;background:radial-gradient(circle,var(--border) 1px,transparent 1px) 0 0 / 20px 20px;outline:none}.vo-frames{position:absolute;inset:0 auto auto 0;z-index:0;pointer-events:none;overflow:visible}.vo-package-frame{fill:#0e7c8609;stroke:var(--muted);stroke-width:1.2}.vo-package.current .vo-package-frame{stroke:var(--accent);fill:var(--accent-faint)}.vo-package-name{font:600 12px ui-monospace,SF Mono,Menlo,Consolas,monospace;fill:var(--muted)}.vo-package.current .vo-package-name{fill:var(--accent)}.vo-lines{position:absolute;inset:0 auto auto 0;z-index:3;pointer-events:none;overflow:visible}.vo-rel{stroke:var(--text);stroke-width:1.4;fill:none}.vo-rel.ghost{stroke:var(--accent);stroke-dasharray:4 4}.vo-hit{stroke:transparent;stroke-width:12;pointer-events:stroke;cursor:pointer}.vo-relation:hover .vo-rel,.vo-relation:hover .vo-diamond{stroke:var(--accent)}.vo-relation.selected .vo-rel,.vo-relation.selected .vo-diamond{stroke:var(--accent);stroke-width:2.4}.vo-relation.selected .vo-label-svg{fill:var(--accent)}.vo-diamond{fill:var(--panel);stroke:var(--text);stroke-width:1.4}.vo-diamond.filled{fill:var(--text)}.vo-relation.selected .vo-diamond.filled{fill:var(--accent)}.vo-label-svg.name{font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-style:italic;fill:var(--text)}.vo-rel.dashed{stroke-dasharray:6 4}.vo-hollow,.vo-open{fill:none;stroke:var(--text);stroke-width:1.4}.vo-label-svg{font:12px ui-monospace,SF Mono,Menlo,Consolas,monospace;fill:var(--muted);paint-order:stroke;stroke:var(--panel);stroke-width:4px}.vo-empty{margin:24px;max-width:40ch;color:var(--muted)}.vo-status{margin:0;color:#b3261e}.vo-status:empty{display:none}.vo-status.hint{color:var(--accent)}.uml-class{position:absolute;left:16px;top:16px;min-width:150px;background:var(--panel);border:1.5px solid var(--text);font:13px/1.5 ui-monospace,SF Mono,Menlo,Consolas,monospace;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.uml-connect{position:absolute;right:-11px;top:50%;width:20px;height:20px;margin-top:-10px;padding:0;border:2px solid var(--panel);border-radius:50%;background:var(--accent);box-shadow:0 1px 4px #00000040;cursor:crosshair;touch-action:none}.uml-connect:after{content:"";position:absolute;top:5px;right:4px;bottom:5px;left:5px;background:#fff;clip-path:polygon(0 35%,55% 35%,55% 0,100% 50%,55% 100%,55% 65%,0 65%)}.uml-class.drop{border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}.vo-relmenu{position:absolute;z-index:10;display:grid;min-width:220px;padding:6px;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #0000002e;font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-relmenu p{margin:2px 8px 6px;color:var(--muted);font-size:12px}.vo-relmenu button{display:flex;align-items:center;gap:10px;padding:6px 8px;border:0;border-radius:6px;background:none;color:var(--text);font:inherit;text-align:left;cursor:pointer}.vo-relmenu button:hover,.vo-relmenu button:focus-visible{background:var(--accent-faint);color:var(--accent);outline:none}.vo-relicon{flex:none}.vo-palette{display:flex;flex-wrap:wrap;align-items:stretch;gap:2px;padding:4px 6px;border-bottom:1px solid var(--border);background:var(--panel)}.vo-palette-sep{width:1px;margin:4px;background:var(--border)}.vo-tool{display:grid;justify-items:center;gap:1px;min-width:44px;padding:3px 3px 2px;border:1px solid transparent;border-radius:7px;background:none;color:var(--text);font:11px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer;touch-action:none;-webkit-user-select:none;user-select:none}.vo-tool:hover{background:var(--accent-faint);color:var(--accent)}.vo-tool[aria-pressed=true]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}.vo-tool[data-tool=class],.vo-tool[data-tool=interface]{cursor:grab}.vo-tool-ghost{position:fixed;z-index:1000;display:grid;justify-items:center;min-width:120px;padding:4px 10px 14px;margin:-14px 0 0 -60px;border:1.5px dashed var(--accent);background:#ffffffe6;font:13px ui-monospace,SF Mono,Menlo,Consolas,monospace;pointer-events:none}.vo-tool-ghost small{color:var(--muted);font-size:11px}.vo-canvas:not([data-tool=select])[data-tool]{cursor:crosshair}.vo-canvas:not([data-tool=select])[data-tool] .uml-class{cursor:crosshair}.vo-canvas:not([data-tool=select])[data-tool] .uml-class:hover,.uml-class.source{border-color:var(--accent)}.uml-class.source{box-shadow:0 0 0 4px var(--accent-soft)}.vo-stage{position:relative;display:flex;flex:1;min-height:0}.vo-stage .vo-canvas{flex:1}.vo-hsplit{flex:0 0 6px;margin:-3px 0;position:relative;z-index:5;cursor:row-resize;touch-action:none}.vo-hsplit:after{content:"";position:absolute;left:0;right:0;top:2px;height:2px;background:transparent}.vo-hsplit:hover:after,.vo-hsplit:focus-visible:after{background:var(--accent)}.vo-hsplit:focus-visible{outline:none}.vo-dock.collapsed+.vo-hsplit,.vo-hsplit:has(+.vo-dock.collapsed){cursor:default;pointer-events:none}.vo-dock{border-top:1px solid var(--border);background:var(--panel)}.vo-dock-bar{min-height:30px}.vo-dock-bar .vo-bar-title{font-size:13px}.vo-dock.collapsed .vo-inspector{display:none}.vo-inspector{display:grid;align-content:start;gap:8px;height:32vh;overflow:auto;padding:8px 12px 10px;font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-inspector-row>label.check,.vo-inspector label.check{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;padding-bottom:6px;color:var(--text);font-size:13px}.vo-inspector input[type=checkbox]{width:auto;margin:0;accent-color:var(--accent)}.vo-inspector fieldset.vo-inspector-ifaces{display:flex;flex-wrap:wrap;gap:4px 14px}.vo-inspector-empty{color:var(--muted)}.vo-inspector-row{display:flex;flex-wrap:wrap;align-items:end;gap:8px 12px}.vo-inspector-row>label{flex:1 1 160px;max-width:260px}.vo-inspector-ends{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:8px}.vo-inspector label{display:grid;gap:3px;color:var(--muted);font-size:12px}.vo-inspector input,.vo-inspector select{box-sizing:border-box;width:100%;min-width:0;padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-inspector input:focus,.vo-inspector select:focus{border-color:var(--accent);outline:2px solid var(--accent-soft)}.vo-inspector fieldset{display:grid;grid-template-columns:minmax(0,1fr) 84px;align-items:start;gap:6px;min-width:0;margin:0;padding:6px 8px 8px;border:1px solid var(--border);border-radius:8px}.vo-inspector fieldset .vo-wide{grid-column:1 / -1}.vo-reading{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px;color:var(--muted)}.vo-reading b{color:var(--text)}.shell.visuobject .vo-reading button.text-button{padding:1px 8px;font-size:12px}.vo-inspector legend{padding:0 4px;color:var(--text);font-weight:600}.vo-inspector small{color:var(--muted);font-size:11px}.vo-inspector p{margin:0}.vo-inspector-kind{font-weight:600;padding-top:4px}.shell.visuobject .vo-inspector button.vo-danger{display:inline-flex;align-items:center;justify-self:start;gap:6px;color:#b3261e}.vo-inspector .vo-danger svg{width:15px;height:15px}.vo-insp-head{position:sticky;top:-8px;z-index:1;margin-top:-8px;padding-top:8px;background:var(--panel);display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 12px;border-bottom:1px solid var(--border)}.vo-insp-head .vo-inspector-kind{padding:0}.vo-insp-tabs{display:flex;gap:2px}.shell.visuobject .vo-insp-tabs button{margin-bottom:-1px;padding:5px 12px;border:1px solid transparent;border-bottom:none;border-radius:6px 6px 0 0;background:none;color:var(--muted);font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer}.shell.visuobject .vo-insp-tabs button[aria-selected=true]{border-color:var(--border);background:var(--panel);color:var(--text);font-weight:600}.vo-members{width:100%;border-collapse:collapse}.vo-members th{padding:0 4px 3px;color:var(--muted);font-size:12px;font-weight:500;text-align:left}.vo-members td{padding:2px 4px;vertical-align:middle}.vo-members td.c{width:52px;text-align:center}.vo-members td:first-child{width:112px}.vo-members td:last-child{width:32px}.vo-members .icon svg{width:15px;height:15px}.vo-doc textarea{box-sizing:border-box;width:100%;max-width:780px;padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;resize:vertical}.vo-insp-sep{align-self:stretch;width:1px;margin:0 4px;background:var(--border)}.vo-insp-label{align-self:center;color:var(--muted);font-size:12px}.uml-class.selected{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);z-index:2}.uml-head{display:grid;justify-items:center;padding:4px 10px;font-weight:700}.uml-head small{font-weight:400;font-size:11px;color:var(--muted)}.uml-class.abstract .uml-name,.uml-member.abstract{font-style:italic}.uml-member.static{text-decoration:underline}.uml-class ul{list-style:none;margin:0;padding:3px 0;border-top:1.5px solid var(--text);min-height:12px}.uml-class.selected ul{border-top-color:var(--accent)}.uml-class li{padding:0 10px;white-space:nowrap}.uml-member.selected{background:var(--accent-soft)}.uml-add{color:var(--accent);font-style:italic;cursor:pointer;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:12px}.uml-add:hover{text-decoration:underline}.uml-input{font:inherit;padding:0 4px;margin:0 -5px;border:1px solid var(--accent);border-radius:4px;outline:none;max-width:340px}.uml-tools{display:flex;flex-wrap:wrap;gap:6px 10px;align-items:center;padding:6px 10px;border-top:1px dashed var(--border);font:12px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:default}.uml-tools label{display:inline-flex;gap:4px;align-items:center}.uml-tools button.icon svg{width:16px;height:16px}.vo-ws{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 10px 4px;font-size:13px}.vo-ws[hidden]{display:none}.vo-ws.ask{margin:8px 10px 4px;padding:10px;border:1px solid var(--accent);border-radius:8px;background:var(--bg, #fff)}.vo-ws.ask p{flex-basis:100%;margin:0}.vo-ws.ask .hint{color:var(--muted);font-size:12px;margin-bottom:4px}.vo-ws-name{display:inline-flex;align-items:center;gap:6px;margin-right:auto;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shell.visuobject .vo-ws button.text-button{padding:2px 8px;border-radius:6px}.shell.visuobject .vo-ws button.text-button.primary{background:var(--accent);border-color:var(--accent);color:#fff}.vo-lines .vo-end-hit{fill:transparent;pointer-events:all;cursor:context-menu}.vo-lines .vo-label-svg.editable{pointer-events:all;cursor:pointer}.vo-lines .vo-label-svg.editable:hover{fill:var(--accent);text-decoration:underline}.vo-lines .vo-label-svg.placeholder{fill:var(--muted);opacity:.6;font-style:italic}.vo-endpop{position:absolute;z-index:12;display:grid;gap:8px;width:min(330px,calc(100% - 16px));box-sizing:border-box;padding:10px 12px;background:var(--panel);border:1px solid var(--accent);border-radius:10px;box-shadow:0 8px 24px #00000029;font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-endpop p{margin:0}.vo-endpop label{display:grid;gap:3px;color:var(--muted);font-size:12px}.vo-endpop input{box-sizing:border-box;min-width:0;padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-endpop-row{display:flex;flex-wrap:wrap;align-items:center;gap:4px}.vo-endpop-row>span{flex-basis:100%;color:var(--muted);font-size:12px}.vo-endpop-row button{padding:2px 8px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:12px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer}.vo-endpop-row button[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:#fff}.vo-endpop-row input{width:64px}.vo-new{position:relative}.vo-new-menu{position:absolute;top:calc(100% + 4px);left:0;z-index:30;display:grid;min-width:190px;padding:4px;background:var(--panel);border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 24px #00000024}.vo-new-menu[hidden]{display:none}.vo-new-menu button{display:flex;align-items:center;gap:8px;padding:6px 8px;border:0;border-radius:6px;background:none;color:var(--text);font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;text-align:left;cursor:pointer}.vo-new-menu button:hover,.vo-new-menu button:focus-visible{background:var(--accent-soft);outline:none}.vo-badge.folder.source{box-shadow:inset 0 3px #ffffff59,inset -5px -4px #8a6d2b}.confirm-card.vo-wizard{display:grid;gap:10px;width:min(520px,100%);max-width:none;max-height:calc(100vh - 32px);overflow:auto;box-sizing:border-box;font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-wizard h2{margin:0;font-size:17px}.vo-wizard .hint{margin:0;color:var(--muted);font-size:13px}.vo-wizard>label{display:grid;grid-template-columns:130px minmax(0,1fr);align-items:center;gap:8px;color:var(--muted);font-size:13px}.vo-wizard input[type=text],.vo-wizard select{box-sizing:border-box;width:100%;min-width:0;padding:5px 7px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:inherit}.vo-wizard fieldset{margin:0;padding:6px 10px 8px;border:1px solid var(--border);border-radius:8px}.vo-wizard legend{padding:0 4px;color:var(--muted);font-size:13px}.vo-wizard-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px}.vo-wizard-row select,.vo-wizard-row input[type=text]{width:auto;flex:1 1 160px}.vo-wizard-list{display:grid;gap:4px}.vo-wizard .check{display:inline-flex;align-items:center;gap:6px}.vo-wizard code{font-size:12px}.vo-wizard-error{min-height:1em;margin:0;color:#b3261e;font-size:13px}.vo-wizard .group button.primary{background:var(--accent);border-color:var(--accent);color:#fff}@media(max-width:560px){.vo-wizard>label{grid-template-columns:1fr}}.vo-dirty{color:var(--accent)}.vo-tree-tools{display:flex;flex-wrap:wrap;gap:6px;padding:8px 10px 4px}.shell.visuobject .vo-tree-tools button.text-button{padding:2px 8px;border-radius:6px}.vo-tree{flex:1;min-height:0;overflow:auto;padding:6px;font:13px/1.3 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-tree ul{list-style:none;margin:0;padding:0}.vo-row{display:flex;align-items:center;gap:6px;min-height:28px;padding:0 6px 0 calc(4px + var(--depth, 0) * 14px);border-radius:7px;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;outline:none}.vo-row:hover{background:var(--accent-faint)}.vo-row:focus-visible{box-shadow:inset 0 0 0 2px var(--accent-soft)}.vo-row.active .vo-label{font-weight:600}.vo-row.selected{background:var(--accent-soft);color:var(--text)}.vo-twisty,.vo-twisty-space{flex:none;width:18px;height:18px}.vo-twisty{display:grid;place-items:center;padding:0;border:0;border-radius:4px;background:none;color:var(--muted);cursor:pointer}.vo-twisty svg{transition:transform .15s ease}[aria-expanded=true]>.vo-row .vo-twisty svg{transform:rotate(90deg)}.vo-twisty:hover{color:var(--accent)}.vo-label{min-width:0;overflow:hidden;text-overflow:ellipsis}.vo-type{color:var(--muted);font-size:12px;overflow:hidden;text-overflow:ellipsis}.vo-row .uml-input{margin:0;font:inherit}.vo-row-delete{margin-left:auto;visibility:hidden}.vo-tree button.vo-row-delete{width:24px;height:24px}.vo-tree button.vo-row-delete svg{width:14px;height:14px}.vo-row:hover .vo-row-delete,.vo-row.selected .vo-row-delete{visibility:visible}.vo-tree-empty{padding:6px 10px 6px 52px;color:var(--muted);font-size:12px;white-space:normal}.vo-badge{flex:none;display:inline-grid;place-items:center;width:16px;height:16px;border-radius:4px;font:700 10px/1 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#fff}.vo-badge.project{background:var(--accent);border-radius:5px;box-shadow:inset 0 -5px #0000002e}.vo-badge.project.closed{opacity:.55}.vo-badge.folder{width:17px;height:13px;border-radius:2px 4px 3px 3px;background:#e0a63b;box-shadow:inset 0 3px #ffffff59}.vo-badge.package{width:14px;height:14px;border-radius:3px;background:#b07a2a;transform:rotate(45deg) scale(.82)}.vo-badge.package.empty{background:none;border:1.5px solid #b07a2a}.vo-badge.file{background:#e66a2c;border-radius:3px 6px 3px 3px}.vo-badge.type.class{background:#2f7d32;border-radius:50%}.vo-badge.type.class.abstract{background:#6a9c3a;font-style:italic}.vo-badge.type.interface{background:#7b4fb0;border-radius:50%}.vo-badge.field,.vo-badge.method{width:9px;height:9px;margin:0 3px}.vo-badge.field{border-radius:2px}.vo-badge.method{border-radius:50%}.vo-badge.public{background:#2f9e44}.vo-badge.private{background:#d6453d}.vo-badge.protected{background:#e0a63b}.vo-badge.package.field,.vo-badge.package.method{background:#3b82c4;transform:none;border:0}.vo-badge.static{box-shadow:0 0 0 2px var(--panel),0 0 0 3px currentColor;color:var(--muted)}@media(max-width:760px){.vo-columns{grid-template-columns:1fr;grid-auto-rows:auto;overflow:auto}.vo-splitter{display:none}.vo-explorer:not(.collapsed){height:260px}.vo-code:not(.collapsed){height:320px}.vo-diagram:not(.collapsed){min-height:420px}.vo-pane{border-bottom:1px solid var(--border)}.vo-strip{writing-mode:horizontal-tb;padding:10px}}.shell.visuobject .vo-run-group button.vo-run{color:var(--accent);font-weight:600}.vo-console{display:flex;flex-direction:column;height:32vh;min-height:120px;border-top:1px solid var(--border)}.vo-console[hidden],.vo-swing[hidden]{display:none}.vo-console .vo-dock-bar{gap:10px}.vo-console-status{flex:1;color:var(--muted);font-size:12px}.vo-console-status.error{color:#b3261e}.vo-swing{display:flex;height:60%;padding:6px}.vo-console-lines{flex:1;min-height:0;overflow:auto;margin:0;padding:6px 12px;font-size:13px;white-space:pre-wrap}.uml-note{position:absolute;min-width:120px;max-width:260px;padding:8px 22px 8px 10px;background:#fffbe6;border:1.2px solid var(--text);clip-path:polygon(0 0,calc(100% - 14px) 0,100% 14px,100% 100%,0 100%);font:13px/1.45 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#17292e;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none;z-index:1}.uml-note:after{content:"";position:absolute;top:0;right:0;width:14px;height:14px;background:linear-gradient(to bottom left,transparent 50%,#e9dfae 50%);border-left:1.2px solid var(--text);border-bottom:1.2px solid var(--text)}.uml-note.selected{outline:3px solid var(--accent-soft);border-color:var(--accent);clip-path:none}.uml-note .uml-connect{z-index:2}.uml-note-text{white-space:pre-wrap;overflow-wrap:anywhere}.uml-note-text.placeholder{color:#8a8a8a;font-style:italic}.uml-note-edit{box-sizing:border-box;width:220px;border:1px solid var(--accent);background:#fffef5;font:inherit;resize:both}.vo-note-link{stroke-dasharray:5 4}.vo-canvas[hidden],.vo-palette[hidden]{display:none}.vo-diagram-switch{display:flex;gap:2px;padding:2px;border:1px solid var(--border);border-radius:8px;background:var(--panel)}.shell.visuobject .vo-diagram-switch button{padding:3px 10px;border:none;border-radius:6px;background:none;color:var(--muted);font:600 13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer}.shell.visuobject .vo-diagram-switch button[aria-selected=true]{background:var(--accent);color:#fff}.vo-obj-palette{align-items:center;gap:8px;padding:6px 10px}.vo-obj-new{display:flex;align-items:center;gap:6px;font-size:13px}.vo-obj-new select{padding:3px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.uml-object .uml-objname{text-decoration:underline;font-weight:600}.uml-object.unknown{border-style:dashed}.uml-object .uml-member.changed,.vo-objlink.changed{animation:vo-changed 1.2s ease-out}.uml-object .uml-member.changed{background:#fff3b0}@keyframes vo-changed{0%{background:#ffe066}}.vo-obj-values td:first-child{width:auto;white-space:nowrap}.vo-obj-values td:last-child{width:50%}.vo-dbg-controls{display:inline-flex;gap:2px}.vo-dbg-controls[hidden]{display:none}.vo-console-lines .vo-out-err{color:#b3261e}.vo-console-lines .vo-out-in{color:var(--accent);font-weight:600}.vo-console-input{display:flex;align-items:center;gap:6px;padding:4px 12px 8px;color:var(--accent)}.vo-console-input[hidden]{display:none}.vo-console-input input{flex:1;font-size:13px;padding:4px 6px;border:1px solid var(--accent);border-radius:4px}.vo-dbg{display:grid;grid-template-columns:minmax(160px,1fr) minmax(220px,2fr);gap:12px;padding:8px 12px}.vo-dbg h3{margin:0 0 6px;font-size:12px;font-weight:600;color:var(--muted)}.vo-dbg ol{list-style:none;margin:0;padding:0}.vo-dbg-frame{display:block;width:100%;text-align:start;padding:3px 6px;border:0;border-radius:4px;background:none;color:inherit;font:inherit;cursor:pointer}.vo-dbg-frame.on{background:var(--accent-soft)}.vo-dbg-frame small{color:var(--muted)}.vo-dbg-vars tr.changed td{background:#ffd60a59}@media(max-width:760px){.vo-dbg{grid-template-columns:1fr}}.vo-seqcanvas{overflow:auto}.vo-seqcanvas .vo-empty[hidden]{display:none}.vo-seq{display:block;font:12px ui-monospace,SFMono-Regular,Menlo,monospace}.vo-seq-head rect{fill:var(--panel);stroke:var(--text);stroke-width:1.2}.vo-seq-head text{fill:var(--text);text-decoration:underline}.vo-seq-head.static text{text-decoration:none;font-weight:600}.vo-seq-life{stroke:var(--muted);stroke-dasharray:5 4}.vo-seq-bar{fill:var(--panel);stroke:var(--text);stroke-width:1}.vo-seq-bar.running{fill:var(--accent-soft)}.vo-seq-msg{cursor:pointer}.vo-seq-msg line,.vo-seq-msg path{stroke:var(--text);stroke-width:1.2}.vo-seq-msg .head.filled{fill:var(--text)}.vo-seq-msg text{fill:var(--text)}.vo-seq-msg.return line,.vo-seq-msg.create line{stroke-dasharray:6 4}.vo-seq-msg.exception line,.vo-seq-msg.exception text{stroke:#b3261e;fill:#b3261e}.vo-seq-msg.current line,.vo-seq-msg.current path{stroke:#e0a800;stroke-width:2.4}.vo-seq-msg.current .head.filled{fill:#e0a800}.vo-seq-msg.current text{font-weight:700}.vo-seq-msg:hover text{fill:var(--accent)}.vo-seq-more{fill:var(--muted)}.palette-head{display:flex;align-items:center;gap:4px;margin:0 0 4px}.palette-head h2{flex:1;min-width:0;margin:0}.palette-hide{min-height:26px;padding:2px 5px}.app.compact-palette .palette-head{flex-direction:column;gap:2px}.palette-rail{display:none;grid-area:pal;width:auto}.app.palette-hidden .palette,.app.palette-hidden .palette-resizer{display:none}.app.palette-hidden:not(.simulating) .palette-rail{display:flex}@media(max-width:820px){.palette-head{display:none}.app.palette-hidden .palette{display:block}.app.palette-hidden .palette-rail{display:none!important}}.diagram-tools .pseudocode-toggle{gap:4px;margin:0 4px;white-space:nowrap;cursor:pointer} diff --git a/website/app/assets/index-CqnqsqSP.js b/website/app/assets/index-CBJVdWXq.js similarity index 94% rename from website/app/assets/index-CqnqsqSP.js rename to website/app/assets/index-CBJVdWXq.js index 39337c8d..c147bfdb 100644 --- a/website/app/assets/index-CqnqsqSP.js +++ b/website/app/assets/index-CBJVdWXq.js @@ -1,23 +1,23 @@ -var l2=Object.defineProperty;var u2=(i,e,t)=>e in i?l2(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var y=(i,e,t)=>u2(i,typeof e!="symbol"?e+"":e,t);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))n(a);new MutationObserver(a=>{for(const s of a)if(s.type==="childList")for(const r of s.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&n(r)}).observe(document,{childList:!0,subtree:!0});function t(a){const s={};return a.integrity&&(s.integrity=a.integrity),a.referrerPolicy&&(s.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?s.credentials="include":a.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function n(a){if(a.ep)return;a.ep=!0;const s=t(a);fetch(a.href,s)}})();const c2="modulepreload",m2=function(i,e){return new URL(i,e).href},Q0={},ee=function(e,t,n){let a=Promise.resolve();if(t&&t.length>0){let r=function(c){return Promise.all(c.map(m=>Promise.resolve(m).then(d=>({status:"fulfilled",value:d}),d=>({status:"rejected",reason:d}))))};const o=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),u=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));a=r(t.map(c=>{if(c=m2(c,n),c in Q0)return;Q0[c]=!0;const m=c.endsWith(".css"),d=m?'[rel="stylesheet"]':"";if(!!n)for(let f=o.length-1;f>=0;f--){const b=o[f];if(b.href===c&&(!m||b.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${c}"]${d}`))return;const g=document.createElement("link");if(g.rel=m?"stylesheet":c2,m||(g.as="script"),g.crossOrigin="",g.href=c,u&&g.setAttribute("nonce",u),document.head.appendChild(g),m)return new Promise((f,b)=>{g.addEventListener("load",f),g.addEventListener("error",()=>b(new Error(`Unable to preload CSS for ${c}`)))})}))}function s(r){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=r,window.dispatchEvent(o),!o.defaultPrevented)throw r}return a.then(r=>{for(const o of r||[])o.status==="rejected"&&s(o.reason);return e().catch(s)})};var S=(i=>(i[i.anweisung=0]="anweisung",i[i.verzweigung=1]="verzweigung",i[i.fallauswahl=2]="fallauswahl",i[i.forSchleife=3]="forSchleife",i[i.whileSchleife=4]="whileSchleife",i[i.doUntilSchleife=5]="doUntilSchleife",i[i.endlosschleife=6]="endlosschleife",i[i.aussprung=7]="aussprung",i[i.aufruf=8]="aufruf",i[i.leerElement=9]="leerElement",i))(S||{});function d2(i){return i===3||i===4||i===5||i===6}function h2(i){return i===1||i===2}function Oe(i,e={}){return{type:i,zoomX:0,zoomY:0,textLines:[""],...e}}function g2(i){const e=i.textLines;if(!e.every(t=>t.trim()===""))switch(i.type){case S.forSchleife:return e.length<=1?e:[f2(e)];case S.verzweigung:return Ui("if",e);case S.whileSchleife:return Ui("while",e);case S.doUntilSchleife:return Ui("while",p2(e));case S.fallauswahl:return Ui("switch",e);default:return e}}function p2(i){if(i.length===0)return i;const e=i[0].trim(),t=e.toLowerCase(),n=[...i];if(t==="until")n[0]="";else if(t.startsWith("until "))n[0]=e.slice(6).trim();else if(t.startsWith("until("))n[0]=e.slice(5);else return i;return n}function U0(i){const e=new Set(["if","for","while","until","switch"]),t=["input:","output:","print:"],n=i.trim(),a=n.toLowerCase();for(const o of t){if(a===o)return{keyword:n,rest:""};if(a.startsWith(o+" "))return{keyword:n.slice(0,o.length),rest:n.slice(o.length).trim()}}const s=n.indexOf(" ");if(s<0)return;const r=n.slice(0,s);if(e.has(r.toLowerCase()))return{keyword:r,rest:n.slice(s+1).trim()}}function Ui(i,e){if(e.length===0)return e;const t=e[0].trim(),n=t.toLowerCase();if(n===i||n.startsWith(i+" "))return e;const a=[...e];return a[0]=i+" "+t,a}function f2(i){let e=[...i];for(;e.length<3;)e.push("");e=e.slice(0,3);const t=a=>{let s=a.trim();for(;s.endsWith(";");)s=s.slice(0,-1).trim();return s},n=e.map(t).join("; ").trim();return n===""?"for":"for "+n}const Ld={[S.anweisung]:"Anweisung",[S.verzweigung]:"Bedingung",[S.fallauswahl]:"Fallauswahl",[S.forSchleife]:"for 0 < i < anzahl",[S.whileSchleife]:"while …",[S.doUntilSchleife]:"while …",[S.endlosschleife]:"endless",[S.aussprung]:"break",[S.aufruf]:"Aufruf()",[S.leerElement]:"ø"};function b2(i){Object.assign(Ld,i)}function Dl(i){return g2(i)??[Ld[i.type]]}class Le extends Error{}const pn=i=>structuredClone(i);function nn(){return Oe(S.anweisung,{textLines:["ø"]})}function x2(){return{caption:"",elements:[nn()]}}function Bl(i){if(i.type===S.leerElement)return!0;if(i.type===S.anweisung){const e=i.textLines;return e.length===0||e.length===1&&e[0]==="ø"}return!1}function In(i,e){const t=Jt(i,e);return t!==void 0&&Bl(t)}function Ei(i,e){if(e.length===0)throw new Le("Invalid element path.");const[t,...n]=e;if(t<0||t>=i.length)throw new Le("Invalid element path.");if(n.length===0)return{list:i,index:t};const[a,...s]=n;if(s.length===0)throw new Le("Invalid element path.");return Ei(Ed(i[t],a),s)}function Ed(i,e){if(d2(i.type)){if(e!==0||!i.loopBody)throw new Le("Invalid element path.");return i.loopBody}if(h2(i.type)){if(!i.cases||e<0||e>=i.cases.length)throw new Le("Invalid element path.");return i.cases[e].elements}throw new Le("Invalid element path.")}function jt(i,e){const{list:t,index:n}=Ei(i.elements,e);return t[n]}function Jt(i,e){try{return jt(i,e)}catch{return}}function jn(i,e,t){const n=pn(i),{list:a,index:s}=Ei(n.elements,e);return a[s]=pn(t),n}function N1(i,e,t){const n=pn(jt(i,e));return n.textLines=t.length===0?[""]:t,jn(i,e,n)}function cr(i,e){return e.length===0?!1:e.length===1&&i.elements.length===1?!In(i,e):Jt(i,e)!==void 0}function vi(i,e){const t=pn(i),{list:n,index:a}=Ei(t.elements,e);if(e.length===1&&n.length===1){if(Bl(n[0]))throw new Le("The last root element cannot be deleted.");return n[0]=nn(),t}return n.splice(a,1),e.length>1&&n.length===0&&n.push(nn()),t}function ai(i,e,t,n){const a=pn(i);let s;if(e.length===0)s=a.elements;else{const r=e.slice(0,-1),o=e[e.length-1],{list:l,index:u}=Ei(a.elements,r);s=Ed(l[u],o)}return s.splice(Math.min(Math.max(0,t),s.length),0,pn(n)),a}function Wd(i,e,t){if(t.length===0)throw new Le("Invalid element path.");return ai(i,t.slice(0,-1),t[t.length-1],e)}function lo(i,e,t){if(t.length===0)throw new Le("Invalid element path.");return ai(i,t.slice(0,-1),t[t.length-1]+1,e)}function Zl(i,e){return i.lengthe[n]===t)}function Ml(i,e){if(e.length===0)return i;const t=e[e.length-1],n=e.slice(0,-1);if(i.length<=n.length||!n.every((r,o)=>i[o]===r))return i;const a=n.length;if(i[a]<=t)return i;const s=[...i];return s[a]-=1,s}const Ll=(i,e)=>i.length===e.length&&i.every((t,n)=>t===e[n]);function v2(i,e,t){if(Ll(e,t))return i;if(Zl(e,t))throw new Le("Invalid element path.");const n=jt(i,e),a=vi(i,e);return Wd(a,n,Ml(t,e))}function y2(i,e,t){if(Ll(e,t))return i;if(Zl(e,t))throw new Le("Invalid element path.");const n=jt(i,e),a=vi(i,e);return lo(a,n,Ml(t,e))}function w2(i,e,t){if(!In(i,t))throw new Le("Invalid element path.");if(Ll(e,t))return i;if(Zl(e,t))throw new Le("Invalid element path.");const n=jt(i,e),a=vi(i,e);return jn(a,Ml(t,e),n)}function z2(i,e){const t=pn(jt(i,e)),n=t.cases;if(t.type!==S.fallauswahl||!n||n.length===0)throw new Le("Invalid element path.");const a=n[n.length-1].name.toLowerCase()==="default",s=a?n.length-1:n.length,r=String(a?n.length:n.length+1);return n.splice(s,0,{name:r,elements:[nn()]}),{doc:jn(i,e,t),path:[...e,s,0]}}function I2(i,e,t){const n=pn(jt(i,e)),a=n.cases;if(n.type!==S.fallauswahl||!a)throw new Le("Invalid element path.");if(a.length<=2)throw new Le("A switch needs at least two cases.");if(t<0||t>=a.length)throw new Le("Invalid element path.");a.splice(t,1);const s=Math.min(t,a.length-1);return{doc:jn(i,e,n),path:[...e,s,0]}}function k2(i,e,t,n){const a=pn(jt(i,e)),s=a.cases;if(a.type!==S.fallauswahl||!s)throw new Le("Invalid element path.");if(t<0||t>=s.length)throw new Le("Invalid element path.");const r=n.trim();if(r==="")throw new Le("Invalid element path.");return s[t].name=r,jn(i,e,a)}function S2(i,e){var t;if(!(!i||i.length===0))for(let n=i.length;n>=1;n--){const a=i.slice(0,n);if(((t=Jt(e,a))==null?void 0:t.type)===S.fallauswahl)return a}}function T2(i,e){if(!(!i||i.length<=e.length))return i[e.length]}function mr(i,e){if(e.elements.length!==0)return!i||!Jt(e,i)?[0]:i}const Nd=i=>i!==void 0&&/\s/.test(i);function $a(i){const e=i.trim().toLowerCase();return e.startsWith("input:")?"input":e.startsWith("output:")||e.startsWith("print:")?"output":"statement"}function _2(i){const e=i.trim(),t=e.toLowerCase();return t.startsWith("input:")?e.slice(6).trim():t.startsWith("output:")?e.slice(7).trim():t.startsWith("print:")?e.slice(6).trim():i}function $0(i,e){const t=e.trim();return t===""?`${i} `:`${i} ${t}`}function O2(i,e){const t=_2(e);switch(i){case"statement":return t;case"input":return $0("input:",t);case"output":return $0("output:",t)}}const Ba=i=>Nd(i[0])?i.slice(1):i;function A2(i){const e=i.replace(/^\s+/,""),t=e.toLowerCase();return t.startsWith("input:")?Ba(e.slice(6)):t.startsWith("output:")?Ba(e.slice(7)):t.startsWith("print:")?Ba(e.slice(6)):i}function Y0(i,e){const t=e.replace(/^\s+/,"");if(!t.toLowerCase().startsWith(i.toLowerCase()))return e;const n=t.slice(i.length);if(!(n===""||Nd(n[0])||n[0]==="("))return e;const a=Ba(n);return a.startsWith("(")&&a.endsWith(")")&&a.length>=2?a.slice(1,-1):a}function X0(i,e){if(i==="input:"||i==="output:")return A2(e);const t=Y0(i,e);if(i==="while"&&t===e){const n=Y0("until",e);if(n!==e)return n}return t}function C2(i,e){return e===""?`${i} `:`${i} ${e}`}function Fd(i){return i.replace(/[“”„«»]/g,'"').replace(/[’‘‚´]/g,"'")}function K0(i){const e=i.length===0?[""]:i.slice(0,3);for(;e.length<3;)e.push("");return e}function P2(i){let e=Fd(i);for(;;){const t=e.trim();if(!t.endsWith(";"))return e;e=t.slice(0,-1).trim()}}const Ns='system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';function j2(i,e){return`${e==="bold"?700:500} ${i}px ${Ns}`}const Jd=(i,e,t)=>[...i].length*e*(t==="bold"?.68:.62);function D2(){if(typeof document>"u"||!document.body)return;const i="http://www.w3.org/2000/svg",e=document.createElementNS(i,"svg");e.setAttribute("aria-hidden","true"),e.setAttribute("width","0"),e.setAttribute("height","0"),e.style.cssText="position:absolute;left:-9999px;top:0;visibility:hidden;overflow:hidden";const t=document.createElementNS(i,"text");if(t.setAttribute("font-family",Ns),t.style.whiteSpace="pre",e.append(t),document.body.append(e),typeof t.getComputedTextLength!="function"||typeof t.getBBox!="function"){e.remove();return}if(t.textContent="Mg",t.setAttribute("font-size","20"),!(t.getComputedTextLength()>0)){e.remove();return}return t}let dr;function Rd(){return dr===void 0&&(dr=D2()??null),dr??void 0}function Gd(i,e,t){i.setAttribute("font-size",String(e)),i.setAttribute("font-weight",t==="bold"?"700":"500")}function eu(i,e){const t=`${i}|${e}`;let n=tu.get(t);if(!n){const a=Rd();if(n={ascent:i*.95,descent:i*.24},a){Gd(a,i,e),a.setAttribute("y","0"),a.textContent="Mg";const s=a.getBBox();s.height>0&&(n={ascent:-s.y,descent:s.height+s.y})}tu.set(t,n)}return n}const tu=new Map;function B2(){const i=Rd();if(i){const n=new Map;return(a,s,r)=>{const o=`${s}|${r}|${a}`;let l=n.get(o);return l===void 0&&(Gd(i,s,r),i.textContent=a,l=a===""?0:i.getComputedTextLength(),n.size>2e3&&n.clear(),n.set(o,l)),l}}const e=typeof document<"u"?document.createElement("canvas").getContext("2d"):null;if(!e)return Jd;const t=new Map;return(n,a,s)=>{const r=`${a}|${s}|${n}`;let o=t.get(r);return o===void 0&&(e.font=j2(a,s),o=e.measureText(n).width,t.size>2e3&&t.clear(),t.set(r,o)),o}}const Hd={fontSize:15,lineHeight:20,charWidth:7,baseHeaderExtra:20,minSidePadding:42,cellTextInsetY:15,doUntilDoLabelTopInset:2,doUntilFooterTopInset:6,doUntilFooterBottomInset:8};function Z2(i){return{...Hd,fontSize:14,lineHeight:21,charWidth:5.5*(14/12),baseHeaderExtra:21,minSidePadding:40}}const $i=i=>i===S.forSchleife||i===S.whileSchleife||i===S.doUntilSchleife||i===S.endlosschleife,Yi=i=>i===S.fallauswahl||i===S.verzweigung;function Xi(i,e,t,n=0){return{idPath:i,element:e,frame:t,headerBandHeight:n,topBandHeight:0,loopBodyLeadingInset:0,caseColumnFrames:[],children:[]}}function it(i){return{...i,frame:{...i.frame}}}class Vd{constructor(e=Hd,t=Jd){this.metrics=e,this.measure=t}layout(e,t={left:28,top:28}){const a=this.layoutList(e.elements,t.left,t.top,[]).map(l=>this.stretchLoopBodiesVertically(l));let s=0,r=0;const o=l=>{s=Math.max(s,l.frame.x+l.frame.width),r=Math.max(r,l.frame.y+l.frame.height),l.children.forEach(o)};return a.forEach(o),{canvasSize:{width:s+t.left,height:r+t.top},elements:a}}lineWidth(e){return Math.ceil(this.measure(e,this.metrics.fontSize,"medium"))}lineWidthBold(e){return Math.ceil(this.measure(e,this.metrics.fontSize,"bold"))}layoutList(e,t,n,a){let s=[],r=n;e.forEach((l,u)=>{const c=this.layoutElement(l,t,r,[...a,u]);s.push(c),r+=c.frame.height});const o=Math.max(0,...s.map(l=>l.frame.width));return o>0&&(s=s.map(l=>this.stretchNodeTreeToWidth(l,o))),s}stretchMultiwayNodeToWidth(e,t){const n=it(e),a=n.frame.width;if(!(a>0)||n.caseColumnFrames.length===0)return n;const s=t/a;n.frame.width=t;let r=n.frame.x;const o=n.caseColumnFrames.map(l=>{const u=l.width*s,c={x:r,y:l.y,width:u,height:l.height};return r+=u,c});return n.caseColumnFrames=o,n.dividerX=o.length>0?o[o.length-1].x:n.frame.x+t,n.columns&&n.columns.length===o.length&&(n.columns=n.columns.map((l,u)=>{const c=o[u];return l.map(m=>{const d=it(m);return d.frame.x=c.x,d.frame.width=c.width,this.stretchDescendantsWidths(d,c.width)})}),n.children=n.columns.flat()),n}stretchLoopChildren(e,t){const n=this.effectiveLoopBodyLeading(e),a=Math.max(0,t-n);e.children=e.children.map(s=>{const r=it(s);return r.frame.x=e.frame.x+n,r.frame.width=a,this.stretchDescendantsWidths(r,a)})}stretchNodeTreeToWidth(e,t){const n=it(e);return n.frame.width>0?Yi(n.element.type)&&n.caseColumnFrames.length>0?this.stretchMultiwayNodeToWidth(n,t):(n.frame.width=t,$i(n.element.type)?this.stretchLoopChildren(n,t):n.children=n.children.map(s=>this.stretchDescendantsWidths(s,t)),n):n}stretchDescendantsWidths(e,t){let n=it(e);return Yi(n.element.type)?n=this.stretchNodeTreeToWidth(n,t):$i(n.element.type)?(n.frame.width=t,this.stretchLoopChildren(n,t)):(n.frame.width=t,n.children=n.children.map(a=>this.stretchDescendantsWidths(a,t))),n}stretchLoopBodiesVertically(e){const t=it(e);if(t.columns&&t.columns.length>0)return t.columns=t.columns.map(s=>s.map(r=>this.stretchLoopBodiesVertically(r))),t.children=t.columns.flat(),t;t.children=t.children.map(s=>this.stretchLoopBodiesVertically(s));const n=s=>s===S.anweisung||s===S.leerElement||s===S.aufruf||s===S.aussprung||$i(s);let a;switch(t.element.type){case S.forSchleife:case S.whileSchleife:case S.endlosschleife:{const s=t.element.type===S.endlosschleife?40:0;a=t.frame.y+t.frame.height-s;break}case S.doUntilSchleife:a=t.frame.y+t.frame.height-t.headerBandHeight;break}if(a!==void 0&&t.children.length>0){const s=t.children.length-1;let r=it(t.children[s]);const o=a-(r.frame.y+r.frame.height);o>.5&&n(r.element.type)&&(r.frame.height+=o,r=this.stretchLoopBodiesVertically(r),t.children=[...t.children.slice(0,s),r])}return t}headerHeight(e){const t=this.metrics,n=Math.max(1,e.textLines.length);if(e.type===S.doUntilSchleife)return t.doUntilFooterTopInset+n*t.lineHeight+t.doUntilFooterBottomInset+e.zoomY;let a;switch(e.type){case S.fallauswahl:a=40;break;case S.verzweigung:a=20;break;case S.forSchleife:case S.whileSchleife:case S.endlosschleife:a=t.baseHeaderExtra+4;break;default:a=14}return a+n*t.lineHeight+e.zoomY}doUntilBodyLeadingInset(){return Math.max(20,this.lineWidthBold("do")+12)}effectiveLoopBodyLeading(e){return e.element.type===S.doUntilSchleife?e.loopBodyLeadingInset>0?e.loopBodyLeadingInset:this.doUntilBodyLeadingInset():20}horizontalPaddingInsideCell(e){return Yi(e)?Math.max(100,this.metrics.minSidePadding*2.45):this.metrics.minSidePadding}minWidth(e){const t=e.textLines.length===0?0:Math.max(...e.textLines.map(s=>this.lineWidth(s)));let n=t+e.zoomX+this.horizontalPaddingInsideCell(e.type);if(e.type===S.aufruf){const s=Math.max(68,this.metrics.minSidePadding*1.7),r=Math.max(8,this.metrics.minSidePadding*.2);n=Math.max(n,t+e.zoomX+s+r)}const a=e.type===S.leerElement?76:e.type===S.aufruf?104:72;return Math.max(a,n)}layoutElement(e,t,n,a){if(Yi(e.type))return this.layoutMultiway(e,t,n,a);if($i(e.type))return this.layoutLoop(e,t,n,a);const s=this.headerHeight(e);return Xi(a,e,{x:t,y:n,width:this.minWidth(e),height:s},s)}layoutLoop(e,t,n,a){const s=b=>b.reduce((x,v)=>x+v.frame.height,0),r=b=>Math.max(0,...b.map(x=>x.frame.width)),o=e.loopBody??[];if(e.type===S.doUntilSchleife){const b=this.doUntilBodyLeadingInset(),x=e.zoomY,v=this.headerHeight(e),w=this.layoutList(o,t+b,n+x,[...a,0]),I=Math.max(this.minWidth(e),r(w)+b),z=s(w)+v+x,k=Math.max(0,I-b),T=Xi(a,e,{x:t,y:n,width:I,height:z},v);return T.topBandHeight=x,T.loopBodyLeadingInset=b,T.children=w.map(O=>{const D=it(O);return D.frame.x=t+b,D.frame.width=k,this.stretchDescendantsWidths(D,k)}),T}const l=20,u=this.headerHeight(e),c=e.type===S.endlosschleife?40:0,m=this.layoutList(o,t+l,n+u,[...a,0]),d=Math.max(this.minWidth(e),r(m)+l),h=u+c+s(m),g=Math.max(0,d-l),f=Xi(a,e,{x:t,y:n,width:d,height:h},u);return f.children=m.map(b=>{const x=it(b);return x.frame.x=t+l,x.frame.width=g,this.stretchDescendantsWidths(x,g)}),f}layoutMultiway(e,t,n,a){const s=this.headerHeight(e),r=e.cases??[],o=Math.max(1,r.length),l=Math.max(this.minWidth(e)/o,132);let u=[],c=[],m=0,d=0;if(r.forEach((b,x)=>{const v=t+m,w=this.layoutList(b.elements,v,n+s,[...a,x]),I=Math.max(0,...w.map(T=>T.frame.width));let z;e.type===S.verzweigung&&o===2?z=Math.max(I,(x===0?"true":"false").length*this.metrics.charWidth+24):z=Math.max(l,I);const k=w.reduce((T,O)=>T+O.frame.height,0);d=Math.max(d,k),u.push({x:v,y:n+s,width:z,height:k}),c.push(w.map(T=>{const O=it(T);return O.frame.x=v,O.frame.width=z,this.stretchDescendantsWidths(O,z)})),m+=z}),e.type===S.verzweigung&&o===2&&u.length===2){const b=Math.max(u[0].width,u[1].width),x=t,v=t+b,w=v-u[1].x;u[0]={...u[0],x,width:b},u[1]={...u[1],x:v,width:b},m=b*2,c[0]=c[0].map(I=>{const z=it(I);return z.frame.x=x,z.frame.width=b,this.stretchDescendantsWidths(z,b)}),c[1]=c[1].map(I=>{const z=uo(I,w);return z.frame.width=b,this.stretchDescendantsWidths(z,b)})}if(c.length>0){const b=M2(c,n+s);c=b.columns.map(x=>x.map(v=>this.stretchLoopBodiesVertically(v)));for(let x=0;x0?Math.max(...b.columnHeights):d}let h=Math.max(m,this.minWidth(e));if(m>.5&&h>m+.5){const b=h/m;let x=t;const v=[],w=[];u.forEach((I,z)=>{const k=I.width*b;w.push(c[z].map(T=>{const O=it(T);return O.frame.x=x,O.frame.width=k,this.stretchDescendantsWidths(O,k)})),v.push({x,y:I.y,width:k,height:I.height}),x+=k}),u=v,c=w,m=x-t,h=m}const g=u.length>0?u[u.length-1].width:m/o,f=Xi(a,e,{x:t,y:n,width:h,height:s+d},s);return f.caseColumnFrames=u,f.dividerX=u.length>0?u[u.length-1].x:t+m-g,f.dividerYInset=e.type===S.fallauswahl?-20:0,f.columns=c,f.children=c.flat(),f}}function qd(i,e){if(Math.abs(e)<=1e-4)return i;const t=it(i),n=a=>{const s=it(a);return s.frame.y+=e,qd(s,e)};return t.columns?(t.columns=t.columns.map(a=>a.map(n)),t.children=t.columns.flat()):t.children=t.children.map(n),t}function uo(i,e){if(Math.abs(e)<=1e-4)return i;const t=it(i);return t.frame.x+=e,t.columns?(t.columns=t.columns.map(n=>n.map(a=>uo(a,e))),t.children=t.columns.flat()):t.children=t.children.map(n=>uo(n,e)),t}function M2(i,e){if(i.length<2)return{columns:i,columnHeights:i.map(u=>u.reduce((c,m)=>c+m.frame.height,0))};const t=.5,n=[e];for(const u of i)for(const c of u)n.push(c.frame.y+c.frame.height);const a=Math.max(...n);n.push(a),n.sort((u,c)=>u-c);let s=[];for(const u of n)s.length>0&&Math.abs(u-s[s.length-1])<=t||s.push(u);(s.length===0||Math.abs(s[0]-e)>t)&&s.unshift(e),s.length===0?s=[e,a]:s[s.length-1]{let m=Math.max(0,c);for(;m{let g=it(d);const f=s[m],b=d.frame.y+d.frame.height,x=h===u.length-1?s.length-1:r(b,m+1),v=s[x],w=f-g.frame.y;g.frame.y=f,g.frame.height=Math.max(0,v-f),g=qd(g,w),c.push(g),m=x}),o.push(c),l.push(s[s.length-1]-e)}return{columns:o,columnHeights:l}}const L2=[{item:"anweisung",label:"Anweisung"},{item:"verzweigung",label:"Verzweigung"},{item:"fallauswahl",label:"Fallauswahl"},{item:"forZaehlSchleife",label:"For-Schleife"},{item:"whileSchleife",label:"While-Schleife"},{item:"doUntilSchleife",label:"Do-while-Schleife"},{item:"endlosschleife",label:"Endlosschleife"},{item:"aufruf",label:"Aufruf"},{item:"aussprung",label:"Aussprung"}];function nu(i){const e=nn;switch(i){case"anweisung":return Oe(S.anweisung);case"verzweigung":return Oe(S.verzweigung,{cases:[{name:"true",elements:[e()]},{name:"false",elements:[e()]}]});case"fallauswahl":return Oe(S.fallauswahl,{cases:[{name:"1",elements:[e()]},{name:"2",elements:[e()]},{name:"default",elements:[e()]}]});case"forZaehlSchleife":return Oe(S.forSchleife,{textLines:["","",""],loopBody:[e()]});case"whileSchleife":return Oe(S.whileSchleife,{loopBody:[e()]});case"doUntilSchleife":return Oe(S.doUntilSchleife,{loopBody:[e()]});case"endlosschleife":return Oe(S.endlosschleife,{loopBody:[e()]});case"aussprung":return Oe(S.aussprung);case"aufruf":return Oe(S.aufruf)}}function Ya(i){if(i==="")return"-1;";let e="";for(const t of i)e+=t.codePointAt(0)+";";return e}function co(i){const e=i.split(";").filter(n=>n!=="");if(e.length===1&&e[0]==="-1")return"";let t="";for(const n of e){if(!/^[+-]?\d+$/.test(n))continue;const a=Number(n);a!==-1&&(a<0||a>1114111||a>=55296&&a<=57343||(t+=String.fromCodePoint(a)))}return t}class iu extends Error{}function El(i){const e=new DOMParser().parseFromString(i,"application/xml");if(e.getElementsByTagName("parsererror").length>0)throw new iu("Could not read XML.");const t=e.documentElement;if(!t||t.tagName!=="struktogramm")throw new iu("Invalid XML: root element is not .");const n={caption:su(t,"caption")??"",elements:ho(t)},a=su(t,"fontfamily");a!==void 0&&(n.fontFamily=a);const s=si(t,"fontsize");s!==void 0&&(n.fontSize=s);const r=si(t,"fontstyle");return r!==void 0&&(n.fontStyle=r),t.getAttribute("pseudocode")==="true"&&(n.pseudocode=!0),n}function u1(i){const e=(n,a)=>a===void 0?"":` ${n}="${Qd(a)}"`;let t=` +var u2=Object.defineProperty;var c2=(i,e,t)=>e in i?u2(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var y=(i,e,t)=>c2(i,typeof e!="symbol"?e+"":e,t);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))n(a);new MutationObserver(a=>{for(const s of a)if(s.type==="childList")for(const r of s.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&n(r)}).observe(document,{childList:!0,subtree:!0});function t(a){const s={};return a.integrity&&(s.integrity=a.integrity),a.referrerPolicy&&(s.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?s.credentials="include":a.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function n(a){if(a.ep)return;a.ep=!0;const s=t(a);fetch(a.href,s)}})();const m2="modulepreload",d2=function(i,e){return new URL(i,e).href},Q0={},ee=function(e,t,n){let a=Promise.resolve();if(t&&t.length>0){let r=function(c){return Promise.all(c.map(m=>Promise.resolve(m).then(d=>({status:"fulfilled",value:d}),d=>({status:"rejected",reason:d}))))};const o=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),u=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));a=r(t.map(c=>{if(c=d2(c,n),c in Q0)return;Q0[c]=!0;const m=c.endsWith(".css"),d=m?'[rel="stylesheet"]':"";if(!!n)for(let f=o.length-1;f>=0;f--){const b=o[f];if(b.href===c&&(!m||b.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${c}"]${d}`))return;const g=document.createElement("link");if(g.rel=m?"stylesheet":m2,m||(g.as="script"),g.crossOrigin="",g.href=c,u&&g.setAttribute("nonce",u),document.head.appendChild(g),m)return new Promise((f,b)=>{g.addEventListener("load",f),g.addEventListener("error",()=>b(new Error(`Unable to preload CSS for ${c}`)))})}))}function s(r){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=r,window.dispatchEvent(o),!o.defaultPrevented)throw r}return a.then(r=>{for(const o of r||[])o.status==="rejected"&&s(o.reason);return e().catch(s)})};var S=(i=>(i[i.anweisung=0]="anweisung",i[i.verzweigung=1]="verzweigung",i[i.fallauswahl=2]="fallauswahl",i[i.forSchleife=3]="forSchleife",i[i.whileSchleife=4]="whileSchleife",i[i.doUntilSchleife=5]="doUntilSchleife",i[i.endlosschleife=6]="endlosschleife",i[i.aussprung=7]="aussprung",i[i.aufruf=8]="aufruf",i[i.leerElement=9]="leerElement",i))(S||{});function h2(i){return i===3||i===4||i===5||i===6}function g2(i){return i===1||i===2}function Oe(i,e={}){return{type:i,zoomX:0,zoomY:0,textLines:[""],...e}}function p2(i){const e=i.textLines;if(!e.every(t=>t.trim()===""))switch(i.type){case S.forSchleife:return e.length<=1?e:[b2(e)];case S.verzweigung:return Ui("if",e);case S.whileSchleife:return Ui("while",e);case S.doUntilSchleife:return Ui("while",f2(e));case S.fallauswahl:return Ui("switch",e);default:return e}}function f2(i){if(i.length===0)return i;const e=i[0].trim(),t=e.toLowerCase(),n=[...i];if(t==="until")n[0]="";else if(t.startsWith("until "))n[0]=e.slice(6).trim();else if(t.startsWith("until("))n[0]=e.slice(5);else return i;return n}function U0(i){const e=new Set(["if","for","while","until","switch"]),t=["input:","output:","print:"],n=i.trim(),a=n.toLowerCase();for(const o of t){if(a===o)return{keyword:n,rest:""};if(a.startsWith(o+" "))return{keyword:n.slice(0,o.length),rest:n.slice(o.length).trim()}}const s=n.indexOf(" ");if(s<0)return;const r=n.slice(0,s);if(e.has(r.toLowerCase()))return{keyword:r,rest:n.slice(s+1).trim()}}function Ui(i,e){if(e.length===0)return e;const t=e[0].trim(),n=t.toLowerCase();if(n===i||n.startsWith(i+" "))return e;const a=[...e];return a[0]=i+" "+t,a}function b2(i){let e=[...i];for(;e.length<3;)e.push("");e=e.slice(0,3);const t=a=>{let s=a.trim();for(;s.endsWith(";");)s=s.slice(0,-1).trim();return s},n=e.map(t).join("; ").trim();return n===""?"for":"for "+n}const Ld={[S.anweisung]:"Anweisung",[S.verzweigung]:"Bedingung",[S.fallauswahl]:"Fallauswahl",[S.forSchleife]:"for 0 < i < anzahl",[S.whileSchleife]:"while …",[S.doUntilSchleife]:"while …",[S.endlosschleife]:"endless",[S.aussprung]:"break",[S.aufruf]:"Aufruf()",[S.leerElement]:"ø"};function x2(i){Object.assign(Ld,i)}function Dl(i){return p2(i)??[Ld[i.type]]}class Le extends Error{}const pn=i=>structuredClone(i);function nn(){return Oe(S.anweisung,{textLines:["ø"]})}function v2(){return{caption:"",elements:[nn()]}}function Bl(i){if(i.type===S.leerElement)return!0;if(i.type===S.anweisung){const e=i.textLines;return e.length===0||e.length===1&&e[0]==="ø"}return!1}function In(i,e){const t=Jt(i,e);return t!==void 0&&Bl(t)}function Ei(i,e){if(e.length===0)throw new Le("Invalid element path.");const[t,...n]=e;if(t<0||t>=i.length)throw new Le("Invalid element path.");if(n.length===0)return{list:i,index:t};const[a,...s]=n;if(s.length===0)throw new Le("Invalid element path.");return Ei(Ed(i[t],a),s)}function Ed(i,e){if(h2(i.type)){if(e!==0||!i.loopBody)throw new Le("Invalid element path.");return i.loopBody}if(g2(i.type)){if(!i.cases||e<0||e>=i.cases.length)throw new Le("Invalid element path.");return i.cases[e].elements}throw new Le("Invalid element path.")}function Pt(i,e){const{list:t,index:n}=Ei(i.elements,e);return t[n]}function Jt(i,e){try{return Pt(i,e)}catch{return}}function Pn(i,e,t){const n=pn(i),{list:a,index:s}=Ei(n.elements,e);return a[s]=pn(t),n}function N1(i,e,t){const n=pn(Pt(i,e));return n.textLines=t.length===0?[""]:t,Pn(i,e,n)}function cr(i,e){return e.length===0?!1:e.length===1&&i.elements.length===1?!In(i,e):Jt(i,e)!==void 0}function vi(i,e){const t=pn(i),{list:n,index:a}=Ei(t.elements,e);if(e.length===1&&n.length===1){if(Bl(n[0]))throw new Le("The last root element cannot be deleted.");return n[0]=nn(),t}return n.splice(a,1),e.length>1&&n.length===0&&n.push(nn()),t}function ai(i,e,t,n){const a=pn(i);let s;if(e.length===0)s=a.elements;else{const r=e.slice(0,-1),o=e[e.length-1],{list:l,index:u}=Ei(a.elements,r);s=Ed(l[u],o)}return s.splice(Math.min(Math.max(0,t),s.length),0,pn(n)),a}function Wd(i,e,t){if(t.length===0)throw new Le("Invalid element path.");return ai(i,t.slice(0,-1),t[t.length-1],e)}function lo(i,e,t){if(t.length===0)throw new Le("Invalid element path.");return ai(i,t.slice(0,-1),t[t.length-1]+1,e)}function Zl(i,e){return i.lengthe[n]===t)}function Ml(i,e){if(e.length===0)return i;const t=e[e.length-1],n=e.slice(0,-1);if(i.length<=n.length||!n.every((r,o)=>i[o]===r))return i;const a=n.length;if(i[a]<=t)return i;const s=[...i];return s[a]-=1,s}const Ll=(i,e)=>i.length===e.length&&i.every((t,n)=>t===e[n]);function y2(i,e,t){if(Ll(e,t))return i;if(Zl(e,t))throw new Le("Invalid element path.");const n=Pt(i,e),a=vi(i,e);return Wd(a,n,Ml(t,e))}function w2(i,e,t){if(Ll(e,t))return i;if(Zl(e,t))throw new Le("Invalid element path.");const n=Pt(i,e),a=vi(i,e);return lo(a,n,Ml(t,e))}function z2(i,e,t){if(!In(i,t))throw new Le("Invalid element path.");if(Ll(e,t))return i;if(Zl(e,t))throw new Le("Invalid element path.");const n=Pt(i,e),a=vi(i,e);return Pn(a,Ml(t,e),n)}function I2(i,e){const t=pn(Pt(i,e)),n=t.cases;if(t.type!==S.fallauswahl||!n||n.length===0)throw new Le("Invalid element path.");const a=n[n.length-1].name.toLowerCase()==="default",s=a?n.length-1:n.length,r=String(a?n.length:n.length+1);return n.splice(s,0,{name:r,elements:[nn()]}),{doc:Pn(i,e,t),path:[...e,s,0]}}function k2(i,e,t){const n=pn(Pt(i,e)),a=n.cases;if(n.type!==S.fallauswahl||!a)throw new Le("Invalid element path.");if(a.length<=2)throw new Le("A switch needs at least two cases.");if(t<0||t>=a.length)throw new Le("Invalid element path.");a.splice(t,1);const s=Math.min(t,a.length-1);return{doc:Pn(i,e,n),path:[...e,s,0]}}function S2(i,e,t,n){const a=pn(Pt(i,e)),s=a.cases;if(a.type!==S.fallauswahl||!s)throw new Le("Invalid element path.");if(t<0||t>=s.length)throw new Le("Invalid element path.");const r=n.trim();if(r==="")throw new Le("Invalid element path.");return s[t].name=r,Pn(i,e,a)}function T2(i,e){var t;if(!(!i||i.length===0))for(let n=i.length;n>=1;n--){const a=i.slice(0,n);if(((t=Jt(e,a))==null?void 0:t.type)===S.fallauswahl)return a}}function _2(i,e){if(!(!i||i.length<=e.length))return i[e.length]}function mr(i,e){if(e.elements.length!==0)return!i||!Jt(e,i)?[0]:i}const Nd=i=>i!==void 0&&/\s/.test(i);function $a(i){const e=i.trim().toLowerCase();return e.startsWith("input:")?"input":e.startsWith("output:")||e.startsWith("print:")?"output":"statement"}function O2(i){const e=i.trim(),t=e.toLowerCase();return t.startsWith("input:")?e.slice(6).trim():t.startsWith("output:")?e.slice(7).trim():t.startsWith("print:")?e.slice(6).trim():i}function $0(i,e){const t=e.trim();return t===""?`${i} `:`${i} ${t}`}function A2(i,e){const t=O2(e);switch(i){case"statement":return t;case"input":return $0("input:",t);case"output":return $0("output:",t)}}const Ba=i=>Nd(i[0])?i.slice(1):i;function C2(i){const e=i.replace(/^\s+/,""),t=e.toLowerCase();return t.startsWith("input:")?Ba(e.slice(6)):t.startsWith("output:")?Ba(e.slice(7)):t.startsWith("print:")?Ba(e.slice(6)):i}function Y0(i,e){const t=e.replace(/^\s+/,"");if(!t.toLowerCase().startsWith(i.toLowerCase()))return e;const n=t.slice(i.length);if(!(n===""||Nd(n[0])||n[0]==="("))return e;const a=Ba(n);return a.startsWith("(")&&a.endsWith(")")&&a.length>=2?a.slice(1,-1):a}function X0(i,e){if(i==="input:"||i==="output:")return C2(e);const t=Y0(i,e);if(i==="while"&&t===e){const n=Y0("until",e);if(n!==e)return n}return t}function j2(i,e){return e===""?`${i} `:`${i} ${e}`}function Fd(i){return i.replace(/[“”„«»]/g,'"').replace(/[’‘‚´]/g,"'")}function K0(i){const e=i.length===0?[""]:i.slice(0,3);for(;e.length<3;)e.push("");return e}function P2(i){let e=Fd(i);for(;;){const t=e.trim();if(!t.endsWith(";"))return e;e=t.slice(0,-1).trim()}}const Ns='system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';function D2(i,e){return`${e==="bold"?700:500} ${i}px ${Ns}`}const Jd=(i,e,t)=>[...i].length*e*(t==="bold"?.68:.62);function B2(){if(typeof document>"u"||!document.body)return;const i="http://www.w3.org/2000/svg",e=document.createElementNS(i,"svg");e.setAttribute("aria-hidden","true"),e.setAttribute("width","0"),e.setAttribute("height","0"),e.style.cssText="position:absolute;left:-9999px;top:0;visibility:hidden;overflow:hidden";const t=document.createElementNS(i,"text");if(t.setAttribute("font-family",Ns),t.style.whiteSpace="pre",e.append(t),document.body.append(e),typeof t.getComputedTextLength!="function"||typeof t.getBBox!="function"){e.remove();return}if(t.textContent="Mg",t.setAttribute("font-size","20"),!(t.getComputedTextLength()>0)){e.remove();return}return t}let dr;function Rd(){return dr===void 0&&(dr=B2()??null),dr??void 0}function Gd(i,e,t){i.setAttribute("font-size",String(e)),i.setAttribute("font-weight",t==="bold"?"700":"500")}function eu(i,e){const t=`${i}|${e}`;let n=tu.get(t);if(!n){const a=Rd();if(n={ascent:i*.95,descent:i*.24},a){Gd(a,i,e),a.setAttribute("y","0"),a.textContent="Mg";const s=a.getBBox();s.height>0&&(n={ascent:-s.y,descent:s.height+s.y})}tu.set(t,n)}return n}const tu=new Map;function Z2(){const i=Rd();if(i){const n=new Map;return(a,s,r)=>{const o=`${s}|${r}|${a}`;let l=n.get(o);return l===void 0&&(Gd(i,s,r),i.textContent=a,l=a===""?0:i.getComputedTextLength(),n.size>2e3&&n.clear(),n.set(o,l)),l}}const e=typeof document<"u"?document.createElement("canvas").getContext("2d"):null;if(!e)return Jd;const t=new Map;return(n,a,s)=>{const r=`${a}|${s}|${n}`;let o=t.get(r);return o===void 0&&(e.font=D2(a,s),o=e.measureText(n).width,t.size>2e3&&t.clear(),t.set(r,o)),o}}const Hd={fontSize:15,lineHeight:20,charWidth:7,baseHeaderExtra:20,minSidePadding:42,cellTextInsetY:15,doUntilDoLabelTopInset:2,doUntilFooterTopInset:6,doUntilFooterBottomInset:8};function M2(i){return{...Hd,fontSize:14,lineHeight:21,charWidth:5.5*(14/12),baseHeaderExtra:21,minSidePadding:40}}const $i=i=>i===S.forSchleife||i===S.whileSchleife||i===S.doUntilSchleife||i===S.endlosschleife,Yi=i=>i===S.fallauswahl||i===S.verzweigung;function Xi(i,e,t,n=0){return{idPath:i,element:e,frame:t,headerBandHeight:n,topBandHeight:0,loopBodyLeadingInset:0,caseColumnFrames:[],children:[]}}function it(i){return{...i,frame:{...i.frame}}}class Vd{constructor(e=Hd,t=Jd){this.metrics=e,this.measure=t}layout(e,t={left:28,top:28}){const a=this.layoutList(e.elements,t.left,t.top,[]).map(l=>this.stretchLoopBodiesVertically(l));let s=0,r=0;const o=l=>{s=Math.max(s,l.frame.x+l.frame.width),r=Math.max(r,l.frame.y+l.frame.height),l.children.forEach(o)};return a.forEach(o),{canvasSize:{width:s+t.left,height:r+t.top},elements:a}}lineWidth(e){return Math.ceil(this.measure(e,this.metrics.fontSize,"medium"))}lineWidthBold(e){return Math.ceil(this.measure(e,this.metrics.fontSize,"bold"))}layoutList(e,t,n,a){let s=[],r=n;e.forEach((l,u)=>{const c=this.layoutElement(l,t,r,[...a,u]);s.push(c),r+=c.frame.height});const o=Math.max(0,...s.map(l=>l.frame.width));return o>0&&(s=s.map(l=>this.stretchNodeTreeToWidth(l,o))),s}stretchMultiwayNodeToWidth(e,t){const n=it(e),a=n.frame.width;if(!(a>0)||n.caseColumnFrames.length===0)return n;const s=t/a;n.frame.width=t;let r=n.frame.x;const o=n.caseColumnFrames.map(l=>{const u=l.width*s,c={x:r,y:l.y,width:u,height:l.height};return r+=u,c});return n.caseColumnFrames=o,n.dividerX=o.length>0?o[o.length-1].x:n.frame.x+t,n.columns&&n.columns.length===o.length&&(n.columns=n.columns.map((l,u)=>{const c=o[u];return l.map(m=>{const d=it(m);return d.frame.x=c.x,d.frame.width=c.width,this.stretchDescendantsWidths(d,c.width)})}),n.children=n.columns.flat()),n}stretchLoopChildren(e,t){const n=this.effectiveLoopBodyLeading(e),a=Math.max(0,t-n);e.children=e.children.map(s=>{const r=it(s);return r.frame.x=e.frame.x+n,r.frame.width=a,this.stretchDescendantsWidths(r,a)})}stretchNodeTreeToWidth(e,t){const n=it(e);return n.frame.width>0?Yi(n.element.type)&&n.caseColumnFrames.length>0?this.stretchMultiwayNodeToWidth(n,t):(n.frame.width=t,$i(n.element.type)?this.stretchLoopChildren(n,t):n.children=n.children.map(s=>this.stretchDescendantsWidths(s,t)),n):n}stretchDescendantsWidths(e,t){let n=it(e);return Yi(n.element.type)?n=this.stretchNodeTreeToWidth(n,t):$i(n.element.type)?(n.frame.width=t,this.stretchLoopChildren(n,t)):(n.frame.width=t,n.children=n.children.map(a=>this.stretchDescendantsWidths(a,t))),n}stretchLoopBodiesVertically(e){const t=it(e);if(t.columns&&t.columns.length>0)return t.columns=t.columns.map(s=>s.map(r=>this.stretchLoopBodiesVertically(r))),t.children=t.columns.flat(),t;t.children=t.children.map(s=>this.stretchLoopBodiesVertically(s));const n=s=>s===S.anweisung||s===S.leerElement||s===S.aufruf||s===S.aussprung||$i(s);let a;switch(t.element.type){case S.forSchleife:case S.whileSchleife:case S.endlosschleife:{const s=t.element.type===S.endlosschleife?40:0;a=t.frame.y+t.frame.height-s;break}case S.doUntilSchleife:a=t.frame.y+t.frame.height-t.headerBandHeight;break}if(a!==void 0&&t.children.length>0){const s=t.children.length-1;let r=it(t.children[s]);const o=a-(r.frame.y+r.frame.height);o>.5&&n(r.element.type)&&(r.frame.height+=o,r=this.stretchLoopBodiesVertically(r),t.children=[...t.children.slice(0,s),r])}return t}headerHeight(e){const t=this.metrics,n=Math.max(1,e.textLines.length);if(e.type===S.doUntilSchleife)return t.doUntilFooterTopInset+n*t.lineHeight+t.doUntilFooterBottomInset+e.zoomY;let a;switch(e.type){case S.fallauswahl:a=40;break;case S.verzweigung:a=20;break;case S.forSchleife:case S.whileSchleife:case S.endlosschleife:a=t.baseHeaderExtra+4;break;default:a=14}return a+n*t.lineHeight+e.zoomY}doUntilBodyLeadingInset(){return Math.max(20,this.lineWidthBold("do")+12)}effectiveLoopBodyLeading(e){return e.element.type===S.doUntilSchleife?e.loopBodyLeadingInset>0?e.loopBodyLeadingInset:this.doUntilBodyLeadingInset():20}horizontalPaddingInsideCell(e){return Yi(e)?Math.max(100,this.metrics.minSidePadding*2.45):this.metrics.minSidePadding}minWidth(e){const t=e.textLines.length===0?0:Math.max(...e.textLines.map(s=>this.lineWidth(s)));let n=t+e.zoomX+this.horizontalPaddingInsideCell(e.type);if(e.type===S.aufruf){const s=Math.max(68,this.metrics.minSidePadding*1.7),r=Math.max(8,this.metrics.minSidePadding*.2);n=Math.max(n,t+e.zoomX+s+r)}const a=e.type===S.leerElement?76:e.type===S.aufruf?104:72;return Math.max(a,n)}layoutElement(e,t,n,a){if(Yi(e.type))return this.layoutMultiway(e,t,n,a);if($i(e.type))return this.layoutLoop(e,t,n,a);const s=this.headerHeight(e);return Xi(a,e,{x:t,y:n,width:this.minWidth(e),height:s},s)}layoutLoop(e,t,n,a){const s=b=>b.reduce((x,v)=>x+v.frame.height,0),r=b=>Math.max(0,...b.map(x=>x.frame.width)),o=e.loopBody??[];if(e.type===S.doUntilSchleife){const b=this.doUntilBodyLeadingInset(),x=e.zoomY,v=this.headerHeight(e),w=this.layoutList(o,t+b,n+x,[...a,0]),I=Math.max(this.minWidth(e),r(w)+b),z=s(w)+v+x,k=Math.max(0,I-b),T=Xi(a,e,{x:t,y:n,width:I,height:z},v);return T.topBandHeight=x,T.loopBodyLeadingInset=b,T.children=w.map(O=>{const D=it(O);return D.frame.x=t+b,D.frame.width=k,this.stretchDescendantsWidths(D,k)}),T}const l=20,u=this.headerHeight(e),c=e.type===S.endlosschleife?40:0,m=this.layoutList(o,t+l,n+u,[...a,0]),d=Math.max(this.minWidth(e),r(m)+l),h=u+c+s(m),g=Math.max(0,d-l),f=Xi(a,e,{x:t,y:n,width:d,height:h},u);return f.children=m.map(b=>{const x=it(b);return x.frame.x=t+l,x.frame.width=g,this.stretchDescendantsWidths(x,g)}),f}layoutMultiway(e,t,n,a){const s=this.headerHeight(e),r=e.cases??[],o=Math.max(1,r.length),l=Math.max(this.minWidth(e)/o,132);let u=[],c=[],m=0,d=0;if(r.forEach((b,x)=>{const v=t+m,w=this.layoutList(b.elements,v,n+s,[...a,x]),I=Math.max(0,...w.map(T=>T.frame.width));let z;e.type===S.verzweigung&&o===2?z=Math.max(I,(x===0?"true":"false").length*this.metrics.charWidth+24):z=Math.max(l,I);const k=w.reduce((T,O)=>T+O.frame.height,0);d=Math.max(d,k),u.push({x:v,y:n+s,width:z,height:k}),c.push(w.map(T=>{const O=it(T);return O.frame.x=v,O.frame.width=z,this.stretchDescendantsWidths(O,z)})),m+=z}),e.type===S.verzweigung&&o===2&&u.length===2){const b=Math.max(u[0].width,u[1].width),x=t,v=t+b,w=v-u[1].x;u[0]={...u[0],x,width:b},u[1]={...u[1],x:v,width:b},m=b*2,c[0]=c[0].map(I=>{const z=it(I);return z.frame.x=x,z.frame.width=b,this.stretchDescendantsWidths(z,b)}),c[1]=c[1].map(I=>{const z=uo(I,w);return z.frame.width=b,this.stretchDescendantsWidths(z,b)})}if(c.length>0){const b=L2(c,n+s);c=b.columns.map(x=>x.map(v=>this.stretchLoopBodiesVertically(v)));for(let x=0;x0?Math.max(...b.columnHeights):d}let h=Math.max(m,this.minWidth(e));if(m>.5&&h>m+.5){const b=h/m;let x=t;const v=[],w=[];u.forEach((I,z)=>{const k=I.width*b;w.push(c[z].map(T=>{const O=it(T);return O.frame.x=x,O.frame.width=k,this.stretchDescendantsWidths(O,k)})),v.push({x,y:I.y,width:k,height:I.height}),x+=k}),u=v,c=w,m=x-t,h=m}const g=u.length>0?u[u.length-1].width:m/o,f=Xi(a,e,{x:t,y:n,width:h,height:s+d},s);return f.caseColumnFrames=u,f.dividerX=u.length>0?u[u.length-1].x:t+m-g,f.dividerYInset=e.type===S.fallauswahl?-20:0,f.columns=c,f.children=c.flat(),f}}function qd(i,e){if(Math.abs(e)<=1e-4)return i;const t=it(i),n=a=>{const s=it(a);return s.frame.y+=e,qd(s,e)};return t.columns?(t.columns=t.columns.map(a=>a.map(n)),t.children=t.columns.flat()):t.children=t.children.map(n),t}function uo(i,e){if(Math.abs(e)<=1e-4)return i;const t=it(i);return t.frame.x+=e,t.columns?(t.columns=t.columns.map(n=>n.map(a=>uo(a,e))),t.children=t.columns.flat()):t.children=t.children.map(n=>uo(n,e)),t}function L2(i,e){if(i.length<2)return{columns:i,columnHeights:i.map(u=>u.reduce((c,m)=>c+m.frame.height,0))};const t=.5,n=[e];for(const u of i)for(const c of u)n.push(c.frame.y+c.frame.height);const a=Math.max(...n);n.push(a),n.sort((u,c)=>u-c);let s=[];for(const u of n)s.length>0&&Math.abs(u-s[s.length-1])<=t||s.push(u);(s.length===0||Math.abs(s[0]-e)>t)&&s.unshift(e),s.length===0?s=[e,a]:s[s.length-1]{let m=Math.max(0,c);for(;m{let g=it(d);const f=s[m],b=d.frame.y+d.frame.height,x=h===u.length-1?s.length-1:r(b,m+1),v=s[x],w=f-g.frame.y;g.frame.y=f,g.frame.height=Math.max(0,v-f),g=qd(g,w),c.push(g),m=x}),o.push(c),l.push(s[s.length-1]-e)}return{columns:o,columnHeights:l}}const E2=[{item:"anweisung",label:"Anweisung"},{item:"verzweigung",label:"Verzweigung"},{item:"fallauswahl",label:"Fallauswahl"},{item:"forZaehlSchleife",label:"For-Schleife"},{item:"whileSchleife",label:"While-Schleife"},{item:"doUntilSchleife",label:"Do-while-Schleife"},{item:"endlosschleife",label:"Endlosschleife"},{item:"aufruf",label:"Aufruf"},{item:"aussprung",label:"Aussprung"}];function nu(i){const e=nn;switch(i){case"anweisung":return Oe(S.anweisung);case"verzweigung":return Oe(S.verzweigung,{cases:[{name:"true",elements:[e()]},{name:"false",elements:[e()]}]});case"fallauswahl":return Oe(S.fallauswahl,{cases:[{name:"1",elements:[e()]},{name:"2",elements:[e()]},{name:"default",elements:[e()]}]});case"forZaehlSchleife":return Oe(S.forSchleife,{textLines:["","",""],loopBody:[e()]});case"whileSchleife":return Oe(S.whileSchleife,{loopBody:[e()]});case"doUntilSchleife":return Oe(S.doUntilSchleife,{loopBody:[e()]});case"endlosschleife":return Oe(S.endlosschleife,{loopBody:[e()]});case"aussprung":return Oe(S.aussprung);case"aufruf":return Oe(S.aufruf)}}function Ya(i){if(i==="")return"-1;";let e="";for(const t of i)e+=t.codePointAt(0)+";";return e}function co(i){const e=i.split(";").filter(n=>n!=="");if(e.length===1&&e[0]==="-1")return"";let t="";for(const n of e){if(!/^[+-]?\d+$/.test(n))continue;const a=Number(n);a!==-1&&(a<0||a>1114111||a>=55296&&a<=57343||(t+=String.fromCodePoint(a)))}return t}class iu extends Error{}function El(i){const e=new DOMParser().parseFromString(i,"application/xml");if(e.getElementsByTagName("parsererror").length>0)throw new iu("Could not read XML.");const t=e.documentElement;if(!t||t.tagName!=="struktogramm")throw new iu("Invalid XML: root element is not .");const n={caption:su(t,"caption")??"",elements:ho(t)},a=su(t,"fontfamily");a!==void 0&&(n.fontFamily=a);const s=si(t,"fontsize");s!==void 0&&(n.fontSize=s);const r=si(t,"fontstyle");return r!==void 0&&(n.fontStyle=r),t.getAttribute("pseudocode")==="true"&&(n.pseudocode=!0),n}function u1(i){const e=(n,a)=>a===void 0?"":` ${n}="${Qd(a)}"`;let t=` `;t+=" `;for(const n of i.elements)t+=mo(n," ");return t+=` `,t}function mo(i,e){let t=`${e} -`;for(const n of i.textLines)t+=`${e} ${E2(Ya(n))} +`;for(const n of i.textLines)t+=`${e} ${W2(Ya(n))} `;if(i.loopBody){t+=`${e} `;for(const n of i.loopBody)t+=mo(n,e+" ");t+=`${e} `}if(i.cases)for(const n of i.cases){t+=`${e} `;for(const a of n.elements)t+=mo(a,e+" ");t+=`${e} `}return t+=`${e} -`,t}function Qd(i){return i.replace(/&/g,"&").replace(/"/g,""").replace(//g,">")}function E2(i){return i.replace(/&/g,"&").replace(//g,">")}function au(i){return String(i.a<<24|i.r<<16|i.g<<8|i.b|0)}function Za(i,e){return Array.from(i.children).filter(t=>t.tagName===e)}function ho(i){const e=[];for(const t of Za(i,"strelem")){const n=W2(t);n&&e.push(n)}return e}function W2(i){const e=si(i,"typ");if(e===void 0||S[e]===void 0)return;const t={type:e,zoomX:si(i,"zx")??0,zoomY:si(i,"zy")??0,textLines:Za(i,"text").map(o=>co((o.textContent??"").trim()))},n=ru(i.getAttribute("textcolor"));n&&(t.textColor=n);const a=ru(i.getAttribute("bgcolor"));a&&(t.backgroundColor=a),t.textLines.length===0&&(t.textLines=[""]);const s=Za(i,"schleifeninhalt")[0];if(s){const o=ho(s);o.length>0&&(t.loopBody=o)}const r=Za(i,"fall").map(o=>({name:co(o.getAttribute("fallname")??""),elements:ho(o)}));return r.length>0&&(t.cases=r),t}function su(i,e){const t=i.getAttribute(e);return t===null?void 0:co(t)}function si(i,e){const t=i.getAttribute(e);if(!(t===null||!/^[+-]?\d+$/.test(t)))return Number(t)}function ru(i){if(i===null||!/^[+-]?\d+$/.test(i))return;const e=Number(i);if(e<-2147483648||e>2147483647)return;const t=e>>>0;return{a:t>>>24&255,r:t>>>16&255,g:t>>>8&255,b:t&255}}const N2="http://www.w3.org/2000/svg",Ee={diagramLineWidth:2,outerFrameLineWidth:2,selectionLineWidth:3.5,canvasOuterMargin:16,cellTextInsetX:18,cellTextInsetY:15,multiHeaderFirstLineY:14,branchLabelInsetX:10,fallauswahlCaseLabelBand:26,callSideBarInset:14,callTextInsetFromSideBar:20,loopBodyLeadingInset:20};function Ud(i){switch(i){case S.forSchleife:case S.whileSchleife:case S.doUntilSchleife:case S.endlosschleife:return"loop";case S.verzweigung:case S.fallauswahl:return"if";default:return}}function Se(i,e={}){const t=document.createElementNS(N2,i);for(const[n,a]of Object.entries(e))t.setAttribute(n,String(a));return t}class $d{constructor(e,t){y(this,"usesSimulationHighlight",!1);y(this,"fillsSelection",!1);this.metrics=e,this.measure=t}get lineHeight(){return this.metrics.lineHeight}get fontSize(){return this.metrics.fontSize}render(e,t,n,a=Ee.canvasOuterMargin){const s=Se("svg",{width:t.width,height:t.height,viewBox:`0 0 ${t.width} ${t.height}`,"font-family":Ns,"font-size":this.fontSize,class:"diagram"});s.append(Se("rect",{x:0,y:0,width:t.width,height:t.height,fill:"#fafafa"}));const r=a;s.append(Se("rect",{x:r,y:r,width:e.canvasSize.width-2*r-1,height:e.canvasSize.height-2*r-1,fill:"none",stroke:"black","stroke-width":Ee.outerFrameLineWidth}));const o=Se("g");for(const l of e.elements)this.drawNode(l,o,n,{},void 0,"method");return s.append(o),s}line(e,t){e.append(Se("polyline",{points:t.map(n=>n.join(",")).join(" "),fill:"none",stroke:"black","stroke-width":Ee.diagramLineWidth,"stroke-linejoin":"miter"}))}strokeCellBorder(e,t,n){const a=t.x,s=t.y,r=t.x+t.width,o=t.y+t.height;if(!n.top&&!n.left&&!n.bottom&&!n.right){e.append(Se("rect",{x:a,y:s,width:t.width,height:t.height,fill:"none",stroke:"black","stroke-width":Ee.diagramLineWidth}));return}n.top||this.line(e,[[a,s],[r,s]]),n.right||this.line(e,[[r,s],[r,o]]),n.bottom||this.line(e,[[r,o],[a,o]]),n.left||this.line(e,[[a,o],[a,s]])}textWidth(e){const t=U0(e);return t?this.measure(t.keyword,this.fontSize,"bold")+(t.rest===""?0:this.measure(" "+t.rest,this.fontSize,"medium")):this.measure(e,this.fontSize,"medium")}drawKeywordLine(e,t,n,a){const s=Se("text",{x:n,y:a+eu(this.fontSize,"medium").ascent,"font-weight":500});s.style.whiteSpace="pre";const r=U0(t);if(r){const o=Se("tspan",{"font-weight":700});if(o.textContent=r.keyword,s.append(o),r.rest!==""){const l=Se("tspan",{});l.textContent=" "+r.rest,s.append(l)}}else s.textContent=t;e.append(s)}drawLabel(e,t,n,a,s,r){const o=eu(this.fontSize,s?"bold":"medium"),l=Se("text",{x:n,y:r==="top"?a+o.ascent:a-o.descent,"font-weight":s?700:500});l.style.whiteSpace="pre",l.textContent=t,e.append(l)}roofMetrics(e,t,n,a){const s=t.y+n,r=e.dividerYInset??0,o=12,l=Math.max(e.element.textLines.length,1)*this.lineHeight,u=t.y+Ee.multiHeaderFirstLineY;if(e.element.type===S.fallauswahl){const m=Math.max(Ee.fallauswahlCaseLabelBand,this.lineHeight+10),d=s-m,h=Math.min(s+r,d-8),g=Math.max(h,u+l+6);return{apex:{x:a,y:g},maxTextBottom:d-o,roofBottom:s}}const c={x:a,y:s+r};return{apex:c,maxTextBottom:c.y-o,roofBottom:s}}drawNode(e,t,n,a,s,r){var O;const o=e.frame,l=e.element,u=o.x+o.width,c=o.y+o.height,m=l.type===S.verzweigung||l.type===S.fallauswahl,d=m?e.headerBandHeight:0,h=n!==void 0&&go(e.idPath,n),g=Dl(l),f=Se("g",{"data-path":e.idPath.join(",")});t.append(f);const b=this.usesSimulationHighlight,x=l.backgroundColor,v=x&&x.a>0?`rgba(${x.r}, ${x.g}, ${x.b}, ${x.a/255})`:"white",w=h&&(b||this.fillsSelection)?"rgba(199, 230, 255, 0.55)":v,I=Ud(l.type)??(l.type===S.leerElement?r:"method"),z=Se("rect",{x:o.x,y:o.y,width:o.width,height:o.height,fill:w});w==="white"&&I&&z.setAttribute("class",`ns-scope ns-scope-${I}`),f.append(z),this.strokeCellBorder(f,o,a);const k=Ee.callSideBarInset;if(l.type===S.aufruf?(this.line(f,[[o.x+k,o.y],[o.x+k,c]]),this.line(f,[[u-k,o.y],[u-k,c]])):l.type===S.aussprung&&this.line(f,[[o.x+k,o.y],[o.x,o.y+o.height/2],[o.x+k,c]]),m&&e.dividerX!==void 0){const D=e.dividerX,j=this.roofMetrics(e,o,d,D),P=Math.max(g.length,1)*this.lineHeight,A=o.y+Ee.multiHeaderFirstLineY;this.line(f,[[o.x,o.y],[j.apex.x,j.apex.y],[u,o.y]]),l.type===S.fallauswahl&&this.line(f,[[o.x,j.roofBottom],[u,j.roofBottom]]);let M;A+P<=j.maxTextBottom?M=A:M=Math.max(o.y+2,j.maxTextBottom-(Math.max(g.length,1)-1)*this.lineHeight-this.lineHeight),g.forEach((W,U)=>{const K=this.textWidth(W);let he;if(l.type===S.verzweigung){const Ie=o.x+Ee.cellTextInsetX,fe=u-K-Ee.cellTextInsetX;he=Math.min(Math.max(D-K/2,Ie),fe)}else he=o.x+o.width/2-K/2;this.drawKeywordLine(f,W,he,M+U*this.lineHeight)})}else if(l.type!==S.doUntilSchleife)if(l.type===S.anweisung||l.type===S.aufruf||l.type===S.aussprung){const D=Ee.cellTextInsetX;let j=o.x+D,P=u-D;l.type===S.aufruf?(j=o.x+k+Ee.callTextInsetFromSideBar,P=u-k-Ee.callTextInsetFromSideBar):l.type===S.aussprung&&(j=o.x+k+D);const A=Math.max(0,P-j);let M=o.y+o.height/2-Math.max(1,g.length)*this.lineHeight/2;for(const W of g)this.drawKeywordLine(f,W,j+(A-this.textWidth(W))/2,M),M+=this.lineHeight}else{const D=Math.max(1,g.length)*this.lineHeight;let j=s===S.doUntilSchleife?o.y+o.height/2-D/2:o.y+Ee.cellTextInsetY;for(const P of g)this.drawKeywordLine(f,P,o.x+Ee.cellTextInsetX,j),j+=this.lineHeight}e.children.forEach((D,j)=>{const P=l.type===S.doUntilSchleife&&j===0?{top:!0,left:!0}:{};this.drawNode(D,t,n,P,l.type,I)});const T=Se("g");if(t.append(T),l.type===S.doUntilSchleife){const D=((O=e.children[0])==null?void 0:O.frame.x)??o.x+(e.loopBodyLeadingInset>0?e.loopBodyLeadingInset:Ee.loopBodyLeadingInset);this.drawLabel(T,"do",o.x+4,o.y+this.metrics.doUntilDoLabelTopInset,!0,"top");const j=c-e.headerBandHeight;this.line(T,[[D,j],[u,j]]),this.line(T,[[D,o.y],[D,j]]);let P=j+this.metrics.doUntilFooterTopInset;for(const A of g)this.drawKeywordLine(T,A,o.x+Ee.cellTextInsetX,P),P+=this.lineHeight}if(m&&e.dividerX!==void 0&&e.caseColumnFrames.length>1){const D=this.roofMetrics(e,o,d,e.dividerX),j=D.apex;e.caseColumnFrames.forEach((A,M)=>{if(M>=e.caseColumnFrames.length-1)return;const W=A.x+A.width,U=F2(W,o,j),K=Number.isFinite(U)?Math.min(Math.max(U,o.y),c):o.y;this.line(T,[[W,c],[W,K]])});const P=l.cases;if(P&&P.length===e.caseColumnFrames.length){const A=l.type===S.fallauswahl?D.roofBottom-6:o.y+d-8,M=Ee.branchLabelInsetX;if(l.type===S.verzweigung&&P.length===2){this.drawLabel(T,"true",o.x+M,A,!0,"bottom");const W=e.caseColumnFrames[1],U=this.measure("false",this.fontSize,"bold");this.drawLabel(T,"false",W.x+W.width-M-U,A,!0,"bottom")}else P.forEach((W,U)=>{const K=e.caseColumnFrames[U],he=["default","true","false"].includes(W.name.toLowerCase()),Ie=this.measure(W.name,this.fontSize,he?"bold":"medium");this.drawLabel(T,W.name,K.x+K.width/2-Ie/2,A,he,"bottom")})}}h&&T.append(Se("rect",{x:o.x,y:o.y,width:o.width,height:o.height,class:"selection-frame",fill:"none",stroke:b?"rgba(66, 140, 242, 0.78)":"rgba(0, 122, 255, 0.9)","stroke-width":Ee.selectionLineWidth}))}}function F2(i,e,t){const n=e.y;if(i<=t.x){const s=t.x-e.x;return Math.abs(s)<.5?t.y:n+(t.y-n)/s*(i-e.x)}const a=e.x+e.width-t.x;return Math.abs(a)<.5?t.y:t.y+(n-t.y)/a*(i-t.x)}function go(i,e){return i.length===e.length&&i.every((t,n)=>t===e[n])}function J2(i){const e=[],t=n=>{e.push(n),n.children.forEach(t)};return i.forEach(t),e}function Xa(i){var e,t;return{...i,textLines:Dl(i),loopBody:(e=i.loopBody)==null?void 0:e.map(Xa),cases:(t=i.cases)==null?void 0:t.map(n=>({name:n.name,elements:n.elements.map(Xa)}))}}const R2=[{code:"de",name:"Deutsch"},{code:"en",name:"English"},{code:"es",name:"Español"},{code:"fr",name:"Français"},{code:"it",name:"Italiano"},{code:"pl",name:"Polski"},{code:"tr",name:"Türkçe"},{code:"ko",name:"한국어"},{code:"ja",name:"日本語"},{code:"el",name:"Ελληνικά"},{code:"uk",name:"Українська"},{code:"ar",name:"العربية"},{code:"ru",name:"Русский"},{code:"he",name:"עברית"},{code:"nl",name:"Nederlands"},{code:"sv",name:"Svenska"},{code:"da",name:"Dansk"},{code:"nb",name:"Norsk bokmål"},{code:"zh-Hans",name:"中文(简体)"},{code:"zh-Hant",name:"中文(繁體)"},{code:"pt-PT",name:"Português"},{code:"java",name:"Java (Keywords)"}],Yd=["de","en","pt-PT"],Xd=R2.filter(i=>Yd.includes(i.code)),ou=i=>Yd.includes(i),G2=Object.assign({"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ar.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-CxCno28C.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/da.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BAutdlBb.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/de.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-Dk8F86qS.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/el.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-rqA-20hM.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/en.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-DBLIUcBd.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/es.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-LSTVB2Q5.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/fr.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-ByPZS4RL.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/he.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-R-16GCrk.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/it.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-DXAPah1g.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ja.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-CkJEmEEP.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ko.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BudCXCER.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/nb.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-DSvkBkp-.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/nl.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BJ55WGVD.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/pl.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BYJK0mdR.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/pt-PT.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-CHv0OL9S.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ru.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-1QZ0wfvJ.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/sv.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-M33nNbEe.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/tr.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BM86Igqt.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/uk.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-UGog_aku.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/zh-Hans.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-CaVEL1es.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/zh-Hant.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-DqIDp_hh.js"),[],import.meta.url).then(i=>i.default)}),Kd=Object.assign({"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/Java.strings":()=>ee(()=>import("./Java-Bpx1Vwvg.js"),[],import.meta.url).then(i=>i.default)}),H2=Object.assign({"../i18n/ar.strings":()=>ee(()=>import("./ar-DeE-RHam.js"),[],import.meta.url).then(i=>i.default),"../i18n/da.strings":()=>ee(()=>import("./da-D4INXE4p.js"),[],import.meta.url).then(i=>i.default),"../i18n/de.strings":()=>ee(()=>import("./de-B05MOgXv.js"),[],import.meta.url).then(i=>i.default),"../i18n/el.strings":()=>ee(()=>import("./el-CtIZyj0I.js"),[],import.meta.url).then(i=>i.default),"../i18n/en.strings":()=>ee(()=>import("./en-OfXp05Y3.js"),[],import.meta.url).then(i=>i.default),"../i18n/es.strings":()=>ee(()=>import("./es-BAduFB3L.js"),[],import.meta.url).then(i=>i.default),"../i18n/fr.strings":()=>ee(()=>import("./fr-C_mSEvw5.js"),[],import.meta.url).then(i=>i.default),"../i18n/he.strings":()=>ee(()=>import("./he-BAg3LrWK.js"),[],import.meta.url).then(i=>i.default),"../i18n/it.strings":()=>ee(()=>import("./it-ClGS2uQV.js"),[],import.meta.url).then(i=>i.default),"../i18n/ja.strings":()=>ee(()=>import("./ja-JQ8MwNFB.js"),[],import.meta.url).then(i=>i.default),"../i18n/ko.strings":()=>ee(()=>import("./ko-tfdKG8Fb.js"),[],import.meta.url).then(i=>i.default),"../i18n/nb.strings":()=>ee(()=>import("./nb-BpibUAkX.js"),[],import.meta.url).then(i=>i.default),"../i18n/nl.strings":()=>ee(()=>import("./nl-HArZjiga.js"),[],import.meta.url).then(i=>i.default),"../i18n/pl.strings":()=>ee(()=>import("./pl-C3HmQqUD.js"),[],import.meta.url).then(i=>i.default),"../i18n/pt-PT.strings":()=>ee(()=>import("./pt-PT-DYKlzJlW.js"),[],import.meta.url).then(i=>i.default),"../i18n/ru.strings":()=>ee(()=>import("./ru-B4vTuE57.js"),[],import.meta.url).then(i=>i.default),"../i18n/sv.strings":()=>ee(()=>import("./sv-Dau75zUV.js"),[],import.meta.url).then(i=>i.default),"../i18n/tr.strings":()=>ee(()=>import("./tr-DrZsTe-O.js"),[],import.meta.url).then(i=>i.default),"../i18n/uk.strings":()=>ee(()=>import("./uk-DQrOpK2W.js"),[],import.meta.url).then(i=>i.default),"../i18n/zh-Hans.strings":()=>ee(()=>import("./zh-Hans-CeIYjS3N.js"),[],import.meta.url).then(i=>i.default),"../i18n/zh-Hant.strings":()=>ee(()=>import("./zh-Hant-7-ScZHAu.js"),[],import.meta.url).then(i=>i.default)});function Ma(i,e){var t;return(t=Object.entries(i).find(([n])=>n.endsWith(e)))==null?void 0:t[1]}function eh(i){const e=new Map,t=i.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,""),n=/"((?:[^"\\]|\\.)*)"\s*=\s*"((?:[^"\\]|\\.)*)"\s*;/g,a=s=>s.replace(/\\(u[0-9a-fA-F]{4}|.)/g,(r,o)=>o==="n"?` -`:o==="t"?" ":o.startsWith("u")&&o.length===5?String.fromCharCode(parseInt(o.slice(1),16)):o);for(const s of t.matchAll(n))e.set(a(s[1]),a(s[2]));return e}async function po(i){const e=i==="java"?Ma(Kd,"/Java.strings"):Ma(G2,`/${i}.lproj/Localizable.strings`),t=Ma(H2,`/${i}.strings`),n=new Map;for(const a of[e,t])if(a)for(const[s,r]of eh(await a()))n.set(s,r);return n}let th="en",nh=new Map,Xn=new Map;const Ka="appLanguageCode",Wl="visustruct.keywords";let fo=new Map,Nl=!1;const V2=i=>i.startsWith("element_")||i.startsWith("canvas_stub_");function q2(){try{const i=new URLSearchParams(location.search).get("lang")==="java"||localStorage.getItem(Ka)==="java";return i&&(localStorage.setItem(Ka,"en"),localStorage.setItem(Wl,"1")),i}catch{return!1}}function Q2(){try{return localStorage.getItem(Wl)==="1"}catch{return!1}}async function ih(i,e=!0){if(i&&fo.size===0){Xn.size===0&&(Xn=await po("en"));const t=Ma(Kd,"/Java.strings");if(t)for(const[n,a]of eh(await t()))V2(n)&&a!==Xn.get(n)&&fo.set(n,a)}if(Nl=i,e)try{localStorage.setItem(Wl,i?"1":"0")}catch{}}function U2(){return Nl}function $2(){if(q2())return"en";const i=new URLSearchParams(location.search).get("lang");if(i&&ou(i))return i;try{const e=localStorage.getItem(Ka);if(e&&ou(e))return e}catch{}for(const e of navigator.languages??[navigator.language]){const t=e.toLowerCase();if(t.startsWith("pt"))return"pt-PT";const n=Xd.find(a=>a.code===t.split("-")[0]);if(n)return n.code}return"en"}async function ah(i,e=!0){if(Xn.size===0&&(Xn=await po("en")),nh=i==="en"?Xn:await po(i),th=i,e)try{localStorage.setItem(Ka,i)}catch{}const t=document.documentElement;t.lang=i==="java"?"en":i,t.dir=i==="ar"||i==="he"?"rtl":"ltr"}function s1(){return th}function p(i,...e){const t=(Nl?fo.get(i):void 0)??nh.get(i)??Xn.get(i)??i;if(e.length===0)return t;let n=0;return t.replace(/%(?:(\d+)\$)?[@d]/g,(a,s)=>String(e[s?Number(s)-1:n++]??""))}const es=243,Y2=244,sh=40,hr=4,X2=1;function Fl(i){const e=i.length,t=es+(e&255)+(e>>8)&255,n=i.reduce((a,s)=>a+s,0)&255;return Uint8Array.from([es,t,e&255,e>>8,...i,n,Y2])}function K2(i,e,t){const n=Array.from(new TextEncoder().encode(i));return Fl([sh,e,t&255,t>>8&255,n.length&255,n.length>>8,...n])}function e3(i){if(i[0]!==sh||i.length<6)return;const e=new TextDecoder().decode(Uint8Array.from(i.slice(6))),t=/"ret"\s*:\s*([^}]*)\}/.exec(e);return t?{idx:i[2]|i[3]<<8,value:n3(t[1].trim())}:void 0}function t3(i){const e=[];for(;;){const t=i.indexOf(es);if(t<0){i.length=0;break}if(i.splice(0,t),i.length<4)break;const n=i[2]|i[3]<<8;if(i[1]!==(es+i[2]+i[3]&255)||n>4096){i.splice(0,1);continue}if(i.length/g,">")}function W2(i){return i.replace(/&/g,"&").replace(//g,">")}function au(i){return String(i.a<<24|i.r<<16|i.g<<8|i.b|0)}function Za(i,e){return Array.from(i.children).filter(t=>t.tagName===e)}function ho(i){const e=[];for(const t of Za(i,"strelem")){const n=N2(t);n&&e.push(n)}return e}function N2(i){const e=si(i,"typ");if(e===void 0||S[e]===void 0)return;const t={type:e,zoomX:si(i,"zx")??0,zoomY:si(i,"zy")??0,textLines:Za(i,"text").map(o=>co((o.textContent??"").trim()))},n=ru(i.getAttribute("textcolor"));n&&(t.textColor=n);const a=ru(i.getAttribute("bgcolor"));a&&(t.backgroundColor=a),t.textLines.length===0&&(t.textLines=[""]);const s=Za(i,"schleifeninhalt")[0];if(s){const o=ho(s);o.length>0&&(t.loopBody=o)}const r=Za(i,"fall").map(o=>({name:co(o.getAttribute("fallname")??""),elements:ho(o)}));return r.length>0&&(t.cases=r),t}function su(i,e){const t=i.getAttribute(e);return t===null?void 0:co(t)}function si(i,e){const t=i.getAttribute(e);if(!(t===null||!/^[+-]?\d+$/.test(t)))return Number(t)}function ru(i){if(i===null||!/^[+-]?\d+$/.test(i))return;const e=Number(i);if(e<-2147483648||e>2147483647)return;const t=e>>>0;return{a:t>>>24&255,r:t>>>16&255,g:t>>>8&255,b:t&255}}const F2="http://www.w3.org/2000/svg",Ee={diagramLineWidth:2,outerFrameLineWidth:2,selectionLineWidth:3.5,canvasOuterMargin:16,cellTextInsetX:18,cellTextInsetY:15,multiHeaderFirstLineY:14,branchLabelInsetX:10,fallauswahlCaseLabelBand:26,callSideBarInset:14,callTextInsetFromSideBar:20,loopBodyLeadingInset:20};function Ud(i){switch(i){case S.forSchleife:case S.whileSchleife:case S.doUntilSchleife:case S.endlosschleife:return"loop";case S.verzweigung:case S.fallauswahl:return"if";default:return}}function Se(i,e={}){const t=document.createElementNS(F2,i);for(const[n,a]of Object.entries(e))t.setAttribute(n,String(a));return t}class $d{constructor(e,t){y(this,"usesSimulationHighlight",!1);y(this,"fillsSelection",!1);this.metrics=e,this.measure=t}get lineHeight(){return this.metrics.lineHeight}get fontSize(){return this.metrics.fontSize}render(e,t,n,a=Ee.canvasOuterMargin){const s=Se("svg",{width:t.width,height:t.height,viewBox:`0 0 ${t.width} ${t.height}`,"font-family":Ns,"font-size":this.fontSize,class:"diagram"});s.append(Se("rect",{x:0,y:0,width:t.width,height:t.height,fill:"#fafafa"}));const r=a;s.append(Se("rect",{x:r,y:r,width:e.canvasSize.width-2*r-1,height:e.canvasSize.height-2*r-1,fill:"none",stroke:"black","stroke-width":Ee.outerFrameLineWidth}));const o=Se("g");for(const l of e.elements)this.drawNode(l,o,n,{},void 0,"method");return s.append(o),s}line(e,t){e.append(Se("polyline",{points:t.map(n=>n.join(",")).join(" "),fill:"none",stroke:"black","stroke-width":Ee.diagramLineWidth,"stroke-linejoin":"miter"}))}strokeCellBorder(e,t,n){const a=t.x,s=t.y,r=t.x+t.width,o=t.y+t.height;if(!n.top&&!n.left&&!n.bottom&&!n.right){e.append(Se("rect",{x:a,y:s,width:t.width,height:t.height,fill:"none",stroke:"black","stroke-width":Ee.diagramLineWidth}));return}n.top||this.line(e,[[a,s],[r,s]]),n.right||this.line(e,[[r,s],[r,o]]),n.bottom||this.line(e,[[r,o],[a,o]]),n.left||this.line(e,[[a,o],[a,s]])}textWidth(e){const t=U0(e);return t?this.measure(t.keyword,this.fontSize,"bold")+(t.rest===""?0:this.measure(" "+t.rest,this.fontSize,"medium")):this.measure(e,this.fontSize,"medium")}drawKeywordLine(e,t,n,a){const s=Se("text",{x:n,y:a+eu(this.fontSize,"medium").ascent,"font-weight":500});s.style.whiteSpace="pre";const r=U0(t);if(r){const o=Se("tspan",{"font-weight":700});if(o.textContent=r.keyword,s.append(o),r.rest!==""){const l=Se("tspan",{});l.textContent=" "+r.rest,s.append(l)}}else s.textContent=t;e.append(s)}drawLabel(e,t,n,a,s,r){const o=eu(this.fontSize,s?"bold":"medium"),l=Se("text",{x:n,y:r==="top"?a+o.ascent:a-o.descent,"font-weight":s?700:500});l.style.whiteSpace="pre",l.textContent=t,e.append(l)}roofMetrics(e,t,n,a){const s=t.y+n,r=e.dividerYInset??0,o=12,l=Math.max(e.element.textLines.length,1)*this.lineHeight,u=t.y+Ee.multiHeaderFirstLineY;if(e.element.type===S.fallauswahl){const m=Math.max(Ee.fallauswahlCaseLabelBand,this.lineHeight+10),d=s-m,h=Math.min(s+r,d-8),g=Math.max(h,u+l+6);return{apex:{x:a,y:g},maxTextBottom:d-o,roofBottom:s}}const c={x:a,y:s+r};return{apex:c,maxTextBottom:c.y-o,roofBottom:s}}drawNode(e,t,n,a,s,r){var O;const o=e.frame,l=e.element,u=o.x+o.width,c=o.y+o.height,m=l.type===S.verzweigung||l.type===S.fallauswahl,d=m?e.headerBandHeight:0,h=n!==void 0&&go(e.idPath,n),g=Dl(l),f=Se("g",{"data-path":e.idPath.join(",")});t.append(f);const b=this.usesSimulationHighlight,x=l.backgroundColor,v=x&&x.a>0?`rgba(${x.r}, ${x.g}, ${x.b}, ${x.a/255})`:"white",w=h&&(b||this.fillsSelection)?"rgba(199, 230, 255, 0.55)":v,I=Ud(l.type)??(l.type===S.leerElement?r:"method"),z=Se("rect",{x:o.x,y:o.y,width:o.width,height:o.height,fill:w});w==="white"&&I&&z.setAttribute("class",`ns-scope ns-scope-${I}`),f.append(z),this.strokeCellBorder(f,o,a);const k=Ee.callSideBarInset;if(l.type===S.aufruf?(this.line(f,[[o.x+k,o.y],[o.x+k,c]]),this.line(f,[[u-k,o.y],[u-k,c]])):l.type===S.aussprung&&this.line(f,[[o.x+k,o.y],[o.x,o.y+o.height/2],[o.x+k,c]]),m&&e.dividerX!==void 0){const D=e.dividerX,P=this.roofMetrics(e,o,d,D),j=Math.max(g.length,1)*this.lineHeight,A=o.y+Ee.multiHeaderFirstLineY;this.line(f,[[o.x,o.y],[P.apex.x,P.apex.y],[u,o.y]]),l.type===S.fallauswahl&&this.line(f,[[o.x,P.roofBottom],[u,P.roofBottom]]);let M;A+j<=P.maxTextBottom?M=A:M=Math.max(o.y+2,P.maxTextBottom-(Math.max(g.length,1)-1)*this.lineHeight-this.lineHeight),g.forEach((W,U)=>{const K=this.textWidth(W);let he;if(l.type===S.verzweigung){const Ie=o.x+Ee.cellTextInsetX,fe=u-K-Ee.cellTextInsetX;he=Math.min(Math.max(D-K/2,Ie),fe)}else he=o.x+o.width/2-K/2;this.drawKeywordLine(f,W,he,M+U*this.lineHeight)})}else if(l.type!==S.doUntilSchleife)if(l.type===S.anweisung||l.type===S.aufruf||l.type===S.aussprung){const D=Ee.cellTextInsetX;let P=o.x+D,j=u-D;l.type===S.aufruf?(P=o.x+k+Ee.callTextInsetFromSideBar,j=u-k-Ee.callTextInsetFromSideBar):l.type===S.aussprung&&(P=o.x+k+D);const A=Math.max(0,j-P);let M=o.y+o.height/2-Math.max(1,g.length)*this.lineHeight/2;for(const W of g)this.drawKeywordLine(f,W,P+(A-this.textWidth(W))/2,M),M+=this.lineHeight}else{const D=Math.max(1,g.length)*this.lineHeight;let P=s===S.doUntilSchleife?o.y+o.height/2-D/2:o.y+Ee.cellTextInsetY;for(const j of g)this.drawKeywordLine(f,j,o.x+Ee.cellTextInsetX,P),P+=this.lineHeight}e.children.forEach((D,P)=>{const j=l.type===S.doUntilSchleife&&P===0?{top:!0,left:!0}:{};this.drawNode(D,t,n,j,l.type,I)});const T=Se("g");if(t.append(T),l.type===S.doUntilSchleife){const D=((O=e.children[0])==null?void 0:O.frame.x)??o.x+(e.loopBodyLeadingInset>0?e.loopBodyLeadingInset:Ee.loopBodyLeadingInset);this.drawLabel(T,"do",o.x+4,o.y+this.metrics.doUntilDoLabelTopInset,!0,"top");const P=c-e.headerBandHeight;this.line(T,[[D,P],[u,P]]),this.line(T,[[D,o.y],[D,P]]);let j=P+this.metrics.doUntilFooterTopInset;for(const A of g)this.drawKeywordLine(T,A,o.x+Ee.cellTextInsetX,j),j+=this.lineHeight}if(m&&e.dividerX!==void 0&&e.caseColumnFrames.length>1){const D=this.roofMetrics(e,o,d,e.dividerX),P=D.apex;e.caseColumnFrames.forEach((A,M)=>{if(M>=e.caseColumnFrames.length-1)return;const W=A.x+A.width,U=J2(W,o,P),K=Number.isFinite(U)?Math.min(Math.max(U,o.y),c):o.y;this.line(T,[[W,c],[W,K]])});const j=l.cases;if(j&&j.length===e.caseColumnFrames.length){const A=l.type===S.fallauswahl?D.roofBottom-6:o.y+d-8,M=Ee.branchLabelInsetX;if(l.type===S.verzweigung&&j.length===2){this.drawLabel(T,"true",o.x+M,A,!0,"bottom");const W=e.caseColumnFrames[1],U=this.measure("false",this.fontSize,"bold");this.drawLabel(T,"false",W.x+W.width-M-U,A,!0,"bottom")}else j.forEach((W,U)=>{const K=e.caseColumnFrames[U],he=["default","true","false"].includes(W.name.toLowerCase()),Ie=this.measure(W.name,this.fontSize,he?"bold":"medium");this.drawLabel(T,W.name,K.x+K.width/2-Ie/2,A,he,"bottom")})}}h&&T.append(Se("rect",{x:o.x,y:o.y,width:o.width,height:o.height,class:"selection-frame",fill:"none",stroke:b?"rgba(66, 140, 242, 0.78)":"rgba(0, 122, 255, 0.9)","stroke-width":Ee.selectionLineWidth}))}}function J2(i,e,t){const n=e.y;if(i<=t.x){const s=t.x-e.x;return Math.abs(s)<.5?t.y:n+(t.y-n)/s*(i-e.x)}const a=e.x+e.width-t.x;return Math.abs(a)<.5?t.y:t.y+(n-t.y)/a*(i-t.x)}function go(i,e){return i.length===e.length&&i.every((t,n)=>t===e[n])}function R2(i){const e=[],t=n=>{e.push(n),n.children.forEach(t)};return i.forEach(t),e}function Xa(i){var e,t;return{...i,textLines:Dl(i),loopBody:(e=i.loopBody)==null?void 0:e.map(Xa),cases:(t=i.cases)==null?void 0:t.map(n=>({name:n.name,elements:n.elements.map(Xa)}))}}const G2=[{code:"de",name:"Deutsch"},{code:"en",name:"English"},{code:"es",name:"Español"},{code:"fr",name:"Français"},{code:"it",name:"Italiano"},{code:"pl",name:"Polski"},{code:"tr",name:"Türkçe"},{code:"ko",name:"한국어"},{code:"ja",name:"日本語"},{code:"el",name:"Ελληνικά"},{code:"uk",name:"Українська"},{code:"ar",name:"العربية"},{code:"ru",name:"Русский"},{code:"he",name:"עברית"},{code:"nl",name:"Nederlands"},{code:"sv",name:"Svenska"},{code:"da",name:"Dansk"},{code:"nb",name:"Norsk bokmål"},{code:"zh-Hans",name:"中文(简体)"},{code:"zh-Hant",name:"中文(繁體)"},{code:"pt-PT",name:"Português"},{code:"java",name:"Java (Keywords)"}],Yd=["de","en","pt-PT"],Xd=G2.filter(i=>Yd.includes(i.code)),ou=i=>Yd.includes(i),H2=Object.assign({"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ar.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-CxCno28C.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/da.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BAutdlBb.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/de.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-Dk8F86qS.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/el.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-rqA-20hM.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/en.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-DBLIUcBd.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/es.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-LSTVB2Q5.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/fr.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-ByPZS4RL.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/he.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-R-16GCrk.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/it.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-DXAPah1g.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ja.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-CkJEmEEP.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ko.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BudCXCER.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/nb.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-DSvkBkp-.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/nl.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BJ55WGVD.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/pl.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BYJK0mdR.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/pt-PT.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-CHv0OL9S.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ru.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-1QZ0wfvJ.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/sv.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-M33nNbEe.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/tr.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-BM86Igqt.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/uk.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-UGog_aku.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/zh-Hans.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-CaVEL1es.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/zh-Hant.lproj/Localizable.strings":()=>ee(()=>import("./Localizable-DqIDp_hh.js"),[],import.meta.url).then(i=>i.default)}),Kd=Object.assign({"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/Java.strings":()=>ee(()=>import("./Java-Bpx1Vwvg.js"),[],import.meta.url).then(i=>i.default)}),V2=Object.assign({"../i18n/ar.strings":()=>ee(()=>import("./ar-DeE-RHam.js"),[],import.meta.url).then(i=>i.default),"../i18n/da.strings":()=>ee(()=>import("./da-D4INXE4p.js"),[],import.meta.url).then(i=>i.default),"../i18n/de.strings":()=>ee(()=>import("./de-DS9kn30Y.js"),[],import.meta.url).then(i=>i.default),"../i18n/el.strings":()=>ee(()=>import("./el-CtIZyj0I.js"),[],import.meta.url).then(i=>i.default),"../i18n/en.strings":()=>ee(()=>import("./en-Mt2ryoik.js"),[],import.meta.url).then(i=>i.default),"../i18n/es.strings":()=>ee(()=>import("./es-BAduFB3L.js"),[],import.meta.url).then(i=>i.default),"../i18n/fr.strings":()=>ee(()=>import("./fr-C_mSEvw5.js"),[],import.meta.url).then(i=>i.default),"../i18n/he.strings":()=>ee(()=>import("./he-BAg3LrWK.js"),[],import.meta.url).then(i=>i.default),"../i18n/it.strings":()=>ee(()=>import("./it-ClGS2uQV.js"),[],import.meta.url).then(i=>i.default),"../i18n/ja.strings":()=>ee(()=>import("./ja-JQ8MwNFB.js"),[],import.meta.url).then(i=>i.default),"../i18n/ko.strings":()=>ee(()=>import("./ko-tfdKG8Fb.js"),[],import.meta.url).then(i=>i.default),"../i18n/nb.strings":()=>ee(()=>import("./nb-BpibUAkX.js"),[],import.meta.url).then(i=>i.default),"../i18n/nl.strings":()=>ee(()=>import("./nl-HArZjiga.js"),[],import.meta.url).then(i=>i.default),"../i18n/pl.strings":()=>ee(()=>import("./pl-C3HmQqUD.js"),[],import.meta.url).then(i=>i.default),"../i18n/pt-PT.strings":()=>ee(()=>import("./pt-PT-ClEeb4rA.js"),[],import.meta.url).then(i=>i.default),"../i18n/ru.strings":()=>ee(()=>import("./ru-B4vTuE57.js"),[],import.meta.url).then(i=>i.default),"../i18n/sv.strings":()=>ee(()=>import("./sv-Dau75zUV.js"),[],import.meta.url).then(i=>i.default),"../i18n/tr.strings":()=>ee(()=>import("./tr-DrZsTe-O.js"),[],import.meta.url).then(i=>i.default),"../i18n/uk.strings":()=>ee(()=>import("./uk-DQrOpK2W.js"),[],import.meta.url).then(i=>i.default),"../i18n/zh-Hans.strings":()=>ee(()=>import("./zh-Hans-CeIYjS3N.js"),[],import.meta.url).then(i=>i.default),"../i18n/zh-Hant.strings":()=>ee(()=>import("./zh-Hant-7-ScZHAu.js"),[],import.meta.url).then(i=>i.default)});function Ma(i,e){var t;return(t=Object.entries(i).find(([n])=>n.endsWith(e)))==null?void 0:t[1]}function eh(i){const e=new Map,t=i.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,""),n=/"((?:[^"\\]|\\.)*)"\s*=\s*"((?:[^"\\]|\\.)*)"\s*;/g,a=s=>s.replace(/\\(u[0-9a-fA-F]{4}|.)/g,(r,o)=>o==="n"?` +`:o==="t"?" ":o.startsWith("u")&&o.length===5?String.fromCharCode(parseInt(o.slice(1),16)):o);for(const s of t.matchAll(n))e.set(a(s[1]),a(s[2]));return e}async function po(i){const e=i==="java"?Ma(Kd,"/Java.strings"):Ma(H2,`/${i}.lproj/Localizable.strings`),t=Ma(V2,`/${i}.strings`),n=new Map;for(const a of[e,t])if(a)for(const[s,r]of eh(await a()))n.set(s,r);return n}let th="en",nh=new Map,Xn=new Map;const Ka="appLanguageCode",Wl="visustruct.keywords";let fo=new Map,Nl=!1;const q2=i=>i.startsWith("element_")||i.startsWith("canvas_stub_");function Q2(){try{const i=new URLSearchParams(location.search).get("lang")==="java"||localStorage.getItem(Ka)==="java";return i&&(localStorage.setItem(Ka,"en"),localStorage.setItem(Wl,"1")),i}catch{return!1}}function U2(){try{return localStorage.getItem(Wl)==="1"}catch{return!1}}async function ih(i,e=!0){if(i&&fo.size===0){Xn.size===0&&(Xn=await po("en"));const t=Ma(Kd,"/Java.strings");if(t)for(const[n,a]of eh(await t()))q2(n)&&a!==Xn.get(n)&&fo.set(n,a)}if(Nl=i,e)try{localStorage.setItem(Wl,i?"1":"0")}catch{}}function $2(){return Nl}function Y2(){if(Q2())return"en";const i=new URLSearchParams(location.search).get("lang");if(i&&ou(i))return i;try{const e=localStorage.getItem(Ka);if(e&&ou(e))return e}catch{}for(const e of navigator.languages??[navigator.language]){const t=e.toLowerCase();if(t.startsWith("pt"))return"pt-PT";const n=Xd.find(a=>a.code===t.split("-")[0]);if(n)return n.code}return"en"}async function ah(i,e=!0){if(Xn.size===0&&(Xn=await po("en")),nh=i==="en"?Xn:await po(i),th=i,e)try{localStorage.setItem(Ka,i)}catch{}const t=document.documentElement;t.lang=i==="java"?"en":i,t.dir=i==="ar"||i==="he"?"rtl":"ltr"}function s1(){return th}function p(i,...e){const t=(Nl?fo.get(i):void 0)??nh.get(i)??Xn.get(i)??i;if(e.length===0)return t;let n=0;return t.replace(/%(?:(\d+)\$)?[@d]/g,(a,s)=>String(e[s?Number(s)-1:n++]??""))}const es=243,X2=244,sh=40,hr=4,K2=1;function Fl(i){const e=i.length,t=es+(e&255)+(e>>8)&255,n=i.reduce((a,s)=>a+s,0)&255;return Uint8Array.from([es,t,e&255,e>>8,...i,n,X2])}function e3(i,e,t){const n=Array.from(new TextEncoder().encode(i));return Fl([sh,e,t&255,t>>8&255,n.length&255,n.length>>8,...n])}function t3(i){if(i[0]!==sh||i.length<6)return;const e=new TextDecoder().decode(Uint8Array.from(i.slice(6))),t=/"ret"\s*:\s*([^}]*)\}/.exec(e);return t?{idx:i[2]|i[3]<<8,value:i3(t[1].trim())}:void 0}function n3(i){const e=[];for(;;){const t=i.indexOf(es);if(t<0){i.length=0;break}if(i.splice(0,t),i.length<4)break;const n=i[2]|i[3]<<8;if(i[1]!==(es+i[2]+i[3]&255)||n>4096){i.splice(0,1);continue}if(i.lengthArray.from({length:e},(t,n)=>i>>>8*n&255);function r3(i){let e=0;for(let t=0;t>>0;return ri(e,4)}const gr=(i,e)=>Fl([1,0,rh,i,...ri(e.length,2),...e]);function o3(i,e=i3){const t=new TextEncoder().encode(i),n=(4-t.length%F1+F1)%F1,a=new Uint8Array(t.length+n).fill(10);a.set(t);const s=[gr(1,[0,...ri(a.length,4),...r3(a),...Array.from(new TextEncoder().encode(e))])],r=a.length-4;for(let o=0;oi.length===3&&i[0]===13,u3=i=>i.length===7||i.some((e,t)=>e===rh&&i[t+1]===240),oh=()=>typeof navigator>"u"?void 0:navigator.serial,pr=()=>oh()!==void 0,c3=(...i)=>`exec(${JSON.stringify(i.join("; "))})`,Fs=(i,e=24)=>c3("cyberpi.display.clear()",`cyberpi.display.show_label(${JSON.stringify(i)}, ${e}, 'center')`),lh=Fs("VisuBot",32);class m3{constructor(){y(this,"port");y(this,"writer");y(this,"reader");y(this,"loop");y(this,"rx",[]);y(this,"idx",1);y(this,"frameWaiters",[]);y(this,"waiting",new Map);y(this,"queue",Promise.resolve());y(this,"listeners",new Set);y(this,"error");y(this,"connecting",!1)}listen(e){return this.listeners.add(e),()=>this.listeners.delete(e)}changed(){for(const e of this.listeners)e()}get connected(){return this.writer!==void 0&&!this.connecting}async connect(){const e=oh();if(!e)throw new Error("Web Serial");const t=await e.requestPort();await t.open({baudRate:115200}),this.port=t,this.writer=t.writable.getWriter(),this.error=void 0,this.connecting=!0,this.changed(),this.loop=this.readLoop(),window.addEventListener("pagehide",()=>void this.disconnect(),{once:!0}),await new Promise(n=>setTimeout(n,3e3)),this.writer&&(this.rx.length=0,this.connecting=!1,this.changed(),await this.run(lh))}async disconnect(e){if(!this.port)return this.error=e,this.changed();if(!e&&this.writer&&!this.connecting)for(const r of["mbot2.EM_stop('ALL')","cyberpi.led.off()",Fs("Bis bald!")])await this.send(r,hr,2e3).catch(()=>{});const t=this.port,n=this.writer,a=this.reader,s=this.loop;this.port=this.writer=this.reader=this.loop=void 0,this.error=e,this.connecting=!1;for(const r of this.waiting.values())r.reject(new Error(e??"getrennt"));this.waiting.clear();try{await(a==null?void 0:a.cancel()),await s,await(n==null?void 0:n.close())}catch{}try{n==null||n.releaseLock(),await t.close()}catch(r){console.warn("[mBot2] Schließen",r.message)}this.changed()}run(e){return this.send(e,hr,3e4).then(()=>{})}ask(e){return this.send(e,X2,3e3)}async upload(e,t=()=>{}){if(this.port||await this.connect(),!this.writer)throw new Error(this.error??"nicht verbunden");const n=o3(e),a=6+n.length+3;let s=0;const r=()=>t(++s,a),o=async()=>{await this.sendFrame(Fl(a3),l3),r();for(const l of s3)await this.send(l,hr,3e3),r()};await o(),await o();for(const l of n)await this.sendFrame(l,u3),r();s=a-3,await o(),await this.restart()}sendFrame(e,t){const n=this.queue.then(async()=>{for(let a=0;a<3;a++){if(!this.writer)throw new Error("nicht verbunden");let s=()=>{};const r=new Promise(u=>s=u),o={match:t,resolve:s};this.frameWaiters.push(o),await this.writer.write(e);const l=await Promise.race([r.then(()=>!0),new Promise(u=>setTimeout(()=>u(!1),3e3))]);if(this.frameWaiters=this.frameWaiters.filter(u=>u!==o),l)return}throw new Error("keine Antwort")});return this.queue=n.catch(()=>{}),n}async restart(){const e=this.port;await this.disconnect("restart"),this.error=void 0,await new Promise(t=>setTimeout(t,300)),await e.open({baudRate:115200}),await new Promise(t=>setTimeout(t,500)),await e.close(),this.changed()}send(e,t,n){const a=this.queue.then(()=>new Promise((s,r)=>{if(!this.writer)return r(new Error("nicht verbunden"));const o=this.idx;this.idx=this.idx%65535+1;const l=setTimeout(()=>{this.waiting.delete(o),r(new Error("keine Antwort"))},n);this.waiting.set(o,{resolve:u=>(clearTimeout(l),s(u)),reject:u=>(clearTimeout(l),r(u))}),this.writer.write(K2(e,t,o)).catch(u=>{this.waiting.delete(o),r(u)})}));return this.queue=a.catch(()=>{}),a}async readLoop(){var e;for(;(e=this.port)!=null&&e.readable;){const t=this.port.readable.getReader();this.reader=t;try{for(;;){const{value:n,done:a}=await t.read();if(a)break;this.rx.push(...n);for(const s of t3(this.rx)){const r=this.frameWaiters.findIndex(u=>u.match(s));r>=0&&this.frameWaiters.splice(r,1)[0].resolve();const o=e3(s);if(!o)continue;const l=this.waiting.get(o.idx);this.waiting.delete(o.idx),l==null||l.resolve(o.value)}}}catch(n){const a=["BufferOverrunError","FramingError","BreakError","ParityError"].includes(n.name);console.warn("[mBot2] Lesefehler",n.name,n.message),!a&&this.port&&this.disconnect(n.message)}finally{t.releaseLock()}if(!this.writer)break}}}const ge=new m3,uh=5,d3=i=>Number.isInteger(i)&&i>=0&&iString(Math.round(i*100)/100),yi={forward:{args:1,defaults:[lu],python:([i])=>`mbot2.straight(${ke(i)})`,label:([i])=>`${ke(i)} cm vorwärts`},backward:{args:1,defaults:[lu],python:([i])=>`mbot2.straight(${ke(-i)})`,label:([i])=>`${ke(i)} cm rückwärts`},turnLeft:{args:1,defaults:[90],python:([i])=>`mbot2.turn(${ke(-i)})`,label:([i])=>`${ke(i)}° nach links drehen`},turnRight:{args:1,defaults:[90],python:([i])=>`mbot2.turn(${ke(i)})`,label:([i])=>`${ke(i)}° nach rechts drehen`},stop:{args:0,python:()=>'mbot2.EM_stop("ALL")',label:()=>"anhalten"},drive:{args:2,python:([i,e])=>`mbot2.drive_power(${ke(i)}, ${ke(-e)})`,label:([i,e])=>`Räder links ${ke(i)} %, rechts ${ke(e)} %`},setLed:{args:3,python:([i,e,t])=>`cyberpi.led.on(${ke(i)}, ${ke(e)}, ${ke(t)})`,label:([i,e,t])=>`LEDs (${ke(i)}, ${ke(e)}, ${ke(t)})`},ledOff:{args:0,python:()=>"cyberpi.led.off()",label:()=>"LEDs aus"},ledColor:{args:1,text:!0,choices:Object.keys(ts),valid:([i])=>d3(i),python:([i],e)=>`cyberpi.led.on(${ts[e].join(", ")}, id=${i+1})`,label:([i],e)=>`LED ${i}: ${e}`},playTone:{args:2,python:([i,e])=>`cyberpi.audio.play_tone(${ke(i)}, ${ke(e/1e3)})`,label:([i,e])=>`Ton ${ke(i)} Hz, ${ke(e)} ms`},pause:{args:1,label:([i])=>`${ke(i)} ms warten`},resetTimer:{args:0,python:()=>"cyberpi.timer.reset()",label:()=>"Stoppuhr auf 0"},emotion:{args:0,text:!0,choices:h3,python:(i,e)=>`cyberpi.emotion.${e}()`,label:(i,e)=>`Gefühl: ${e}`},showText:{args:0,text:!0,python:(i,e)=>Fs(e),label:(i,e)=>`Bildschirm: ${e}`}},uu={red:{de:"rot",en:"red"},green:{de:"grün",en:"green"},blue:{de:"blau",en:"blue"},yellow:{de:"gelb",en:"yellow"},cyan:{de:"türkis",en:"cyan"},purple:{de:"lila",en:"purple"},white:{de:"weiß",en:"white"},black:{de:"schwarz",en:"black"}};let Jl="en";function g3(i){Jl=i==="de"?"de":"en"}const p3=()=>Jl;function ch(i){const e=i.trim().toLowerCase(),t=uu[e]??Object.values(uu).find(n=>n.de===e);return t?t[Jl]:e}const c1=i=>({python:`cyberpi.controller.is_press('${i}')`,simulated:!1}),Ot={getDistance:{python:"mbuild.ultrasonic2.get(1)",simulated:100},getLine:{python:"mbuild.quad_rgb_sensor.get_line_sta('all', 1)",simulated:0},isLineLeft:{python:"mbuild.quad_rgb_sensor.is_line('L1', 1)",simulated:!1},isLineRight:{python:"mbuild.quad_rgb_sensor.is_line('R1', 1)",simulated:!1},getColor:{python:"mbuild.quad_rgb_sensor.get_color_sta('L1', 1)",simulated:"white"},isButtonA:c1("a"),isButtonB:c1("b"),isJoystickUp:c1("up"),isJoystickDown:c1("down"),isJoystickLeft:c1("left"),isJoystickRight:c1("right"),getBrightness:{python:"cyberpi.get_bri()",simulated:50},getLoudness:{python:"cyberpi.get_loudness('maximum')",simulated:0},getPitch:{python:"cyberpi.get_pitch()",simulated:0},getRoll:{python:"cyberpi.get_roll()",simulated:0},isShaken:{python:"cyberpi.is_shake()",simulated:!1},getBattery:{python:"cyberpi.get_battery()",simulated:100},getTimer:{python:"cyberpi.timer.get()",simulated:0}};function f3(i){const e=new Set;for(const t of i.matchAll(/\bmbot\s*\.\s*([A-Za-z_]\w*)\s*\(\s*\)/gu))t[1]in Ot&&e.add(t[1]);return[...e]}function b3(i){const e=/^mbot\s*\.\s*led\s*\(([^()]*(?:\([^()]*\)[^()]*)*)\)\s*\.\s*setColor\s*\(([\s\S]*)\)\s*;?$/u.exec(i.trim());if(e)return{method:"ledColor",args:[e[1].trim(),e[2].trim()]};const t=/^mbot\s*\.\s*([A-Za-z_]\w*)\s*\(([\s\S]*)\)\s*;?$/u.exec(i.trim());if(!t)return;const n=t[2].trim();return{method:t[1],args:n===""?[]:y3(n)}}function ns(i,e){const t=yi[i];if(!t)return;const n=e.length===0&&t.defaults?t.defaults:e;if(n.length===t.args)return!t.valid||t.valid(n)?n:void 0}function cu(i,e,t=""){var a;const n=yi[i];return{method:i,args:e,python:(a=n.python)==null?void 0:a.call(n,e,t),waitMs:i==="pause"?Math.max(0,e[0]):void 0,label:n.label(e,t),...n.text?{text:t}:{}}}function mh(i){return i.map(e=>[e.method,...e.args.map(ke),...e.text!==void 0?[JSON.stringify(e.text)]:[]].join(" "))}function x3(i){let e=0;const t=i.trim(),n=()=>{const s=[];for(;;){for(;t[e]===" "||t[e]===",";)e++;if(e>=t.length||t[e]===")")return s;const r=/^(\d+)\s*[x×]\s*\(/u.exec(t.slice(e));if(r){e+=r[0].length;const m=n();if(t[e]!==")")throw new Error(`„)“ fehlt in „${i}“`);e++;for(let d=0;d{if(!(n in Ot))return t;const a=e(n);return typeof a=="string"?JSON.stringify(n==="getColor"?ch(a):a):String(a)}):i}function y3(i){const e=[];let t=0,n=!1,a=0;for(let s=0;s{const a=t==="turn"?((n+180)%360+360)%360-180:n;if(Math.abs(a)<1e-6)return[];const s=Math.round(Math.abs(a)*100)/100;return t==="drive"?[`${a>0?"forward":"backward"} ${s}`]:[a===-180?"turnRight 180":`${a>0?"turnRight":"turnLeft"} ${s}`]})}function dh(i){let e=0;const t=i.trim(),n=()=>{const s=[];for(;;){for(;t[e]===" "||t[e]===",";)e++;if(e>=t.length||t[e]===")")return s;const r=/^(\d+)\s*[x×]\s*\(/u.exec(t.slice(e));if(r){e+=r[0].length;const u=n();if(t[e]!==")")throw new Error(`„)“ fehlt in „${i}“`);e++;for(let c=0;ca===i[s%t])){const a=X1(i.slice(0,t));return`${n} x ${t===1?a:`(${a})`}`}}return i.join(", ")}const hh=["cyberpi","screen","joystick","buttons","leds","lightSensor","microphone","shield","powerSwitch","motors","wheels","ultrasonic","lineSensor","caster","chassis"],w3=i=>hh.includes(i),z3=100;function gh(i){switch(i.kind){case"finished":return"Simulation finished.";case"infiniteLoopWithoutBody":return"Infinite loop has no body.";case"unsupportedStatement":return`Unsupported statement: ${i.text}`;case"invalidExpression":return`Invalid expression: ${i.text}`;case"unknownVariable":return`Unknown variable: ${i.text}`;case"divisionByZero":return"Division by zero.";case"wholeNumberExpected":return"Please enter a whole number.";case"numberExpected":return"Please enter a number.";case"booleanExpected":return"Please enter true or false.";case"subprogramNotFound":return`No open diagram is called ${i.text}. The call was skipped.`;case"callTooDeep":return"Too many nested calls. Does a subprogram call itself?";case"callArguments":return`The call does not match the header of ${i.text}. Check the values in the parentheses.`;case"missingReturn":return`${i.text} ended without returning a value with return.`;case"fileNotFound":return`There is no file called ${i.text}.`;case"endOfFile":return`The file ${i.text} has no more lines.`;case"nullValue":return`${i.text} is null.`;case"other":return i.text}}class Ne extends Error{constructor(e){super(gh(e)),this.notice=e}}const Ke=i=>new Ne({kind:"unsupportedStatement",text:i}),R=i=>new Ne({kind:"invalidExpression",text:i}),K1=i=>new Ne({kind:"unknownVariable",text:i}),I3=()=>new Ne({kind:"divisionByZero"}),as=new Map;function k3(i,e){as.set(i,e)}const ph=()=>[...as];function mu(i){return i instanceof Ne?i.notice:{kind:"other",text:i instanceof Error?i.message:String(i)}}function S3(i){if(i===0)return"0";if(!Number.isFinite(i))return Number.isNaN(i)?"nan":i>0?"inf":"-inf";const e=Math.floor(Math.log10(Math.abs(Number(i.toPrecision(12)))));if(e<-4||e>=12){const[n,a]=i.toExponential(11).split("e"),s=n.includes(".")?n.replace(/0+$/,"").replace(/\.$/,""):n,r=Number(a);return`${s}e${r<0?"-":"+"}${String(Math.abs(r)).padStart(2,"0")}`}const t=i.toFixed(Math.max(0,11-e));return t.includes(".")?t.replace(/0+$/,"").replace(/\.$/,""):t}function du(i){return Number.isFinite(i)&&Math.round(i)===i?i.toFixed(1):S3(i)}function _e(i){switch(i.kind){case"int":return String(i.value);case"double":return du(i.value);case"string":return i.value;case"boolean":return String(i.value);case"intArray":return"["+i.value.map(String).join(", ")+"]";case"doubleArray":return"["+i.value.map(du).join(", ")+"]";case"stringArray":return"["+i.value.join(", ")+"]";case"booleanArray":return"["+i.value.map(String).join(", ")+"]";case"grid":return"["+T3(i).join(", ")+"]";case"reader":return`${i.className}(${i.file})`;case"writer":return`PrintWriter(${i.file})`;case"null":return"null"}}function T3(i){return i.value.map(e=>"["+e.map(t=>_e(bo(i.elementType,t))).join(", ")+"]")}function bo(i,e){switch(i){case"int":return{kind:"int",value:e};case"double":return{kind:"double",value:e};case"string":return{kind:"string",value:e};case"boolean":return{kind:"boolean",value:e}}}function hu(i){return i==="string"?"":i==="boolean"?!1:0}function xo(i){return i.kind==="intArray"||i.kind==="doubleArray"||i.kind==="stringArray"||i.kind==="booleanArray"||i.kind==="grid"}function _3(i){return i.kind==="int"||i.kind==="double"?i.value:NaN}const It=i=>({kind:"int",value:i}),kt=i=>({kind:"double",value:i}),Rl=i=>i!==void 0&&/\s/u.test(i),ss=i=>new RegExp("\\p{L}","u").test(i),ei=i=>new RegExp("\\p{N}","u").test(i);function oi(i){const e=Array.from(i);return e.length===0||!(ss(e[0])||e[0]==="_")?!1:e.every(t=>ss(t)||ei(t)||t==="_")}function tn(i){switch(i.toLowerCase()){case"int":return"int";case"double":return"double";case"string":return"string";case"char":return"string";case"boolean":case"bool":return"boolean";default:return}}function gu(i){return i.kind==="int"?"int":i.kind==="double"?"double":i.kind==="boolean"?"boolean":"string"}function lt(i){const e=Array.from(i);if(e.length===3&&e[0]==="'"&&e[2]==="'")return e[1];if(e.length<2||e[0]!=='"'||e[e.length-1]!=='"')return;const t=e.slice(1,-1).join("");if(/^(?:[^"\\]|\\.)*$/u.test(t))return t.replaceAll('\\"','"').replaceAll("\\n",` -`)}function pu(i){return i.replaceAll("(int)","").replaceAll("(double)","").trim()}function Gl(i){const e=new Array(i.length).fill(!1);let t=0,n=!1,a=!1;return i.forEach((s,r)=>{if(n){a?a=!1:s==="\\"?a=!0:s==='"'&&(n=!1);return}switch(s){case'"':n=!0;break;case"(":case"[":t+=1;break;case")":case"]":t-=1;break;default:e[r]=t===0}}),e}function rs(i,e){const t=Array.from(i),n=Array.from(e),a=Gl(t),s=[];let r=[],o=0;for(;ot[o+c]===u)&&a.slice(o,l).every(Boolean)){s.push(r.join("").trim()),r=[],o=l;continue}r.push(t[o]),o+=1}return s.push(r.join("").trim()),s}function O3(i){const e=Array.from(i),t=Gl(e);for(let n=0;n=","<=","==","!="].includes(o)&&(a=o)}if(a===void 0&&(e[n]==="<"||e[n]===">")&&(a=e[n]),a===void 0)continue;const s=e.slice(0,n).join("").trim(),r=e.slice(n+a.length).join("").trim();return{lhs:s,op:a,rhs:r}}}function Js(i,e){let t=0,n=!1,a=!1;for(let s=e;se.length||!t.every((r,o)=>e[a+o]===r))continue;const s=a+t.length-1;if(Js(e,s)===e.length-1)return{lhs:e.slice(0,a).join("").trim(),rhs:e.slice(s+1,-1).join("").trim()}}}function Ki(i){const e=i.trim();for(const t of["if","while","until","switch"]){if(!e.startsWith(t))continue;const n=e.slice(t.length);if(!(n===""||Rl(n[0])||n[0]==="("))continue;let a=n.trim();const s=fh(a);return s!==void 0&&(a=s),a===""?"true":a}return e===""?"true":e}function g1(i){const e=i.trim(),t=e.indexOf("[");if(!e.endsWith("]")||t<0)return;const n=e.slice(0,t).trim();if(!oi(n))return;const a=[];let s=t;for(;s2))return{arrayName:n,indexExpressions:a}}function C3(i){const e=i.trim();if(!e.endsWith(")"))return;const t=/^([A-Za-z_]\w*(?:\s*\[[^\[\]]*\])*|"(?:[^"\\]|\\.)*")\s*\.\s*([A-Za-z_]\w*)\s*\(/u.exec(e);if(!t)return;const n=Array.from(e),a=Array.from(t[0]).length-1;if(Js(n,a)!==n.length-1)return;const s=n.slice(a+1,-1).join("").trim();return{target:t[1],method:t[2],args:s===""?[]:rs(s,",")}}function fu(i){return oi(i)||g1(i)!==void 0}function fr(i){const e=[];let t="",n=!1,a=!1,s=0;for(const r of i){if(a){t+=r,a=!1;continue}if(r==="\\"){t+=r,a=!0;continue}if(r==='"'){n=!n,t+=r;continue}if(!n&&r==="("&&(s+=1),!n&&r===")"&&(s-=1),r==="+"&&!n&&s===0){e.push(t),t="";continue}t+=r}if(n)throw R(i);return e.push(t),e}function P3(i){const e=[];let t=0,n="";for(const a of i){if(a==="{"&&(t+=1),a==="}"&&(t-=1),a===","&&t===0){e.push(n),n="";continue}n+=a}return n.trim()!==""&&e.push(n),e}function bu(i){const e=Array.from(i),t=[];let n=0;for(;n1)throw R(i)}else if(!ei(e[n]))break;n+=1}const o=e.slice(s,n).join("");if(o==="."||!/^[0-9]*\.?[0-9]*$/.test(o))throw R(i);t.push({t:"number",literal:o,value:Number(o)});continue}if(ss(a)||a==="_"){const s=n;for(;n=0&&s=0&&o=0&&s|&&|\|\||^\s*!/u.test(e)}function Kn(i){let e=i.trim();for(;e.endsWith(";");)e=e.slice(0,-1).trim();return e}function vu(i){const e=i.slice(0,3);for(;e.length<3;)e.push("");return e}function yo(i){const e=i.map(t=>Kn(t).trim());return e.length===1&&e[0].includes(";")?vu(e[0].split(";").map(t=>t.trim())):vu(e)}const dt=i=>i.frame?{frame:i.frame,callPath:i.callPath}:{};function $t(i,e=[],t={}){const n=[],a=s=>n.push(t.frame?{...s,...t}:s);return i.forEach((s,r)=>{const o=[...e,r],l=s.textLines.join(" ").trim();switch(s.type){case S.anweisung:l!==""&&l!=="ø"&&a({path:o,text:l,kind:"statement"});break;case S.verzweigung:a({path:o,text:l||"true",kind:"branch",cases:s.cases});break;case S.fallauswahl:a({path:o,text:l||"0",kind:"switchSelection",cases:s.cases});break;case S.forSchleife:a({path:o,text:l,kind:"forLoopStart",loopBody:s.loopBody,forParts:yo(s.textLines)});break;case S.whileSchleife:a({path:o,text:l||"true",kind:"whileLoop",loopBody:s.loopBody});break;case S.doUntilSchleife:a({path:o,text:l||"true",kind:"doUntilLoop",loopBody:s.loopBody});break;case S.endlosschleife:a({path:o,text:l||"true",kind:"infiniteLoop",loopBody:s.loopBody});break;case S.aussprung:a({path:o,text:l,kind:"jump"});break;case S.aufruf:l!==""&&l!=="ø"&&a({path:o,text:l,kind:"call"});break}}),n}function D3(i,e){const t=i.trim().replaceAll(",",".");switch(e){case"int":if(!/^[+-]?[0-9]+$/.test(t))throw new Ne({kind:"wholeNumberExpected"});return It(Number(t));case"double":if(!/^[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?$/.test(t))throw new Ne({kind:"numberExpected"});return kt(Number(t));case"string":return{kind:"string",value:i};case"boolean":switch(t.toLowerCase()){case"true":case"wahr":return{kind:"boolean",value:!0};case"false":case"falsch":return{kind:"boolean",value:!1};default:throw new Ne({kind:"booleanExpected"})}}}function yu(){return{stepIndex:0,variables:new Map,outputLines:[],isHalted:!1,files:new Map,robotActions:[]}}function B3(i,e){for(let t=0;tt===e.path[n])}function zt(i){const e=/^(void|int|double|String|boolean)\s+([A-Za-z_]\w*)\s*\((.*)\)$/u.exec(Kn(i));if(!e)return;const t=[];if(e[3].trim()!=="")for(const n of e[3].split(",")){const a=/^(int|double|String|boolean|char)\s*((?:\[\s*\]){0,2})\s+([A-Za-z_]\w*)$/u.exec(n.trim());if(!a)return;const s=(a[2].match(/\[/gu)??[]).length;t.push({type:tn(a[1]),name:a[3],...s>0?{dims:s}:{}})}return{returnType:tn(e[1]),name:e[2],params:t}}function bh(i){const e=/^(?:(?:(int|double|String|boolean)\s+)?([A-Za-z_]\w*)\s*=\s*)?([A-Za-z_]\w*)\s*\((.*)\)$/u.exec(Kn(i));if(e)return{targetType:e[1]?tn(e[1]):void 0,target:e[2],name:e[3],args:e[4].trim()===""?[]:rs(e[4],",")}}function os(i){var t,n;const e=Kn(i);return((t=zt(e))==null?void 0:t.name)??((n=bh(e))==null?void 0:n.name)??e.replace(/\(\s*\)$/u,"").trim()}class wi{constructor(e,t=()=>{}){y(this,"steps");y(this,"state",yu());y(this,"nextFrame",1);y(this,"callDepth",0);y(this,"frames",new Map);y(this,"peeking",!1);y(this,"robotSensors",{});y(this,"pseudocode");y(this,"decided");y(this,"afterOutput",!1);this.resolveSubprogram=t,this.steps=$t(e.elements),this.pseudocode=!!e.pseudocode}get currentStepPath(){const e=this.steps[this.state.stepIndex];return(e==null?void 0:e.callPath)??(e==null?void 0:e.path)}get canStep(){return!this.state.isHalted&&!this.state.inputRequest&&this.state.stepIndex ${_e(n)}`}catch(n){this.state.inputErrorNotice=mu(n);return}this.state.inputRequest=void 0,this.state.inputErrorNotice=void 0,this.state.stepIndex+=1,this.state.notice=this.finishedIfAtEnd()}}provideDecision(e){var s;if(((s=this.state.inputRequest)==null?void 0:s.valueType)==="string")return this.state.inputRequest=void 0,this.decided=e.trim(),this.step();const t=e.trim().toLowerCase(),n=["true","wahr","ja","yes","sim","verdadeiro"].includes(t),a=["false","falsch","nein","no","não","nao","falso"].includes(t);if(!n&&!a){this.state.inputErrorNotice={kind:"booleanExpected"};return}this.state.inputRequest=void 0,this.state.inputErrorNotice=void 0,this.decided=n,this.step()}condition(e){if(!this.pseudocode)return this.evaluateBool(e);const t=this.decided;if(typeof t=="boolean")return this.decided=void 0,t;this.state.inputRequest={variableName:"",valueType:"boolean",prompt:`${e} (true/false)`,decision:!0},this.state.inputErrorNotice=void 0,this.state.notice=void 0}finishedIfAtEnd(){return this.state.stepIndex>=this.steps.length?{kind:"finished"}:void 0}splice(e){this.steps.splice(this.state.stepIndex,1,...e)}noticeAfterEntering(e){return e.length>0?void 0:this.finishedIfAtEnd()}executeBranch(e){const t=e.cases;if(!t||t.length<2)throw Ke(e.text);const n=Ki(e.text),a=this.condition(n);if(a===void 0)return;const s=a?0:1,r=$t(t[s].elements,[...e.path,s],dt(e));this.splice(r),this.state.lastTrace=`${n} -> ${a}`,this.state.notice=this.noticeAfterEntering(r)}executeSwitchSelection(e){const t=e.cases;if(!t||t.length===0)throw Ke(e.text);const n=Ki(e.text);let a;if(this.pseudocode){const r=this.decided;if(typeof r!="string"){const l=t.map(u=>u.name).join(" / ");this.state.inputRequest={variableName:"",valueType:"string",prompt:`${n} (${l})`,decision:!0},this.state.notice=void 0;return}this.decided=void 0;const o=t.findIndex(l=>l.name.trim().toLowerCase()===r.toLowerCase());a=o>=0?o:t.length-1}else a=B3(this.evaluateSwitchSelector(n),t)??t.length-1;const s=$t(t[a].elements,[...e.path,a],dt(e));this.splice(s),this.state.lastTrace=`${n} -> ${t[a].name}`,this.state.notice=this.noticeAfterEntering(s)}executeForLoopStart(e){if(this.pseudocode)return this.splice([{...e,kind:"whileLoop"}]);const t=yo(e.forParts??[e.text]);t[0]!==""&&this.executeStatement(t[0]),this.splice([{...dt(e),path:e.path,text:t[1],kind:"forLoopCondition",loopBody:e.loopBody,forParts:t}])}executeForLoopCondition(e){const t=yo(e.forParts??[e.text]),n=t[1]===""?"true":t[1],a=this.condition(n);if(a!==void 0)if(this.state.lastTrace=`${n} -> ${a}`,a){const s=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...s,{...dt(e),path:e.path,text:t[2],kind:"forLoopIncrement",loopBody:e.loopBody,forParts:t},{...dt(e),path:e.path,text:t[1],kind:"forLoopCondition",loopBody:e.loopBody,forParts:t}])}else this.splice([]),this.state.notice=this.finishedIfAtEnd()}executeForLoopIncrement(e){const t=e.text.trim();t!==""&&this.executeIncrement(t),this.splice([])}executeWhileLoop(e){const t=Ki(e.text),n=this.condition(t);if(n!==void 0)if(this.state.lastTrace=`${t} -> ${n}`,n){const a=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...a,{...dt(e),path:e.path,text:e.text,kind:"whileLoop",loopBody:e.loopBody}]),this.state.notice=this.noticeAfterEntering(a)}else this.splice([]),this.state.notice=this.finishedIfAtEnd()}enterDoUntilLoop(e){const t=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...t,{...dt(e),path:e.path,text:e.text,kind:"doUntilCondition",loopBody:e.loopBody}]),this.state.notice=this.noticeAfterEntering(t)}executeDoUntilCondition(e){const t=Ki(e.text),n=this.condition(t);if(n!==void 0)if(this.state.lastTrace=`${t} -> ${n}`,n){const a=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...a,{...dt(e),path:e.path,text:e.text,kind:"doUntilCondition",loopBody:e.loopBody}])}else this.splice([]),this.state.notice=this.finishedIfAtEnd()}enterInfiniteLoop(e){const t=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...t,{...dt(e),path:e.path,text:e.text,kind:"infiniteLoop",loopBody:e.loopBody}]),this.state.lastTrace="true -> true",this.state.notice=t.length>0?void 0:{kind:"infiniteLoopWithoutBody"}}executeJump(e){const t=e.frame??0,n=o=>o.lengthl===e.path[u]);let a=this.steps.length,s="end";for(let o=this.state.stepIndex+1;o ${s}`,s==="return"&&this.finishFrame(r),this.state.notice=this.finishedIfAtEnd()}executeCall(e){const t=e.text,n=this.resolveSubprogram(os(t));if(!n){this.splice([]),this.state.lastTrace=`${t} -> ?`,this.state.notice={kind:"subprogramNotFound",text:t},this.state.stepIndex>=this.steps.length&&(this.state.notice={kind:"finished"});return}const a=bh(t),s=zt(n.caption);if(s?((a==null?void 0:a.args.length)??0)!==s.params.length||(a==null?void 0:a.target)!==void 0&&!s.returnType:a!==void 0&&(a.args.length>0||a.target!==void 0))throw new Ne({kind:"callArguments",text:(s==null?void 0:s.name)??os(t)});if(this.callDepth>=z3)throw new Ne({kind:"callTooDeep"});const o=new Map,l=[];s==null||s.params.forEach((d,h)=>{const g=a.args[h].trim();if(!d.dims){o.set(d.name,this.evaluateExpression(g,d.type));return}const f=this.state.variables.get(g);if(!f)throw/^[A-Za-z_]\w*$/u.test(g)?new Ne({kind:"unknownVariable",text:g}):R(g);if(!(d.dims===1?f.kind===`${d.type}Array`:f.kind==="grid"&&f.elementType===d.type))throw R(g);o.set(d.name,f),l.push({param:d.name,callerName:g})}),this.callDepth+=1;const u={frame:this.nextFrame++,callPath:e.callPath??e.path};s&&(this.frames.set(u.frame,{saved:this.state.variables,header:s,call:a,references:l}),this.state.variables=o);const c=$t(n.elements,[],u);this.splice([...c,{...u,path:e.path,text:t,kind:"callEnd"}]);const m=s==null?void 0:s.params.map((d,h)=>`${d.name} = ${d.dims?a.args[h].trim():_e(o.get(d.name))}`).join(", ");this.state.lastTrace=m?`${t} -> ${m}`:`${t} -> call`}executeCallEnd(e){this.callDepth-=1,this.splice([]),this.state.lastTrace=`${e.text} -> return`,this.finishFrame(e),this.state.notice=this.finishedIfAtEnd()}executeReturn(e){const t=e.frame??0,n=Kn(e.text).slice(6).trim(),a=this.frames.get(t);if(a&&n!==""){if(!a.header.returnType)throw R(e.text);a.returnValue=this.evaluateExpression(n,a.header.returnType)}const s=a!=null&&a.returnValue?`${e.text} -> ${_e(a.returnValue)}`:`${e.text} -> return`;if(t===0){this.steps.splice(this.state.stepIndex),this.state.lastTrace=s,this.state.notice={kind:"finished"};return}let r=this.state.stepIndex+1;for(;r0?new Map(t.saved):t.saved;for(const c of t.references){const m=this.state.variables.get(c.param);m&&n.set(c.callerName,m)}this.state.variables=n;const a=t.returnValue;if(t.header.returnType&&!a)throw new Ne({kind:"missingReturn",text:t.header.name});const s=(l=t.call)==null?void 0:l.target;if(!s||!a)return;let r=(u=t.call)==null?void 0:u.targetType;if(!r)try{r=this.inferTargetValueType(s)}catch{r=t.header.returnType}const o=r==="double"&&a.kind==="int"?kt(a.value):r==="string"?{kind:"string",value:_e(a)}:a;if(gu(o)!==r)throw R(e.text);this.assignValue(o,s),this.state.lastTrace=`${s} = ${e.text.slice(e.text.indexOf("=")+1).trim()} -> ${_e(o)}`}executeStatement(e){const t=this.state,n=e.trim(),a=n.toLowerCase(),s=this.afterOutput;if(this.afterOutput=!1,a.startsWith("input:")){t.inputRequest=this.parseInputRequest(n,s),t.outputLineOpen=!1,t.inputErrorNotice=void 0;return}const r=/^System\s*\.\s*out\s*\.\s*(println|print)\s*\(([\s\S]*)\)\s*;?$/u.exec(n);if(a.startsWith("output:")||a.startsWith("print:")||r){const v=r?r[2]:n.slice(a.startsWith("output:")?7:6),w=this.peek(()=>this.renderOutputExpression(v)),I=v.trim()===""?"":this.evaluateOutputExpression(v);t.outputLineOpen&&t.outputLines.length?t.outputLines[t.outputLines.length-1]+=I:t.outputLines.push(I),t.outputLineOpen=(r==null?void 0:r[1])==="print",this.afterOutput=!0,t.lastTrace=`${w} -> ${I}`;return}const o=b3(n);if(o){this.executeMBotCommand(o.method,o.args,n);return}if(this.executeFileStatement(n))return;if(n.endsWith("++")||n.endsWith("--")||n.includes("+=")||n.includes("-=")){this.executeIncrement(n);return}const l=/^(?:final\s+)?([A-Za-z]+)\s+([A-Za-z_]\w*(?:\s*,\s*[A-Za-z_]\w*)*)$/u.exec(Kn(n).trim()),u=l?tn(l[1]):void 0;if(l&&u){const v=l[2].split(",").map(w=>w.trim());for(const w of v)t.variables.set(w,bo(u,hu(u)));t.lastTrace=v.map(w=>`${w} = ${_e(t.variables.get(w))}`).join(", ");return}const c=n.indexOf("=");if(c<0)throw Ke(n);const m=n.slice(0,c).trim(),d=n.slice(c+1),h=this.parseArrayDeclaration(m,d);if(h){t.variables.set(h.name,h.value),t.lastTrace=`${h.name} = new ${h.typeName}[${h.count}]`;return}const g=this.parseAssignmentTarget(m);let f;try{f=this.peek(()=>this.renderNumericExpression(d))}catch{f=d.trim()}let b=g.valueType;if(!b)try{b=this.inferTargetValueType(g.variableName)}catch{b="int"}const x=this.evaluateExpression(d,b);this.assignValue(x,g.variableName),t.lastTrace=`${g.variableName} = ${f} -> ${_e(x)}`}executeMBotCommand(e,t,n){var r;if((r=yi[e])!=null&&r.text){const o=yi[e];if(t.length!==o.args+1)throw R(n);const l=ns(e,t.slice(0,-1).map(m=>this.evaluateDouble(m)));if(!l)throw R(n);const u=cu(e,l,this.evaluateOutputExpression(t[t.length-1])),c=o.choices;if(c&&!c.includes(u.text??""))throw R(`${n} (${c.join(", ")})`);this.state.robotActions.push(u),this.state.lastTrace=`${n} -> ${u.label}`;return}const a=ns(e,t.map(o=>this.evaluateDouble(o)));if(!a)throw R(n);const s=cu(e,a);this.state.robotActions.push(s),this.state.lastTrace=`${n} -> ${s.label}`}executeFileStatement(e){const t=this.state,n=Kn(e).trim(),a=/^(?:(Scanner|BufferedReader|PrintWriter)\s+)?([A-Za-z_]\w*)\s*=\s*new\s+(Scanner|BufferedReader|PrintWriter)\s*\(([\s\S]*)\)$/u.exec(n);if(a){const[,c,m,d,h]=a;if(c&&c!==d)throw R(n);const g=d==="Scanner"?/^new\s+File\s*\(([\s\S]+)\)$/u.exec(h.trim()):d==="BufferedReader"?/^new\s+FileReader\s*\(([\s\S]+)\)$/u.exec(h.trim()):/^(?:new\s+(?:File|FileWriter)\s*\(([\s\S]+)\)|([\s\S]+))$/u.exec(h.trim());if(!g)throw Ke(n);const f=this.fileNameValue(g[1]??g[2]);if(d==="PrintWriter")t.variables.set(m,{kind:"writer",file:f,text:""});else{const x=this.fileContent(f).split(/\r?\n/u);x[x.length-1]===""&&x.pop(),t.variables.set(m,{kind:"reader",className:d,file:f,lines:x,next:0})}return t.lastTrace=`${m} = new ${d}(${f})`,!0}const s=/^Files\s*\.\s*writeString\s*\(\s*(?:Path\s*\.\s*of|Paths\s*\.\s*get)\s*\(([^()]+)\)\s*,([\s\S]+)\)$/u.exec(n);if(s){const c=this.fileNameValue(s[1]),m=this.evaluateOutputExpression(s[2]);return t.files.set(c,m),t.lastTrace=`${c} ← ${JSON.stringify(m)}`,!0}const r=/^([A-Za-z_]\w*)\s*\.\s*(println|print|close)\s*\(([\s\S]*)\)$/u.exec(n),o=r&&t.variables.get(r[1]);if(!r||!o)return!1;if(o.kind==="null")throw new Ne({kind:"nullValue",text:r[1]});if(o.kind==="reader"&&r[2]==="close")return t.lastTrace=`${r[1]}.close()`,!0;if(o.kind!=="writer")return!1;if(r[2]==="close")return t.files.set(o.file,o.text),t.lastTrace=`${o.file} ← ${JSON.stringify(o.text)}`,!0;const l=r[3].trim()===""?"":this.evaluateOutputExpression(r[3]),u=r[2]==="println"?l+` -`:l;return t.variables.set(r[1],{...o,text:o.text+u}),t.lastTrace=`${r[1]}.${r[2]}(${JSON.stringify(l)})`,!0}fileNameValue(e){const t=e.trim(),n=lt(t);if(n!==void 0)return n;const a=this.evaluateReference(t);if((a==null?void 0:a.kind)==="string")return a.value;throw R(t)}fileContent(e){const t=this.state.files.get(e)??as.get(e);if(t===void 0)throw new Ne({kind:"fileNotFound",text:e});return t}readerMethod(e,t,n,a){if(n.args.length)throw R(a);const s=t.next0?"+":"-";if(r.kind==="int"){t.set(s,It(r.value+a)),this.state.lastTrace=`${s} = ${r.value} ${o} 1 -> ${r.value+a}`;return}if(r.kind==="double"){const l=r.value+a;t.set(s,kt(l)),this.state.lastTrace=`${s} = ${_e(r)} ${o} 1 -> ${_e(kt(l))}`;return}throw Ke(e)}for(const[n,a]of[["+=",1],["-=",-1]]){const s=e.indexOf(n);if(s<0)continue;const r=e.slice(0,s).trim(),o=e.slice(s+2),l=t.get(r);if(!oi(r)||!l)throw Ke(e);const u=a>0?"+":"-";if(l.kind==="int"){const c=this.evaluateInt(o),m=l.value+a*c;t.set(r,It(m)),this.state.lastTrace=`${r} = ${l.value} ${u} ${c} -> ${m}`;return}if(l.kind==="double"){const c=this.evaluateDouble(o),m=l.value+a*c;t.set(r,kt(m)),this.state.lastTrace=`${r} = ${_e(l)} ${u} ${_e(kt(c))} -> ${_e(kt(m))}`;return}throw Ke(e)}this.executeStatement(e)}parseAssignmentTarget(e){if(g1(e))return{variableName:e.trim()};const t=e.split(/\s+/u).filter(Boolean);let n,a;if(t.length===1)n=t[0];else if(t.length===2&&tn(t[0]))n=t[1],a=tn(t[0]);else if(t.length===3&&t[0]==="const"&&tn(t[1]))n=t[2],a=tn(t[1]);else throw Ke(e);if(!fu(n))throw Ke(e);return{variableName:n,valueType:a}}parseInputRequest(e,t=!1){const n=e.slice(6).trim(),a=/^(\S+)(?:\s+(\S+))?(?:\s+([\s\S]*))?$/u.exec(n);if(!a)throw Ke(e);const s=[a[1],a[2],a[3]].filter(m=>m!==void 0);let r,o,l;const u=tn(s[0]);if(s.length>=2&&u?(r=s[1],o=u,l=(s[2]??"").trim()):(r=s[0],o=this.inferTargetValueType(r),l=(s[1]??"").trim()),!fu(r))throw Ke(e);const c=lt(l)??l;return c===""&&t?this.state.outputLineOpen?{variableName:r,valueType:o,prompt:"",continuesLine:!0}:{variableName:r,valueType:o,prompt:""}:{variableName:r,valueType:o,prompt:c===""?`${r}:`:c}}parseArrayDeclaration(e,t){const n=e.split(/\s+/u).filter(Boolean);if(n.length!==2||!n[0].endsWith("[]"))return;const a=n[0].endsWith("[][]"),s=n[0].slice(0,a?-4:-2),r=tn(s),o=n[1];if(!r||!oi(o))throw Ke(e);if(a)return this.parseGridDeclaration(o,s,r,t);const l=t.trim();if(l.startsWith("{")&&l.endsWith("}")){const h=l.slice(1,-1).split(",").map(f=>f.trim());let g;switch(r){case"int":g={kind:"intArray",value:h.map(f=>this.evaluateInt(f))};break;case"double":g={kind:"doubleArray",value:h.map(f=>this.evaluateDouble(f))};break;case"string":g={kind:"stringArray",value:h.map(f=>lt(f)??this.evaluateOutputExpression(f))};break;case"boolean":g={kind:"booleanArray",value:h.map(f=>this.evaluateBool(f))};break}return{name:o,typeName:s,count:h.length,value:g}}const u=`new ${s}[`;if(!l.startsWith(u)){const h=this.evaluateStringMethod(l);if((h==null?void 0:h.kind)==="stringArray"&&r==="string")return{name:o,typeName:s,count:h.value.length,value:h}}if(!l.startsWith(u)||!l.endsWith("]"))throw Ke(t);const c=l.slice(u.length,-1),m=this.evaluateInt(c);if(m<0)throw R(c);const d=r==="int"?{kind:"intArray",value:new Array(m).fill(0)}:r==="double"?{kind:"doubleArray",value:new Array(m).fill(0)}:r==="boolean"?{kind:"booleanArray",value:new Array(m).fill(!1)}:{kind:"stringArray",value:new Array(m).fill("")};return{name:o,typeName:s,count:m,value:d}}parseGridDeclaration(e,t,n,a){var m;const s=a.trim(),r=d=>{switch(n){case"int":return this.evaluateInt(d);case"double":return this.evaluateDouble(d);case"boolean":return this.evaluateBool(d);case"string":return lt(d.trim())??this.evaluateOutputExpression(d)}};if(s.startsWith("{")&&s.endsWith("}")){const d=P3(s.slice(1,-1)).map(h=>{const g=h.trim();if(!g.startsWith("{")||!g.endsWith("}"))throw R(g);return g.slice(1,-1).trim()===""?[]:g.slice(1,-1).split(",").map(f=>r(f.trim()))});return{name:e,typeName:t,count:`${d.length}][${((m=d[0])==null?void 0:m.length)??0}`,value:{kind:"grid",elementType:n,value:d}}}const o=new RegExp(String.raw`^new\s+${t}\s*\[(.+)\]\s*\[(.+)\]$`,"u").exec(s);if(!o)throw Ke(a);const l=this.evaluateInt(o[1]),u=this.evaluateInt(o[2]);if(l<0)throw R(o[1]);if(u<0)throw R(o[2]);const c={kind:"grid",elementType:n,value:Array.from({length:l},()=>new Array(u).fill(hu(n)))};return{name:e,typeName:t,count:`${l}][${u}`,value:c}}arrayIndex(e){const t=this.evaluateInt(e);if(t<0)throw R(e);return t}evaluateReference(e){const t=e.trim(),n=this.state.variables.get(t);if(n)return n;const a=this.evaluateStringMethod(t);if(a)return a;const s=/^\(\s*char\s*\)\s*(.+)$/su.exec(t);if(s){const o=this.evaluateInt(s[1]);if(!(o>=0&&o<=1114111))throw R(t);return{kind:"string",value:String.fromCodePoint(o)}}const r=g1(t);if(r)return this.valueInArray(r.arrayName,r.indexExpressions.map(o=>this.arrayIndex(o)))}evaluateStringMethod(e){const t=C3(e);if(!t)return;const n=this.evaluateStaticCall(e,t);if(n)return n;const a=this.state.variables.get(t.target.trim());if((a==null?void 0:a.kind)==="reader")return this.readerMethod(t.target.trim(),a,t,e);if((a==null?void 0:a.kind)==="null")throw new Ne({kind:"nullValue",text:t.target.trim()});const s=lt(t.target)??this.stringValueOf(t.target);if(s===void 0)return;const r=t.args,o=d=>{const h=r[d];if(h===void 0)throw R(e);const g=lt(h.trim());if(g!==void 0)return g;const f=this.evaluateReference(h);if((f==null?void 0:f.kind)==="string")return f.value;throw R(h)},l=d=>{if(r[d]===void 0)throw R(e);return this.evaluateInt(r[d])},u=d=>{if(r.length!==d)throw R(e)},c=Array.from(s),m=(d,h)=>{if(d<0||d>h)throw R(e);return d};switch(t.method){case"length":return u(0),It(c.length);case"charAt":return u(1),{kind:"string",value:c[m(l(0),c.length-1)]};case"substring":{if(r.length!==1&&r.length!==2)throw R(e);const d=m(l(0),c.length),h=r.length===2?m(l(1),c.length):c.length;if(h0&&h[h.length-1]==="";)h.pop();return{kind:"stringArray",value:h}}default:return}}evaluateStaticCall(e,t){const n=()=>{if(t.args.length!==1)throw R(e);return t.args[0]},a=s=>{const r=lt(s.trim());if(r!==void 0)return r;const o=this.evaluateReference(s);if((o==null?void 0:o.kind)==="string")return o.value;throw R(s)};switch(`${t.target}.${t.method}`){case"Integer.parseInt":{const s=a(n()).trim();if(!/^[+-]?\d+$/u.test(s))throw new Ne({kind:"wholeNumberExpected"});return It(Number(s))}case"Double.parseDouble":{const s=Number(a(n()).trim());if(!Number.isFinite(s))throw new Ne({kind:"numberExpected"});return kt(s)}case"String.valueOf":return{kind:"string",value:this.evaluateOutputExpression(n())};case"Files.readString":{const s=/^(?:Path\s*\.\s*of|Paths\s*\.\s*get)\s*\(\s*("(?:[^"\\]|\\.)*")\s*\)$/u.exec(n().trim());if(!s)throw R(e);const r=lt(s[1]),o=as.get(r);if(o===void 0)throw new Ne({kind:"fileNotFound",text:r});return{kind:"string",value:o}}default:return}}stringValueOf(e){const t=e.trim(),n=this.state.variables.get(t);if(n)return n.kind==="string"?n.value:void 0;const a=g1(t);if(!a)return;const s=this.valueInArray(a.arrayName,a.indexExpressions.map(r=>this.arrayIndex(r)));return s.kind==="string"?s.value:void 0}substituteStringCalls(e){if(!e.includes("("))return e;let t="",n=e;const a=/([A-Za-z_]\w*(?:\[[^\[\]]*\])*|"(?:[^"\\]|\\.)*")\s*\.\s*(length|indexOf|lastIndexOf|compareTo|charAt|parseInt|parseDouble)\s*\(/u;for(let s=a.exec(n);s;s=a.exec(n)){const r=s.index+s[0].length-1,o=Js(Array.from(n),Array.from(n.slice(0,r)).length);if(o===void 0)break;const l=Array.from(n),u=l.slice(Array.from(n.slice(0,s.index)).length,o+1).join(""),c=this.evaluateStringMethod(u),m=l.slice(0,Array.from(n.slice(0,s.index)).length).join(""),d=(c==null?void 0:c.kind)==="string"?vo(c.value):void 0;(c==null?void 0:c.kind)==="int"?t+=m+String(c.value):(c==null?void 0:c.kind)==="double"?t+=m+(Number.isInteger(c.value)?c.value.toFixed(1):String(c.value)):d!==void 0?t+=m+String(d):t+=m+u,n=l.slice(o+1).join("")}return t+n}valueInArray(e,t){const n=this.state.variables.get(e);if(!n)throw K1(e);const a=`${e}[${t.join("][")}]`;if(n.kind==="grid"){if(t.length!==2)throw R(a);const r=n.value[t[0]];if(!r||t[1]>=r.length)throw R(a);return bo(n.elementType,r[t[1]])}if(t.length!==1)throw R(a);const s=t[0];if(!xo(n))throw R(e);if(s>=n.value.length)throw R(a);switch(n.kind){case"intArray":return It(n.value[s]);case"doubleArray":return kt(n.value[s]);case"stringArray":return{kind:"string",value:n.value[s]};case"booleanArray":return{kind:"boolean",value:n.value[s]};default:throw R(e)}}inferTargetValueType(e){const t=e.trim(),n=this.state.variables.get(t);if(n)return gu(n);const a=g1(t);if(a){const s=this.state.variables.get(a.arrayName);if(!s)throw K1(a.arrayName);if(s.kind==="intArray")return"int";if(s.kind==="doubleArray")return"double";if(s.kind==="stringArray")return"string";if(s.kind==="booleanArray")return"boolean";if(s.kind==="grid")return s.elementType;throw R(a.arrayName)}throw Ke(e)}assignValue(e,t){const n=t.trim(),a=g1(n);if(!a){this.state.variables.set(n,e);return}const s=a.indexExpressions.map(u=>this.arrayIndex(u)),r=this.state.variables.get(a.arrayName);if(!r)throw K1(a.arrayName);if(r.kind==="grid"){if(s.length!==2||s[0]>=r.value.length||s[1]>=r.value[s[0]].length)throw R(n);const u=r.elementType==="double"&&e.kind==="int"||e.kind===r.elementType?e.value:void 0;if(u===void 0||xo(e))throw R(n);const c=r.value.map(m=>[...m]);c[s[0]][s[1]]=u,this.state.variables.set(a.arrayName,{...r,value:c});return}if(s.length!==1)throw R(n);const o=s[0];let l;if(r.kind==="intArray"&&e.kind==="int")l={kind:"intArray",value:[...r.value]};else if(r.kind==="doubleArray"&&(e.kind==="double"||e.kind==="int"))l={kind:"doubleArray",value:[...r.value]};else if(r.kind==="stringArray"&&e.kind==="string")l={kind:"stringArray",value:[...r.value]};else if(r.kind==="booleanArray"&&e.kind==="boolean")l={kind:"booleanArray",value:[...r.value]};else throw R(n);if(o>=l.value.length)throw R(n);l.value[o]=e.value,this.state.variables.set(a.arrayName,l)}evaluateOutputExpression(e){const t=this.withSensors(e).trim();if(xu(t)&&fr(t).every(s=>lt(s.trim())===void 0)&&!this.evaluateReference(t))return String(this.evaluateBool(t));let n,a;for(const s of fr(this.withSensors(e))){const r=s.trim(),o=lt(r),l=o!==void 0?{kind:"string",value:o}:this.evaluateReference(r)??(xu(r)?{kind:"boolean",value:this.evaluateBool(r)}:this.evaluateNumeric(r)),u=l.kind==="int"||l.kind==="double";if(a===void 0&&u){n?n=n.kind==="int"&&l.kind==="int"?It(n.value+l.value):kt(n.value+l.value):n=l;continue}a=(a??(n?_e(n):""))+_e(l),n=void 0}return a??(n?_e(n):"")}renderOutputExpression(e){return fr(e).map(t=>{const n=t.trim();if(lt(n)!==void 0)return n;const a=this.evaluateReference(n);if(a)return _e(a);try{return this.renderNumericExpression(n)}catch{return n}}).join(" + ")}evaluateExpression(e,t){switch(t){case"int":return It(this.evaluateInt(e));case"double":return kt(this.evaluateDouble(e));case"string":{const n=e.trim(),a=lt(n);if(a!==void 0)return{kind:"string",value:a};if(n==="null")return{kind:"null"};const s=this.evaluateReference(n);return(s==null?void 0:s.kind)==="null"?s:s?{kind:"string",value:_e(s)}:{kind:"string",value:this.evaluateOutputExpression(e)}}case"boolean":return{kind:"boolean",value:this.evaluateBool(e)}}}evaluateNumeric(e){const{v:t,int:n}=this.parser(e).parseNumber();return n||Number.isFinite(t)&&Math.round(t)===t?It(t):kt(t)}parser(e){const t=this.withSensors(e);return new j3(bu(pu(this.substituteStringCalls(t))),this.state.variables)}withSensors(e){return v3(e,t=>this.robotSensors[t]??Ot[t].simulated)}evaluateInt(e){return this.parser(e).parseInt()}evaluateDouble(e){return this.parser(e).parseDouble()}evaluateBool(e){const t=this.withSensors(e).trim();if(t==="true")return!0;if(t==="false")return!1;const n=this.evaluateReference(t);if((n==null?void 0:n.kind)==="boolean")return n.value;const a=rs(t,"||");if(a.length>1)return a.some(u=>this.evaluateBool(u));const s=rs(t,"&&");if(s.length>1)return s.every(u=>this.evaluateBool(u));if(t.startsWith("!")&&!t.startsWith("!="))return!this.evaluateBool(t.slice(1));const r=fh(t);if(r!==void 0)return this.evaluateBool(r);const o=A3(t);if(o)return this.evaluateComparison(o.lhs,"==",o.rhs);const l=O3(t);if(l)return this.evaluateComparison(l.lhs,l.op,l.rhs);if(this.stringOperand(t)!==void 0)throw R(t);return this.evaluateDouble(t)!==0}evaluateComparison(e,t,n){if((e.trim()==="null"||n.trim()==="null")&&(t==="=="||t==="!=")){const c=d=>{var h;return d.trim()==="null"||((h=this.evaluateReference(d))==null?void 0:h.kind)==="null"},m=c(e)===c(n);return t==="=="?m:!m}const a=this.booleanOperand(e),s=this.booleanOperand(n);if((a!==void 0||s!==void 0)&&(t==="=="||t==="!=")){const c=a??this.evaluateBool(e),m=s??this.evaluateBool(n);return t==="=="?c===m:c!==m}const r=this.stringOperand(e),o=this.stringOperand(n);let l,u;if(r!==void 0||o!==void 0){if(r===void 0||o===void 0)throw R(`${e} ${t} ${n}`);l=r,u=o}else l=this.evaluateDouble(e),u=this.evaluateDouble(n);switch(t){case"==":return l===u;case"!=":return l!==u;case"<":return l":return l>u;case">=":return l>=u;default:throw R(`${e} ${t} ${n}`)}}booleanOperand(e){const t=e.trim();if(t==="true")return!0;if(t==="false")return!1;const n=this.evaluateReference(t);return(n==null?void 0:n.kind)==="boolean"?n.value:void 0}stringOperand(e){const t=e.trim(),n=lt(t);if(n!==void 0)return n;const a=this.evaluateReference(t);return(a==null?void 0:a.kind)==="string"?a.value:void 0}evaluateSwitchSelector(e){const t=this.withSensors(e).trim(),n=lt(t);if(n!==void 0)return{kind:"text",value:n};const a=this.state.variables.get(t);if(a)switch(a.kind){case"int":return{kind:"int",value:a.value};case"double":return{kind:"int",value:Math.trunc(a.value)};case"string":return{kind:"text",value:a.value};default:throw R(t)}return/^[+-]?[0-9]+$/.test(t)?{kind:"int",value:Number(t)}:{kind:"int",value:this.evaluateInt(t)}}renderNumericExpression(e){return bu(pu(e)).map(t=>{if(t.t==="number")return t.literal;if(t.t==="identifier"){const n=this.state.variables.get(t.name);if(!n)throw K1(t.name);return _e(n)}return t.t}).join(" ").replaceAll("( ","(").replaceAll(" )",")").replaceAll(" . ",".").replaceAll("[ ","[").replaceAll(" ]","]")}}const xh={baseIndent:0,indentPerLevel:4,includeDiagramTextAsComments:!1,includeEmptyElseBranch:!0,pseudocodeNote:"Pseudocode – not a runnable program"};function ls(i,e,t={},n=[]){const a=Hl(i,e,t);let s="";e==="javascript"&&(s+=`"use strict"; + pass`],ri=(i,e)=>Array.from({length:e},(t,n)=>i>>>8*n&255);function o3(i){let e=0;for(let t=0;t>>0;return ri(e,4)}const gr=(i,e)=>Fl([1,0,rh,i,...ri(e.length,2),...e]);function l3(i,e=a3){const t=new TextEncoder().encode(i),n=(4-t.length%F1+F1)%F1,a=new Uint8Array(t.length+n).fill(10);a.set(t);const s=[gr(1,[0,...ri(a.length,4),...o3(a),...Array.from(new TextEncoder().encode(e))])],r=a.length-4;for(let o=0;oi.length===3&&i[0]===13,c3=i=>i.length===7||i.some((e,t)=>e===rh&&i[t+1]===240),oh=()=>typeof navigator>"u"?void 0:navigator.serial,pr=()=>oh()!==void 0,m3=(...i)=>`exec(${JSON.stringify(i.join("; "))})`,Fs=(i,e=24)=>m3("cyberpi.display.clear()",`cyberpi.display.show_label(${JSON.stringify(i)}, ${e}, 'center')`),lh=Fs("VisuBot",32);class d3{constructor(){y(this,"port");y(this,"writer");y(this,"reader");y(this,"loop");y(this,"rx",[]);y(this,"idx",1);y(this,"frameWaiters",[]);y(this,"waiting",new Map);y(this,"queue",Promise.resolve());y(this,"listeners",new Set);y(this,"error");y(this,"connecting",!1)}listen(e){return this.listeners.add(e),()=>this.listeners.delete(e)}changed(){for(const e of this.listeners)e()}get connected(){return this.writer!==void 0&&!this.connecting}async connect(){const e=oh();if(!e)throw new Error("Web Serial");const t=await e.requestPort();await t.open({baudRate:115200}),this.port=t,this.writer=t.writable.getWriter(),this.error=void 0,this.connecting=!0,this.changed(),this.loop=this.readLoop(),window.addEventListener("pagehide",()=>void this.disconnect(),{once:!0}),await new Promise(n=>setTimeout(n,3e3)),this.writer&&(this.rx.length=0,this.connecting=!1,this.changed(),await this.run(lh))}async disconnect(e){if(!this.port)return this.error=e,this.changed();if(!e&&this.writer&&!this.connecting)for(const r of["mbot2.EM_stop('ALL')","cyberpi.led.off()",Fs("Bis bald!")])await this.send(r,hr,2e3).catch(()=>{});const t=this.port,n=this.writer,a=this.reader,s=this.loop;this.port=this.writer=this.reader=this.loop=void 0,this.error=e,this.connecting=!1;for(const r of this.waiting.values())r.reject(new Error(e??"getrennt"));this.waiting.clear();try{await(a==null?void 0:a.cancel()),await s,await(n==null?void 0:n.close())}catch{}try{n==null||n.releaseLock(),await t.close()}catch(r){console.warn("[mBot2] Schließen",r.message)}this.changed()}run(e){return this.send(e,hr,3e4).then(()=>{})}ask(e){return this.send(e,K2,3e3)}async upload(e,t=()=>{}){if(this.port||await this.connect(),!this.writer)throw new Error(this.error??"nicht verbunden");const n=l3(e),a=6+n.length+3;let s=0;const r=()=>t(++s,a),o=async()=>{await this.sendFrame(Fl(s3),u3),r();for(const l of r3)await this.send(l,hr,3e3),r()};await o(),await o();for(const l of n)await this.sendFrame(l,c3),r();s=a-3,await o(),await this.restart()}sendFrame(e,t){const n=this.queue.then(async()=>{for(let a=0;a<3;a++){if(!this.writer)throw new Error("nicht verbunden");let s=()=>{};const r=new Promise(u=>s=u),o={match:t,resolve:s};this.frameWaiters.push(o),await this.writer.write(e);const l=await Promise.race([r.then(()=>!0),new Promise(u=>setTimeout(()=>u(!1),3e3))]);if(this.frameWaiters=this.frameWaiters.filter(u=>u!==o),l)return}throw new Error("keine Antwort")});return this.queue=n.catch(()=>{}),n}async restart(){const e=this.port;await this.disconnect("restart"),this.error=void 0,await new Promise(t=>setTimeout(t,300)),await e.open({baudRate:115200}),await new Promise(t=>setTimeout(t,500)),await e.close(),this.changed()}send(e,t,n){const a=this.queue.then(()=>new Promise((s,r)=>{if(!this.writer)return r(new Error("nicht verbunden"));const o=this.idx;this.idx=this.idx%65535+1;const l=setTimeout(()=>{this.waiting.delete(o),r(new Error("keine Antwort"))},n);this.waiting.set(o,{resolve:u=>(clearTimeout(l),s(u)),reject:u=>(clearTimeout(l),r(u))}),this.writer.write(e3(e,t,o)).catch(u=>{this.waiting.delete(o),r(u)})}));return this.queue=a.catch(()=>{}),a}async readLoop(){var e;for(;(e=this.port)!=null&&e.readable;){const t=this.port.readable.getReader();this.reader=t;try{for(;;){const{value:n,done:a}=await t.read();if(a)break;this.rx.push(...n);for(const s of n3(this.rx)){const r=this.frameWaiters.findIndex(u=>u.match(s));r>=0&&this.frameWaiters.splice(r,1)[0].resolve();const o=t3(s);if(!o)continue;const l=this.waiting.get(o.idx);this.waiting.delete(o.idx),l==null||l.resolve(o.value)}}}catch(n){const a=["BufferOverrunError","FramingError","BreakError","ParityError"].includes(n.name);console.warn("[mBot2] Lesefehler",n.name,n.message),!a&&this.port&&this.disconnect(n.message)}finally{t.releaseLock()}if(!this.writer)break}}}const ge=new d3,uh=5,h3=i=>Number.isInteger(i)&&i>=0&&iString(Math.round(i*100)/100),yi={forward:{args:1,defaults:[lu],python:([i])=>`mbot2.straight(${ke(i)})`,label:([i])=>`${ke(i)} cm vorwärts`},backward:{args:1,defaults:[lu],python:([i])=>`mbot2.straight(${ke(-i)})`,label:([i])=>`${ke(i)} cm rückwärts`},turnLeft:{args:1,defaults:[90],python:([i])=>`mbot2.turn(${ke(-i)})`,label:([i])=>`${ke(i)}° nach links drehen`},turnRight:{args:1,defaults:[90],python:([i])=>`mbot2.turn(${ke(i)})`,label:([i])=>`${ke(i)}° nach rechts drehen`},stop:{args:0,python:()=>'mbot2.EM_stop("ALL")',label:()=>"anhalten"},drive:{args:2,python:([i,e])=>`mbot2.drive_power(${ke(i)}, ${ke(-e)})`,label:([i,e])=>`Räder links ${ke(i)} %, rechts ${ke(e)} %`},setLed:{args:3,python:([i,e,t])=>`cyberpi.led.on(${ke(i)}, ${ke(e)}, ${ke(t)})`,label:([i,e,t])=>`LEDs (${ke(i)}, ${ke(e)}, ${ke(t)})`},ledOff:{args:0,python:()=>"cyberpi.led.off()",label:()=>"LEDs aus"},ledColor:{args:1,text:!0,choices:Object.keys(ts),valid:([i])=>h3(i),python:([i],e)=>`cyberpi.led.on(${ts[e].join(", ")}, id=${i+1})`,label:([i],e)=>`LED ${i}: ${e}`},playTone:{args:2,python:([i,e])=>`cyberpi.audio.play_tone(${ke(i)}, ${ke(e/1e3)})`,label:([i,e])=>`Ton ${ke(i)} Hz, ${ke(e)} ms`},pause:{args:1,label:([i])=>`${ke(i)} ms warten`},resetTimer:{args:0,python:()=>"cyberpi.timer.reset()",label:()=>"Stoppuhr auf 0"},emotion:{args:0,text:!0,choices:g3,python:(i,e)=>`cyberpi.emotion.${e}()`,label:(i,e)=>`Gefühl: ${e}`},showText:{args:0,text:!0,python:(i,e)=>Fs(e),label:(i,e)=>`Bildschirm: ${e}`}},uu={red:{de:"rot",en:"red"},green:{de:"grün",en:"green"},blue:{de:"blau",en:"blue"},yellow:{de:"gelb",en:"yellow"},cyan:{de:"türkis",en:"cyan"},purple:{de:"lila",en:"purple"},white:{de:"weiß",en:"white"},black:{de:"schwarz",en:"black"}};let Jl="en";function p3(i){Jl=i==="de"?"de":"en"}const f3=()=>Jl;function ch(i){const e=i.trim().toLowerCase(),t=uu[e]??Object.values(uu).find(n=>n.de===e);return t?t[Jl]:e}const c1=i=>({python:`cyberpi.controller.is_press('${i}')`,simulated:!1}),Ot={getDistance:{python:"mbuild.ultrasonic2.get(1)",simulated:100},getLine:{python:"mbuild.quad_rgb_sensor.get_line_sta('all', 1)",simulated:0},isLineLeft:{python:"mbuild.quad_rgb_sensor.is_line('L1', 1)",simulated:!1},isLineRight:{python:"mbuild.quad_rgb_sensor.is_line('R1', 1)",simulated:!1},getColor:{python:"mbuild.quad_rgb_sensor.get_color_sta('L1', 1)",simulated:"white"},isButtonA:c1("a"),isButtonB:c1("b"),isJoystickUp:c1("up"),isJoystickDown:c1("down"),isJoystickLeft:c1("left"),isJoystickRight:c1("right"),getBrightness:{python:"cyberpi.get_bri()",simulated:50},getLoudness:{python:"cyberpi.get_loudness('maximum')",simulated:0},getPitch:{python:"cyberpi.get_pitch()",simulated:0},getRoll:{python:"cyberpi.get_roll()",simulated:0},isShaken:{python:"cyberpi.is_shake()",simulated:!1},getBattery:{python:"cyberpi.get_battery()",simulated:100},getTimer:{python:"cyberpi.timer.get()",simulated:0}};function b3(i){const e=new Set;for(const t of i.matchAll(/\bmbot\s*\.\s*([A-Za-z_]\w*)\s*\(\s*\)/gu))t[1]in Ot&&e.add(t[1]);return[...e]}function x3(i){const e=/^mbot\s*\.\s*led\s*\(([^()]*(?:\([^()]*\)[^()]*)*)\)\s*\.\s*setColor\s*\(([\s\S]*)\)\s*;?$/u.exec(i.trim());if(e)return{method:"ledColor",args:[e[1].trim(),e[2].trim()]};const t=/^mbot\s*\.\s*([A-Za-z_]\w*)\s*\(([\s\S]*)\)\s*;?$/u.exec(i.trim());if(!t)return;const n=t[2].trim();return{method:t[1],args:n===""?[]:w3(n)}}function ns(i,e){const t=yi[i];if(!t)return;const n=e.length===0&&t.defaults?t.defaults:e;if(n.length===t.args)return!t.valid||t.valid(n)?n:void 0}function cu(i,e,t=""){var a;const n=yi[i];return{method:i,args:e,python:(a=n.python)==null?void 0:a.call(n,e,t),waitMs:i==="pause"?Math.max(0,e[0]):void 0,label:n.label(e,t),...n.text?{text:t}:{}}}function mh(i){return i.map(e=>[e.method,...e.args.map(ke),...e.text!==void 0?[JSON.stringify(e.text)]:[]].join(" "))}function v3(i){let e=0;const t=i.trim(),n=()=>{const s=[];for(;;){for(;t[e]===" "||t[e]===",";)e++;if(e>=t.length||t[e]===")")return s;const r=/^(\d+)\s*[x×]\s*\(/u.exec(t.slice(e));if(r){e+=r[0].length;const m=n();if(t[e]!==")")throw new Error(`„)“ fehlt in „${i}“`);e++;for(let d=0;d{if(!(n in Ot))return t;const a=e(n);return typeof a=="string"?JSON.stringify(n==="getColor"?ch(a):a):String(a)}):i}function w3(i){const e=[];let t=0,n=!1,a=0;for(let s=0;s{const a=t==="turn"?((n+180)%360+360)%360-180:n;if(Math.abs(a)<1e-6)return[];const s=Math.round(Math.abs(a)*100)/100;return t==="drive"?[`${a>0?"forward":"backward"} ${s}`]:[a===-180?"turnRight 180":`${a>0?"turnRight":"turnLeft"} ${s}`]})}function dh(i){let e=0;const t=i.trim(),n=()=>{const s=[];for(;;){for(;t[e]===" "||t[e]===",";)e++;if(e>=t.length||t[e]===")")return s;const r=/^(\d+)\s*[x×]\s*\(/u.exec(t.slice(e));if(r){e+=r[0].length;const u=n();if(t[e]!==")")throw new Error(`„)“ fehlt in „${i}“`);e++;for(let c=0;ca===i[s%t])){const a=X1(i.slice(0,t));return`${n} x ${t===1?a:`(${a})`}`}}return i.join(", ")}const hh=["cyberpi","screen","joystick","buttons","leds","lightSensor","microphone","shield","powerSwitch","motors","wheels","ultrasonic","lineSensor","caster","chassis"],z3=i=>hh.includes(i),I3=100;function gh(i){switch(i.kind){case"finished":return"Simulation finished.";case"infiniteLoopWithoutBody":return"Infinite loop has no body.";case"unsupportedStatement":return`Unsupported statement: ${i.text}`;case"invalidExpression":return`Invalid expression: ${i.text}`;case"unknownVariable":return`Unknown variable: ${i.text}`;case"divisionByZero":return"Division by zero.";case"wholeNumberExpected":return"Please enter a whole number.";case"numberExpected":return"Please enter a number.";case"booleanExpected":return"Please enter true or false.";case"subprogramNotFound":return`No open diagram is called ${i.text}. The call was skipped.`;case"callTooDeep":return"Too many nested calls. Does a subprogram call itself?";case"callArguments":return`The call does not match the header of ${i.text}. Check the values in the parentheses.`;case"missingReturn":return`${i.text} ended without returning a value with return.`;case"fileNotFound":return`There is no file called ${i.text}.`;case"endOfFile":return`The file ${i.text} has no more lines.`;case"nullValue":return`${i.text} is null.`;case"other":return i.text}}class Ne extends Error{constructor(e){super(gh(e)),this.notice=e}}const Ke=i=>new Ne({kind:"unsupportedStatement",text:i}),R=i=>new Ne({kind:"invalidExpression",text:i}),K1=i=>new Ne({kind:"unknownVariable",text:i}),k3=()=>new Ne({kind:"divisionByZero"}),as=new Map;function S3(i,e){as.set(i,e)}const ph=()=>[...as];function mu(i){return i instanceof Ne?i.notice:{kind:"other",text:i instanceof Error?i.message:String(i)}}function T3(i){if(i===0)return"0";if(!Number.isFinite(i))return Number.isNaN(i)?"nan":i>0?"inf":"-inf";const e=Math.floor(Math.log10(Math.abs(Number(i.toPrecision(12)))));if(e<-4||e>=12){const[n,a]=i.toExponential(11).split("e"),s=n.includes(".")?n.replace(/0+$/,"").replace(/\.$/,""):n,r=Number(a);return`${s}e${r<0?"-":"+"}${String(Math.abs(r)).padStart(2,"0")}`}const t=i.toFixed(Math.max(0,11-e));return t.includes(".")?t.replace(/0+$/,"").replace(/\.$/,""):t}function du(i){return Number.isFinite(i)&&Math.round(i)===i?i.toFixed(1):T3(i)}function _e(i){switch(i.kind){case"int":return String(i.value);case"double":return du(i.value);case"string":return i.value;case"boolean":return String(i.value);case"intArray":return"["+i.value.map(String).join(", ")+"]";case"doubleArray":return"["+i.value.map(du).join(", ")+"]";case"stringArray":return"["+i.value.join(", ")+"]";case"booleanArray":return"["+i.value.map(String).join(", ")+"]";case"grid":return"["+_3(i).join(", ")+"]";case"reader":return`${i.className}(${i.file})`;case"writer":return`PrintWriter(${i.file})`;case"null":return"null"}}function _3(i){return i.value.map(e=>"["+e.map(t=>_e(bo(i.elementType,t))).join(", ")+"]")}function bo(i,e){switch(i){case"int":return{kind:"int",value:e};case"double":return{kind:"double",value:e};case"string":return{kind:"string",value:e};case"boolean":return{kind:"boolean",value:e}}}function hu(i){return i==="string"?"":i==="boolean"?!1:0}function xo(i){return i.kind==="intArray"||i.kind==="doubleArray"||i.kind==="stringArray"||i.kind==="booleanArray"||i.kind==="grid"}function O3(i){return i.kind==="int"||i.kind==="double"?i.value:NaN}const It=i=>({kind:"int",value:i}),kt=i=>({kind:"double",value:i}),Rl=i=>i!==void 0&&/\s/u.test(i),ss=i=>new RegExp("\\p{L}","u").test(i),ei=i=>new RegExp("\\p{N}","u").test(i);function oi(i){const e=Array.from(i);return e.length===0||!(ss(e[0])||e[0]==="_")?!1:e.every(t=>ss(t)||ei(t)||t==="_")}function tn(i){switch(i.toLowerCase()){case"int":return"int";case"double":return"double";case"string":return"string";case"char":return"string";case"boolean":case"bool":return"boolean";default:return}}function gu(i){return i.kind==="int"?"int":i.kind==="double"?"double":i.kind==="boolean"?"boolean":"string"}function lt(i){const e=Array.from(i);if(e.length===3&&e[0]==="'"&&e[2]==="'")return e[1];if(e.length<2||e[0]!=='"'||e[e.length-1]!=='"')return;const t=e.slice(1,-1).join("");if(/^(?:[^"\\]|\\.)*$/u.test(t))return t.replaceAll('\\"','"').replaceAll("\\n",` +`)}function pu(i){return i.replaceAll("(int)","").replaceAll("(double)","").trim()}function Gl(i){const e=new Array(i.length).fill(!1);let t=0,n=!1,a=!1;return i.forEach((s,r)=>{if(n){a?a=!1:s==="\\"?a=!0:s==='"'&&(n=!1);return}switch(s){case'"':n=!0;break;case"(":case"[":t+=1;break;case")":case"]":t-=1;break;default:e[r]=t===0}}),e}function rs(i,e){const t=Array.from(i),n=Array.from(e),a=Gl(t),s=[];let r=[],o=0;for(;ot[o+c]===u)&&a.slice(o,l).every(Boolean)){s.push(r.join("").trim()),r=[],o=l;continue}r.push(t[o]),o+=1}return s.push(r.join("").trim()),s}function A3(i){const e=Array.from(i),t=Gl(e);for(let n=0;n=","<=","==","!="].includes(o)&&(a=o)}if(a===void 0&&(e[n]==="<"||e[n]===">")&&(a=e[n]),a===void 0)continue;const s=e.slice(0,n).join("").trim(),r=e.slice(n+a.length).join("").trim();return{lhs:s,op:a,rhs:r}}}function Js(i,e){let t=0,n=!1,a=!1;for(let s=e;se.length||!t.every((r,o)=>e[a+o]===r))continue;const s=a+t.length-1;if(Js(e,s)===e.length-1)return{lhs:e.slice(0,a).join("").trim(),rhs:e.slice(s+1,-1).join("").trim()}}}function Ki(i){const e=i.trim();for(const t of["if","while","until","switch"]){if(!e.startsWith(t))continue;const n=e.slice(t.length);if(!(n===""||Rl(n[0])||n[0]==="("))continue;let a=n.trim();const s=fh(a);return s!==void 0&&(a=s),a===""?"true":a}return e===""?"true":e}function g1(i){const e=i.trim(),t=e.indexOf("[");if(!e.endsWith("]")||t<0)return;const n=e.slice(0,t).trim();if(!oi(n))return;const a=[];let s=t;for(;s2))return{arrayName:n,indexExpressions:a}}function j3(i){const e=i.trim();if(!e.endsWith(")"))return;const t=/^([A-Za-z_]\w*(?:\s*\[[^\[\]]*\])*|"(?:[^"\\]|\\.)*")\s*\.\s*([A-Za-z_]\w*)\s*\(/u.exec(e);if(!t)return;const n=Array.from(e),a=Array.from(t[0]).length-1;if(Js(n,a)!==n.length-1)return;const s=n.slice(a+1,-1).join("").trim();return{target:t[1],method:t[2],args:s===""?[]:rs(s,",")}}function fu(i){return oi(i)||g1(i)!==void 0}function fr(i){const e=[];let t="",n=!1,a=!1,s=0;for(const r of i){if(a){t+=r,a=!1;continue}if(r==="\\"){t+=r,a=!0;continue}if(r==='"'){n=!n,t+=r;continue}if(!n&&r==="("&&(s+=1),!n&&r===")"&&(s-=1),r==="+"&&!n&&s===0){e.push(t),t="";continue}t+=r}if(n)throw R(i);return e.push(t),e}function P3(i){const e=[];let t=0,n="";for(const a of i){if(a==="{"&&(t+=1),a==="}"&&(t-=1),a===","&&t===0){e.push(n),n="";continue}n+=a}return n.trim()!==""&&e.push(n),e}function bu(i){const e=Array.from(i),t=[];let n=0;for(;n1)throw R(i)}else if(!ei(e[n]))break;n+=1}const o=e.slice(s,n).join("");if(o==="."||!/^[0-9]*\.?[0-9]*$/.test(o))throw R(i);t.push({t:"number",literal:o,value:Number(o)});continue}if(ss(a)||a==="_"){const s=n;for(;n=0&&s=0&&o=0&&s|&&|\|\||^\s*!/u.test(e)}function Kn(i){let e=i.trim();for(;e.endsWith(";");)e=e.slice(0,-1).trim();return e}function vu(i){const e=i.slice(0,3);for(;e.length<3;)e.push("");return e}function yo(i){const e=i.map(t=>Kn(t).trim());return e.length===1&&e[0].includes(";")?vu(e[0].split(";").map(t=>t.trim())):vu(e)}const dt=i=>i.frame?{frame:i.frame,callPath:i.callPath}:{};function $t(i,e=[],t={}){const n=[],a=s=>n.push(t.frame?{...s,...t}:s);return i.forEach((s,r)=>{const o=[...e,r],l=s.textLines.join(" ").trim();switch(s.type){case S.anweisung:l!==""&&l!=="ø"&&a({path:o,text:l,kind:"statement"});break;case S.verzweigung:a({path:o,text:l||"true",kind:"branch",cases:s.cases});break;case S.fallauswahl:a({path:o,text:l||"0",kind:"switchSelection",cases:s.cases});break;case S.forSchleife:a({path:o,text:l,kind:"forLoopStart",loopBody:s.loopBody,forParts:yo(s.textLines)});break;case S.whileSchleife:a({path:o,text:l||"true",kind:"whileLoop",loopBody:s.loopBody});break;case S.doUntilSchleife:a({path:o,text:l||"true",kind:"doUntilLoop",loopBody:s.loopBody});break;case S.endlosschleife:a({path:o,text:l||"true",kind:"infiniteLoop",loopBody:s.loopBody});break;case S.aussprung:a({path:o,text:l,kind:"jump"});break;case S.aufruf:l!==""&&l!=="ø"&&a({path:o,text:l,kind:"call"});break}}),n}function B3(i,e){const t=i.trim().replaceAll(",",".");switch(e){case"int":if(!/^[+-]?[0-9]+$/.test(t))throw new Ne({kind:"wholeNumberExpected"});return It(Number(t));case"double":if(!/^[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?$/.test(t))throw new Ne({kind:"numberExpected"});return kt(Number(t));case"string":return{kind:"string",value:i};case"boolean":switch(t.toLowerCase()){case"true":case"wahr":return{kind:"boolean",value:!0};case"false":case"falsch":return{kind:"boolean",value:!1};default:throw new Ne({kind:"booleanExpected"})}}}function yu(){return{stepIndex:0,variables:new Map,outputLines:[],isHalted:!1,files:new Map,robotActions:[]}}function Z3(i,e){for(let t=0;tt===e.path[n])}function zt(i){const e=/^(void|int|double|String|boolean)\s+([A-Za-z_]\w*)\s*\((.*)\)$/u.exec(Kn(i));if(!e)return;const t=[];if(e[3].trim()!=="")for(const n of e[3].split(",")){const a=/^(int|double|String|boolean|char)\s*((?:\[\s*\]){0,2})\s+([A-Za-z_]\w*)$/u.exec(n.trim());if(!a)return;const s=(a[2].match(/\[/gu)??[]).length;t.push({type:tn(a[1]),name:a[3],...s>0?{dims:s}:{}})}return{returnType:tn(e[1]),name:e[2],params:t}}function bh(i){const e=/^(?:(?:(int|double|String|boolean)\s+)?([A-Za-z_]\w*)\s*=\s*)?([A-Za-z_]\w*)\s*\((.*)\)$/u.exec(Kn(i));if(e)return{targetType:e[1]?tn(e[1]):void 0,target:e[2],name:e[3],args:e[4].trim()===""?[]:rs(e[4],",")}}function os(i){var t,n;const e=Kn(i);return((t=zt(e))==null?void 0:t.name)??((n=bh(e))==null?void 0:n.name)??e.replace(/\(\s*\)$/u,"").trim()}class wi{constructor(e,t=()=>{}){y(this,"steps");y(this,"state",yu());y(this,"nextFrame",1);y(this,"callDepth",0);y(this,"frames",new Map);y(this,"peeking",!1);y(this,"robotSensors",{});y(this,"pseudocode");y(this,"decided");y(this,"afterOutput",!1);this.resolveSubprogram=t,this.steps=$t(e.elements),this.pseudocode=!!e.pseudocode}get currentStepPath(){const e=this.steps[this.state.stepIndex];return(e==null?void 0:e.callPath)??(e==null?void 0:e.path)}get canStep(){return!this.state.isHalted&&!this.state.inputRequest&&this.state.stepIndex ${_e(n)}`}catch(n){this.state.inputErrorNotice=mu(n);return}this.state.inputRequest=void 0,this.state.inputErrorNotice=void 0,this.state.stepIndex+=1,this.state.notice=this.finishedIfAtEnd()}}provideDecision(e){var s;if(((s=this.state.inputRequest)==null?void 0:s.valueType)==="string")return this.state.inputRequest=void 0,this.decided=e.trim(),this.step();const t=e.trim().toLowerCase(),n=["true","wahr","ja","yes","sim","verdadeiro"].includes(t),a=["false","falsch","nein","no","não","nao","falso"].includes(t);if(!n&&!a){this.state.inputErrorNotice={kind:"booleanExpected"};return}this.state.inputRequest=void 0,this.state.inputErrorNotice=void 0,this.decided=n,this.step()}condition(e){if(!this.pseudocode)return this.evaluateBool(e);const t=this.decided;if(typeof t=="boolean")return this.decided=void 0,t;this.state.inputRequest={variableName:"",valueType:"boolean",prompt:`${e} (true/false)`,decision:!0},this.state.inputErrorNotice=void 0,this.state.notice=void 0}finishedIfAtEnd(){return this.state.stepIndex>=this.steps.length?{kind:"finished"}:void 0}splice(e){this.steps.splice(this.state.stepIndex,1,...e)}noticeAfterEntering(e){return e.length>0?void 0:this.finishedIfAtEnd()}executeBranch(e){const t=e.cases;if(!t||t.length<2)throw Ke(e.text);const n=Ki(e.text),a=this.condition(n);if(a===void 0)return;const s=a?0:1,r=$t(t[s].elements,[...e.path,s],dt(e));this.splice(r),this.state.lastTrace=`${n} -> ${a}`,this.state.notice=this.noticeAfterEntering(r)}executeSwitchSelection(e){const t=e.cases;if(!t||t.length===0)throw Ke(e.text);const n=Ki(e.text);let a;if(this.pseudocode){const r=this.decided;if(typeof r!="string"){const l=t.map(u=>u.name).join(" / ");this.state.inputRequest={variableName:"",valueType:"string",prompt:`${n} (${l})`,decision:!0},this.state.notice=void 0;return}this.decided=void 0;const o=t.findIndex(l=>l.name.trim().toLowerCase()===r.toLowerCase());a=o>=0?o:t.length-1}else a=Z3(this.evaluateSwitchSelector(n),t)??t.length-1;const s=$t(t[a].elements,[...e.path,a],dt(e));this.splice(s),this.state.lastTrace=`${n} -> ${t[a].name}`,this.state.notice=this.noticeAfterEntering(s)}executeForLoopStart(e){if(this.pseudocode)return this.splice([{...e,kind:"whileLoop"}]);const t=yo(e.forParts??[e.text]);t[0]!==""&&this.executeStatement(t[0]),this.splice([{...dt(e),path:e.path,text:t[1],kind:"forLoopCondition",loopBody:e.loopBody,forParts:t}])}executeForLoopCondition(e){const t=yo(e.forParts??[e.text]),n=t[1]===""?"true":t[1],a=this.condition(n);if(a!==void 0)if(this.state.lastTrace=`${n} -> ${a}`,a){const s=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...s,{...dt(e),path:e.path,text:t[2],kind:"forLoopIncrement",loopBody:e.loopBody,forParts:t},{...dt(e),path:e.path,text:t[1],kind:"forLoopCondition",loopBody:e.loopBody,forParts:t}])}else this.splice([]),this.state.notice=this.finishedIfAtEnd()}executeForLoopIncrement(e){const t=e.text.trim();t!==""&&this.executeIncrement(t),this.splice([])}executeWhileLoop(e){const t=Ki(e.text),n=this.condition(t);if(n!==void 0)if(this.state.lastTrace=`${t} -> ${n}`,n){const a=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...a,{...dt(e),path:e.path,text:e.text,kind:"whileLoop",loopBody:e.loopBody}]),this.state.notice=this.noticeAfterEntering(a)}else this.splice([]),this.state.notice=this.finishedIfAtEnd()}enterDoUntilLoop(e){const t=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...t,{...dt(e),path:e.path,text:e.text,kind:"doUntilCondition",loopBody:e.loopBody}]),this.state.notice=this.noticeAfterEntering(t)}executeDoUntilCondition(e){const t=Ki(e.text),n=this.condition(t);if(n!==void 0)if(this.state.lastTrace=`${t} -> ${n}`,n){const a=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...a,{...dt(e),path:e.path,text:e.text,kind:"doUntilCondition",loopBody:e.loopBody}])}else this.splice([]),this.state.notice=this.finishedIfAtEnd()}enterInfiniteLoop(e){const t=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...t,{...dt(e),path:e.path,text:e.text,kind:"infiniteLoop",loopBody:e.loopBody}]),this.state.lastTrace="true -> true",this.state.notice=t.length>0?void 0:{kind:"infiniteLoopWithoutBody"}}executeJump(e){const t=e.frame??0,n=o=>o.lengthl===e.path[u]);let a=this.steps.length,s="end";for(let o=this.state.stepIndex+1;o ${s}`,s==="return"&&this.finishFrame(r),this.state.notice=this.finishedIfAtEnd()}executeCall(e){const t=e.text,n=this.resolveSubprogram(os(t));if(!n){this.splice([]),this.state.lastTrace=`${t} -> ?`,this.state.notice={kind:"subprogramNotFound",text:t},this.state.stepIndex>=this.steps.length&&(this.state.notice={kind:"finished"});return}const a=bh(t),s=zt(n.caption);if(s?((a==null?void 0:a.args.length)??0)!==s.params.length||(a==null?void 0:a.target)!==void 0&&!s.returnType:a!==void 0&&(a.args.length>0||a.target!==void 0))throw new Ne({kind:"callArguments",text:(s==null?void 0:s.name)??os(t)});if(this.callDepth>=I3)throw new Ne({kind:"callTooDeep"});const o=new Map,l=[];s==null||s.params.forEach((d,h)=>{const g=a.args[h].trim();if(!d.dims){o.set(d.name,this.evaluateExpression(g,d.type));return}const f=this.state.variables.get(g);if(!f)throw/^[A-Za-z_]\w*$/u.test(g)?new Ne({kind:"unknownVariable",text:g}):R(g);if(!(d.dims===1?f.kind===`${d.type}Array`:f.kind==="grid"&&f.elementType===d.type))throw R(g);o.set(d.name,f),l.push({param:d.name,callerName:g})}),this.callDepth+=1;const u={frame:this.nextFrame++,callPath:e.callPath??e.path};s&&(this.frames.set(u.frame,{saved:this.state.variables,header:s,call:a,references:l}),this.state.variables=o);const c=$t(n.elements,[],u);this.splice([...c,{...u,path:e.path,text:t,kind:"callEnd"}]);const m=s==null?void 0:s.params.map((d,h)=>`${d.name} = ${d.dims?a.args[h].trim():_e(o.get(d.name))}`).join(", ");this.state.lastTrace=m?`${t} -> ${m}`:`${t} -> call`}executeCallEnd(e){this.callDepth-=1,this.splice([]),this.state.lastTrace=`${e.text} -> return`,this.finishFrame(e),this.state.notice=this.finishedIfAtEnd()}executeReturn(e){const t=e.frame??0,n=Kn(e.text).slice(6).trim(),a=this.frames.get(t);if(a&&n!==""){if(!a.header.returnType)throw R(e.text);a.returnValue=this.evaluateExpression(n,a.header.returnType)}const s=a!=null&&a.returnValue?`${e.text} -> ${_e(a.returnValue)}`:`${e.text} -> return`;if(t===0){this.steps.splice(this.state.stepIndex),this.state.lastTrace=s,this.state.notice={kind:"finished"};return}let r=this.state.stepIndex+1;for(;r0?new Map(t.saved):t.saved;for(const c of t.references){const m=this.state.variables.get(c.param);m&&n.set(c.callerName,m)}this.state.variables=n;const a=t.returnValue;if(t.header.returnType&&!a)throw new Ne({kind:"missingReturn",text:t.header.name});const s=(l=t.call)==null?void 0:l.target;if(!s||!a)return;let r=(u=t.call)==null?void 0:u.targetType;if(!r)try{r=this.inferTargetValueType(s)}catch{r=t.header.returnType}const o=r==="double"&&a.kind==="int"?kt(a.value):r==="string"?{kind:"string",value:_e(a)}:a;if(gu(o)!==r)throw R(e.text);this.assignValue(o,s),this.state.lastTrace=`${s} = ${e.text.slice(e.text.indexOf("=")+1).trim()} -> ${_e(o)}`}executeStatement(e){const t=this.state,n=e.trim(),a=n.toLowerCase(),s=this.afterOutput;if(this.afterOutput=!1,a.startsWith("input:")){t.inputRequest=this.parseInputRequest(n,s),t.outputLineOpen=!1,t.inputErrorNotice=void 0;return}const r=/^System\s*\.\s*out\s*\.\s*(println|print)\s*\(([\s\S]*)\)\s*;?$/u.exec(n);if(a.startsWith("output:")||a.startsWith("print:")||r){const v=r?r[2]:n.slice(a.startsWith("output:")?7:6),w=this.peek(()=>this.renderOutputExpression(v)),I=v.trim()===""?"":this.evaluateOutputExpression(v);t.outputLineOpen&&t.outputLines.length?t.outputLines[t.outputLines.length-1]+=I:t.outputLines.push(I),t.outputLineOpen=(r==null?void 0:r[1])==="print",this.afterOutput=!0,t.lastTrace=`${w} -> ${I}`;return}const o=x3(n);if(o){this.executeMBotCommand(o.method,o.args,n);return}if(this.executeFileStatement(n))return;if(n.endsWith("++")||n.endsWith("--")||n.includes("+=")||n.includes("-=")){this.executeIncrement(n);return}const l=/^(?:final\s+)?([A-Za-z]+)\s+([A-Za-z_]\w*(?:\s*,\s*[A-Za-z_]\w*)*)$/u.exec(Kn(n).trim()),u=l?tn(l[1]):void 0;if(l&&u){const v=l[2].split(",").map(w=>w.trim());for(const w of v)t.variables.set(w,bo(u,hu(u)));t.lastTrace=v.map(w=>`${w} = ${_e(t.variables.get(w))}`).join(", ");return}const c=n.indexOf("=");if(c<0)throw Ke(n);const m=n.slice(0,c).trim(),d=n.slice(c+1),h=this.parseArrayDeclaration(m,d);if(h){t.variables.set(h.name,h.value),t.lastTrace=`${h.name} = new ${h.typeName}[${h.count}]`;return}const g=this.parseAssignmentTarget(m);let f;try{f=this.peek(()=>this.renderNumericExpression(d))}catch{f=d.trim()}let b=g.valueType;if(!b)try{b=this.inferTargetValueType(g.variableName)}catch{b="int"}const x=this.evaluateExpression(d,b);this.assignValue(x,g.variableName),t.lastTrace=`${g.variableName} = ${f} -> ${_e(x)}`}executeMBotCommand(e,t,n){var r;if((r=yi[e])!=null&&r.text){const o=yi[e];if(t.length!==o.args+1)throw R(n);const l=ns(e,t.slice(0,-1).map(m=>this.evaluateDouble(m)));if(!l)throw R(n);const u=cu(e,l,this.evaluateOutputExpression(t[t.length-1])),c=o.choices;if(c&&!c.includes(u.text??""))throw R(`${n} (${c.join(", ")})`);this.state.robotActions.push(u),this.state.lastTrace=`${n} -> ${u.label}`;return}const a=ns(e,t.map(o=>this.evaluateDouble(o)));if(!a)throw R(n);const s=cu(e,a);this.state.robotActions.push(s),this.state.lastTrace=`${n} -> ${s.label}`}executeFileStatement(e){const t=this.state,n=Kn(e).trim(),a=/^(?:(Scanner|BufferedReader|PrintWriter)\s+)?([A-Za-z_]\w*)\s*=\s*new\s+(Scanner|BufferedReader|PrintWriter)\s*\(([\s\S]*)\)$/u.exec(n);if(a){const[,c,m,d,h]=a;if(c&&c!==d)throw R(n);const g=d==="Scanner"?/^new\s+File\s*\(([\s\S]+)\)$/u.exec(h.trim()):d==="BufferedReader"?/^new\s+FileReader\s*\(([\s\S]+)\)$/u.exec(h.trim()):/^(?:new\s+(?:File|FileWriter)\s*\(([\s\S]+)\)|([\s\S]+))$/u.exec(h.trim());if(!g)throw Ke(n);const f=this.fileNameValue(g[1]??g[2]);if(d==="PrintWriter")t.variables.set(m,{kind:"writer",file:f,text:""});else{const x=this.fileContent(f).split(/\r?\n/u);x[x.length-1]===""&&x.pop(),t.variables.set(m,{kind:"reader",className:d,file:f,lines:x,next:0})}return t.lastTrace=`${m} = new ${d}(${f})`,!0}const s=/^Files\s*\.\s*writeString\s*\(\s*(?:Path\s*\.\s*of|Paths\s*\.\s*get)\s*\(([^()]+)\)\s*,([\s\S]+)\)$/u.exec(n);if(s){const c=this.fileNameValue(s[1]),m=this.evaluateOutputExpression(s[2]);return t.files.set(c,m),t.lastTrace=`${c} ← ${JSON.stringify(m)}`,!0}const r=/^([A-Za-z_]\w*)\s*\.\s*(println|print|close)\s*\(([\s\S]*)\)$/u.exec(n),o=r&&t.variables.get(r[1]);if(!r||!o)return!1;if(o.kind==="null")throw new Ne({kind:"nullValue",text:r[1]});if(o.kind==="reader"&&r[2]==="close")return t.lastTrace=`${r[1]}.close()`,!0;if(o.kind!=="writer")return!1;if(r[2]==="close")return t.files.set(o.file,o.text),t.lastTrace=`${o.file} ← ${JSON.stringify(o.text)}`,!0;const l=r[3].trim()===""?"":this.evaluateOutputExpression(r[3]),u=r[2]==="println"?l+` +`:l;return t.variables.set(r[1],{...o,text:o.text+u}),t.lastTrace=`${r[1]}.${r[2]}(${JSON.stringify(l)})`,!0}fileNameValue(e){const t=e.trim(),n=lt(t);if(n!==void 0)return n;const a=this.evaluateReference(t);if((a==null?void 0:a.kind)==="string")return a.value;throw R(t)}fileContent(e){const t=this.state.files.get(e)??as.get(e);if(t===void 0)throw new Ne({kind:"fileNotFound",text:e});return t}readerMethod(e,t,n,a){if(n.args.length)throw R(a);const s=t.next0?"+":"-";if(r.kind==="int"){t.set(s,It(r.value+a)),this.state.lastTrace=`${s} = ${r.value} ${o} 1 -> ${r.value+a}`;return}if(r.kind==="double"){const l=r.value+a;t.set(s,kt(l)),this.state.lastTrace=`${s} = ${_e(r)} ${o} 1 -> ${_e(kt(l))}`;return}throw Ke(e)}for(const[n,a]of[["+=",1],["-=",-1]]){const s=e.indexOf(n);if(s<0)continue;const r=e.slice(0,s).trim(),o=e.slice(s+2),l=t.get(r);if(!oi(r)||!l)throw Ke(e);const u=a>0?"+":"-";if(l.kind==="int"){const c=this.evaluateInt(o),m=l.value+a*c;t.set(r,It(m)),this.state.lastTrace=`${r} = ${l.value} ${u} ${c} -> ${m}`;return}if(l.kind==="double"){const c=this.evaluateDouble(o),m=l.value+a*c;t.set(r,kt(m)),this.state.lastTrace=`${r} = ${_e(l)} ${u} ${_e(kt(c))} -> ${_e(kt(m))}`;return}throw Ke(e)}this.executeStatement(e)}parseAssignmentTarget(e){if(g1(e))return{variableName:e.trim()};const t=e.split(/\s+/u).filter(Boolean);let n,a;if(t.length===1)n=t[0];else if(t.length===2&&tn(t[0]))n=t[1],a=tn(t[0]);else if(t.length===3&&t[0]==="const"&&tn(t[1]))n=t[2],a=tn(t[1]);else throw Ke(e);if(!fu(n))throw Ke(e);return{variableName:n,valueType:a}}parseInputRequest(e,t=!1){const n=e.slice(6).trim(),a=/^(\S+)(?:\s+(\S+))?(?:\s+([\s\S]*))?$/u.exec(n);if(!a)throw Ke(e);const s=[a[1],a[2],a[3]].filter(m=>m!==void 0);let r,o,l;const u=tn(s[0]);if(s.length>=2&&u?(r=s[1],o=u,l=(s[2]??"").trim()):(r=s[0],o=this.inferTargetValueType(r),l=(s[1]??"").trim()),!fu(r))throw Ke(e);const c=lt(l)??l;return c===""&&t?this.state.outputLineOpen?{variableName:r,valueType:o,prompt:"",continuesLine:!0}:{variableName:r,valueType:o,prompt:""}:{variableName:r,valueType:o,prompt:c===""?`${r}:`:c}}parseArrayDeclaration(e,t){const n=e.split(/\s+/u).filter(Boolean);if(n.length!==2||!n[0].endsWith("[]"))return;const a=n[0].endsWith("[][]"),s=n[0].slice(0,a?-4:-2),r=tn(s),o=n[1];if(!r||!oi(o))throw Ke(e);if(a)return this.parseGridDeclaration(o,s,r,t);const l=t.trim();if(l.startsWith("{")&&l.endsWith("}")){const h=l.slice(1,-1).split(",").map(f=>f.trim());let g;switch(r){case"int":g={kind:"intArray",value:h.map(f=>this.evaluateInt(f))};break;case"double":g={kind:"doubleArray",value:h.map(f=>this.evaluateDouble(f))};break;case"string":g={kind:"stringArray",value:h.map(f=>lt(f)??this.evaluateOutputExpression(f))};break;case"boolean":g={kind:"booleanArray",value:h.map(f=>this.evaluateBool(f))};break}return{name:o,typeName:s,count:h.length,value:g}}const u=`new ${s}[`;if(!l.startsWith(u)){const h=this.evaluateStringMethod(l);if((h==null?void 0:h.kind)==="stringArray"&&r==="string")return{name:o,typeName:s,count:h.value.length,value:h}}if(!l.startsWith(u)||!l.endsWith("]"))throw Ke(t);const c=l.slice(u.length,-1),m=this.evaluateInt(c);if(m<0)throw R(c);const d=r==="int"?{kind:"intArray",value:new Array(m).fill(0)}:r==="double"?{kind:"doubleArray",value:new Array(m).fill(0)}:r==="boolean"?{kind:"booleanArray",value:new Array(m).fill(!1)}:{kind:"stringArray",value:new Array(m).fill("")};return{name:o,typeName:s,count:m,value:d}}parseGridDeclaration(e,t,n,a){var m;const s=a.trim(),r=d=>{switch(n){case"int":return this.evaluateInt(d);case"double":return this.evaluateDouble(d);case"boolean":return this.evaluateBool(d);case"string":return lt(d.trim())??this.evaluateOutputExpression(d)}};if(s.startsWith("{")&&s.endsWith("}")){const d=P3(s.slice(1,-1)).map(h=>{const g=h.trim();if(!g.startsWith("{")||!g.endsWith("}"))throw R(g);return g.slice(1,-1).trim()===""?[]:g.slice(1,-1).split(",").map(f=>r(f.trim()))});return{name:e,typeName:t,count:`${d.length}][${((m=d[0])==null?void 0:m.length)??0}`,value:{kind:"grid",elementType:n,value:d}}}const o=new RegExp(String.raw`^new\s+${t}\s*\[(.+)\]\s*\[(.+)\]$`,"u").exec(s);if(!o)throw Ke(a);const l=this.evaluateInt(o[1]),u=this.evaluateInt(o[2]);if(l<0)throw R(o[1]);if(u<0)throw R(o[2]);const c={kind:"grid",elementType:n,value:Array.from({length:l},()=>new Array(u).fill(hu(n)))};return{name:e,typeName:t,count:`${l}][${u}`,value:c}}arrayIndex(e){const t=this.evaluateInt(e);if(t<0)throw R(e);return t}evaluateReference(e){const t=e.trim(),n=this.state.variables.get(t);if(n)return n;const a=this.evaluateStringMethod(t);if(a)return a;const s=/^\(\s*char\s*\)\s*(.+)$/su.exec(t);if(s){const o=this.evaluateInt(s[1]);if(!(o>=0&&o<=1114111))throw R(t);return{kind:"string",value:String.fromCodePoint(o)}}const r=g1(t);if(r)return this.valueInArray(r.arrayName,r.indexExpressions.map(o=>this.arrayIndex(o)))}evaluateStringMethod(e){const t=j3(e);if(!t)return;const n=this.evaluateStaticCall(e,t);if(n)return n;const a=this.state.variables.get(t.target.trim());if((a==null?void 0:a.kind)==="reader")return this.readerMethod(t.target.trim(),a,t,e);if((a==null?void 0:a.kind)==="null")throw new Ne({kind:"nullValue",text:t.target.trim()});const s=lt(t.target)??this.stringValueOf(t.target);if(s===void 0)return;const r=t.args,o=d=>{const h=r[d];if(h===void 0)throw R(e);const g=lt(h.trim());if(g!==void 0)return g;const f=this.evaluateReference(h);if((f==null?void 0:f.kind)==="string")return f.value;throw R(h)},l=d=>{if(r[d]===void 0)throw R(e);return this.evaluateInt(r[d])},u=d=>{if(r.length!==d)throw R(e)},c=Array.from(s),m=(d,h)=>{if(d<0||d>h)throw R(e);return d};switch(t.method){case"length":return u(0),It(c.length);case"charAt":return u(1),{kind:"string",value:c[m(l(0),c.length-1)]};case"substring":{if(r.length!==1&&r.length!==2)throw R(e);const d=m(l(0),c.length),h=r.length===2?m(l(1),c.length):c.length;if(h0&&h[h.length-1]==="";)h.pop();return{kind:"stringArray",value:h}}default:return}}evaluateStaticCall(e,t){const n=()=>{if(t.args.length!==1)throw R(e);return t.args[0]},a=s=>{const r=lt(s.trim());if(r!==void 0)return r;const o=this.evaluateReference(s);if((o==null?void 0:o.kind)==="string")return o.value;throw R(s)};switch(`${t.target}.${t.method}`){case"Integer.parseInt":{const s=a(n()).trim();if(!/^[+-]?\d+$/u.test(s))throw new Ne({kind:"wholeNumberExpected"});return It(Number(s))}case"Double.parseDouble":{const s=Number(a(n()).trim());if(!Number.isFinite(s))throw new Ne({kind:"numberExpected"});return kt(s)}case"String.valueOf":return{kind:"string",value:this.evaluateOutputExpression(n())};case"Files.readString":{const s=/^(?:Path\s*\.\s*of|Paths\s*\.\s*get)\s*\(\s*("(?:[^"\\]|\\.)*")\s*\)$/u.exec(n().trim());if(!s)throw R(e);const r=lt(s[1]),o=as.get(r);if(o===void 0)throw new Ne({kind:"fileNotFound",text:r});return{kind:"string",value:o}}default:return}}stringValueOf(e){const t=e.trim(),n=this.state.variables.get(t);if(n)return n.kind==="string"?n.value:void 0;const a=g1(t);if(!a)return;const s=this.valueInArray(a.arrayName,a.indexExpressions.map(r=>this.arrayIndex(r)));return s.kind==="string"?s.value:void 0}substituteStringCalls(e){if(!e.includes("("))return e;let t="",n=e;const a=/([A-Za-z_]\w*(?:\[[^\[\]]*\])*|"(?:[^"\\]|\\.)*")\s*\.\s*(length|indexOf|lastIndexOf|compareTo|charAt|parseInt|parseDouble)\s*\(/u;for(let s=a.exec(n);s;s=a.exec(n)){const r=s.index+s[0].length-1,o=Js(Array.from(n),Array.from(n.slice(0,r)).length);if(o===void 0)break;const l=Array.from(n),u=l.slice(Array.from(n.slice(0,s.index)).length,o+1).join(""),c=this.evaluateStringMethod(u),m=l.slice(0,Array.from(n.slice(0,s.index)).length).join(""),d=(c==null?void 0:c.kind)==="string"?vo(c.value):void 0;(c==null?void 0:c.kind)==="int"?t+=m+String(c.value):(c==null?void 0:c.kind)==="double"?t+=m+(Number.isInteger(c.value)?c.value.toFixed(1):String(c.value)):d!==void 0?t+=m+String(d):t+=m+u,n=l.slice(o+1).join("")}return t+n}valueInArray(e,t){const n=this.state.variables.get(e);if(!n)throw K1(e);const a=`${e}[${t.join("][")}]`;if(n.kind==="grid"){if(t.length!==2)throw R(a);const r=n.value[t[0]];if(!r||t[1]>=r.length)throw R(a);return bo(n.elementType,r[t[1]])}if(t.length!==1)throw R(a);const s=t[0];if(!xo(n))throw R(e);if(s>=n.value.length)throw R(a);switch(n.kind){case"intArray":return It(n.value[s]);case"doubleArray":return kt(n.value[s]);case"stringArray":return{kind:"string",value:n.value[s]};case"booleanArray":return{kind:"boolean",value:n.value[s]};default:throw R(e)}}inferTargetValueType(e){const t=e.trim(),n=this.state.variables.get(t);if(n)return gu(n);const a=g1(t);if(a){const s=this.state.variables.get(a.arrayName);if(!s)throw K1(a.arrayName);if(s.kind==="intArray")return"int";if(s.kind==="doubleArray")return"double";if(s.kind==="stringArray")return"string";if(s.kind==="booleanArray")return"boolean";if(s.kind==="grid")return s.elementType;throw R(a.arrayName)}throw Ke(e)}assignValue(e,t){const n=t.trim(),a=g1(n);if(!a){this.state.variables.set(n,e);return}const s=a.indexExpressions.map(u=>this.arrayIndex(u)),r=this.state.variables.get(a.arrayName);if(!r)throw K1(a.arrayName);if(r.kind==="grid"){if(s.length!==2||s[0]>=r.value.length||s[1]>=r.value[s[0]].length)throw R(n);const u=r.elementType==="double"&&e.kind==="int"||e.kind===r.elementType?e.value:void 0;if(u===void 0||xo(e))throw R(n);const c=r.value.map(m=>[...m]);c[s[0]][s[1]]=u,this.state.variables.set(a.arrayName,{...r,value:c});return}if(s.length!==1)throw R(n);const o=s[0];let l;if(r.kind==="intArray"&&e.kind==="int")l={kind:"intArray",value:[...r.value]};else if(r.kind==="doubleArray"&&(e.kind==="double"||e.kind==="int"))l={kind:"doubleArray",value:[...r.value]};else if(r.kind==="stringArray"&&e.kind==="string")l={kind:"stringArray",value:[...r.value]};else if(r.kind==="booleanArray"&&e.kind==="boolean")l={kind:"booleanArray",value:[...r.value]};else throw R(n);if(o>=l.value.length)throw R(n);l.value[o]=e.value,this.state.variables.set(a.arrayName,l)}evaluateOutputExpression(e){const t=this.withSensors(e).trim();if(xu(t)&&fr(t).every(s=>lt(s.trim())===void 0)&&!this.evaluateReference(t))return String(this.evaluateBool(t));let n,a;for(const s of fr(this.withSensors(e))){const r=s.trim(),o=lt(r),l=o!==void 0?{kind:"string",value:o}:this.evaluateReference(r)??(xu(r)?{kind:"boolean",value:this.evaluateBool(r)}:this.evaluateNumeric(r)),u=l.kind==="int"||l.kind==="double";if(a===void 0&&u){n?n=n.kind==="int"&&l.kind==="int"?It(n.value+l.value):kt(n.value+l.value):n=l;continue}a=(a??(n?_e(n):""))+_e(l),n=void 0}return a??(n?_e(n):"")}renderOutputExpression(e){return fr(e).map(t=>{const n=t.trim();if(lt(n)!==void 0)return n;const a=this.evaluateReference(n);if(a)return _e(a);try{return this.renderNumericExpression(n)}catch{return n}}).join(" + ")}evaluateExpression(e,t){switch(t){case"int":return It(this.evaluateInt(e));case"double":return kt(this.evaluateDouble(e));case"string":{const n=e.trim(),a=lt(n);if(a!==void 0)return{kind:"string",value:a};if(n==="null")return{kind:"null"};const s=this.evaluateReference(n);return(s==null?void 0:s.kind)==="null"?s:s?{kind:"string",value:_e(s)}:{kind:"string",value:this.evaluateOutputExpression(e)}}case"boolean":return{kind:"boolean",value:this.evaluateBool(e)}}}evaluateNumeric(e){const{v:t,int:n}=this.parser(e).parseNumber();return n||Number.isFinite(t)&&Math.round(t)===t?It(t):kt(t)}parser(e){const t=this.withSensors(e);return new D3(bu(pu(this.substituteStringCalls(t))),this.state.variables)}withSensors(e){return y3(e,t=>this.robotSensors[t]??Ot[t].simulated)}evaluateInt(e){return this.parser(e).parseInt()}evaluateDouble(e){return this.parser(e).parseDouble()}evaluateBool(e){const t=this.withSensors(e).trim();if(t==="true")return!0;if(t==="false")return!1;const n=this.evaluateReference(t);if((n==null?void 0:n.kind)==="boolean")return n.value;const a=rs(t,"||");if(a.length>1)return a.some(u=>this.evaluateBool(u));const s=rs(t,"&&");if(s.length>1)return s.every(u=>this.evaluateBool(u));if(t.startsWith("!")&&!t.startsWith("!="))return!this.evaluateBool(t.slice(1));const r=fh(t);if(r!==void 0)return this.evaluateBool(r);const o=C3(t);if(o)return this.evaluateComparison(o.lhs,"==",o.rhs);const l=A3(t);if(l)return this.evaluateComparison(l.lhs,l.op,l.rhs);if(this.stringOperand(t)!==void 0)throw R(t);return this.evaluateDouble(t)!==0}evaluateComparison(e,t,n){if((e.trim()==="null"||n.trim()==="null")&&(t==="=="||t==="!=")){const c=d=>{var h;return d.trim()==="null"||((h=this.evaluateReference(d))==null?void 0:h.kind)==="null"},m=c(e)===c(n);return t==="=="?m:!m}const a=this.booleanOperand(e),s=this.booleanOperand(n);if((a!==void 0||s!==void 0)&&(t==="=="||t==="!=")){const c=a??this.evaluateBool(e),m=s??this.evaluateBool(n);return t==="=="?c===m:c!==m}const r=this.stringOperand(e),o=this.stringOperand(n);let l,u;if(r!==void 0||o!==void 0){if(r===void 0||o===void 0)throw R(`${e} ${t} ${n}`);l=r,u=o}else l=this.evaluateDouble(e),u=this.evaluateDouble(n);switch(t){case"==":return l===u;case"!=":return l!==u;case"<":return l":return l>u;case">=":return l>=u;default:throw R(`${e} ${t} ${n}`)}}booleanOperand(e){const t=e.trim();if(t==="true")return!0;if(t==="false")return!1;const n=this.evaluateReference(t);return(n==null?void 0:n.kind)==="boolean"?n.value:void 0}stringOperand(e){const t=e.trim(),n=lt(t);if(n!==void 0)return n;const a=this.evaluateReference(t);return(a==null?void 0:a.kind)==="string"?a.value:void 0}evaluateSwitchSelector(e){const t=this.withSensors(e).trim(),n=lt(t);if(n!==void 0)return{kind:"text",value:n};const a=this.state.variables.get(t);if(a)switch(a.kind){case"int":return{kind:"int",value:a.value};case"double":return{kind:"int",value:Math.trunc(a.value)};case"string":return{kind:"text",value:a.value};default:throw R(t)}return/^[+-]?[0-9]+$/.test(t)?{kind:"int",value:Number(t)}:{kind:"int",value:this.evaluateInt(t)}}renderNumericExpression(e){return bu(pu(e)).map(t=>{if(t.t==="number")return t.literal;if(t.t==="identifier"){const n=this.state.variables.get(t.name);if(!n)throw K1(t.name);return _e(n)}return t.t}).join(" ").replaceAll("( ","(").replaceAll(" )",")").replaceAll(" . ",".").replaceAll("[ ","[").replaceAll(" ]","]")}}const xh={baseIndent:0,indentPerLevel:4,includeDiagramTextAsComments:!1,includeEmptyElseBranch:!0,pseudocodeNote:"Pseudocode – not a runnable program"};function ls(i,e,t={},n=[]){const a=Hl(i,e,t);let s="";e==="javascript"&&(s+=`"use strict"; `);const r=[i,...e==="java"?[]:n];if(e==="python"&&r.some(Dh)&&(s+=`import random @@ -27,49 +27,49 @@ except: `),i.pseudocode&&(s+=(e==="python"?"# ":"// ")+a.pseudocodeNote+` `),e!=="java")for(const u of n){if(u===i)continue;const c=zt(u.caption);c&&(s+=wo(u,c,e,t,0)+` -`)}const o=zt(i.caption),l={out:""};if(o)l.out=wo(i,o,e,t,a.baseIndent);else for(const u of i.elements)Vs(u,e,a,a.baseIndent,l);if(s+=l.out,s.trim()===""){const u=L3(e);return e==="javascript"?`"use strict"; +`)}const o=zt(i.caption),l={out:""};if(o)l.out=wo(i,o,e,t,a.baseIndent);else for(const u of i.elements)Vs(u,e,a,a.baseIndent,l);if(s+=l.out,s.trim()===""){const u=E3(e);return e==="javascript"?`"use strict"; -`+u:u}return Lh(s.replace(/^[\n\r]+|[\n\r]+$/g,""),e)}function Hl(i,e,t){const n={...xh,...t,jsIntVariables:new Set,arrayElementTypes:V3(i),stringVariables:H3(i)};return e!=="java"&&(n.jsIntVariables=hb(i)),n}const wu=i=>i==="string"?"String":i===void 0?"void":i;function vh(i){const e=i.params.map(t=>`${wu(t.type)}${"[]".repeat(t.dims??0)} ${t.name}`).join(", ");return`public static ${wu(i.returnType)} ${i.name}(${e}) {`}function wo(i,e,t,n,a){const s=Hl(i,t,n);for(const l of e.params)l.dims||(l.type==="int"&&s.jsIntVariables.add(l.name),l.type==="string"&&s.stringVariables.add(l.name));const r=e.params.map(l=>l.name).join(", "),o={out:""};for(const l of i.elements)Vs(l,t,s,a+s.indentPerLevel,o);switch(o.out.trim()===""&&(o.out=Z(a+s.indentPerLevel)+(t==="python"?`pass +`+u:u}return Lh(s.replace(/^[\n\r]+|[\n\r]+$/g,""),e)}function Hl(i,e,t){const n={...xh,...t,jsIntVariables:new Set,arrayElementTypes:q3(i),stringVariables:V3(i)};return e!=="java"&&(n.jsIntVariables=gb(i)),n}const wu=i=>i==="string"?"String":i===void 0?"void":i;function vh(i){const e=i.params.map(t=>`${wu(t.type)}${"[]".repeat(t.dims??0)} ${t.name}`).join(", ");return`public static ${wu(i.returnType)} ${i.name}(${e}) {`}function wo(i,e,t,n,a){const s=Hl(i,t,n);for(const l of e.params)l.dims||(l.type==="int"&&s.jsIntVariables.add(l.name),l.type==="string"&&s.stringVariables.add(l.name));const r=e.params.map(l=>l.name).join(", "),o={out:""};for(const l of i.elements)Vs(l,t,s,a+s.indentPerLevel,o);switch(o.out.trim()===""&&(o.out=Z(a+s.indentPerLevel)+(t==="python"?`pass `:` `)),t){case"java":return`${Z(a)}${vh(e)} ${o.out}${Z(a)}} `;case"python":return`${Z(a)}def ${e.name}(${r}): ${o.out}`;case"javascript":return`${Z(a)}function ${e.name}(${r}) { ${o.out}${Z(a)}} -`}}const Z=i=>i>0?" ".repeat(i):"";function ve(i,e){const t=i.exec(e);return t?Array.from(t,n=>n??""):void 0}function L3(i,e){return i==="python"?"# empty element":"// empty element"}const zo=i=>i.trim()==="ø";function yh(i,e){return Z(i)+(e==="python"?`# empty element +`}}const Z=i=>i>0?" ".repeat(i):"";function ve(i,e){const t=i.exec(e);return t?Array.from(t,n=>n??""):void 0}function E3(i,e){return i==="python"?"# empty element":"// empty element"}const zo=i=>i.trim()==="ø";function yh(i,e){return Z(i)+(e==="python"?`# empty element `:`// empty element -`)}function E3(i){switch(i.type){case S.leerElement:return!0;case S.anweisung:case S.aufruf:return i.textLines.map(e=>e.trim()).every(e=>e===""||zo(e));default:return!1}}function W3(i){return i.every(E3)}function Vl(i,e,t){const n=i.map(a=>a.replace(/^[ \t]+|[ \t]+$/g,"")).filter(a=>a!=="");return n.length===0?"":e==="python"?Z(t)+`""" +`)}function W3(i){switch(i.type){case S.leerElement:return!0;case S.anweisung:case S.aufruf:return i.textLines.map(e=>e.trim()).every(e=>e===""||zo(e));default:return!1}}function N3(i){return i.every(W3)}function Vl(i,e,t){const n=i.map(a=>a.replace(/^[ \t]+|[ \t]+$/g,"")).filter(a=>a!=="");return n.length===0?"":e==="python"?Z(t)+`""" `+n.map(a=>Z(t)+a+` `).join("")+Z(t)+`""" `:n.length===1?Z(t)+"/* "+n[0]+` */ `:Z(t)+`/* `+n.map(a=>Z(t)+" * "+a+` `).join("")+Z(t)+` */ -`}const N3=i=>i==="java"||i==="javascript";function us(i){const e=i.trim();if(e==="")return"";if(e.startsWith("//")||e.startsWith("/*")||e.startsWith("*")||e.startsWith("#")||e.startsWith("{")||e.startsWith("}")||e.endsWith("{")||e.endsWith(";"))return e;const t=e.toLowerCase();for(const n of["if ","else","for ","while ","do ","switch ","case ","default"])if(t.startsWith(n))return e;return e+";"}function La(i){const e=i.map(t=>t.trim()).filter(t=>t!=="");return F3(e.length===0?"true":e.join(" "))}function F3(i){const e=i.trim();for(const t of["if","while","until","switch"]){const n=wh(t,e);if(n!==void 0)return n===""?"true":n}return e}function wh(i,e){if(!e.toLowerCase().startsWith(i))return;const t=e.slice(i.length);if(!(t===""||/^\s/.test(t)||t[0]==="("))return;let n=t.trim();return n.startsWith("(")&&n.endsWith(")")&&n.length>=2&&(n=n.slice(1,-1).trim()),n}function qt(i){let e=i.trim();for(;e.endsWith(";");)e=e.slice(0,-1).trim();return e}function J3(i){const e=i.trim(),t=e.toLowerCase();let n;if(t.startsWith("output:"))n=e.slice(7).trim();else if(t.startsWith("print:"))n=e.slice(6).trim();else return;return n===""?void 0:n}const Rs=i=>i.name.includes("[")&&i.name.includes("]");function ql(i){const e=i.trim();if(e==="")return;const t=ve(/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s+([a-zA-Z_]\w*(?:\s*\[[^\]]+\])?)(?:\s+"([^"]*)")?\s*$/i,e);if(t){const s=t[2].replaceAll(" ","");if(s==="")return;const r=(t[3]??"").trim();return{type:cs(t[1]),name:s,customPrompt:r===""?void 0:r}}const n=ve(/^\s*([a-zA-Z_]\w*(?:\s*\[[^\]]+\])?)\s+"([^"]*)"\s*$/i,e);if(n){const s=n[1].replaceAll(" ","");return["int","integer","long","float","double","string","boolean","char","bool","void"].includes(s.toLowerCase())?void 0:{type:s.includes("[")?"String":"int",name:s,customPrompt:n[2].trim()}}const a=R3(e);if(a)return{type:cs(a[0]),name:a[1]}}function cs(i){switch(i.trim().toLowerCase()){case"integer":case"int":return"int";case"long":return"long";case"float":return"float";case"double":return"double";case"string":return"String";case"boolean":case"bool":return"boolean";case"char":return"char";default:return i}}function R3(i){const e=i.split(/[ \t]+/).filter(Boolean);if(e.length===0)return;if(e.length>=2)return[e[0],e[1]];if(!["int","double","string","boolean","char","long","float","short","byte","void","bool","integer"].includes(e[0].toLowerCase()))return["int",e[0]]}function G3(i,e,t,n,a){const s=qt(i).trim();if(s.startsWith('"'))switch(e){case"java":return Z(t)+"System.out.println("+s+`); +`}const F3=i=>i==="java"||i==="javascript";function us(i){const e=i.trim();if(e==="")return"";if(e.startsWith("//")||e.startsWith("/*")||e.startsWith("*")||e.startsWith("#")||e.startsWith("{")||e.startsWith("}")||e.endsWith("{")||e.endsWith(";"))return e;const t=e.toLowerCase();for(const n of["if ","else","for ","while ","do ","switch ","case ","default"])if(t.startsWith(n))return e;return e+";"}function La(i){const e=i.map(t=>t.trim()).filter(t=>t!=="");return J3(e.length===0?"true":e.join(" "))}function J3(i){const e=i.trim();for(const t of["if","while","until","switch"]){const n=wh(t,e);if(n!==void 0)return n===""?"true":n}return e}function wh(i,e){if(!e.toLowerCase().startsWith(i))return;const t=e.slice(i.length);if(!(t===""||/^\s/.test(t)||t[0]==="("))return;let n=t.trim();return n.startsWith("(")&&n.endsWith(")")&&n.length>=2&&(n=n.slice(1,-1).trim()),n}function qt(i){let e=i.trim();for(;e.endsWith(";");)e=e.slice(0,-1).trim();return e}function R3(i){const e=i.trim(),t=e.toLowerCase();let n;if(t.startsWith("output:"))n=e.slice(7).trim();else if(t.startsWith("print:"))n=e.slice(6).trim();else return;return n===""?void 0:n}const Rs=i=>i.name.includes("[")&&i.name.includes("]");function ql(i){const e=i.trim();if(e==="")return;const t=ve(/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s+([a-zA-Z_]\w*(?:\s*\[[^\]]+\])?)(?:\s+"([^"]*)")?\s*$/i,e);if(t){const s=t[2].replaceAll(" ","");if(s==="")return;const r=(t[3]??"").trim();return{type:cs(t[1]),name:s,customPrompt:r===""?void 0:r}}const n=ve(/^\s*([a-zA-Z_]\w*(?:\s*\[[^\]]+\])?)\s+"([^"]*)"\s*$/i,e);if(n){const s=n[1].replaceAll(" ","");return["int","integer","long","float","double","string","boolean","char","bool","void"].includes(s.toLowerCase())?void 0:{type:s.includes("[")?"String":"int",name:s,customPrompt:n[2].trim()}}const a=G3(e);if(a)return{type:cs(a[0]),name:a[1]}}function cs(i){switch(i.trim().toLowerCase()){case"integer":case"int":return"int";case"long":return"long";case"float":return"float";case"double":return"double";case"string":return"String";case"boolean":case"bool":return"boolean";case"char":return"char";default:return i}}function G3(i){const e=i.split(/[ \t]+/).filter(Boolean);if(e.length===0)return;if(e.length>=2)return[e[0],e[1]];if(!["int","double","string","boolean","char","long","float","short","byte","void","bool","integer"].includes(e[0].toLowerCase()))return["int",e[0]]}function H3(i,e,t,n,a){const s=qt(i).trim();if(s.startsWith('"'))switch(e){case"java":return Z(t)+"System.out.println("+s+`); `;case"javascript":return Z(t)+"console.log("+s+`); `;case"python":return Z(t)+"print("+Dn(s,n,a)+`) `}}function zi(i){return i.replaceAll("\\","\\\\").replaceAll('"','\\"').replaceAll(` -`,"\\n").replaceAll("\r","\\r")}function Ql(i,e){const t=i.trim();if(!t.toLowerCase().startsWith("input:"))return;const n=t.slice(6).trim();if(n==="")return;const a=ql(n);if(a&&Rs(a)&&!/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s/i.test(n)){const s=e.get(a.name.slice(0,a.name.indexOf("[")).trim());if(s)return{...a,type:s}}return a}function H3(i){const e=new Set;return fn(i.elements,t=>{for(const n of t.textLines){const a=n.trim();if(a.toLowerCase().startsWith("input:")){const o=ql(a.slice(6).trim());(o==null?void 0:o.type)==="String"&&!Rs(o)&&e.add(o.name);continue}const s=ve(/^\s*(?:const\s+)?string\s+([a-zA-Z_]\w*)\s*=/i,a);s&&e.add(s[1]);const r=ve(/^\s*string\s*\[\s*\]\s*([a-zA-Z_]\w*)\s*=/i,a);r&&e.add(r[1]+"[]")}}),e}function V3(i){const e=new Map;return fn(i.elements,t=>{for(const n of t.textLines){const a=ve(/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s*\[\s*\]\s*([a-zA-Z_]\w*)/i,n)??ve(/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s+([a-zA-Z_]\w*)\s*\[\s*\]/i,n);a&&e.set(a[2],cs(a[1]))}}),e}function q3(i,e,t){const n=Ql(i,t);if(!n)return;const a=n.customPrompt?n.customPrompt:n.name+": ",s=Z(e)+'System.out.println("'+zi(a)+`"); +`,"\\n").replaceAll("\r","\\r")}function Ql(i,e){const t=i.trim();if(!t.toLowerCase().startsWith("input:"))return;const n=t.slice(6).trim();if(n==="")return;const a=ql(n);if(a&&Rs(a)&&!/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s/i.test(n)){const s=e.get(a.name.slice(0,a.name.indexOf("[")).trim());if(s)return{...a,type:s}}return a}function V3(i){const e=new Set;return fn(i.elements,t=>{for(const n of t.textLines){const a=n.trim();if(a.toLowerCase().startsWith("input:")){const o=ql(a.slice(6).trim());(o==null?void 0:o.type)==="String"&&!Rs(o)&&e.add(o.name);continue}const s=ve(/^\s*(?:const\s+)?string\s+([a-zA-Z_]\w*)\s*=/i,a);s&&e.add(s[1]);const r=ve(/^\s*string\s*\[\s*\]\s*([a-zA-Z_]\w*)\s*=/i,a);r&&e.add(r[1]+"[]")}}),e}function q3(i){const e=new Map;return fn(i.elements,t=>{for(const n of t.textLines){const a=ve(/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s*\[\s*\]\s*([a-zA-Z_]\w*)/i,n)??ve(/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s+([a-zA-Z_]\w*)\s*\[\s*\]/i,n);a&&e.set(a[2],cs(a[1]))}}),e}function Q3(i,e,t){const n=Ql(i,t);if(!n)return;const a=n.customPrompt?n.customPrompt:n.name+": ",s=Z(e)+'System.out.println("'+zi(a)+`"); `,r=o=>Rs(n)?n.name:`${o} ${n.name}`;switch(n.type){case"int":return s+Z(e)+`${r("int")} = scanner.nextInt(); `;case"double":return s+Z(e)+`${r("double")} = scanner.nextDouble(); `;case"String":return s+Z(e)+`${r("String")} = scanner.next(); `;case"boolean":return s+Z(e)+`${r("boolean")} = scanner.nextBoolean(); -`;default:return}}function Q3(i,e,t){const n=Ql(i,t);if(!n)return;const a=!!n.customPrompt,s=a?"":Z(e)+'console.log("'+zi(n.name+": ")+`"); +`;default:return}}function U3(i,e,t){const n=Ql(i,t);if(!n)return;const a=!!n.customPrompt,s=a?"":Z(e)+'console.log("'+zi(n.name+": ")+`"); `,r=l=>{const u=a?n.customPrompt:n.name+": ";return`(prompt("${zi(u)}") ?? "${l}")`},o=Rs(n)?n.name:`let ${n.name}`;switch(n.type){case"int":return s+Z(e)+`${o} = parseInt(${r("0")}, 10); `;case"double":return s+Z(e)+`${o} = Number(${r("0")}); `;case"String":return s+Z(e)+`${o} = ${r("")}; `;case"boolean":return s+Z(e)+`${o} = ${r("")}.trim().toLowerCase() === "true"; -`;default:return}}function U3(i,e,t){const n=Ql(i,t);if(!n)return;const a=!!n.customPrompt,s=a?"":Z(e)+'print("'+zi(n.name+": ")+`") +`;default:return}}function $3(i,e,t){const n=Ql(i,t);if(!n)return;const a=!!n.customPrompt,s=a?"":Z(e)+'print("'+zi(n.name+": ")+`") `,r=`input("${zi(a?n.customPrompt:n.name+": ")}")`;switch(n.type){case"int":return s+Z(e)+`${n.name} = int(${r}) `;case"double":return s+Z(e)+`${n.name} = float(${r}) `;case"String":return s+Z(e)+`${n.name} = ${r} `;case"boolean":return s+Z(e)+`${n.name} = ${r}.strip().lower() in ("true", "wahr") -`;default:return}}const br=String.raw`("(?:[^"\\]|\\.)*"|[A-Za-z_]\w*)`,$3=[[new RegExp(String.raw`^new\s+Scanner\s*\(\s*new\s+File\s*\(\s*${br}\s*\)\s*\)$`),"Scanner"],[new RegExp(String.raw`^new\s+BufferedReader\s*\(\s*new\s+FileReader\s*\(\s*${br}\s*\)\s*\)$`),"BufferedReader"],[new RegExp(String.raw`^new\s+PrintWriter\s*\(\s*(?:new\s+(?:File|FileWriter)\s*\(\s*)?${br}\s*\)?\s*\)$`),"PrintWriter"]];function zh(i){const e=i.trim();for(const[t,n]of $3){const a=t.exec(e);if(a)return{kind:n,name:a[1]}}}function Y3(i,e,t,n,a){if(e==="java")return;const s=qt(i).trim(),r=/^(?:(?:Scanner|BufferedReader|PrintWriter)\s+)?([A-Za-z_]\w*)\s*=\s*(new\s[\s\S]+)$/.exec(s),o=r&&zh(r[2]);if(r&&o){const c=/^(?:Scanner|BufferedReader|PrintWriter)\s/.test(s);return e==="python"?Z(t)+`${r[1]} = ${o.kind}(${o.name}) +`;default:return}}const br=String.raw`("(?:[^"\\]|\\.)*"|[A-Za-z_]\w*)`,Y3=[[new RegExp(String.raw`^new\s+Scanner\s*\(\s*new\s+File\s*\(\s*${br}\s*\)\s*\)$`),"Scanner"],[new RegExp(String.raw`^new\s+BufferedReader\s*\(\s*new\s+FileReader\s*\(\s*${br}\s*\)\s*\)$`),"BufferedReader"],[new RegExp(String.raw`^new\s+PrintWriter\s*\(\s*(?:new\s+(?:File|FileWriter)\s*\(\s*)?${br}\s*\)?\s*\)$`),"PrintWriter"]];function zh(i){const e=i.trim();for(const[t,n]of Y3){const a=t.exec(e);if(a)return{kind:n,name:a[1]}}}function X3(i,e,t,n,a){if(e==="java")return;const s=qt(i).trim(),r=/^(?:(?:Scanner|BufferedReader|PrintWriter)\s+)?([A-Za-z_]\w*)\s*=\s*(new\s[\s\S]+)$/.exec(s),o=r&&zh(r[2]);if(r&&o){const c=/^(?:Scanner|BufferedReader|PrintWriter)\s/.test(s);return e==="python"?Z(t)+`${r[1]} = ${o.kind}(${o.name}) `:Z(t)+`${c?"let ":""}${r[1]} = new ${o.kind}(${o.name}); `}const l=/^([A-Za-z_]\w*)\.(println|print)\s*\(([\s\S]*)\)$/.exec(s);if(l&&l[1]!=="System"){const c=l[3].trim(),m=e==="python"&&c!==""?Dn(c,n,a):c;return Z(t)+`${l[1]}.${l[2]}(${m})${e==="javascript"?";":""} `}const u=/^Files\.writeString\s*\(\s*(?:Path\.of|Paths\.get)\s*\(\s*("(?:[^"\\]|\\.)*")\s*\)\s*,\s*([\s\S]+)\)$/.exec(s);if(u){const c=u[2].trim();return e==="python"?Z(t)+`open(${u[1]}, "w", encoding="utf-8").write(${Dn(c,n,a)}) `:Z(t)+`require("fs").writeFileSync(${u[1]}, ${c}); -`}}function X3(i){const e=new Set;for(const t of i)fn(t.elements,n=>{for(const a of n.textLines){const s=/=\s*(new\s.+?);?\s*$/.exec(a),r=s&&zh(s[1]);r&&e.add(r.kind)}});return e}const K3={Scanner:`class Scanner: +`}}function K3(i){const e=new Set;for(const t of i)fn(t.elements,n=>{for(const a of n.textLines){const s=/=\s*(new\s.+?);?\s*$/.exec(a),r=s&&zh(s[1]);r&&e.add(r.kind)}});return e}const eb={Scanner:`class Scanner: def __init__(self, name): self.lines = open(name, encoding="utf-8").read().splitlines() def hasNextLine(self): @@ -94,7 +94,7 @@ ${o.out}${Z(a)}} self.file.write(str(text)) def close(self): self.file.close() -`},eb={Scanner:`class Scanner { +`},tb={Scanner:`class Scanner { constructor(name) { this.lines = require("fs").readFileSync(name, "utf8").split(/\\r?\\n/); if (this.lines.at(-1) === "") this.lines.pop(); } hasNextLine() { return this.lines.length > 0; } nextLine() { return this.lines.shift(); } @@ -111,34 +111,34 @@ ${o.out}${Z(a)}} print(text) { this.text += text; } close() { require("fs").writeFileSync(this.name, this.text); } } -`};function Io(i,e){const t=X3(i);if(t.size===0)return"";const n=e==="python"?K3:eb;return[...t].map(a=>n[a]).join(` +`};function Io(i,e){const t=K3(i);if(t.size===0)return"";const n=e==="python"?eb:tb;return[...t].map(a=>n[a]).join(` `)+` -`}function tb(i,e,t,n,a){const s=/^System\s*\.\s*out\s*\.\s*print\s*\(([\s\S]*)\)$/.exec(qt(i).trim());if(s){const o=s[1].trim();switch(e){case"java":return Z(t)+"System.out.print("+o+`); +`}function nb(i,e,t,n,a){const s=/^System\s*\.\s*out\s*\.\s*print\s*\(([\s\S]*)\)$/.exec(qt(i).trim());if(s){const o=s[1].trim();switch(e){case"java":return Z(t)+"System.out.print("+o+`); `;case"javascript":return Z(t)+"process.stdout.write(String("+o+`)); `;case"python":return Z(t)+"print("+(o===""?"":Dn(o,n,a)+", ")+`end="") -`}}const r=J3(i);if(r===void 0)return/^\s*(?:output|print):\s*$/i.test(i)?Z(t)+{java:"System.out.println();",javascript:"console.log();",python:"print()"}[e]+` +`}}const r=R3(i);if(r===void 0)return/^\s*(?:output|print):\s*$/i.test(i)?Z(t)+{java:"System.out.println();",javascript:"console.log();",python:"print()"}[e]+` `:void 0;switch(e){case"java":return Z(t)+"System.out.println("+r+`); `;case"javascript":return Z(t)+"console.log("+r+`); `;case"python":return Z(t)+"print("+Dn(r,n,a)+`) -`}}function Ul(i){const e=i.map(qt).filter(t=>t!=="");return e.length===0?";;":e.join("; ")}function nb(i){const t=Ul(i).split(";"),n=Ih(t[0]);return n!==void 0&&(t[0]=n),t.join(";")}function Ih(i){const e=ve(/^(\s*)(?:integer|int|long|float|double|string|boolean|char|bool)\s+(\w+)(?:\s*=\s*(.*))?\s*$/i,i);if(!e)return;const t=e[2].trim();if(t==="")return;const n=(e[3]??"").trim();return i.includes("=")&&n!==""?e[1]+`let ${t} = ${n}`:e[1]+`let ${t}`}function ib(i){const e=i.map(n=>qt(n).trim()).filter(n=>n!=="");let t=e;if(e.length===1){let n=e[0];const a=wh("for",n);a!==void 0&&(n=a),t=n.split(";").map(s=>s.trim())}if(!(t.length!==3||t.some(n=>n==="")))return[t[0],t[1],t[2]]}function kh(i,e){let t=ve(/^\s*(\w+)\s*(\+\+|--)\s*$/,i)??ve(/^\s*(\+\+|--)\s*(\w+)\s*$/,i);if(t){const[n,a]=t[1]==="++"||t[1]==="--"?[t[2],t[1]]:[t[1],t[2]];return n===e?a==="++"?1:-1:void 0}if(t=ve(/^\s*(\w+)\s*(\+|-)=\s*(\d+)\s*$/,i),t)return t[1]===e?(t[2]==="+"?1:-1)*Number(t[3]):void 0;if(t=ve(/^\s*(\w+)\s*=\s*(\w+)\s*(\+|-)\s*(\d+)\s*$/,i),t)return t[1]===e&&t[2]===e?(t[3]==="+"?1:-1)*Number(t[4]):void 0}function ko(i,e){if(/^-?\d+$/.test(i))return String(Number(i)+e);const t=/^[\w.()[\]]+$/.test(i)?i:`(${i})`;return e>0?`${t} + ${e}`:`${t} - ${-e}`}function ab(i,e){const t=ib(i);if(!t)return;const[n,a,s]=t,r=ve(/^\s*(?:integer|int|long|short|byte|double|float)?\s*([a-zA-Z_]\w*)\s*=\s*(.+)$/i,n);if(!r)return;const o=r[1],l={variable:o,init:`${o} = ${Ze(r[2],e)}`,condition:a,increment:s},u=ve(/^\s*(\w+)\s*(<=|<|>=|>)\s*(.+)$/,a),c=kh(s,o);if(!u||u[1]!==o||c===void 0||c===0)return l;const m=Ze(r[2],e);let d=Ze(u[3],e);const h=u[2];if(c>0&&h==="<=")d=ko(d,1);else if(c<0&&h===">=")d=ko(d,-1);else if(!(c>0&&h==="<")&&!(c<0&&h===">"))return l;const g=c===1?m==="0"?[d]:[m,d]:[m,d,String(c)];return l.rangeLine=`for ${o} in range(${g.join(", ")}):`,l}function Sh(i){const e=qt(i).trim();if(e==="")return;const t=ve(/^\s*const\s+(integer|int|long|float|double|string|boolean|char|bool)\s+(\w+)(?:\s*=\s*(.*))?$/i,e);if(!t)return;const n=t[2].trim();if(n==="")return;if(!e.includes("="))return{rawType:t[1].trim(),name:n};const a=(t[3]??"").trim();if(a!=="")return{rawType:t[1].trim(),name:n,rhs:a}}function sb(i,e,t,n){var o;const a=Sh(i);if(!a)return;const s=cs(a.rawType),r=(o=a.rhs)==null?void 0:o.trim();switch(e){case"java":return Z(t)+us(r?`final ${s} ${a.name} = ${r}`:`final ${s} ${a.name}`)+` +`}}function Ul(i){const e=i.map(qt).filter(t=>t!=="");return e.length===0?";;":e.join("; ")}function ib(i){const t=Ul(i).split(";"),n=Ih(t[0]);return n!==void 0&&(t[0]=n),t.join(";")}function Ih(i){const e=ve(/^(\s*)(?:integer|int|long|float|double|string|boolean|char|bool)\s+(\w+)(?:\s*=\s*(.*))?\s*$/i,i);if(!e)return;const t=e[2].trim();if(t==="")return;const n=(e[3]??"").trim();return i.includes("=")&&n!==""?e[1]+`let ${t} = ${n}`:e[1]+`let ${t}`}function ab(i){const e=i.map(n=>qt(n).trim()).filter(n=>n!=="");let t=e;if(e.length===1){let n=e[0];const a=wh("for",n);a!==void 0&&(n=a),t=n.split(";").map(s=>s.trim())}if(!(t.length!==3||t.some(n=>n==="")))return[t[0],t[1],t[2]]}function kh(i,e){let t=ve(/^\s*(\w+)\s*(\+\+|--)\s*$/,i)??ve(/^\s*(\+\+|--)\s*(\w+)\s*$/,i);if(t){const[n,a]=t[1]==="++"||t[1]==="--"?[t[2],t[1]]:[t[1],t[2]];return n===e?a==="++"?1:-1:void 0}if(t=ve(/^\s*(\w+)\s*(\+|-)=\s*(\d+)\s*$/,i),t)return t[1]===e?(t[2]==="+"?1:-1)*Number(t[3]):void 0;if(t=ve(/^\s*(\w+)\s*=\s*(\w+)\s*(\+|-)\s*(\d+)\s*$/,i),t)return t[1]===e&&t[2]===e?(t[3]==="+"?1:-1)*Number(t[4]):void 0}function ko(i,e){if(/^-?\d+$/.test(i))return String(Number(i)+e);const t=/^[\w.()[\]]+$/.test(i)?i:`(${i})`;return e>0?`${t} + ${e}`:`${t} - ${-e}`}function sb(i,e){const t=ab(i);if(!t)return;const[n,a,s]=t,r=ve(/^\s*(?:integer|int|long|short|byte|double|float)?\s*([a-zA-Z_]\w*)\s*=\s*(.+)$/i,n);if(!r)return;const o=r[1],l={variable:o,init:`${o} = ${Ze(r[2],e)}`,condition:a,increment:s},u=ve(/^\s*(\w+)\s*(<=|<|>=|>)\s*(.+)$/,a),c=kh(s,o);if(!u||u[1]!==o||c===void 0||c===0)return l;const m=Ze(r[2],e);let d=Ze(u[3],e);const h=u[2];if(c>0&&h==="<=")d=ko(d,1);else if(c<0&&h===">=")d=ko(d,-1);else if(!(c>0&&h==="<")&&!(c<0&&h===">"))return l;const g=c===1?m==="0"?[d]:[m,d]:[m,d,String(c)];return l.rangeLine=`for ${o} in range(${g.join(", ")}):`,l}function Sh(i){const e=qt(i).trim();if(e==="")return;const t=ve(/^\s*const\s+(integer|int|long|float|double|string|boolean|char|bool)\s+(\w+)(?:\s*=\s*(.*))?$/i,e);if(!t)return;const n=t[2].trim();if(n==="")return;if(!e.includes("="))return{rawType:t[1].trim(),name:n};const a=(t[3]??"").trim();if(a!=="")return{rawType:t[1].trim(),name:n,rhs:a}}function rb(i,e,t,n){var o;const a=Sh(i);if(!a)return;const s=cs(a.rawType),r=(o=a.rhs)==null?void 0:o.trim();switch(e){case"java":return Z(t)+us(r?`final ${s} ${a.name} = ${r}`:`final ${s} ${a.name}`)+` `;case"javascript":return r?Z(t)+us(`const ${a.name} = ${r}`)+` `:Z(t)+`let ${a.name}; // from diagram: const ${s} ${a.name} `;case"python":return r?Z(t)+`${a.name} = ${Hs(r,n)} # const ${s} `:Z(t)+`${a.name} = None # const ${s}, uninitialized -`}}function rb(i){const e=qt(i).trim();if(e===""||Ph(e))return;const t=ve(/^\s*(?:integer|int|long|float|double|string|boolean|char|bool)(?:\s*\[\s*\]\s+(\w+)|\s+(\w+)(\s*\[\s*\])?)\s*=\s*(.*)$/i,e);if(!t)return;const n=t[1]===""?t[2]:t[1],a=t[4].trim();if(a!=="")return{name:n,rhs:a,isArray:t[1]!==""||t[3]!==""}}function Gs(i){const e=ve(/^\s*\(\s*int(?:eger)?\s*\)\s*(.+?)\s*$/i,i),t=e==null?void 0:e[1].trim();if(!(!t||Th(t)))return t.startsWith("(")&&So(t,0)===t.length-1?t.slice(1,-1).trim():t}function So(i,e){let t=0;for(let n=e;n/^'.'$/u.test(i)||/\.charAt\(.*\)$/.test(i);function ob(i,e){if(i[e]==="("){const a=So(i,e);return a<0?-1:a+1}if(i[e]==="'")return i[e+2]==="'"?e+3:-1;const t=/^(?:[A-Za-z_]\w*|\d+)/.exec(i.slice(e));if(!t)return-1;let n=e+t[0].length;for(;;){const a=/^\.[A-Za-z_]\w*/.exec(i.slice(n));if(a)n+=a[0].length;else if(i[n]==="("||i[n]==="["){const s=So(i,n);if(s<0)return-1;n=s+1}else return n}}function To(i,e){return $l(i,t=>{const n=/\(\s*(int|char)\s*\)\s*/g;let a="",s=0;for(let r=n.exec(t);r;r=n.exec(t)){const o=r.index+r[0].length,l=ob(t,o);if(l<0)continue;const u=t.slice(o,l);if(r[1]==="int"&&!Th(u))continue;const c=To(u.startsWith("(")?u.slice(1,-1).trim():u,e),m=r[1]==="int"?e==="python"?`ord(${c})`:`${c}.charCodeAt(0)`:e==="python"?`chr(${c})`:`String.fromCharCode(${c})`;a+=t.slice(s,r.index)+m,s=l,n.lastIndex=l}return a+t.slice(s)})}function Hs(i,e=new Set){const t=i.trim();if(t==="null")return"None";const n=Gs(t);return n!==void 0?`int(${Hs(n,e)})`:Ze(t,e)}function $l(i,e){let t="",n="",a=0;for(;a/^\d+$/.test(a)||e.has(a);return $l(t,a=>a.replace(/\bMath\.random\s*\(\s*\)/gi,"random.random()").replace(/===/g,"==").replace(/!==/g,"!=").replace(/\s*&&\s*/g," and ").replace(/\s*\|\|\s*/g," or ").replace(/!(?!=)\s*/g,"not ").replace(/\btrue\b/g,"True").replace(/\bfalse\b/g,"False").replace(/\bnull\b/g,"None").replace(new RegExp("(?n(r)&&n(o)?`${r} // ${o}`:s))}function _h(i){const e=[];let t=0,n="",a=!1;for(let s=0;s/^"(?:[^"\\]|\\.)*"$/.test(i);function Dn(i,e,t){const n=_h(i),a=s=>Yl(s)||t.has(s)||t.has(s.replace(/^([A-Za-z_]\w*)\[[^[\]]*\]$/u,"$1[]"));return n.length<2||!n.some(a)||n.some(s=>s==="")?Ze(i,e):n.map(s=>a(s)?s:`str(${Ze(s,e)})`).join(" + ")}function Oh(i,e,t=new Set){const n=qt(i).trim(),a=ve(/^(\w+(?:\[[^\]]*\])?)\s*(\+\+|--)$/,n)??ve(/^(\+\+|--)\s*(\w+(?:\[[^\]]*\])?)$/,n);if(a){const[o,l]=a[1]==="++"||a[1]==="--"?[a[2],a[1]]:[a[1],a[2]];return`${Ze(o,e)} ${l==="++"?"+=":"-="} 1`}const s=ve(/^(\w+)\s*\/=\s*(.+)$/,n);if(s&&e.has(s[1]))return`${s[1]} //= ${Ze(s[2],e)}`;const r=ve(/^([\w[\]. ]+?)\s*(=|\+=|-=|\*=|\/=|%=)\s*(.+)$/,n);if(r&&!r[3].startsWith("=")){const[,o,l,u]=r;let c;if(l==="+="&&t.has(o.trim())){const m=_h(u);c=Dn(`"" + ${u}`,e,t).replace(/^"" \+ /,""),m.length===1&&!Yl(u.trim())&&!t.has(u.trim())&&(c=`str(${Ze(u,e)})`)}else l==="="&&Gs(u)===void 0&&u.trim()!=="null"?c=Dn(u,e,t):c=l==="="?Hs(u,e):Ze(u,e);return`${o} ${l} ${c}`}return Ze(n,e)}const lb=i=>i.replace(/\bMath\.random\b(?!\s*\()/gi,"Math.random()");function Ah(i){const e=i.trim();return e.startsWith("{")&&e.endsWith("}")?"["+e.slice(1,-1)+"]":i}function Ch(i){const e=ve(/^\s*new\s+(?:byte|short|int|long|float|double|boolean|char|string)\s*\[\s*(.+)\s*\]\s*$/i,i),t=e==null?void 0:e[1].trim();return t||void 0}function Ph(i){const e=ve(/^\s*(int|double|string|boolean)\s*\[\s*\]\s*\[\s*\]\s*([a-zA-Z_]\w*)\s*=\s*(.+)$/i,qt(i).trim());return e?{elementType:e[1].toLowerCase(),name:e[2],rhs:e[3].trim()}:void 0}function ub(i){const e=ve(/^\s*new\s+(?:int|double|string|boolean)\s*\[\s*(.+?)\s*\]\s*\[\s*(.+?)\s*\]\s*$/i,i);return e?[e[1],e[2]]:void 0}const zu=i=>i.replaceAll("{","[").replaceAll("}","]");function Iu(i,e){return i==="boolean"?e==="python"?"False":"false":i==="string"?'""':i==="double"?"0.0":"0"}function cb(i,e,t){const n=ub(i.rhs);return e==="javascript"?n?`Array.from({ length: ${n[0]} }, () => new Array(${n[1]}).fill(${Iu(i.elementType,e)}))`:zu(i.rhs):n?`[[${Iu(i.elementType,e)}] * ${Ze(n[1],t)} for _ in range(${Ze(n[0],t)})]`:Ze(zu(i.rhs),t)}function jh(i,e){const t=i.trim();if(e){const a=Ch(t);return a!==void 0?`new Array(${a})`:Ah(t)}const n=Gs(t);return n!==void 0?`Math.floor(${jh(n,!1)})`:lb(t)}function mb(i,e,t){const n=i.trim();if(e){const a=Ch(n);return a!==void 0?`[None] * ${a}`:Ze(Ah(n),t)}return Hs(n,t)}function db(i,e,t,n,a){if(e==="java")return;const s=Ph(i);if(s){const u=cb(s,e,n);return e==="javascript"?Z(t)+`let ${s.name} = ${u}; +`}}function ob(i){const e=qt(i).trim();if(e===""||jh(e))return;const t=ve(/^\s*(?:integer|int|long|float|double|string|boolean|char|bool)(?:\s*\[\s*\]\s+(\w+)|\s+(\w+)(\s*\[\s*\])?)\s*=\s*(.*)$/i,e);if(!t)return;const n=t[1]===""?t[2]:t[1],a=t[4].trim();if(a!=="")return{name:n,rhs:a,isArray:t[1]!==""||t[3]!==""}}function Gs(i){const e=ve(/^\s*\(\s*int(?:eger)?\s*\)\s*(.+?)\s*$/i,i),t=e==null?void 0:e[1].trim();if(!(!t||Th(t)))return t.startsWith("(")&&So(t,0)===t.length-1?t.slice(1,-1).trim():t}function So(i,e){let t=0;for(let n=e;n/^'.'$/u.test(i)||/\.charAt\(.*\)$/.test(i);function lb(i,e){if(i[e]==="("){const a=So(i,e);return a<0?-1:a+1}if(i[e]==="'")return i[e+2]==="'"?e+3:-1;const t=/^(?:[A-Za-z_]\w*|\d+)/.exec(i.slice(e));if(!t)return-1;let n=e+t[0].length;for(;;){const a=/^\.[A-Za-z_]\w*/.exec(i.slice(n));if(a)n+=a[0].length;else if(i[n]==="("||i[n]==="["){const s=So(i,n);if(s<0)return-1;n=s+1}else return n}}function To(i,e){return $l(i,t=>{const n=/\(\s*(int|char)\s*\)\s*/g;let a="",s=0;for(let r=n.exec(t);r;r=n.exec(t)){const o=r.index+r[0].length,l=lb(t,o);if(l<0)continue;const u=t.slice(o,l);if(r[1]==="int"&&!Th(u))continue;const c=To(u.startsWith("(")?u.slice(1,-1).trim():u,e),m=r[1]==="int"?e==="python"?`ord(${c})`:`${c}.charCodeAt(0)`:e==="python"?`chr(${c})`:`String.fromCharCode(${c})`;a+=t.slice(s,r.index)+m,s=l,n.lastIndex=l}return a+t.slice(s)})}function Hs(i,e=new Set){const t=i.trim();if(t==="null")return"None";const n=Gs(t);return n!==void 0?`int(${Hs(n,e)})`:Ze(t,e)}function $l(i,e){let t="",n="",a=0;for(;a/^\d+$/.test(a)||e.has(a);return $l(t,a=>a.replace(/\bMath\.random\s*\(\s*\)/gi,"random.random()").replace(/===/g,"==").replace(/!==/g,"!=").replace(/\s*&&\s*/g," and ").replace(/\s*\|\|\s*/g," or ").replace(/!(?!=)\s*/g,"not ").replace(/\btrue\b/g,"True").replace(/\bfalse\b/g,"False").replace(/\bnull\b/g,"None").replace(new RegExp("(?n(r)&&n(o)?`${r} // ${o}`:s))}function _h(i){const e=[];let t=0,n="",a=!1;for(let s=0;s/^"(?:[^"\\]|\\.)*"$/.test(i);function Dn(i,e,t){const n=_h(i),a=s=>Yl(s)||t.has(s)||t.has(s.replace(/^([A-Za-z_]\w*)\[[^[\]]*\]$/u,"$1[]"));return n.length<2||!n.some(a)||n.some(s=>s==="")?Ze(i,e):n.map(s=>a(s)?s:`str(${Ze(s,e)})`).join(" + ")}function Oh(i,e,t=new Set){const n=qt(i).trim(),a=ve(/^(\w+(?:\[[^\]]*\])?)\s*(\+\+|--)$/,n)??ve(/^(\+\+|--)\s*(\w+(?:\[[^\]]*\])?)$/,n);if(a){const[o,l]=a[1]==="++"||a[1]==="--"?[a[2],a[1]]:[a[1],a[2]];return`${Ze(o,e)} ${l==="++"?"+=":"-="} 1`}const s=ve(/^(\w+)\s*\/=\s*(.+)$/,n);if(s&&e.has(s[1]))return`${s[1]} //= ${Ze(s[2],e)}`;const r=ve(/^([\w[\]. ]+?)\s*(=|\+=|-=|\*=|\/=|%=)\s*(.+)$/,n);if(r&&!r[3].startsWith("=")){const[,o,l,u]=r;let c;if(l==="+="&&t.has(o.trim())){const m=_h(u);c=Dn(`"" + ${u}`,e,t).replace(/^"" \+ /,""),m.length===1&&!Yl(u.trim())&&!t.has(u.trim())&&(c=`str(${Ze(u,e)})`)}else l==="="&&Gs(u)===void 0&&u.trim()!=="null"?c=Dn(u,e,t):c=l==="="?Hs(u,e):Ze(u,e);return`${o} ${l} ${c}`}return Ze(n,e)}const ub=i=>i.replace(/\bMath\.random\b(?!\s*\()/gi,"Math.random()");function Ah(i){const e=i.trim();return e.startsWith("{")&&e.endsWith("}")?"["+e.slice(1,-1)+"]":i}function Ch(i){const e=ve(/^\s*new\s+(?:byte|short|int|long|float|double|boolean|char|string)\s*\[\s*(.+)\s*\]\s*$/i,i),t=e==null?void 0:e[1].trim();return t||void 0}function jh(i){const e=ve(/^\s*(int|double|string|boolean)\s*\[\s*\]\s*\[\s*\]\s*([a-zA-Z_]\w*)\s*=\s*(.+)$/i,qt(i).trim());return e?{elementType:e[1].toLowerCase(),name:e[2],rhs:e[3].trim()}:void 0}function cb(i){const e=ve(/^\s*new\s+(?:int|double|string|boolean)\s*\[\s*(.+?)\s*\]\s*\[\s*(.+?)\s*\]\s*$/i,i);return e?[e[1],e[2]]:void 0}const zu=i=>i.replaceAll("{","[").replaceAll("}","]");function Iu(i,e){return i==="boolean"?e==="python"?"False":"false":i==="string"?'""':i==="double"?"0.0":"0"}function mb(i,e,t){const n=cb(i.rhs);return e==="javascript"?n?`Array.from({ length: ${n[0]} }, () => new Array(${n[1]}).fill(${Iu(i.elementType,e)}))`:zu(i.rhs):n?`[[${Iu(i.elementType,e)}] * ${Ze(n[1],t)} for _ in range(${Ze(n[0],t)})]`:Ze(zu(i.rhs),t)}function Ph(i,e){const t=i.trim();if(e){const a=Ch(t);return a!==void 0?`new Array(${a})`:Ah(t)}const n=Gs(t);return n!==void 0?`Math.floor(${Ph(n,!1)})`:ub(t)}function db(i,e,t){const n=i.trim();if(e){const a=Ch(n);return a!==void 0?`[None] * ${a}`:Ze(Ah(n),t)}return Hs(n,t)}function hb(i,e,t,n,a){if(e==="java")return;const s=jh(i);if(s){const u=mb(s,e,n);return e==="javascript"?Z(t)+`let ${s.name} = ${u}; `:Z(t)+`${s.name} = ${u} -`}const r=rb(i);if(!r)return;if(e==="javascript")return Z(t)+us(`let ${r.name} = ${jh(r.rhs,r.isArray)}`)+` -`;const l=!r.isArray&&Gs(r.rhs)===void 0&&r.rhs.trim()!=="null"?Dn(r.rhs,n,a):mb(r.rhs,r.isArray,n);return Z(t)+`${r.name} = ${l} -`}function fn(i,e){for(const t of i){e(t),t.loopBody&&fn(t.loopBody,e);for(const n of t.cases??[])fn(n.elements,e)}}function hb(i){const e=n=>["int","integer","long","short","byte"].includes(n.trim().toLowerCase()),t=new Set;return fn(i.elements,n=>{for(const a of n.textLines){const s=a.trim();if(s==="")continue;if(s.toLowerCase().startsWith("input:")){const l=ql(s.slice(6).trim());l&&e(l.type)&&!l.name.includes("[")&&t.add(l.name);continue}const r=Sh(s);if(r&&e(r.rawType)){t.add(r.name);continue}const o=ve(/^\s*(integer|int|long|short|byte)\s+([a-zA-Z_]\w*)\s*=/i,s);o&&t.add(o[2].trim())}}),t}function _o(i,e){const t=r=>/^\d+$/.test(r)||e.has(r),n=String.raw`(?:[a-zA-Z_]\w*|\d+(?:\.\d+)?)`,a=new RegExp(String.raw`(?{const o=r.split(/\s*([*/%])\s*/);if(!o.some(c=>c==="/"))return r;let l=o[0],u=t(o[0]);for(let c=1;cr.replace(a,s).replace(new RegExp("(?t(l)&&t(u)?`${l} = Math.trunc(${l} / ${u})`:o))}function ms(i){let e=!1;return fn(i.elements,t=>{t.type===S.anweisung&&t.textLines.some(n=>n.trim().toLowerCase().startsWith("input:"))&&(e=!0)}),e}function Xl(i){let e=!1,t=!1,n=!1;return fn(i.elements,a=>{for(const s of a.textLines)/\bFiles\s*\./.test(s)&&(e=!0),/\bnew\s+(?:File|PrintWriter|FileReader|FileWriter|BufferedReader)\s*\(/.test(s)&&(t=!0),/\bnew\s+Scanner\s*\(\s*new\s+File\b/.test(s)&&(n=!0)}),[...t?["import java.io.*;"]:[],...e?["import java.nio.file.*;"]:[],...n?["import java.util.Scanner;"]:[]]}function gb(i){return Xl(i).length>0}function Dh(i){let e=!1;return fn(i.elements,t=>{t.textLines.some(n=>/\bMath\.random\s*\(/i.test(n))&&(e=!0)}),e}function ea(i,e){const t=i.trim();return t===""?e==="python"?'""':"0":e==="java"||new RegExp("^\\p{N}+$","u").test(t)||Yl(t)?t:'"'+t.replaceAll('"','\\"')+'"'}function J1(i,e){const t=i.trim();if(t==="")return"";switch(e){case"java":return"/* "+t+" */";case"python":return" # "+t;case"javascript":return" /* "+t+" */"}}function pb(i,e,t,n,a){const s=i.map(r=>r.trim());if(s.every(r=>r==="")){t.live&&(a.out+=Z(n)+(e==="python"?"pass":";")+` -`);return}if(t.includeDiagramTextAsComments){const r=s.filter(o=>o!==""&&!zo(o));r.length>0&&(a.out+=Vl(r,e,n))}for(const r of s){if(r==="")continue;if(zo(r)){a.out+=t.live?e0(n,t.live):yh(n,e);continue}const o=t.jsIntVariables??new Set,l=t.arrayElementTypes??new Map,u=t.stringVariables??new Set,c=(e==="java"?q3(r,n,l):void 0)??(e==="javascript"?Q3(r,n,l):void 0)??(e==="python"?U3(r,n,l):void 0)??Y3(r,e,n,o,u)??tb(r,e,n,o,u)??sb(r,e,n,o)??db(r,e,n,o,u)??G3(r,e,n,o,u);if(c!==void 0){a.out+=e==="javascript"?_o(c,o):c;continue}let m=r;N3(e)?m=us(e==="javascript"?_o(r,o):r):e==="python"&&(m=Oh(r,o,u)),m!==""&&(a.out+=Z(n)+m+` +`}const r=ob(i);if(!r)return;if(e==="javascript")return Z(t)+us(`let ${r.name} = ${Ph(r.rhs,r.isArray)}`)+` +`;const l=!r.isArray&&Gs(r.rhs)===void 0&&r.rhs.trim()!=="null"?Dn(r.rhs,n,a):db(r.rhs,r.isArray,n);return Z(t)+`${r.name} = ${l} +`}function fn(i,e){for(const t of i){e(t),t.loopBody&&fn(t.loopBody,e);for(const n of t.cases??[])fn(n.elements,e)}}function gb(i){const e=n=>["int","integer","long","short","byte"].includes(n.trim().toLowerCase()),t=new Set;return fn(i.elements,n=>{for(const a of n.textLines){const s=a.trim();if(s==="")continue;if(s.toLowerCase().startsWith("input:")){const l=ql(s.slice(6).trim());l&&e(l.type)&&!l.name.includes("[")&&t.add(l.name);continue}const r=Sh(s);if(r&&e(r.rawType)){t.add(r.name);continue}const o=ve(/^\s*(integer|int|long|short|byte)\s+([a-zA-Z_]\w*)\s*=/i,s);o&&t.add(o[2].trim())}}),t}function _o(i,e){const t=r=>/^\d+$/.test(r)||e.has(r),n=String.raw`(?:[a-zA-Z_]\w*|\d+(?:\.\d+)?)`,a=new RegExp(String.raw`(?{const o=r.split(/\s*([*/%])\s*/);if(!o.some(c=>c==="/"))return r;let l=o[0],u=t(o[0]);for(let c=1;cr.replace(a,s).replace(new RegExp("(?t(l)&&t(u)?`${l} = Math.trunc(${l} / ${u})`:o))}function ms(i){let e=!1;return fn(i.elements,t=>{t.type===S.anweisung&&t.textLines.some(n=>n.trim().toLowerCase().startsWith("input:"))&&(e=!0)}),e}function Xl(i){let e=!1,t=!1,n=!1;return fn(i.elements,a=>{for(const s of a.textLines)/\bFiles\s*\./.test(s)&&(e=!0),/\bnew\s+(?:File|PrintWriter|FileReader|FileWriter|BufferedReader)\s*\(/.test(s)&&(t=!0),/\bnew\s+Scanner\s*\(\s*new\s+File\b/.test(s)&&(n=!0)}),[...t?["import java.io.*;"]:[],...e?["import java.nio.file.*;"]:[],...n?["import java.util.Scanner;"]:[]]}function pb(i){return Xl(i).length>0}function Dh(i){let e=!1;return fn(i.elements,t=>{t.textLines.some(n=>/\bMath\.random\s*\(/i.test(n))&&(e=!0)}),e}function ea(i,e){const t=i.trim();return t===""?e==="python"?'""':"0":e==="java"||new RegExp("^\\p{N}+$","u").test(t)||Yl(t)?t:'"'+t.replaceAll('"','\\"')+'"'}function J1(i,e){const t=i.trim();if(t==="")return"";switch(e){case"java":return"/* "+t+" */";case"python":return" # "+t;case"javascript":return" /* "+t+" */"}}function fb(i,e,t,n,a){const s=i.map(r=>r.trim());if(s.every(r=>r==="")){t.live&&(a.out+=Z(n)+(e==="python"?"pass":";")+` +`);return}if(t.includeDiagramTextAsComments){const r=s.filter(o=>o!==""&&!zo(o));r.length>0&&(a.out+=Vl(r,e,n))}for(const r of s){if(r==="")continue;if(zo(r)){a.out+=t.live?e0(n,t.live):yh(n,e);continue}const o=t.jsIntVariables??new Set,l=t.arrayElementTypes??new Map,u=t.stringVariables??new Set,c=(e==="java"?Q3(r,n,l):void 0)??(e==="javascript"?U3(r,n,l):void 0)??(e==="python"?$3(r,n,l):void 0)??X3(r,e,n,o,u)??nb(r,e,n,o,u)??rb(r,e,n,o)??hb(r,e,n,o,u)??H3(r,e,n,o,u);if(c!==void 0){a.out+=e==="javascript"?_o(c,o):c;continue}let m=r;F3(e)?m=us(e==="javascript"?_o(r,o):r):e==="python"&&(m=Oh(r,o,u)),m!==""&&(a.out+=Z(n)+m+` `)}}function li(i,e,t,n,a,s,r,o=(l=>(l=a.live)==null?void 0:l.labels.condition)()){if(a.includeDiagramTextAsComments&&(r.out+=Vl(t,n,s)),o!==void 0&&t0(t)){r.out+=Z(s)+i+e1(o)+e;return}const u=La(t),c=a.jsIntVariables??new Set,m=n==="python"?Ze(u,c):n==="javascript"?_o(u,c):u;r.out+=Z(s)+i+m+e}function b1(i,e,t,n,a){const s=a.out.length;for(const o of i)Vs(o,e,t,n,a);if(t.live&&a.out.length===s&&(a.out+=e0(n,t.live)),e!=="python")return;a.out.slice(s).split(` `).map(o=>o.trim()).every(o=>o===""||o.startsWith("#"))&&(a.out+=Z(n)+`pass -`)}function fb(i,e){var n;if(e.includeDiagramTextAsComments||i.length!==1)return;const t=i[0];return t.type===S.verzweigung&&(((n=t.cases)==null?void 0:n.length)??0)>=2?t:void 0}function Oo(i,e,t,n,a,s){const r=i.cases;if(!r||r.length<2)return;const o=e==="python",l=n+t.indentPerLevel,u=!t.includeEmptyElseBranch&&W3(r[1].elements),c=u?void 0:fb(r[1].elements,t);if(o){li(s?"elif ":"if ",`: +`)}function bb(i,e){var n;if(e.includeDiagramTextAsComments||i.length!==1)return;const t=i[0];return t.type===S.verzweigung&&(((n=t.cases)==null?void 0:n.length)??0)>=2?t:void 0}function Oo(i,e,t,n,a,s){const r=i.cases;if(!r||r.length<2)return;const o=e==="python",l=n+t.indentPerLevel,u=!t.includeEmptyElseBranch&&N3(r[1].elements),c=u?void 0:bb(r[1].elements,t);if(o){li(s?"elif ":"if ",`: `,i.textLines,e,t,n,a),b1(r[0].elements,e,t,l,a),c?Oo(c,e,t,n,a,!0):u||(a.out+=Z(n)+`else: `,b1(r[1].elements,e,t,l,a));return}if(li(s?"} else if (":"if (",`) { `,i.textLines,e,t,n,a),b1(r[0].elements,e,t,l,a),c){const m=a.out.length;Oo(c,e,t,n,a,!0),Zh(t,c,a,m)}else u||(a.out+=Z(n)+`} else { `,b1(r[1].elements,e,t,l,a)),a.out+=Z(n)+`} -`}function Vs(i,e,t,n,a){const s=a.out.length;bb(i,e,t,n,a),Zh(t,i,a,s)}function bb(i,e,t,n,a){var c;const s=t.indentPerLevel,r=e==="python",o=(m,d)=>b1(m,e,t,d,a),l=(m,d)=>li(m,d,i.textLines,e,t,n,a),u=(m=n)=>{t.includeDiagramTextAsComments&&(a.out+=Vl(i.textLines,e,m))};switch(i.type){case S.leerElement:a.out+=t.live?e0(n,t.live):yh(n,e);return;case S.anweisung:case S.aufruf:pb(i.textLines,e,t,n,a);return;case S.aussprung:{const m=La(i.textLines);i.textLines.some(d=>d.trim()!=="")&&u(),r?a.out+=Z(n)+(m===""?`break +`}function Vs(i,e,t,n,a){const s=a.out.length;xb(i,e,t,n,a),Zh(t,i,a,s)}function xb(i,e,t,n,a){var c;const s=t.indentPerLevel,r=e==="python",o=(m,d)=>b1(m,e,t,d,a),l=(m,d)=>li(m,d,i.textLines,e,t,n,a),u=(m=n)=>{t.includeDiagramTextAsComments&&(a.out+=Vl(i.textLines,e,m))};switch(i.type){case S.leerElement:a.out+=t.live?e0(n,t.live):yh(n,e);return;case S.anweisung:case S.aufruf:fb(i.textLines,e,t,n,a);return;case S.aussprung:{const m=La(i.textLines);i.textLines.some(d=>d.trim()!=="")&&u(),r?a.out+=Z(n)+(m===""?`break `:`break # ${m} `):a.out+=Z(n)+(m===""?`break; `:`break; // ${m} @@ -156,13 +156,13 @@ ${o.out}${Z(a)}} `,o(d.elements,n+s*2),a.out+=Z(n+s*2)+`break; `}}),r||(a.out+=Z(n)+`} `);return}case S.forSchleife:if(e==="java"){u();const m=t.live?Bh(i.textLines,t.live.labels):Ul(i.textLines);a.out+=Z(n)+"for ("+m+`) { -`}else if(r){const m=t.jsIntVariables??new Set,d=ab(i.textLines,m);if((d==null?void 0:d.rangeLine)!==void 0)u(),a.out+=Z(n)+d.rangeLine+` +`}else if(r){const m=t.jsIntVariables??new Set,d=sb(i.textLines,m);if((d==null?void 0:d.rangeLine)!==void 0)u(),a.out+=Z(n)+d.rangeLine+` `;else if(d){u(),a.out+=Z(n)+d.init+` `,a.out+=Z(n)+"while "+Ze(d.condition,m)+`: `;for(const h of i.loopBody??[])Vs(h,e,t,n+s,a);a.out+=Z(n+s)+Oh(d.increment,m)+` -`;return}else t.live?a.out+=Z(n)+vb(i.textLines,t.live.labels,m)+` +`;return}else t.live?a.out+=Z(n)+yb(i.textLines,t.live.labels,m)+` `:l("for ",`: -`)}else{u();const m=t.live?xb(i.textLines,t.live.labels):nb(i.textLines);a.out+=Z(n)+"for ("+m+`) { +`)}else{u();const m=t.live?vb(i.textLines,t.live.labels):ib(i.textLines);a.out+=Z(n)+"for ("+m+`) { `}o(i.loopBody??[],n+s),r||(a.out+=Z(n)+`} `);return;case S.whileSchleife:l(r?"while ":"while (",r?`: `:`) { @@ -178,7 +178,7 @@ ${o.out}${Z(a)}} `:`while (true) /* ${m} */ { `),o(i.loopBody??[],n+s),r||(a.out+=Z(n)+`} `);return}}}const Wi="",Kl="",e1=i=>Wi+i+Kl,e0=(i,e)=>Z(i)+e1(e.target==="python"?`pass # ${e.labels.code}`:`// ${e.labels.code}`)+` -`,t0=i=>i.every(e=>e.trim()==="");function Bh(i,e){return t0(i)||i.length===3?[e.start,e.condition,e.step].map((n,a)=>{const s=qt(i[a]??"");return s===""?e1(n):s}).join("; "):Ul(i)}function xb(i,e){const t=Bh(i,e).split(";"),n=t[0].includes(Wi)?void 0:Ih(t[0]);return n!==void 0&&(t[0]=n),t.join(";")}function vb(i,e,t){var h;const[n="",a="",s=""]=i.length===3?i.map(g=>qt(g)):[],r=ve(/^\s*(?:integer|int|long|short|byte|double|float)?\s*([a-zA-Z_]\w*)\s*=\s*(.+)$/i,n),o=(r==null?void 0:r[1])??((h=ve(/^\s*([a-zA-Z_]\w*)\s*(?:<=|<|>=|>)/,a))==null?void 0:h[1]),l=r?Ze(r[2],t):e1(e.start),u=ve(/^\s*(\w+)\s*(<=|<)\s*(.+)$/,a);let c=e1(e.end);u&&(o===void 0||u[1]===o)&&(c=Ze(u[3],t),u[2]==="<="&&(c=ko(c,1)));const m=o===void 0?void 0:kh(s,o),d=[l,c,...m!==void 0&&m!==1?[String(m)]:[]];return`for ${o??e1(e.selector)} in range(${d.join(", ")}):`}function Ao(i,e=[],t=new Map){return i.forEach((n,a)=>{var r;const s=[...e,a];t.has(n)||t.set(n,s),n.loopBody&&Ao(n.loopBody,[...s,0],t),(r=n.cases)==null||r.forEach((o,l)=>Ao(o.elements,[...s,l],t))}),t}function Zh(i,e,t,n){const a=i.live,s=a==null?void 0:a.paths.get(e);if(!a||!s||t.out.length===n)return;const r=o=>t.out.slice(0,o).split(` +`,t0=i=>i.every(e=>e.trim()==="");function Bh(i,e){return t0(i)||i.length===3?[e.start,e.condition,e.step].map((n,a)=>{const s=qt(i[a]??"");return s===""?e1(n):s}).join("; "):Ul(i)}function vb(i,e){const t=Bh(i,e).split(";"),n=t[0].includes(Wi)?void 0:Ih(t[0]);return n!==void 0&&(t[0]=n),t.join(";")}function yb(i,e,t){var h;const[n="",a="",s=""]=i.length===3?i.map(g=>qt(g)):[],r=ve(/^\s*(?:integer|int|long|short|byte|double|float)?\s*([a-zA-Z_]\w*)\s*=\s*(.+)$/i,n),o=(r==null?void 0:r[1])??((h=ve(/^\s*([a-zA-Z_]\w*)\s*(?:<=|<|>=|>)/,a))==null?void 0:h[1]),l=r?Ze(r[2],t):e1(e.start),u=ve(/^\s*(\w+)\s*(<=|<)\s*(.+)$/,a);let c=e1(e.end);u&&(o===void 0||u[1]===o)&&(c=Ze(u[3],t),u[2]==="<="&&(c=ko(c,1)));const m=o===void 0?void 0:kh(s,o),d=[l,c,...m!==void 0&&m!==1?[String(m)]:[]];return`for ${o??e1(e.selector)} in range(${d.join(", ")}):`}function Ao(i,e=[],t=new Map){return i.forEach((n,a)=>{var r;const s=[...e,a];t.has(n)||t.set(n,s),n.loopBody&&Ao(n.loopBody,[...s,0],t),(r=n.cases)==null||r.forEach((o,l)=>Ao(o.elements,[...s,l],t))}),t}function Zh(i,e,t,n){const a=i.live,s=a==null?void 0:a.paths.get(e);if(!a||!s||t.out.length===n)return;const r=o=>t.out.slice(0,o).split(` `).length-1;a.spans.push({path:s,from:r(n),to:r(t.out.length-1)})}function Mh(i,e,t){const n={target:e,labels:t,paths:Ao(i.elements),spans:[]},a=Hl(i,e,{includeEmptyElseBranch:!0,live:n}),s=zt(i.caption);let r="";if(e==="java"){const u=Xl(i);for(const c of u)r+=c+` `;ms(i)?(u.includes("import java.util.Scanner;")||(r+=`import java.util.Scanner; `),r+=`Scanner scanner = new Scanner(System.in); @@ -193,7 +193,7 @@ ${o.out}${Z(a)}} `),r+=Io([i],"python"),s&&(r+=`def ${s.name}(${u}): `))}const o={out:""};b1(i.elements,e,a,s?a.indentPerLevel:0,o),s&&e!=="python"&&(o.out+=`} `);const l=r.split(` -`).length-1;return{text:Lh((r+o.out).replace(/\n+$/,""),e),spans:n.spans.map(u=>({...u,from:u.from+l,to:u.to+l}))}}function Lh(i,e){switch(e){case"javascript":return zb(To(i,"javascript")).replace(/\.length\(\)/g,".length").replace(/\.contains\(/g,".includes(");case"python":return yb(To(i,"python")).replace(/\b([a-zA-Z_]\w*(?:\[[^[\]]*\])?)\.length(?:\(\)|\b)/g,"len($1)");case"java":return Sb(i)}}function yb(i){for(let e=0;e<5;e++){const t=Eh(wb(i),"python");if(t===i)break;i=t}return i}const ku={indexOf:"find",lastIndexOf:"rfind",toUpperCase:"upper",toLowerCase:"lower",trim:"strip",startsWith:"startswith",endsWith:"endswith"};function wb(i){return n0(i,["charAt","substring","contains","isEmpty","equalsIgnoreCase","compareTo","repeat","concat",...Object.keys(ku)],(e,t,n)=>{switch(t){case"charAt":return`${e}[${n}]`;case"substring":{const a=Ib(n);return a.length===2?`${e}[${a[0].trim()}:${a[1].trim()}]`:`${e}[${n.trim()}:]`}case"contains":return`(${n.trim()} in ${e})`;case"isEmpty":return`(len(${e}) == 0)`;case"equalsIgnoreCase":return`(${e}.lower() == ${n.trim()}.lower())`;case"compareTo":return`((${e} > ${n.trim()}) - (${e} < ${n.trim()}))`;case"repeat":return`(${e} * ${n.trim()})`;case"concat":return`(${e} + ${n.trim()})`;default:return`${e}.${ku[t]}(${n})`}})}function zb(i){for(let e=0;e<5;e++){const t=Eh(n0(i,["isEmpty","equalsIgnoreCase","compareTo","replace"],(n,a,s)=>{switch(a){case"isEmpty":return`(${n}.length === 0)`;case"equalsIgnoreCase":return`(${n}.toLowerCase() === ${s.trim()}.toLowerCase())`;case"compareTo":return`${n}.localeCompare(${s.trim()})`;default:return`${n}.replaceAll(${s})`}}),"javascript");if(t===i)break;i=t}return i}function Eh(i,e){const t=/\bFiles\.readString\(\s*(?:Path\.of|Paths\.get)\(\s*("(?:[^"\\]|\\.)*")\s*\)\s*\)/g;return e==="python"?i.replace(t,'open($1, encoding="utf-8").read()').replace(/\bInteger\.parseInt\(/g,"int(").replace(/\bDouble\.parseDouble\(/g,"float(").replace(/\bString\.valueOf\(/g,"str("):i.replace(t,'require("fs").readFileSync($1, "utf8")').replace(/\bInteger\.parseInt\(/g,"parseInt(").replace(/\bDouble\.parseDouble\(/g,"parseFloat(").replace(/\bString\.valueOf\(/g,"String(")}function Ib(i){let e=0;const t=[...i].findIndex(n=>n==="("?(e+=1,!1):n===")"?(e-=1,!1):n===","&&e===0);return t<0?[i]:[i.slice(0,t),i.slice(t+1)]}function n0(i,e,t){const n=new RegExp(`([A-Za-z_]\\w*(?:\\[[^[\\]]*\\]|\\.\\w+\\(\\))*|"(?:[^"\\\\]|\\\\.)*")\\.(${e.join("|")})\\(`,"g");let a="",s=0;for(let r=n.exec(i);r;r=n.exec(i)){const o=r.index+r[0].length-1;let l=0,u=-1;for(let m=o;me.has(n.toLowerCase())?t:`${n}.length()`)}const Tb=new Set("abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while true false null var record sealed permits yield module open opens requires exports to uses provides with transitive".split(" "));function qs(i){const e=i.trim();if(e==="")return"Main";let t="";return Array.from(e).forEach((n,a)=>{a===0?new RegExp("\\p{L}","u").test(n)||n==="_"||n==="$"?t+=n:new RegExp("\\p{Nd}","u").test(n)?t+="_"+n:t+="_":/[\p{L}\p{M}\p{N}]/u.test(n)||n==="_"||n==="$"?t+=n:t+="_"}),t=t.replace(/_{2,}/g,"_").replace(/^_+|_+$/g,""),t===""?"Main":(new RegExp("^\\p{Nd}","u").test(t)&&(t="_"+t),Tb.has(t.toLowerCase())&&(t="_"+t),t)}function Su(i,e,t={},n=[]){const a={...xh,...t},s=qs(e),r=[i,...n].filter((I,z,k)=>k.indexOf(I)===z).map(I=>({d:I,header:zt(I.caption)})).filter(I=>I.header!==void 0),o=r.map(I=>wo(I.d,I.header,"java",t,a.indentPerLevel)),l=zt(i.caption),u=r.some(I=>ms(I.d)),c=ls(i,"java",a),m=a.indentPerLevel*2,d=ms(i),h=d?_b(c):c,g=Z(m),f=h.trim()===""?"":h.split(` +`).length-1;return{text:Lh((r+o.out).replace(/\n+$/,""),e),spans:n.spans.map(u=>({...u,from:u.from+l,to:u.to+l}))}}function Lh(i,e){switch(e){case"javascript":return Ib(To(i,"javascript")).replace(/\.length\(\)/g,".length").replace(/\.contains\(/g,".includes(");case"python":return wb(To(i,"python")).replace(/\b([a-zA-Z_]\w*(?:\[[^[\]]*\])?)\.length(?:\(\)|\b)/g,"len($1)");case"java":return Tb(i)}}function wb(i){for(let e=0;e<5;e++){const t=Eh(zb(i),"python");if(t===i)break;i=t}return i}const ku={indexOf:"find",lastIndexOf:"rfind",toUpperCase:"upper",toLowerCase:"lower",trim:"strip",startsWith:"startswith",endsWith:"endswith"};function zb(i){return n0(i,["charAt","substring","contains","isEmpty","equalsIgnoreCase","compareTo","repeat","concat",...Object.keys(ku)],(e,t,n)=>{switch(t){case"charAt":return`${e}[${n}]`;case"substring":{const a=kb(n);return a.length===2?`${e}[${a[0].trim()}:${a[1].trim()}]`:`${e}[${n.trim()}:]`}case"contains":return`(${n.trim()} in ${e})`;case"isEmpty":return`(len(${e}) == 0)`;case"equalsIgnoreCase":return`(${e}.lower() == ${n.trim()}.lower())`;case"compareTo":return`((${e} > ${n.trim()}) - (${e} < ${n.trim()}))`;case"repeat":return`(${e} * ${n.trim()})`;case"concat":return`(${e} + ${n.trim()})`;default:return`${e}.${ku[t]}(${n})`}})}function Ib(i){for(let e=0;e<5;e++){const t=Eh(n0(i,["isEmpty","equalsIgnoreCase","compareTo","replace"],(n,a,s)=>{switch(a){case"isEmpty":return`(${n}.length === 0)`;case"equalsIgnoreCase":return`(${n}.toLowerCase() === ${s.trim()}.toLowerCase())`;case"compareTo":return`${n}.localeCompare(${s.trim()})`;default:return`${n}.replaceAll(${s})`}}),"javascript");if(t===i)break;i=t}return i}function Eh(i,e){const t=/\bFiles\.readString\(\s*(?:Path\.of|Paths\.get)\(\s*("(?:[^"\\]|\\.)*")\s*\)\s*\)/g;return e==="python"?i.replace(t,'open($1, encoding="utf-8").read()').replace(/\bInteger\.parseInt\(/g,"int(").replace(/\bDouble\.parseDouble\(/g,"float(").replace(/\bString\.valueOf\(/g,"str("):i.replace(t,'require("fs").readFileSync($1, "utf8")').replace(/\bInteger\.parseInt\(/g,"parseInt(").replace(/\bDouble\.parseDouble\(/g,"parseFloat(").replace(/\bString\.valueOf\(/g,"String(")}function kb(i){let e=0;const t=[...i].findIndex(n=>n==="("?(e+=1,!1):n===")"?(e-=1,!1):n===","&&e===0);return t<0?[i]:[i.slice(0,t),i.slice(t+1)]}function n0(i,e,t){const n=new RegExp(`([A-Za-z_]\\w*(?:\\[[^[\\]]*\\]|\\.\\w+\\(\\))*|"(?:[^"\\\\]|\\\\.)*")\\.(${e.join("|")})\\(`,"g");let a="",s=0;for(let r=n.exec(i);r;r=n.exec(i)){const o=r.index+r[0].length-1;let l=0,u=-1;for(let m=o;me.has(n.toLowerCase())?t:`${n}.length()`)}const _b=new Set("abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while true false null var record sealed permits yield module open opens requires exports to uses provides with transitive".split(" "));function qs(i){const e=i.trim();if(e==="")return"Main";let t="";return Array.from(e).forEach((n,a)=>{a===0?new RegExp("\\p{L}","u").test(n)||n==="_"||n==="$"?t+=n:new RegExp("\\p{Nd}","u").test(n)?t+="_"+n:t+="_":/[\p{L}\p{M}\p{N}]/u.test(n)||n==="_"||n==="$"?t+=n:t+="_"}),t=t.replace(/_{2,}/g,"_").replace(/^_+|_+$/g,""),t===""?"Main":(new RegExp("^\\p{Nd}","u").test(t)&&(t="_"+t),_b.has(t.toLowerCase())&&(t="_"+t),t)}function Su(i,e,t={},n=[]){const a={...xh,...t},s=qs(e),r=[i,...n].filter((I,z,k)=>k.indexOf(I)===z).map(I=>({d:I,header:zt(I.caption)})).filter(I=>I.header!==void 0),o=r.map(I=>wo(I.d,I.header,"java",t,a.indentPerLevel)),l=zt(i.caption),u=r.some(I=>ms(I.d)),c=ls(i,"java",a),m=a.indentPerLevel*2,d=ms(i),h=d?Ob(c):c,g=Z(m),f=h.trim()===""?"":h.split(` `).map(I=>I.trim()===""?g:g+I).join(` `);let b="";const x=o.length>0&&(d||u),v=[...new Set([i,...r.map(I=>I.d)].flatMap(Xl))],w=v.length>0;(d||u)&&!v.includes("import java.util.Scanner;")&&v.push("import java.util.Scanner;");for(const I of v)b+=I+` `;v.length&&(b+=` @@ -208,9 +208,9 @@ ${o.out}${Z(a)}} `),b+=Z(a.indentPerLevel)+`} `);for(const[I,z]of o.entries())b+=(I>0||!l?` `:"")+z;return b+=`} -`,b}function _b(i){const e=i.split(` +`,b}function Ob(i){const e=i.split(` `);let t=0;for(e[t]==="// import java.util.Scanner;"&&t++;t=e.length?"":e.slice(t).join(` -`)}const vn={target:"visustruct.codegen.target",javaMode:"visustruct.codegen.javaOutputMode",comments:"visustruct.codegen.includeDiagramComments",emptyElse:"visustruct.codegen.includeEmptyElse"};function ta(i){try{return localStorage.getItem(i)}catch{return null}}function na(i,e){try{localStorage.setItem(i,e)}catch{}}const Ob=()=>p("web_run_stopped_loop"),Wh=()=>p("web_run_cancelled"),We=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,""");function Ab(i){let e=0;return i.replace(/^(\s*)while\s*\(\s*true\s*\)(?:\s*\/\*.*?\*\/)?\s*\{/gm,(t,n)=>{const a=`__visuStructLoopGuard${e++}`;return`${n}for (let ${a} = 0; ${a} < 100000 || (() => { throw new Error(${JSON.stringify(Ob())}); })(); ${a}++) {`})}function Cb(i){return Ab(i).replace(/\bprompt\s*\(/g,"await __visuStructPrompt(")}const Pb=` +`)}const vn={target:"visustruct.codegen.target",javaMode:"visustruct.codegen.javaOutputMode",comments:"visustruct.codegen.includeDiagramComments",emptyElse:"visustruct.codegen.includeEmptyElse"};function ta(i){try{return localStorage.getItem(i)}catch{return null}}function na(i,e){try{localStorage.setItem(i,e)}catch{}}const Ab=()=>p("web_run_stopped_loop"),Wh=()=>p("web_run_cancelled"),We=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,""");function Cb(i){let e=0;return i.replace(/^(\s*)while\s*\(\s*true\s*\)(?:\s*\/\*.*?\*\/)?\s*\{/gm,(t,n)=>{const a=`__visuStructLoopGuard${e++}`;return`${n}for (let ${a} = 0; ${a} < 100000 || (() => { throw new Error(${JSON.stringify(Ab())}); })(); ${a}++) {`})}function jb(i){return Cb(i).replace(/\bprompt\s*\(/g,"await __visuStructPrompt(")}const Pb=` let answer let lines = [] // Text von \`process.stdout.write\` ohne neue Zeile (wie \`System.out.print\`). @@ -255,7 +255,7 @@ onmessage = async (e) => { send('error', String(err)) } } -`,xr=2e3;class jb{constructor(e,t,n,a,s=()=>[]){y(this,"element");y(this,"target");y(this,"javaMode");y(this,"comments");y(this,"emptyElse");y(this,"code","");y(this,"codeView");y(this,"javaModeRow");y(this,"runButton");y(this,"saveButton");y(this,"copyButton");y(this,"runner");y(this,"runOutput");y(this,"runInput");y(this,"pseudocodeBox");y(this,"pseudocodeHint");y(this,"worker");y(this,"outputLines",[]);y(this,"droppedLines",0);y(this,"outputFrame");y(this,"pendingAnswer");this.currentDocument=e,this.saveFile=t,this.onClose=n,this.setPseudocode=a,this.subprograms=s;const r=ta(vn.target);this.target=r==="python"||r==="javascript"?r:"java",this.javaMode=ta(vn.javaMode)==="class"?"class":"snippet",this.comments=ta(vn.comments)==="true",this.emptyElse=ta(vn.emptyElse)!=="false",this.element=document.createElement("aside"),this.element.className="codepanel",this.build()}refresh(){const e=this.currentDocument(),t=this.options();this.code=this.target==="java"&&this.javaMode==="class"?Su(e,this.classStem(),t,this.subprograms()):ls(e,this.target,t,this.subprograms()),this.codeView.textContent=this.code,this.javaModeRow.hidden=this.target!=="java",this.saveButton.hidden=this.target!=="java",this.runButton.hidden=this.target!=="javascript"||!!e.pseudocode,this.runButton.hidden&&this.stopRun(!0),this.pseudocodeBox.checked=!!e.pseudocode,this.pseudocodeHint.hidden=!e.pseudocode;for(const n of this.element.querySelectorAll("[data-target]"))n.setAttribute("aria-pressed",String(n.dataset.target===this.target));for(const n of this.element.querySelectorAll("[data-java-mode]"))n.setAttribute("aria-pressed",String(n.dataset.javaMode===this.javaMode))}close(){this.stopRun(!0)}options(){return{includeDiagramTextAsComments:this.comments,includeEmptyElseBranch:this.emptyElse,pseudocodeNote:p("codegen_pseudocode_note")}}classStem(){return os(this.currentDocument().caption)||"Main"}build(){this.element.innerHTML=` +`,xr=2e3;class Db{constructor(e,t,n,a,s=()=>[]){y(this,"element");y(this,"target");y(this,"javaMode");y(this,"comments");y(this,"emptyElse");y(this,"code","");y(this,"codeView");y(this,"javaModeRow");y(this,"runButton");y(this,"saveButton");y(this,"copyButton");y(this,"runner");y(this,"runOutput");y(this,"runInput");y(this,"pseudocodeBox");y(this,"pseudocodeHint");y(this,"worker");y(this,"outputLines",[]);y(this,"droppedLines",0);y(this,"outputFrame");y(this,"pendingAnswer");this.currentDocument=e,this.saveFile=t,this.onClose=n,this.setPseudocode=a,this.subprograms=s;const r=ta(vn.target);this.target=r==="python"||r==="javascript"?r:"java",this.javaMode=ta(vn.javaMode)==="class"?"class":"snippet",this.comments=ta(vn.comments)==="true",this.emptyElse=ta(vn.emptyElse)!=="false",this.element=document.createElement("aside"),this.element.className="codepanel",this.build()}refresh(){const e=this.currentDocument(),t=this.options();this.code=this.target==="java"&&this.javaMode==="class"?Su(e,this.classStem(),t,this.subprograms()):ls(e,this.target,t,this.subprograms()),this.codeView.textContent=this.code,this.javaModeRow.hidden=this.target!=="java",this.saveButton.hidden=this.target!=="java",this.runButton.hidden=this.target!=="javascript"||!!e.pseudocode,this.runButton.hidden&&this.stopRun(!0),this.pseudocodeBox.checked=!!e.pseudocode,this.pseudocodeHint.hidden=!e.pseudocode;for(const n of this.element.querySelectorAll("[data-target]"))n.setAttribute("aria-pressed",String(n.dataset.target===this.target));for(const n of this.element.querySelectorAll("[data-java-mode]"))n.setAttribute("aria-pressed",String(n.dataset.javaMode===this.javaMode))}close(){this.stopRun(!0)}options(){return{includeDiagramTextAsComments:this.comments,includeEmptyElseBranch:this.emptyElse,pseudocodeNote:p("codegen_pseudocode_note")}}classStem(){return os(this.currentDocument().caption)||"Main"}build(){this.element.innerHTML=`

${We(p("codegen_placeholder_title"))}

@@ -285,12 +285,12 @@ onmessage = async (e) => {

${We(p("codegen_generated_hint"))}

- `;const e=a=>this.element.querySelector(a);this.codeView=e(".code-view"),this.javaModeRow=e(".java-mode"),this.runButton=e("[data-act=run]"),this.saveButton=e("[data-act=save]"),this.copyButton=e("[data-act=copy]"),this.runner=e(".runner"),this.runOutput=e(".runner-out"),this.runInput=e(".runner-input"),this.pseudocodeBox=e("[data-opt=pseudocode]"),this.pseudocodeHint=e(".pseudocode-hint"),this.pseudocodeBox.addEventListener("change",()=>this.setPseudocode(this.pseudocodeBox.checked)),e(".code-close").addEventListener("click",()=>this.onClose());for(const a of this.element.querySelectorAll("[data-target]"))a.addEventListener("click",()=>{this.target=a.dataset.target,na(vn.target,this.target),this.refresh()});for(const a of this.element.querySelectorAll("[data-java-mode]"))a.addEventListener("click",()=>{this.javaMode=a.dataset.javaMode,na(vn.javaMode,this.javaMode),this.refresh()});const t=e("[data-opt=comments]");t.checked=this.comments,t.addEventListener("change",()=>{this.comments=t.checked,na(vn.comments,String(this.comments)),this.refresh()});const n=e("[data-opt=emptyElse]");n.checked=this.emptyElse,n.addEventListener("change",()=>{this.emptyElse=n.checked,na(vn.emptyElse,String(this.emptyElse)),this.refresh()}),this.copyButton.addEventListener("click",()=>this.copy()),this.saveButton.addEventListener("click",()=>{const a=qs(this.classStem()),s=Su(this.currentDocument(),this.classStem(),this.options());this.saveFile(`${a}.java`,s)}),this.runButton.addEventListener("click",()=>this.run()),e("[data-act=stop]").addEventListener("click",()=>this.stopRun(!1)),e("[data-act=cancel]").addEventListener("click",()=>this.answer(null)),this.runInput.addEventListener("submit",a=>{a.preventDefault(),this.answer(this.runInput.querySelector("input").value)})}async copy(){var t;let e=!1;try{await navigator.clipboard.writeText(this.code),e=!0}catch{const n=document.createRange();n.selectNodeContents(this.codeView);const a=getSelection();a==null||a.removeAllRanges(),a==null||a.addRange(n),e=((t=document.execCommand)==null?void 0:t.call(document,"copy"))??!1}this.copyButton.textContent=p(e?"web_copied_check":"web_copy_manual"),setTimeout(()=>this.copyButton.textContent=p("codegen_copy"),2e3)}run(){this.stopRun(!0),this.runner.hidden=!1,this.runOutput.textContent="",this.outputLines=[],this.droppedLines=0,this.runOutput.classList.remove("error");const e=Cb(this.code),t=n=>this.onRunnerMessage(n);try{const n=URL.createObjectURL(new Blob([Pb],{type:"text/javascript"})),a=new Worker(n);URL.revokeObjectURL(n),a.onmessage=s=>t(s.data),a.onerror=s=>{s.preventDefault(),t({type:"error",text:s.message||p("web_run_error")})},a.postMessage({type:"run",code:e}),this.worker=a}catch{this.runInPage(e,t)}this.setRunning(!0)}runInPage(e,t){const n={log:(...r)=>t({type:"log",lines:[r.map(o=>typeof o=="string"?o:JSON.stringify(o)).join(" ")]})},a=r=>new Promise((o,l)=>{this.pendingAnswer=u=>u===null?l(new Error(Wh())):o(u),t({type:"prompt",text:r})}),s=(async()=>{}).constructor;new s("__visuStructPrompt","console",e)(a,n).then(()=>t({type:"done"})).catch(r=>t({type:"error",text:String(r)}))}onRunnerMessage(e){switch(e.type){case"log":this.appendOutput(e.lines??[]);break;case"prompt":{this.runInput.hidden=!1,this.runInput.querySelector("label").textContent=e.text??"";const t=this.runInput.querySelector("input");t.value="",t.focus();break}case"error":this.appendOutput([e.text??""]),this.runOutput.classList.add("error"),this.stopRun(!1);break;case"done":this.stopRun(!1);break}}appendOutput(e){this.outputLines.push(...e),this.outputLines.length>xr&&(this.droppedLines+=this.outputLines.length-xr,this.outputLines.splice(0,this.outputLines.length-xr)),this.outputFrame===void 0&&(this.outputFrame=requestAnimationFrame(()=>{this.outputFrame=void 0;const t=this.droppedLines>0?p("web_run_dropped_fmt",this.droppedLines)+` + `;const e=a=>this.element.querySelector(a);this.codeView=e(".code-view"),this.javaModeRow=e(".java-mode"),this.runButton=e("[data-act=run]"),this.saveButton=e("[data-act=save]"),this.copyButton=e("[data-act=copy]"),this.runner=e(".runner"),this.runOutput=e(".runner-out"),this.runInput=e(".runner-input"),this.pseudocodeBox=e("[data-opt=pseudocode]"),this.pseudocodeHint=e(".pseudocode-hint"),this.pseudocodeBox.addEventListener("change",()=>this.setPseudocode(this.pseudocodeBox.checked)),e(".code-close").addEventListener("click",()=>this.onClose());for(const a of this.element.querySelectorAll("[data-target]"))a.addEventListener("click",()=>{this.target=a.dataset.target,na(vn.target,this.target),this.refresh()});for(const a of this.element.querySelectorAll("[data-java-mode]"))a.addEventListener("click",()=>{this.javaMode=a.dataset.javaMode,na(vn.javaMode,this.javaMode),this.refresh()});const t=e("[data-opt=comments]");t.checked=this.comments,t.addEventListener("change",()=>{this.comments=t.checked,na(vn.comments,String(this.comments)),this.refresh()});const n=e("[data-opt=emptyElse]");n.checked=this.emptyElse,n.addEventListener("change",()=>{this.emptyElse=n.checked,na(vn.emptyElse,String(this.emptyElse)),this.refresh()}),this.copyButton.addEventListener("click",()=>this.copy()),this.saveButton.addEventListener("click",()=>{const a=qs(this.classStem()),s=Su(this.currentDocument(),this.classStem(),this.options());this.saveFile(`${a}.java`,s)}),this.runButton.addEventListener("click",()=>this.run()),e("[data-act=stop]").addEventListener("click",()=>this.stopRun(!1)),e("[data-act=cancel]").addEventListener("click",()=>this.answer(null)),this.runInput.addEventListener("submit",a=>{a.preventDefault(),this.answer(this.runInput.querySelector("input").value)})}async copy(){var t;let e=!1;try{await navigator.clipboard.writeText(this.code),e=!0}catch{const n=document.createRange();n.selectNodeContents(this.codeView);const a=getSelection();a==null||a.removeAllRanges(),a==null||a.addRange(n),e=((t=document.execCommand)==null?void 0:t.call(document,"copy"))??!1}this.copyButton.textContent=p(e?"web_copied_check":"web_copy_manual"),setTimeout(()=>this.copyButton.textContent=p("codegen_copy"),2e3)}run(){this.stopRun(!0),this.runner.hidden=!1,this.runOutput.textContent="",this.outputLines=[],this.droppedLines=0,this.runOutput.classList.remove("error");const e=jb(this.code),t=n=>this.onRunnerMessage(n);try{const n=URL.createObjectURL(new Blob([Pb],{type:"text/javascript"})),a=new Worker(n);URL.revokeObjectURL(n),a.onmessage=s=>t(s.data),a.onerror=s=>{s.preventDefault(),t({type:"error",text:s.message||p("web_run_error")})},a.postMessage({type:"run",code:e}),this.worker=a}catch{this.runInPage(e,t)}this.setRunning(!0)}runInPage(e,t){const n={log:(...r)=>t({type:"log",lines:[r.map(o=>typeof o=="string"?o:JSON.stringify(o)).join(" ")]})},a=r=>new Promise((o,l)=>{this.pendingAnswer=u=>u===null?l(new Error(Wh())):o(u),t({type:"prompt",text:r})}),s=(async()=>{}).constructor;new s("__visuStructPrompt","console",e)(a,n).then(()=>t({type:"done"})).catch(r=>t({type:"error",text:String(r)}))}onRunnerMessage(e){switch(e.type){case"log":this.appendOutput(e.lines??[]);break;case"prompt":{this.runInput.hidden=!1,this.runInput.querySelector("label").textContent=e.text??"";const t=this.runInput.querySelector("input");t.value="",t.focus();break}case"error":this.appendOutput([e.text??""]),this.runOutput.classList.add("error"),this.stopRun(!1);break;case"done":this.stopRun(!1);break}}appendOutput(e){this.outputLines.push(...e),this.outputLines.length>xr&&(this.droppedLines+=this.outputLines.length-xr,this.outputLines.splice(0,this.outputLines.length-xr)),this.outputFrame===void 0&&(this.outputFrame=requestAnimationFrame(()=>{this.outputFrame=void 0;const t=this.droppedLines>0?p("web_run_dropped_fmt",this.droppedLines)+` `:"";this.runOutput.textContent=t+this.outputLines.join(` `)+(this.outputLines.length?` -`:""),this.runOutput.scrollTop=this.runOutput.scrollHeight}))}answer(e){var t;this.runInput.hidden=!0,this.worker?this.worker.postMessage({type:"answer",value:e}):(t=this.pendingAnswer)==null||t.call(this,e),this.pendingAnswer=void 0}stopRun(e){var t;(t=this.worker)==null||t.terminate(),this.worker=void 0,this.pendingAnswer=void 0,this.runInput&&(this.runInput.hidden=!0),e&&this.runner&&(this.runner.hidden=!0),this.setRunning(!1)}setRunning(e){const t=this.element.querySelector("[data-act=stop]");t&&(t.disabled=!e)}}const De=(i,e=!1)=>``,se={newFile:De(''),open:De(''),save:De(''),undo:De(''),redo:De(''),cut:De(''),copy:De(''),paste:De(''),trash:De(''),share:De(''),book:De(''),code:De(''),play:De('',!0),step:De(''),indent:De(''),stop:De('',!0),folder:De(''),newFolder:De(''),diagram:De(''),fileText:De('')},Db="visustruct.learn.progress",vr={"04-sequenz":"05-sequenz","05-variablen-und-datentypen":"04-variablen-und-datentypen","07-verzweigung":"08-verzweigung","08-bedingungen-verknuepfen":"09-bedingungen-verknuepfen","09-fallauswahl":"10-fallauswahl","10-while-schleife":"11-while-schleife","11-do-while-schleife":"12-do-while-schleife","12-for-schleife":"13-for-schleife","13-verschachteln":"14-verschachteln","14-arrays":"15-arrays","15-aufruf-und-aussprung":"18-aufruf-und-aussprung","16-aufruf-und-aussprung":"18-aufruf-und-aussprung","17-aufruf-und-aussprung":"18-aufruf-und-aussprung","17-suchen-und-sortieren":"19-suchen-und-sortieren","18-suchen-und-sortieren":"19-suchen-und-sortieren","16-simulation-und-schreibtischtest":"07-simulation-und-schreibtischtest","17-java":"20-java","18-java":"20-java","19-java":"20-java","18-python-und-javascript":"21-python-und-javascript","19-python-und-javascript":"21-python-und-javascript","20-python-und-javascript":"21-python-und-javascript","22-erstes-fenster":"28-erstes-fenster","23-knopf-im-fenster":"29-knopf-im-fenster","24-der-knopf-reagiert":"30-der-knopf-reagiert","23-erstes-fenster":"28-erstes-fenster","24-knopf-im-fenster":"29-knopf-im-fenster","25-der-knopf-reagiert":"30-der-knopf-reagiert","26-zahl-verdoppeln":"31-zahl-verdoppeln","27-klickzaehler":"32-klickzaehler","28-ampel":"33-ampel","29-notenrechner":"34-notenrechner","30-taschenrechner":"35-taschenrechner","31-zahlenraten":"36-zahlenraten","13-lautsprecher":"16-lautsprecher","14-bildschirm":"18-bildschirm","15-motoren":"20-motoren","16-stoppuhr-akku":"21-stoppuhr-akku","03-sensoren":"04-sensoren","04-bis-zur-wand":"05-bis-zur-wand","05-abstand":"06-abstand","06-linie":"07-linie","07-farben":"08-farben","08-tasten-joystick":"10-tasten-joystick","09-licht":"11-licht","10-lautstaerke":"12-lautstaerke","11-neigung":"13-neigung","12-leds":"14-leds","13-einzelne-leds":"15-einzelne-leds","14-lautsprecher":"16-lautsprecher","15-bildschirm":"18-bildschirm","16-motoren":"20-motoren","17-stoppuhr-akku":"21-stoppuhr-akku"};function Bb(i){var n;const e={...i.lessons};for(const[a,s]of Object.entries(vr))i.lessons[a]&&!i.lessons[s]&&(e[s]=i.lessons[a]),i.lessons[a]&&delete e[a];const t=(n=i.view)!=null&&n.lesson&&vr[i.view.lesson]?{...i.view,lesson:vr[i.view.lesson]}:i.view;return{...i,lessons:e,view:t}}function Zb(){try{localStorage.removeItem(Db)}catch{}}const Nh=()=>({lessons:{},exercises:{}});Zb();let et=Nh();const Co=new Set;function ia(){for(const i of Co)i()}const Tu="visustruct-lernstand";function Fh(i,e){return i||e||void 0}function Mb(i,e){if(!i)return e;const t={...e.checks};for(const[n,a]of Object.entries(i.checks??{}))t[n]=a||t[n]||!1;return{step:Math.max(i.step??0,e.step??0),done:Fh(i.done,e.done),checks:Object.keys(t).length?t:void 0,quiz:i.quiz||e.quiz?{...e.quiz,...i.quiz}:void 0}}function Lb(i,e){const t={...i.lessons};for(const[a,s]of Object.entries(e.lessons))t[a]=Mb(i.lessons[a],s);const n={...i.exercises};for(const[a,s]of Object.entries(e.exercises)){const r=i.exercises[a];n[a]=r?{done:Fh(r.done,s.done),xml:r.xml??s.xml}:s}return{lessons:t,exercises:n}}const be={lesson(i){return et.lessons[i]??{step:0}},updateLesson(i,e){et.lessons[i]={...be.lesson(i),...e},ia()},exercise(i){return et.exercises[i]??{}},updateExercise(i,e){et.exercises[i]={...be.exercise(i),...e},ia()},resetExercise(i){delete et.exercises[i],ia()},view(){return et.view},hasContent(){return Object.values(et.lessons).some(i=>i.step>0||i.done||i.checks||i.quiz)||Object.keys(et.exercises).length>0},setView(i){et.view=i,ia()},onChange(i){return Co.add(i),()=>Co.delete(i)},toFile(){return JSON.stringify({format:Tu,version:1,saved:new Date().toISOString(),lessons:et.lessons,exercises:et.exercises,view:et.view},null,2)},loadFile(i,e=!1){let t;try{t=JSON.parse(i)}catch{return!1}if((t==null?void 0:t.format)!==Tu)return!1;const n=Bb({lessons:t.lessons??{},exercises:t.exercises??{},view:t.view});return et=e?{...Lb(et,n),view:n.view??et.view}:n,!0},clear(){et=Nh()}};function _u(i=new Date){const e=t=>String(t).padStart(2,"0");return`${i.getFullYear()}-${e(i.getMonth()+1)}-${e(i.getDate())}`}const Ou=i=>/^\d{4}-\d{2}-\d{2}$/.test(i);function Eb(i,e){return i.kind!==e.kind?i.kind==="directory"?-1:1:Ou(i.name)&&Ou(e.name)?e.name.localeCompare(i.name):i.name.localeCompare(e.name,void 0,{numeric:!0,sensitivity:"base"})}function Wb(i,e){return i.replace(/\.(visustruct|strk|java)$/i,"").replace(/[\\/:*?"<>|\u0000-\u001f]/g,"-").replace(/\s+/g," ").trim().replace(/^\.+/,"")||e}function Nb(i,e){const t=new Set([...e].map(a=>a.toLowerCase())),n=a=>!t.has(`${a}.visustruct`.toLowerCase())&&!t.has(`${a}.java`.toLowerCase());if(n(i))return i;for(let a=2;;a++)if(n(`${i} ${a}`))return`${i} ${a}`}function Fb(i){const e=i.replace(/[\\/:*?"<>|\u0000-\u001f]/g,"").trim();return e&&e!=="."&&e!==".."?e:void 0}const Qn=10;function Jb(i){let e=i.replace(/\r/g,"").split(` -`).filter(c=>!c.startsWith("//"));const t=e.filter(c=>/^linie:/.test(c)).map(c=>c.slice(6).trim());e=e.filter(c=>!/^linie:/.test(c));const n=e.findIndex(c=>/^raster:\s*\d+\s*$/.test(c));if(n>=0){const c=Number(e[n].split(":")[1]);e.splice(n,1),e=e.flatMap(m=>Array.from({length:c},(d,h)=>Array.from(m).map(g=>Array.from({length:c},(f,b)=>"^>v<".includes(g)?h===c>>1&&b===c>>1?g:".":g).join("")).join("")))}for(;e.length&&e[e.length-1].trim()==="";)e.pop();for(;e.length&&e[0].trim()==="";)e.shift();const s=Math.max(...e.map(c=>c.length))*Qn,r=e.length*Qn,o=(c,m)=>({x:-s/2+(c+.5)*Qn,y:r/2-(m+.5)*Qn}),l={width:s,depth:r,start:{x:0,y:0,heading:0},walls:[],lines:[],blocks:[],marks:[],goals:[],targets:[],colors:[]};let u=0;e.forEach((c,m)=>{Array.from(c).forEach((d,h)=>{const g=o(h,m);d==="#"?l.blocks.push(g):d==="="?l.marks.push(g):d==="Z"?l.goals.push(g):d==="o"?l.targets.push(g):d in Au?l.colors.push({at:g,color:Au[d]}):"^>v<".includes(d)&&(u++,l.start={...g,heading:{"^":0,">":90,v:180,"<":270}[d]})})});for(const c of t)l.lines.push(c.split(/\s+/).map(m=>{const[d,h]=m.split(",").map(Number);if(!Number.isFinite(d)||!Number.isFinite(h))throw new Error(`Linie: „${m}“ ist kein Feld (Spalte,Zeile).`);return o(d,h)}));if(u!==1)throw new Error(`Die Weltkarte braucht genau einen Start (^ > v <), gefunden: ${u}`);return l}const Au={r:"red",g:"green",b:"blue",y:"yellow"},R1=(i,e)=>Math.abs(i.x-e.x)<=Qn/2&&Math.abs(i.y-e.y)<=Qn/2,Cu=10,Pu=9,Rb=300,m1=8,Gb=[-3.6,-1.2,1.2,3.6],Hb=2.5,Vb=20,qb=12,i0=100,Ii={width:200,depth:200,start:{x:0,y:0,heading:0},walls:[],lines:[]},ju=i=>i*Math.PI/180,d1=i=>({x:Math.sin(ju(i)),y:Math.cos(ju(i))}),aa=()=>Array.from({length:uh},()=>{}),Du=([i,e,t])=>i>0||e>0||t>0?[i,e,t]:void 0;class ds{constructor(e=Ii){y(this,"pose");y(this,"trail");y(this,"bumps",0);y(this,"leds",aa());y(this,"screen");y(this,"wheels",[0,0]);y(this,"time",0);y(this,"timerStart",0);y(this,"blocked",!1);y(this,"blockWallCache");this.setup=e,this.pose={...e.start},this.trail=[{x:e.start.x,y:e.start.y}]}reset(){this.pose={...this.setup.start},this.trail=[{x:this.pose.x,y:this.pose.y}],this.bumps=0,this.leds=aa(),this.screen=void 0,this.wheels=[0,0],this.time=0,this.timerStart=0,this.blocked=!1}get allWalls(){const e=this.setup.width/2,t=this.setup.depth/2,n=[{x:-e,y:-t},{x:e,y:-t},{x:e,y:t},{x:-e,y:t}];return[...this.setup.walls,...n.map((a,s)=>({from:a,to:n[(s+1)%4]})),...this.blockWalls]}get blockWalls(){return this.blockWallCache??(this.blockWallCache=(this.setup.blocks??[]).flatMap(e=>{const t=Qn/2,n=[{x:e.x-t,y:e.y-t},{x:e.x+t,y:e.y-t},{x:e.x+t,y:e.y+t},{x:e.x-t,y:e.y+t}];return n.map((a,s)=>({from:a,to:n[(s+1)%4]}))})),this.blockWallCache}atGoal(){const e=d1(this.pose.heading),t={x:this.pose.x+e.x*m1,y:this.pose.y+e.y*m1};return(this.setup.goals??[]).some(n=>R1(this.pose,n)||R1(t,n))||(this.setup.targets??[]).some(n=>R1(this.pose,n))}apply(e){switch(e.method){case"forward":return this.wheels=[0,0],this.drive(e.args[0]);case"backward":return this.wheels=[0,0],this.drive(-e.args[0]);case"turnRight":return this.wheels=[0,0],this.turn(e.args[0]);case"turnLeft":return this.wheels=[0,0],this.turn(-e.args[0]);case"stop":this.wheels=[0,0];return;case"drive":this.wheels=[Bu(e.args[0]),Bu(e.args[1])];return;case"pause":return this.tick(e.args[0]);case"resetTimer":this.timerStart=this.time;return;case"setLed":this.leds=aa().map(()=>Du(e.args));return;case"ledOff":this.leds=aa();return;case"ledColor":this.leds[e.args[0]]=Du(ts[e.text??""]??[0,0,0]);return;case"showText":this.screen=e.text;return}}tick(e){if(e<=0)return;this.time+=e;const[t,n]=this.wheels.map(o=>o/100*Vb);if(t===0&&n===0)return;const a=Math.ceil(e/10),s=e/1e3/a;let r=!1;for(let o=0;o{const r={x:this.pose.x+e.x*m1+t.x*a,y:this.pose.y+e.y*m1+t.y*a};([...this.setup.marks??[],...this.setup.goals??[]].some(l=>R1(r,l))||this.setup.lines.some(l=>Ub(r,l)<=Hb/2))&&(n|=1<<3-s)}),n}colorUnder(){var n;const e=d1(this.pose.heading),t={x:this.pose.x+e.x*m1,y:this.pose.y+e.y*m1};return(n=(this.setup.colors??[]).find(a=>R1(t,a.at)))==null?void 0:n.color}sensors(){const e=this.lineState();return{getDistance:this.distance(),getLine:e,getColor:this.colorUnder()??(e&6?"black":"white"),isLineLeft:(e&4)!==0,isLineRight:(e&2)!==0,getTimer:this.timer}}freeDistance(e,t){let n=1/0;for(const a of this.allWalls){const s=Qb(e,t,a.from,a.to);s!==void 0&&sMath.max(-100,Math.min(100,i));function Zu(i){const e=(i%360+360)%360;return Math.abs(e-360)<1e-9?0:e}function Qb(i,e,t,n){const a={x:n.x-t.x,y:n.y-t.y},s=e.x*a.y-e.y*a.x;if(Math.abs(s)<1e-12)return;const r={x:t.x-i.x,y:t.y-i.y},o=(r.x*a.y-r.y*a.x)/s,l=(r.x*e.y-r.y*e.x)/s;return o>=0&&l>=0&&l<=1?o:void 0}function Ub(i,e){let t=1/0;for(let n=0;n+10&&o.tick(i0),s.robotSensors={...o.sensors(),...tx(a,u)};const m=()=>({outputs:[...c.outputLines],files:new Map(c.files),drive:c.robotActions.length?is(c.robotActions):void 0,...n?{atGoal:o.atGoal(),bumps:o.bumps}:{},led:o.leds.some(d=>d!==void 0),tone:c.robotActions.some(d=>d.method==="playTone"),screen:o.screen,actions:mh(c.robotActions.filter(d=>!Kb.has(d.method)))});if(c.inputRequest){const d=r.shift();if(d===void 0)return{...m(),missingInput:!0};if(s.provideInput(d),c.inputErrorNotice)return{...m(),error:c.inputErrorNotice};continue}if(c.isHalted)return{...m(),error:c.notice};if(!s.canStep)return{...m(),unusedInputs:r.length||void 0};s.step()}return{outputs:[...s.state.outputLines],files:new Map(s.state.files),drive:is(s.state.robotActions),tooManySteps:!0}}function tx(i,e){const t=Math.floor(e/Yb);return Object.fromEntries(Object.entries(i??{}).map(([n,a])=>[n,a[Math.min(t,a.length-1)]]))}function Jh(i){return i===void 0||i===""?[]:i.replace(/\n$/,"").split(` -`)}function sa(i,e){return i.length!==e.length?!1:i.every((t,n)=>Mu(t)===Mu(e[n]))}function Mu(i){const e=i.trim().replace(/\s+/g," ");return/^-?\d+\.0+$/.test(e)?e.replace(/\.0+$/,""):e}function nx(i,e,t,n){return e.map(a=>{var d,h,g;const s=a.world?n==null?void 0:n(a.world):void 0;if(a.world&&!s)throw new Error(`Weltkarte „${a.world}“ fehlt.`);const r=ex(i,a.inputs,t,s,a.sensors),o=(a.files??[]).every(f=>{var b;return sa(Jh((b=r.files)==null?void 0:b.get(f.name)),f.lines)}),l=!a.drive||sa(r.drive??[],a.drive),u=!a.world||r.bumps===0&&(!((d=s==null?void 0:s.goals)!=null&&d.length||(h=s==null?void 0:s.targets)!=null&&h.length)||r.atGoal===!0),c=(a.led===void 0||r.led===a.led)&&(a.tone===void 0||r.tone===a.tone)&&(a.screen===void 0||r.screen===a.screen)&&(a.drives===void 0||(((g=r.drive)==null?void 0:g.length)??0)>0===a.drives)&&(!a.actions||sa(r.actions??[],a.actions)),m=!r.error&&!r.missingInput&&!r.tooManySteps&&sa(r.outputs,a.expected)&&o&&l&&u&&c;return{test:a,result:r,passed:m}})}function ix(i){const e=new Set,t=n=>{for(const a of n){e.add(a.type),a.loopBody&&t(a.loopBody);for(const s of a.cases??[])t(s.elements)}};return t(i.elements),e}function Po(i){const e=[S.forSchleife,S.whileSchleife,S.doUntilSchleife,S.endlosschleife];let t=0;for(const n of i){const a=Math.max(Po(n.loopBody??[]),...(n.cases??[]).map(s=>Po(s.elements)));t=Math.max(t,a+(e.includes(n.type)?1:0))}return t}class ki extends Error{}function ax(i,e){const t=[],n=[];for(const a of i){const s=a.trim();if(!s)continue;if(s.startsWith("?")){const o=s.slice(1).trim();hs(o,sx(t)),n.push(o);continue}const r=/^([A-Za-z_]\w*)\s*:\s*(?:(-?\d+)\s*\.\.\s*(-?\d+)|(boolean))$/.exec(s);if(!r)throw new ki(`${e}: Unbekannte Zeile im Spiel: „${s}“`);t.push(r[4]?{name:r[1],kind:"boolean"}:{name:r[1],kind:"int",min:Number(r[2]),max:Number(r[3])})}if(!n.length)throw new ki(`${e}: Das Spiel braucht mindestens eine Zeile „? bedingung“.`);return{vars:t,conditions:n}}function sx(i){return Object.fromEntries(i.map(e=>[e.name,e.kind==="boolean"?!0:e.min]))}function rx(i){const e=[],t=/\s*(?:(\d+)|(true|false)\b|([A-Za-z_]\w*)|(&&|\|\||==|!=|<=|>=|<|>|!|\(|\)))/y;let n=0;for(;nt[n],s=d=>{var h;return((h=a())==null?void 0:h.kind)==="op"&&a().value===d},r=()=>{throw new ki(`Bedingung nicht lesbar: „${i}“`)},o=()=>{const d=t[n++]??r();if(d.kind==="num"||d.kind==="bool")return d.value;if(d.kind==="name"){if(!(d.value in e))throw new ki(`Unbekannte Variable „${d.value}“ in „${i}“`);return e[d.value]}if(d.value==="("){const h=c();return s(")")||r(),n++,h}if(d.value==="!"){const h=o();return typeof h!="boolean"&&r(),!h}return r()},l=()=>{const d=o(),h=a();if((h==null?void 0:h.kind)==="op"&&["==","!=","<","<=",">",">="].includes(h.value)){n++;const g=o();switch(h.value){case"==":return d===g;case"!=":return d!==g}(typeof d!="number"||typeof g!="number")&&r();const[f,b]=[d,g];return h.value==="<"?f"?f>b:f>=b}return d},u=()=>{let d=l();for(;s("&&");){n++;const h=l();d=d&&h}return d},c=()=>{let d=u();for(;s("||");){n++;const h=u();d=d||h}return d},m=c();return n!==t.length||typeof m!="boolean"?r():m}function ox(i,e){const t=[i],n=i.replace(/\b[A-Za-z_]\w*\b/g,r=>r in e?String(e[r]):r);n!==i&&t.push(n);const a=n.replace(/(-?\d+|true|false)\s*(==|!=|<=|>=|<|>)\s*(-?\d+|true|false)/g,r=>String(hs(r,{})));a!==t[t.length-1]&&t.push(a);const s=String(hs(i,e));return s!==t[t.length-1]&&t.push(s),t}function lx(i,e){const t=[],n=new RegExp(`\\b${e}\\s*(?:==|!=|<=|>=|<|>)\\s*(-?\\d+)|(-?\\d+)\\s*(?:==|!=|<=|>=|<|>)\\s*${e}\\b`,"g");for(const a of i.matchAll(n)){const s=Number(a[1]??a[2]);t.push(s-1,s,s+1)}return t}function ux(i,e,t,n=Math.random){const a=i.conditions.length,s=Math.floor(e*a/t),r=Math.min(a-1,s+(n()<.5?0:1)),o=i.conditions[r],l={};for(const u of i.vars){if(u.kind==="boolean"){l[u.name]=n()<.5;continue}const c=lx(o,u.name).filter(m=>m>=u.min&&m<=u.max);l[u.name]=c.length&&n()<.6?c[Math.floor(n()*c.length)]:u.min+Math.floor(n()*(u.max-u.min+1))}return{condition:o,values:l,answer:hs(o,l)}}function cx(i){return Object.entries(i.values).filter(([e])=>new RegExp(`\\b${e}\\b`).test(i.condition))}const mx=`--- +`:""),this.runOutput.scrollTop=this.runOutput.scrollHeight}))}answer(e){var t;this.runInput.hidden=!0,this.worker?this.worker.postMessage({type:"answer",value:e}):(t=this.pendingAnswer)==null||t.call(this,e),this.pendingAnswer=void 0}stopRun(e){var t;(t=this.worker)==null||t.terminate(),this.worker=void 0,this.pendingAnswer=void 0,this.runInput&&(this.runInput.hidden=!0),e&&this.runner&&(this.runner.hidden=!0),this.setRunning(!1)}setRunning(e){const t=this.element.querySelector("[data-act=stop]");t&&(t.disabled=!e)}}const De=(i,e=!1)=>``,se={newFile:De(''),open:De(''),save:De(''),undo:De(''),redo:De(''),cut:De(''),copy:De(''),paste:De(''),trash:De(''),share:De(''),book:De(''),code:De(''),play:De('',!0),step:De(''),indent:De(''),stop:De('',!0),folder:De(''),newFolder:De(''),diagram:De(''),fileText:De('')},Bb="visustruct.learn.progress",vr={"04-sequenz":"05-sequenz","05-variablen-und-datentypen":"04-variablen-und-datentypen","07-verzweigung":"08-verzweigung","08-bedingungen-verknuepfen":"09-bedingungen-verknuepfen","09-fallauswahl":"10-fallauswahl","10-while-schleife":"11-while-schleife","11-do-while-schleife":"12-do-while-schleife","12-for-schleife":"13-for-schleife","13-verschachteln":"14-verschachteln","14-arrays":"15-arrays","15-aufruf-und-aussprung":"18-aufruf-und-aussprung","16-aufruf-und-aussprung":"18-aufruf-und-aussprung","17-aufruf-und-aussprung":"18-aufruf-und-aussprung","17-suchen-und-sortieren":"19-suchen-und-sortieren","18-suchen-und-sortieren":"19-suchen-und-sortieren","16-simulation-und-schreibtischtest":"07-simulation-und-schreibtischtest","17-java":"20-java","18-java":"20-java","19-java":"20-java","18-python-und-javascript":"21-python-und-javascript","19-python-und-javascript":"21-python-und-javascript","20-python-und-javascript":"21-python-und-javascript","22-erstes-fenster":"28-erstes-fenster","23-knopf-im-fenster":"29-knopf-im-fenster","24-der-knopf-reagiert":"30-der-knopf-reagiert","23-erstes-fenster":"28-erstes-fenster","24-knopf-im-fenster":"29-knopf-im-fenster","25-der-knopf-reagiert":"30-der-knopf-reagiert","26-zahl-verdoppeln":"31-zahl-verdoppeln","27-klickzaehler":"32-klickzaehler","28-ampel":"33-ampel","29-notenrechner":"34-notenrechner","30-taschenrechner":"35-taschenrechner","31-zahlenraten":"36-zahlenraten","13-lautsprecher":"16-lautsprecher","14-bildschirm":"18-bildschirm","15-motoren":"20-motoren","16-stoppuhr-akku":"21-stoppuhr-akku","03-sensoren":"04-sensoren","04-bis-zur-wand":"05-bis-zur-wand","05-abstand":"06-abstand","06-linie":"07-linie","07-farben":"08-farben","08-tasten-joystick":"10-tasten-joystick","09-licht":"11-licht","10-lautstaerke":"12-lautstaerke","11-neigung":"13-neigung","12-leds":"14-leds","13-einzelne-leds":"15-einzelne-leds","14-lautsprecher":"16-lautsprecher","15-bildschirm":"18-bildschirm","16-motoren":"20-motoren","17-stoppuhr-akku":"21-stoppuhr-akku"};function Zb(i){var n;const e={...i.lessons};for(const[a,s]of Object.entries(vr))i.lessons[a]&&!i.lessons[s]&&(e[s]=i.lessons[a]),i.lessons[a]&&delete e[a];const t=(n=i.view)!=null&&n.lesson&&vr[i.view.lesson]?{...i.view,lesson:vr[i.view.lesson]}:i.view;return{...i,lessons:e,view:t}}function Mb(){try{localStorage.removeItem(Bb)}catch{}}const Nh=()=>({lessons:{},exercises:{}});Mb();let et=Nh();const Co=new Set;function ia(){for(const i of Co)i()}const Tu="visustruct-lernstand";function Fh(i,e){return i||e||void 0}function Lb(i,e){if(!i)return e;const t={...e.checks};for(const[n,a]of Object.entries(i.checks??{}))t[n]=a||t[n]||!1;return{step:Math.max(i.step??0,e.step??0),done:Fh(i.done,e.done),checks:Object.keys(t).length?t:void 0,quiz:i.quiz||e.quiz?{...e.quiz,...i.quiz}:void 0}}function Eb(i,e){const t={...i.lessons};for(const[a,s]of Object.entries(e.lessons))t[a]=Lb(i.lessons[a],s);const n={...i.exercises};for(const[a,s]of Object.entries(e.exercises)){const r=i.exercises[a];n[a]=r?{done:Fh(r.done,s.done),xml:r.xml??s.xml}:s}return{lessons:t,exercises:n}}const be={lesson(i){return et.lessons[i]??{step:0}},updateLesson(i,e){et.lessons[i]={...be.lesson(i),...e},ia()},exercise(i){return et.exercises[i]??{}},updateExercise(i,e){et.exercises[i]={...be.exercise(i),...e},ia()},resetExercise(i){delete et.exercises[i],ia()},view(){return et.view},hasContent(){return Object.values(et.lessons).some(i=>i.step>0||i.done||i.checks||i.quiz)||Object.keys(et.exercises).length>0},setView(i){et.view=i,ia()},onChange(i){return Co.add(i),()=>Co.delete(i)},toFile(){return JSON.stringify({format:Tu,version:1,saved:new Date().toISOString(),lessons:et.lessons,exercises:et.exercises,view:et.view},null,2)},loadFile(i,e=!1){let t;try{t=JSON.parse(i)}catch{return!1}if((t==null?void 0:t.format)!==Tu)return!1;const n=Zb({lessons:t.lessons??{},exercises:t.exercises??{},view:t.view});return et=e?{...Eb(et,n),view:n.view??et.view}:n,!0},clear(){et=Nh()}};function _u(i=new Date){const e=t=>String(t).padStart(2,"0");return`${i.getFullYear()}-${e(i.getMonth()+1)}-${e(i.getDate())}`}const Ou=i=>/^\d{4}-\d{2}-\d{2}$/.test(i);function Wb(i,e){return i.kind!==e.kind?i.kind==="directory"?-1:1:Ou(i.name)&&Ou(e.name)?e.name.localeCompare(i.name):i.name.localeCompare(e.name,void 0,{numeric:!0,sensitivity:"base"})}function Nb(i,e){return i.replace(/\.(visustruct|strk|java)$/i,"").replace(/[\\/:*?"<>|\u0000-\u001f]/g,"-").replace(/\s+/g," ").trim().replace(/^\.+/,"")||e}function Fb(i,e){const t=new Set([...e].map(a=>a.toLowerCase())),n=a=>!t.has(`${a}.visustruct`.toLowerCase())&&!t.has(`${a}.java`.toLowerCase());if(n(i))return i;for(let a=2;;a++)if(n(`${i} ${a}`))return`${i} ${a}`}function Jb(i){const e=i.replace(/[\\/:*?"<>|\u0000-\u001f]/g,"").trim();return e&&e!=="."&&e!==".."?e:void 0}const Qn=10;function Rb(i){let e=i.replace(/\r/g,"").split(` +`).filter(c=>!c.startsWith("//"));const t=e.filter(c=>/^linie:/.test(c)).map(c=>c.slice(6).trim());e=e.filter(c=>!/^linie:/.test(c));const n=e.findIndex(c=>/^raster:\s*\d+\s*$/.test(c));if(n>=0){const c=Number(e[n].split(":")[1]);e.splice(n,1),e=e.flatMap(m=>Array.from({length:c},(d,h)=>Array.from(m).map(g=>Array.from({length:c},(f,b)=>"^>v<".includes(g)?h===c>>1&&b===c>>1?g:".":g).join("")).join("")))}for(;e.length&&e[e.length-1].trim()==="";)e.pop();for(;e.length&&e[0].trim()==="";)e.shift();const s=Math.max(...e.map(c=>c.length))*Qn,r=e.length*Qn,o=(c,m)=>({x:-s/2+(c+.5)*Qn,y:r/2-(m+.5)*Qn}),l={width:s,depth:r,start:{x:0,y:0,heading:0},walls:[],lines:[],blocks:[],marks:[],goals:[],targets:[],colors:[]};let u=0;e.forEach((c,m)=>{Array.from(c).forEach((d,h)=>{const g=o(h,m);d==="#"?l.blocks.push(g):d==="="?l.marks.push(g):d==="Z"?l.goals.push(g):d==="o"?l.targets.push(g):d in Au?l.colors.push({at:g,color:Au[d]}):"^>v<".includes(d)&&(u++,l.start={...g,heading:{"^":0,">":90,v:180,"<":270}[d]})})});for(const c of t)l.lines.push(c.split(/\s+/).map(m=>{const[d,h]=m.split(",").map(Number);if(!Number.isFinite(d)||!Number.isFinite(h))throw new Error(`Linie: „${m}“ ist kein Feld (Spalte,Zeile).`);return o(d,h)}));if(u!==1)throw new Error(`Die Weltkarte braucht genau einen Start (^ > v <), gefunden: ${u}`);return l}const Au={r:"red",g:"green",b:"blue",y:"yellow"},R1=(i,e)=>Math.abs(i.x-e.x)<=Qn/2&&Math.abs(i.y-e.y)<=Qn/2,Cu=10,ju=9,Gb=300,m1=8,Hb=[-3.6,-1.2,1.2,3.6],Vb=2.5,qb=20,Qb=12,i0=100,Ii={width:200,depth:200,start:{x:0,y:0,heading:0},walls:[],lines:[]},Pu=i=>i*Math.PI/180,d1=i=>({x:Math.sin(Pu(i)),y:Math.cos(Pu(i))}),aa=()=>Array.from({length:uh},()=>{}),Du=([i,e,t])=>i>0||e>0||t>0?[i,e,t]:void 0;class ds{constructor(e=Ii){y(this,"pose");y(this,"trail");y(this,"bumps",0);y(this,"leds",aa());y(this,"screen");y(this,"wheels",[0,0]);y(this,"time",0);y(this,"timerStart",0);y(this,"blocked",!1);y(this,"blockWallCache");this.setup=e,this.pose={...e.start},this.trail=[{x:e.start.x,y:e.start.y}]}reset(){this.pose={...this.setup.start},this.trail=[{x:this.pose.x,y:this.pose.y}],this.bumps=0,this.leds=aa(),this.screen=void 0,this.wheels=[0,0],this.time=0,this.timerStart=0,this.blocked=!1}get allWalls(){const e=this.setup.width/2,t=this.setup.depth/2,n=[{x:-e,y:-t},{x:e,y:-t},{x:e,y:t},{x:-e,y:t}];return[...this.setup.walls,...n.map((a,s)=>({from:a,to:n[(s+1)%4]})),...this.blockWalls]}get blockWalls(){return this.blockWallCache??(this.blockWallCache=(this.setup.blocks??[]).flatMap(e=>{const t=Qn/2,n=[{x:e.x-t,y:e.y-t},{x:e.x+t,y:e.y-t},{x:e.x+t,y:e.y+t},{x:e.x-t,y:e.y+t}];return n.map((a,s)=>({from:a,to:n[(s+1)%4]}))})),this.blockWallCache}atGoal(){const e=d1(this.pose.heading),t={x:this.pose.x+e.x*m1,y:this.pose.y+e.y*m1};return(this.setup.goals??[]).some(n=>R1(this.pose,n)||R1(t,n))||(this.setup.targets??[]).some(n=>R1(this.pose,n))}apply(e){switch(e.method){case"forward":return this.wheels=[0,0],this.drive(e.args[0]);case"backward":return this.wheels=[0,0],this.drive(-e.args[0]);case"turnRight":return this.wheels=[0,0],this.turn(e.args[0]);case"turnLeft":return this.wheels=[0,0],this.turn(-e.args[0]);case"stop":this.wheels=[0,0];return;case"drive":this.wheels=[Bu(e.args[0]),Bu(e.args[1])];return;case"pause":return this.tick(e.args[0]);case"resetTimer":this.timerStart=this.time;return;case"setLed":this.leds=aa().map(()=>Du(e.args));return;case"ledOff":this.leds=aa();return;case"ledColor":this.leds[e.args[0]]=Du(ts[e.text??""]??[0,0,0]);return;case"showText":this.screen=e.text;return}}tick(e){if(e<=0)return;this.time+=e;const[t,n]=this.wheels.map(o=>o/100*qb);if(t===0&&n===0)return;const a=Math.ceil(e/10),s=e/1e3/a;let r=!1;for(let o=0;o{const r={x:this.pose.x+e.x*m1+t.x*a,y:this.pose.y+e.y*m1+t.y*a};([...this.setup.marks??[],...this.setup.goals??[]].some(l=>R1(r,l))||this.setup.lines.some(l=>$b(r,l)<=Vb/2))&&(n|=1<<3-s)}),n}colorUnder(){var n;const e=d1(this.pose.heading),t={x:this.pose.x+e.x*m1,y:this.pose.y+e.y*m1};return(n=(this.setup.colors??[]).find(a=>R1(t,a.at)))==null?void 0:n.color}sensors(){const e=this.lineState();return{getDistance:this.distance(),getLine:e,getColor:this.colorUnder()??(e&6?"black":"white"),isLineLeft:(e&4)!==0,isLineRight:(e&2)!==0,getTimer:this.timer}}freeDistance(e,t){let n=1/0;for(const a of this.allWalls){const s=Ub(e,t,a.from,a.to);s!==void 0&&sMath.max(-100,Math.min(100,i));function Zu(i){const e=(i%360+360)%360;return Math.abs(e-360)<1e-9?0:e}function Ub(i,e,t,n){const a={x:n.x-t.x,y:n.y-t.y},s=e.x*a.y-e.y*a.x;if(Math.abs(s)<1e-12)return;const r={x:t.x-i.x,y:t.y-i.y},o=(r.x*a.y-r.y*a.x)/s,l=(r.x*e.y-r.y*e.x)/s;return o>=0&&l>=0&&l<=1?o:void 0}function $b(i,e){let t=1/0;for(let n=0;n+10&&o.tick(i0),s.robotSensors={...o.sensors(),...nx(a,u)};const m=()=>({outputs:[...c.outputLines],files:new Map(c.files),drive:c.robotActions.length?is(c.robotActions):void 0,...n?{atGoal:o.atGoal(),bumps:o.bumps}:{},led:o.leds.some(d=>d!==void 0),tone:c.robotActions.some(d=>d.method==="playTone"),screen:o.screen,actions:mh(c.robotActions.filter(d=>!ex.has(d.method)))});if(c.inputRequest){const d=r.shift();if(d===void 0)return{...m(),missingInput:!0};if(s.provideInput(d),c.inputErrorNotice)return{...m(),error:c.inputErrorNotice};continue}if(c.isHalted)return{...m(),error:c.notice};if(!s.canStep)return{...m(),unusedInputs:r.length||void 0};s.step()}return{outputs:[...s.state.outputLines],files:new Map(s.state.files),drive:is(s.state.robotActions),tooManySteps:!0}}function nx(i,e){const t=Math.floor(e/Xb);return Object.fromEntries(Object.entries(i??{}).map(([n,a])=>[n,a[Math.min(t,a.length-1)]]))}function Jh(i){return i===void 0||i===""?[]:i.replace(/\n$/,"").split(` +`)}function sa(i,e){return i.length!==e.length?!1:i.every((t,n)=>Mu(t)===Mu(e[n]))}function Mu(i){const e=i.trim().replace(/\s+/g," ");return/^-?\d+\.0+$/.test(e)?e.replace(/\.0+$/,""):e}function ix(i,e,t,n){return e.map(a=>{var d,h,g;const s=a.world?n==null?void 0:n(a.world):void 0;if(a.world&&!s)throw new Error(`Weltkarte „${a.world}“ fehlt.`);const r=tx(i,a.inputs,t,s,a.sensors),o=(a.files??[]).every(f=>{var b;return sa(Jh((b=r.files)==null?void 0:b.get(f.name)),f.lines)}),l=!a.drive||sa(r.drive??[],a.drive),u=!a.world||r.bumps===0&&(!((d=s==null?void 0:s.goals)!=null&&d.length||(h=s==null?void 0:s.targets)!=null&&h.length)||r.atGoal===!0),c=(a.led===void 0||r.led===a.led)&&(a.tone===void 0||r.tone===a.tone)&&(a.screen===void 0||r.screen===a.screen)&&(a.drives===void 0||(((g=r.drive)==null?void 0:g.length)??0)>0===a.drives)&&(!a.actions||sa(r.actions??[],a.actions)),m=!r.error&&!r.missingInput&&!r.tooManySteps&&sa(r.outputs,a.expected)&&o&&l&&u&&c;return{test:a,result:r,passed:m}})}function ax(i){const e=new Set,t=n=>{for(const a of n){e.add(a.type),a.loopBody&&t(a.loopBody);for(const s of a.cases??[])t(s.elements)}};return t(i.elements),e}function jo(i){const e=[S.forSchleife,S.whileSchleife,S.doUntilSchleife,S.endlosschleife];let t=0;for(const n of i){const a=Math.max(jo(n.loopBody??[]),...(n.cases??[]).map(s=>jo(s.elements)));t=Math.max(t,a+(e.includes(n.type)?1:0))}return t}class ki extends Error{}function sx(i,e){const t=[],n=[];for(const a of i){const s=a.trim();if(!s)continue;if(s.startsWith("?")){const o=s.slice(1).trim();hs(o,rx(t)),n.push(o);continue}const r=/^([A-Za-z_]\w*)\s*:\s*(?:(-?\d+)\s*\.\.\s*(-?\d+)|(boolean))$/.exec(s);if(!r)throw new ki(`${e}: Unbekannte Zeile im Spiel: „${s}“`);t.push(r[4]?{name:r[1],kind:"boolean"}:{name:r[1],kind:"int",min:Number(r[2]),max:Number(r[3])})}if(!n.length)throw new ki(`${e}: Das Spiel braucht mindestens eine Zeile „? bedingung“.`);return{vars:t,conditions:n}}function rx(i){return Object.fromEntries(i.map(e=>[e.name,e.kind==="boolean"?!0:e.min]))}function ox(i){const e=[],t=/\s*(?:(\d+)|(true|false)\b|([A-Za-z_]\w*)|(&&|\|\||==|!=|<=|>=|<|>|!|\(|\)))/y;let n=0;for(;nt[n],s=d=>{var h;return((h=a())==null?void 0:h.kind)==="op"&&a().value===d},r=()=>{throw new ki(`Bedingung nicht lesbar: „${i}“`)},o=()=>{const d=t[n++]??r();if(d.kind==="num"||d.kind==="bool")return d.value;if(d.kind==="name"){if(!(d.value in e))throw new ki(`Unbekannte Variable „${d.value}“ in „${i}“`);return e[d.value]}if(d.value==="("){const h=c();return s(")")||r(),n++,h}if(d.value==="!"){const h=o();return typeof h!="boolean"&&r(),!h}return r()},l=()=>{const d=o(),h=a();if((h==null?void 0:h.kind)==="op"&&["==","!=","<","<=",">",">="].includes(h.value)){n++;const g=o();switch(h.value){case"==":return d===g;case"!=":return d!==g}(typeof d!="number"||typeof g!="number")&&r();const[f,b]=[d,g];return h.value==="<"?f"?f>b:f>=b}return d},u=()=>{let d=l();for(;s("&&");){n++;const h=l();d=d&&h}return d},c=()=>{let d=u();for(;s("||");){n++;const h=u();d=d||h}return d},m=c();return n!==t.length||typeof m!="boolean"?r():m}function lx(i,e){const t=[i],n=i.replace(/\b[A-Za-z_]\w*\b/g,r=>r in e?String(e[r]):r);n!==i&&t.push(n);const a=n.replace(/(-?\d+|true|false)\s*(==|!=|<=|>=|<|>)\s*(-?\d+|true|false)/g,r=>String(hs(r,{})));a!==t[t.length-1]&&t.push(a);const s=String(hs(i,e));return s!==t[t.length-1]&&t.push(s),t}function ux(i,e){const t=[],n=new RegExp(`\\b${e}\\s*(?:==|!=|<=|>=|<|>)\\s*(-?\\d+)|(-?\\d+)\\s*(?:==|!=|<=|>=|<|>)\\s*${e}\\b`,"g");for(const a of i.matchAll(n)){const s=Number(a[1]??a[2]);t.push(s-1,s,s+1)}return t}function cx(i,e,t,n=Math.random){const a=i.conditions.length,s=Math.floor(e*a/t),r=Math.min(a-1,s+(n()<.5?0:1)),o=i.conditions[r],l={};for(const u of i.vars){if(u.kind==="boolean"){l[u.name]=n()<.5;continue}const c=ux(o,u.name).filter(m=>m>=u.min&&m<=u.max);l[u.name]=c.length&&n()<.6?c[Math.floor(n()*c.length)]:u.min+Math.floor(n()*(u.max-u.min+1))}return{condition:o,values:l,answer:hs(o,l)}}function mx(i){return Object.entries(i.values).filter(([e])=>new RegExp(`\\b${e}\\b`).test(i.condition))}const dx=`--- titel: Was ist ein Struktogramm? bereich: Erste Schritte kurz: Algorithmen als Folge klarer Schritte darstellen und lesen. @@ -684,7 +684,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Ein Pfeil > Alles zwischen SOLANGE und ENDE SOLANGE ist eingerückt und wird wiederholt. ::: -`,dx=`--- +`,hx=`--- titel: Der Editor bereich: Erste Schritte kurz: Elemente einfügen, Text eingeben, verschieben und löschen. @@ -700,7 +700,7 @@ kurz: Elemente einfügen, Text eingeben, verschieben und löschen. ## Die Oberfläche -VisuStruct hat zwei Editoren: den [Struktogramm-Editor](#zeige-editor), um den es in dieser Lektion geht, und rechts den Bereich [Programmieren](#zeige-codelive) für Java-Code (ab Lektion 4). Ist der Struktogramm-Editor eingeklappt, öffnet ihn diese Lektion von selbst. Die blauen Wörter zeigen dir die Bereiche, auch wenn sie gerade eingeklappt sind: Fährst du mit der Maus darüber, öffnet sich der Bereich neben dem Lernbereich und leuchtet auf. Klickst du darauf (oder tippst es an), bleibt er offen. +VisuStruct hat zwei Editoren: den [Struktogramm-Editor](#zeige-editor), um den es in dieser Lektion geht, und rechts den Bereich [Code](#zeige-codelive) für Java-Code (ab Lektion 4). Ist der Struktogramm-Editor eingeklappt, öffnet ihn diese Lektion von selbst. Die blauen Wörter zeigen dir die Bereiche, auch wenn sie gerade eingeklappt sind: Fährst du mit der Maus darüber, öffnet sich der Bereich neben dem Lernbereich und leuchtet auf. Klickst du darauf (oder tippst es an), bleibt er offen. Der Struktogramm-Editor besteht aus mehreren Bereichen. Fahre mit der Maus über ein blaues Wort oder tippe es an, dann leuchtet der Bereich im Editor auf, eingeklappte Bereiche wie die Elemente öffnen sich dabei. @@ -710,7 +710,7 @@ Der Struktogramm-Editor besteht aus mehreren Bereichen. Fahre mit der Maus über - **In der Mitte das [Struktogramm](#zeige-struktogramm):** Ein neues Diagramm enthält nur einen leeren Platzhalter, erkennbar an **ø**. - **Unten der [Objektinspektor](#zeige-objektinspektor):** Hier bearbeitest du den Text des ausgewählten Elements. -> Diesen Lernbereich kannst du jederzeit mit dem [Seitenleisten-Symbol](#zeige-lernen) oben in diesem Bereich einklappen. Dann bleibt links nur die schmale Leiste „🎓 Lernen“, ein Klick darauf öffnet ihn wieder. Er bleibt neben dem Editor offen, damit du gleich ausprobieren kannst, was du liest. Genauso gibt es links die Spalte [📁 Dateien](#zeige-dateien) für deine gespeicherten Programme (Lektion 3) und rechts den Bereich [Programmieren](#zeige-codelive) für Java (ab Lektion 4). +> Diesen Lernbereich kannst du jederzeit mit dem [Seitenleisten-Symbol](#zeige-lernen) oben in diesem Bereich einklappen. Dann bleibt links nur die schmale Leiste „🎓 Lernen“, ein Klick darauf öffnet ihn wieder. Er bleibt neben dem Editor offen, damit du gleich ausprobieren kannst, was du liest. Genauso gibt es links die Spalte [📁 Dateien](#zeige-dateien) für deine gespeicherten Programme (Lektion 3) und rechts den Bereich [Code](#zeige-codelive) für Java (ab Lektion 4). ## Ein Element einfügen @@ -870,7 +870,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] input: "Guten Tag" > Ohne Anführungszeichen wird Guten Tag als Name einer Variablen verstanden. ::: -`,hx=`--- +`,gx=`--- titel: Speichern, Öffnen, Exportieren bereich: Erste Schritte kurz: Dateien sichern, deinen Workspace nutzen, mehrere Diagramme öffnen und als Bild oder PDF weitergeben. @@ -1024,7 +1024,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Direkt im Workspace ohne Unterordner > VisuStruct legt für jeden Tag automatisch einen Datumsordner an. So bleiben die Programme nach Stunden sortiert. ::: -`,gx=`--- +`,px=`--- titel: Variablen und Datentypen bereich: Grundlagen kurz: Werte speichern, die Datentypen int, double, String und boolean kennen und rechnen. @@ -1222,14 +1222,14 @@ System.out.println("Größe: " + groesse + " m"); - \`String\` schreibst du groß, \`int\`, \`double\` und \`boolean\` klein. Java unterscheidet das. - Mit \`+\` hängst du Text und Zahlen aneinander. -Java tippst du im Bereich [Programmieren](#zeige-codelive). Das Struktogramm entsteht dabei von selbst. „Im Editor öffnen“ holt das Beispiel in den Bereich Programmieren. Klicke dort auf „Ausführen“, ändere dann Name, Alter oder Größe und probiere es noch einmal. +Java tippst du im Bereich [Code](#zeige-codelive). Das Struktogramm entsteht dabei von selbst. „Im Editor öffnen“ holt das Beispiel in den Bereich Code. Klicke dort auf „Ausführen“, ändere dann Name, Alter oder Größe und probiere es noch einmal. ::: übung l04-java-steckbrief titel: Steckbrief in Java code: java auftrag: Schreibe einen Steckbrief für Ludwig den Geißbock. Lege drei Variablen an: den Namen **Ludwig**, das Alter **7** und die Größe **1.2**. Gib dann diese zwei Zeilen aus: **Ludwig ist 7 Jahre alt.** und **Größe: 1.2 m** - „Im Editor öffnen“ öffnet rechts auch den Bereich Programmieren. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. + „Im Editor öffnen“ öffnet rechts auch den Bereich Code. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. test: - -> Ludwig ist 7 Jahre alt. | Größe: 1.2 m braucht: anweisung tipp: Du brauchst einen \`String\`, einen \`int\` und einen \`double\`. Jede Zeile endet mit einem Semikolon. @@ -1253,7 +1253,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 Programmieren 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 „Java“. ::: ## Fehler finden: Sekunden @@ -1262,7 +1262,7 @@ erklärung: Ganze Zahlen sind \`int\`, Kommazahlen \`double\`, Texte \`String\` titel: Sekunden reparieren code: java auftrag: Das Programm soll 200 Sekunden in Minuten und Sekunden umrechnen und **3 min 20 s** ausgeben. Es gibt aber **20 min 3 s** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l04-java-fehler-start.visustruct test: - -> 3 min 20 s braucht: anweisung @@ -1370,7 +1370,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Double preis = 2.5 > Kommazahlen schreibst du mit Punkt, und am Ende steht ein Semikolon. ::: -`,px=`--- +`,fx=`--- titel: Sequenz bereich: Grundlagen kurz: Schritte nacheinander ausführen, auf die Reihenfolge achten und Werte tauschen. @@ -1472,13 +1472,13 @@ System.out.println("b = " + b); - Am Ende jeder Anweisung steht ein **Semikolon** \`;\`. - Eine Ausgabe heißt in Java \`System.out.println(…)\`. Achte auf das große S bei \`System\`, Java unterscheidet Groß- und Kleinbuchstaben. -Java tippst du im Bereich [Programmieren](#zeige-codelive) rechts neben dem Struktogramm. Während du tippst, baut VisuStruct das Struktogramm mit. So siehst du sofort, welcher Kasten zu welcher Zeile gehört. +Java tippst du im Bereich [Code](#zeige-codelive) rechts neben dem Struktogramm. Während du tippst, baut VisuStruct das Struktogramm mit. So siehst du sofort, welcher Kasten zu welcher Zeile gehört. ::: übung l05-java-kino titel: Kinokarten in Java code: java auftrag: Eine Kinokarte kostet 9 Euro. Schreibe ein Java-Programm, das den Preis für 3 Karten ausrechnet und **Gesamt: 27** ausgibt. - „Im Editor öffnen“ öffnet rechts auch den Bereich Programmieren. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. + „Im Editor öffnen“ öffnet rechts auch den Bereich Code. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. test: - -> Gesamt: 27 braucht: anweisung tipp: Du brauchst drei Variablen: den Preis, die Anzahl und das Ergebnis. Jede Zeile endet mit einem Semikolon. @@ -1508,7 +1508,7 @@ erklärung: Erst rettest du \`a\` in die Hilfsvariable, dann bekommt \`a\` den W titel: Guthaben reparieren code: java auftrag: Auf der Mensakarte sind 20 Euro. Ein Essen kostet 7 Euro. Das Programm soll das Guthaben **nach** dem Bezahlen ausgeben, also **Übrig: 13**. Es gibt aber **Übrig: 20** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l05-java-fehler-start.visustruct test: - -> Übrig: 13 braucht: anweisung @@ -1607,7 +1607,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Mit einem Doppelpunkt : > Fehlt das Semikolon, zeigt VisuStruct unter dem Code einen Hinweis. ::: -`,fx=`--- +`,bx=`--- titel: Eingabe und Ausgabe bereich: Grundlagen kurz: Werte abfragen, Ergebnisse anzeigen und das EVA-Prinzip anwenden. @@ -1801,7 +1801,7 @@ erklärung: \`scanner.next()\` liest ein Wort, \`scanner.nextInt()\` eine ganze titel: Summe reparieren code: java auftrag: Das Programm liest zwei Zahlen ein und soll ihre Summe ausgeben. Bei 3 und 4 erscheint aber **Summe: 34** statt **Summe: 7**. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l06-java-fehler-start.visustruct test: 3, 4 -> Summe: 7 test: 10, 5 -> Summe: 15 @@ -1938,7 +1938,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Einen ganzen Satz > Für Kommazahlen gibt es \`scanner.nextDouble()\`, für ein Wort \`scanner.next()\`. ::: -`,bx=`--- +`,xx=`--- titel: Simulation und Schreibtischtest bereich: Grundlagen kurz: Ein Struktogramm Schritt für Schritt ausführen, von Hand nachrechnen und Fehler finden. @@ -1981,7 +1981,7 @@ Die Werte von a und b werden vertauscht. Die Variable hilf merkt sich dabei eine - **Variablen:** Alle Variablen mit ihren aktuellen Werten. - **Ausgabe:** Alles, was mit \`output:\` ausgegeben wurde. -Ist rechts der Bereich [Programmieren](#zeige-codelive) geöffnet, läuft dort zusätzlich die [Konsole](#zeige-konsole) mit. Sie wird beim Start geleert und zeigt dann die Ausgaben und Eingaben so, wie sie auch beim echten Programm erscheinen würden. +Ist rechts der Bereich [Code](#zeige-codelive) geöffnet, läuft dort zusätzlich die [Konsole](#zeige-konsole) mit. Sie wird beim Start geleert und zeigt dann die Ausgaben und Eingaben so, wie sie auch beim echten Programm erscheinen würden. Am Ende erscheint **Simulation beendet**. Geht etwas schief, bleibt die Simulation auf dem fehlerhaften Kasten stehen und zeigt eine Meldung, z. B. **Unbekannte Variable: gesamt**. @@ -2062,7 +2062,7 @@ lösung: sim-kino-loesung.visustruct ## Jetzt in Java -Auch Java-Code kannst du Schritt für Schritt ausführen. Im Bereich [Programmieren](#zeige-codelive) heißt das Werkzeug dafür **Debugger**: +Auch Java-Code kannst du Schritt für Schritt ausführen. Im Bereich [Code](#zeige-codelive) heißt das Werkzeug dafür **Debugger**: - Klicke links auf eine Zeilennummer. Ein roter Punkt erscheint, das ist ein **Haltepunkt**. [▶︎ Ausführen](#zeige-ausfuehren) hält vor dieser Zeile an. - Der Knopf [Einzelschritt](#zeige-einzelschritt) führt genau eine Zeile aus, wie **Schritt** in der Simulation. @@ -2094,7 +2094,7 @@ b = a * 2; // b ist jetzt [[14]] a = b - a; // a ist jetzt [[7]] System.out.println(a + b); // Ausgabe: [[21]] \`\`\` -erklärung: Jede Zeile rechnet mit den Werten, die gerade in den Variablen stehen: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, Ausgabe 7 + 14 = 21. Mit dem Einzelschritt im Bereich Programmieren kannst du es nachprüfen. +erklärung: Jede Zeile rechnet mit den Werten, die gerade in den Variablen stehen: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, Ausgabe 7 + 14 = 21. Mit dem Einzelschritt im Bereich Code kannst du es nachprüfen. ::: ## Fehler finden: Spielstand @@ -2226,14 +2226,14 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] summe ist zu groß. - [ ] Das Struktogramm hat zu viele Kästen. -? Was macht ein roter Punkt vor einer Zeilennummer im Bereich Programmieren? +? Was macht ein roter Punkt vor einer Zeilennummer im Bereich Code? → Jetzt in Java - [ ] Er markiert einen Fehler. - [x] Das Programm hält vor dieser Zeile an. - [ ] Die Zeile wird übersprungen. > Das ist ein Haltepunkt. Mit ▶︎ oder dem Einzelschritt geht es weiter. ::: -`,xx=`--- +`,vx=`--- titel: Verzweigung bereich: Grundlagen kurz: Mit einer Bedingung entscheiden, welcher von zwei Wegen ausgeführt wird. @@ -2365,7 +2365,7 @@ Java hat auch ein Maskottchen: **Duke**, ein kleiner schwarz-weißer Kerl mit gr titel: Bestanden in Java code: java auftrag: Schreibe ein Java-Programm, das nach der Punktzahl fragt. Ab 50 Punkten gibt es **bestanden** aus, sonst **nicht bestanden**. - Tippe den Code im Bereich Programmieren und klicke dann auf Prüfen. + Tippe den Code im Bereich Code und klicke dann auf Prüfen. test: 50 -> bestanden test: 49 -> nicht bestanden test: 100 -> bestanden @@ -2402,7 +2402,7 @@ erklärung: \`zahl % 2\` ist der Rest beim Teilen durch 2. Ist er 0, ist die Zah titel: Eintritt reparieren code: java auftrag: Im Zoo haben Kinder **unter** 6 Jahren freien Eintritt, alle anderen zahlen 4 Euro. Das Programm lässt aber auch Sechsjährige umsonst hinein. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l08-java-fehler-start.visustruct test: 5 -> Eintritt frei test: 6 -> 4 Euro @@ -2568,7 +2568,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Hinter einem Semikolon > \`if (alter >= 18) { … }\`: Die runden Klammern gehören zur Bedingung, die geschweiften zum Zweig. ::: -`,vx=`--- +`,yx=`--- titel: Bedingungen verknüpfen bereich: Grundlagen kurz: Mehrere Bedingungen mit und, oder und nicht verbinden und Wertebereiche prüfen. @@ -2817,7 +2817,7 @@ erklärung: Eine Note ist gültig, wenn **beide** Bedingungen stimmen, also \`&& titel: Schulfrei reparieren code: java auftrag: Das Programm soll bei Tag 6 (Samstag) und Tag 7 (Sonntag) **schulfrei** ausgeben, sonst **Schule**. Es gibt aber immer **Schule** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l09-java-fehler-start.visustruct test: 6 -> schulfrei test: 7 -> schulfrei @@ -2880,7 +2880,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] if (alter >= 12 || alter < 18) > Jeder Vergleich steht für sich, verbunden mit \`&&\`. ::: -`,yx=`--- +`,wx=`--- titel: Fallauswahl bereich: Grundlagen kurz: Je nach Wert einer Variablen einen von vielen Fällen ausführen. @@ -3053,7 +3053,7 @@ erklärung: Nach \`switch\` steht die Variable in runden Klammern. Jeder Fall be titel: Rechner reparieren code: java auftrag: Der Rechner liest zwei Zahlen und eine Wahl ein: 1 plus, 2 minus, 3 mal. Bei 7, 3 und Wahl 2 soll **4** herauskommen, er rechnet aber **-4**. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l10-java-fehler-start.visustruct test: 7, 3, 2 -> 4 test: 7, 3, 1 -> 10 @@ -3194,7 +3194,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [x] default - [ ] case 0 ::: -`,wx=`--- +`,zx=`--- titel: While-Schleife bereich: Grundlagen kurz: Schritte wiederholen, solange eine Bedingung wahr ist. @@ -3538,7 +3538,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] while (zahl > 0); > Die Bedingung steht in runden Klammern, danach öffnet \`{\` den Rumpf. ::: -`,zx=`--- +`,Ix=`--- titel: Do-while-Schleife bereich: Grundlagen kurz: Erst ausführen, dann prüfen: Schleifen mit mindestens einem Durchlauf. @@ -3672,7 +3672,7 @@ erklärung: Der Rumpf steht zwischen \`do {\` und \`}\`, die Bedingung erst dana titel: Halbieren reparieren code: java auftrag: Das Programm liest eine Startzahl ein und teilt sie mit einer Do-while-Schleife immer wieder ganzzahlig durch 2. Jedes Ergebnis wird ausgegeben, bis **0** erreicht ist. Bei 10 also 5, 2, 1 und 0. Die 0 fehlt aber. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l12-java-fehler-start.visustruct test: 10 -> 5 | 2 | 1 | 0 test: 1 -> 0 @@ -3801,7 +3801,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] } until (bedingung); > Nach der Bedingung kommt ein Semikolon. ::: -`,Ix=`--- +`,kx=`--- titel: For-Schleife bereich: Grundlagen kurz: Mit Start, Bedingung und Schritt eine feste Anzahl von Durchläufen zählen. @@ -3972,7 +3972,7 @@ erklärung: In den runden Klammern stehen Startwert, Bedingung und Schritt, getr titel: Einmaleins reparieren code: java auftrag: Das Programm fragt nach einer Reihe und soll sie vom 1-fachen bis zum 10-fachen ausgeben, bei 7 also 7, 14, … bis 70. Die 70 fehlt aber. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l13-java-fehler-start.visustruct test: 7 -> 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 test: 3 -> 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 @@ -4113,7 +4113,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] i wird ausgegeben. > \`i++\` ist die Kurzform von \`i = i + 1\`. ::: -`,kx=`--- +`,Sx=`--- titel: Verschachteln bereich: Grundlagen kurz: Verzweigungen in Schleifen und Schleifen in Schleifen kombinieren. @@ -4217,7 +4217,7 @@ for (int i = 1; i <= n; i++) { System.out.println(anzahl); \`\`\` -Was im Struktogramm ineinander steckt, steht in Java in geschweiften Klammern ineinander. Jede Ebene ist vier Leerzeichen weiter eingerückt. Ist dein Code durcheinander, hilft der Knopf **Einrücken** oben im Bereich Programmieren. +Was im Struktogramm ineinander steckt, steht in Java in geschweiften Klammern ineinander. Jede Ebene ist vier Leerzeichen weiter eingerückt. Ist dein Code durcheinander, hilft der Knopf **Einrücken** oben im Bereich Code. \`anzahl++\` ist die Kurzform von \`anzahl = anzahl + 1\`. @@ -4257,7 +4257,7 @@ erklärung: Die innere Schleife baut eine Zeile aus 4 Sternchen, die äußere wi titel: Zählen reparieren code: java auftrag: Das Programm soll zählen, wie viele Zahlen von 1 bis \`n\` durch 3 teilbar sind, und **einmal** das Ergebnis ausgeben. Bei 10 also nur **Anzahl: 3**. Es gibt aber viel zu viele Zeilen aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l14-java-fehler-start.visustruct test: 10 -> Anzahl: 3 test: 3 -> Anzahl: 1 @@ -4394,7 +4394,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [x] An den geschweiften Klammern und der Einrückung - [ ] An den Semikolons ::: -`,Sx=`--- +`,Tx=`--- titel: Arrays bereich: Grundlagen kurz: Viele Werte unter einem Namen speichern, mit dem Index darauf zugreifen und sie mit einer Schleife durchlaufen. @@ -4587,7 +4587,7 @@ erklärung: \`int[]\` ist ein Array aus ganzen Zahlen, \`werte.length\` seine L titel: Höchste Temperatur reparieren code: java auftrag: Im Januar wurden die Temperaturen -5, -2, -8 und -3 Grad gemessen. Das Programm soll die höchste ausgeben, also **Höchste Temperatur: -2**. Es behauptet aber 0 Grad, obwohl es so warm nie war. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l15-java-fehler-start.visustruct test: - -> Höchste Temperatur: -2 braucht: forSchleife, verzweigung @@ -4722,7 +4722,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] int zahlen = [1, 2, 3]; - [ ] array zahlen = (1, 2, 3); ::: -`,Tx=`--- +`,_x=`--- titel: Zweidimensionale Arrays bereich: Grundlagen kurz: Werte in Zeilen und Spalten speichern, wie die Sitze in einem Kinosaal, und mit zwei verschachtelten Schleifen durchlaufen. @@ -4893,7 +4893,7 @@ erklärung: \`int[][]\` ist eine Tabelle. \`feld.length\` ist die Zahl der Reihe titel: Spieler 2 reparieren code: java auftrag: In der Tabelle \`punkte\` steht jede Reihe für einen Spieler. Das Programm soll die Punkte von Spieler 2 (Reihe 1) zusammenzählen, also **Spieler 2: 11**. Stattdessen meldet es einen Fehler. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l16-java-fehler-start.visustruct test: - -> Spieler 2: 11 braucht: forSchleife @@ -5024,7 +5024,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] 5, die Zahl der Plätze - [ ] 15, alle Plätze zusammen ::: -`,_x=`--- +`,Ox=`--- titel: Zeichenketten bereich: Grundlagen kurz: Mit Texten arbeiten, also einzelne Zeichen lesen, Teile herausschneiden, suchen, vergleichen und zerlegen. @@ -5248,7 +5248,7 @@ erklärung: \`length()\` zählt die Zeichen, \`toUpperCase()\` macht alles groß titel: Initialen reparieren code: java auftrag: Das Programm liest Vor- und Nachnamen ein und soll die Initialen ausgeben. Bei Ludwig Geißbock also **L. G.** Es gibt aber **u. e.** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l17-java-fehler-start.visustruct test: Ludwig, Geißbock -> L. G. test: Mia, Meyer -> M. M. @@ -5535,7 +5535,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] eine Fehlermeldung > parseInt macht aus dem Text eine Zahl. Danach rechnet Java ganz normal. ::: -`,Ox=`--- +`,Ax=`--- titel: Aufruf und Aussprung bereich: Grundlagen kurz: Große Aufgaben in Unterprogramme zerlegen und Schleifen vorzeitig verlassen. @@ -5765,7 +5765,7 @@ System.out.println("Das Quadrat ist " + q); - In der Kopfzeile steht vor dem Namen, was die Methode zurückgibt (\`int\`). Gibt sie nichts zurück, steht dort \`void\`. - Die Parameter stehen mit Datentyp in den runden Klammern: \`(int x)\`. Mehrere trennst du mit Komma. -- Im Bereich Programmieren schreibst du jede Methode in einen eigenen Reiter, so wie jedes Unterprogramm ein eigenes Struktogramm hat. +- Im Bereich Code schreibst du jede Methode in einen eigenen Reiter, so wie jedes Unterprogramm ein eigenes Struktogramm hat. - Der Aussprung heißt in Java \`break\`. Mit \`while (true)\` baust du eine Schleife, die nur durch \`break\` endet. ::: übung l18-java-kasse @@ -5786,7 +5786,7 @@ lösung: l18-java-kasse-loesung.visustruct ::: lückentext titel: Methode und Aussprung -auftrag: Ergänze die fehlenden Wörter. Oben steht die Methode, die ein Quadrat ausrechnet. Darunter steht das Hauptprogramm, das sie aufruft. Im Bereich Programmieren stehen beide in eigenen Reitern. +auftrag: Ergänze die fehlenden Wörter. Oben steht die Methode, die ein Quadrat ausrechnet. Darunter steht das Hauptprogramm, das sie aufruft. Im Bereich Code stehen beide in eigenen Reitern. \`\`\`java public static [[int]] quadrat(int x) { [[return]] x * x; @@ -5812,7 +5812,7 @@ erklärung: \`int\` vor dem Methodennamen heißt: Die Methode gibt eine ganze Za titel: Versuche zählen reparieren code: java auftrag: Beim Zahlenraten ist die gesuchte Zahl 7. Das Programm fragt so lange nach einem Tipp, bis die 7 kommt, und gibt dann die Zahl der Versuche aus. Bei 3, 5 und 7 waren es 3 Versuche, das Programm sagt aber **Versuche: 2**. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l18-java-fehler-start.visustruct test: 3, 5, 7 -> Versuche: 3 test: 7 -> Versuche: 1 @@ -6018,7 +6018,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] return > void heißt „leer“: Die Methode macht etwas, gibt aber keinen Wert zurück. ::: -`,Ax=`--- +`,Cx=`--- titel: Suchen und Sortieren bereich: Grundlagen kurz: Mit Spielkarten verstehen, wie lineare und binäre Suche und Bubblesort arbeiten und warum manche Verfahren viel schneller sind. @@ -6209,7 +6209,7 @@ erklärung: Ist eine Karte größer als ihre rechte Nachbarin, werden die beiden titel: Lineare Suche reparieren code: java auftrag: Die Karten {8, 4, 11, 4, 6} liegen in einem Array. Das Programm soll die **erste** Position der gesuchten Karte ausgeben, bei 4 also **Position: 1**. Es gibt aber **Position: 3** aus. - „Im Editor öffnen“ zeigt den Code im Bereich Programmieren. Finde den Fehler, repariere ihn und klicke auf Prüfen. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. start: l19-java-fehler-start.visustruct test: 4 -> Position: 1 test: 6 -> Position: 4 @@ -6354,10 +6354,10 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Eine While-Schleife kann keine Arrays durchlaufen. > Die Karte kann mehrmals vorkommen. Darum gehst du alle Karten bis zum Ende durch. ::: -`,Cx=`--- +`,jx=`--- titel: Struktogramm und Code bereich: Vom Struktogramm zum Code -kurz: Alle Elemente in Java auf einen Blick, Code erzeugen, im Bereich Programmieren Java schreiben, ausführen und Fehler suchen. +kurz: Alle Elemente in Java auf einen Blick, Code erzeugen, im Bereich Code Java schreiben, ausführen und Fehler suchen. --- ## Diese Kompetenzen erwerbe ich jetzt @@ -6367,7 +6367,7 @@ kurz: Alle Elemente in Java auf einen Blick, Code erzeugen, im Bereich Programmi - Ausgabe, Eingabe, Verzweigung und Schleifen in Java erkennen - den Unterschied zwischen Snippet und Class erklären - ein kurzes Java-Programm als Struktogramm nachbauen -- im Bereich Programmieren Java tippen und das entstehende Struktogramm lesen +- im Bereich Code Java tippen und das entstehende Struktogramm lesen - ein Programm mit ▶︎ ausführen und Ein- und Ausgaben in der Konsole nutzen - Haltepunkte setzen und ein Programm im Einzelschritt verfolgen ::: @@ -6474,25 +6474,25 @@ Das hilft dir, die Kästen und die Java-Befehle einander zuzuordnen. Dein Diagra ## Java direkt schreiben -Bisher hast du zuerst das Struktogramm gezeichnet und dann den Code angesehen. Im Bereich [Programmieren](#zeige-codelive) geht es auch andersherum. Klicke rechts auf die schmale Leiste **Programmieren**. Neben dem Struktogramm erscheint eine Spalte, in die du Java selbst tippst. +Bisher hast du zuerst das Struktogramm gezeichnet und dann den Code angesehen. Im Bereich [Code](#zeige-codelive) geht es auch andersherum. Klicke rechts auf die schmale Leiste **Code**. Neben dem Struktogramm erscheint eine Spalte, in die du Java selbst tippst. - **Struktogramm zu Code:** Änderst du etwas im Struktogramm, ändert sich der Java-Code sofort mit. - **Code zu Struktogramm:** Tippst du Java, baut VisuStruct beim Tippen das Struktogramm dazu. Fehlt noch etwas, zum Beispiel eine schließende Klammer \`}\`, steht unter dem Code ein Hinweis. - **Vorschläge:** Beim Tippen schlägt VisuStruct Vorlagen vor, etwa für \`if\`, \`for\` oder \`while\`. Mit der Eingabetaste übernimmst du eine Vorlage. Grau geschriebene Platzhalter ersetzt du einfach durch deinen Text. -- **Einrücken:** Ist dein Code durcheinandergeraten, klicke oben im Bereich Programmieren auf den Knopf **Einrücken**. Jede Ebene steht dann vier Leerzeichen tiefer, wie in Eclipse oder IntelliJ. Hast du Zeilen markiert, rückt VisuStruct nur diese ein. +- **Einrücken:** Ist dein Code durcheinandergeraten, klicke oben im Bereich Code auf den Knopf **Einrücken**. Jede Ebene steht dann vier Leerzeichen tiefer, wie in Eclipse oder IntelliJ. Hast du Zeilen markiert, rückt VisuStruct nur diese ein. So kannst du beide Wege ausprobieren. Erst das Struktogramm zeichnen ist gut, um einen Ablauf zu planen. Direkt Code schreiben ist schneller, wenn du schon weißt, was du willst. Das Struktogramm hilft dir dann, deinen Code zu kontrollieren. ## Das Programm ausführen -Oben im Bereich Programmieren startet [▶︎ Ausführen](#zeige-ausfuehren) dein Programm, **■ Stopp** bricht es ab, zum Beispiel bei einer Endlosschleife. Was dein Programm ausgibt, erscheint unten in der [Konsole](#zeige-konsole). Fragt es nach einer Eingabe, tippst du sie dort ein und drückst die Eingabetaste. +Oben im Bereich Code startet [▶︎ Ausführen](#zeige-ausfuehren) dein Programm, **■ Stopp** bricht es ab, zum Beispiel bei einer Endlosschleife. Was dein Programm ausgibt, erscheint unten in der [Konsole](#zeige-konsole). Fragt es nach einer Eingabe, tippst du sie dort ein und drückst die Eingabetaste. Die Grenze zwischen Code und Konsole kannst du mit der Maus nach oben oder unten ziehen. -> Der Bereich Programmieren versteht die Java-Befehle, die es auch als Kasten im Struktogramm gibt. Eigene Klassen und Objekte kennt es noch nicht. Fenster mit Swing gehen trotzdem: Schalte dafür im Zahnrad **Echtes Java (mit Swing)** ein (Lektion „Dein erstes Fenster“). +> Der Bereich Code versteht die Java-Befehle, die es auch als Kasten im Struktogramm gibt. Eigene Klassen und Objekte kennt es noch nicht. Fenster mit Swing gehen trotzdem: Schalte dafür im Zahnrad **Echtes Java (mit Swing)** ein (Lektion „Dein erstes Fenster“). ::: angeberwissen -Profis nennen ein Programm, in dem man Code schreibt, ausführt und Fehler sucht, eine **IDE** (Integrated Development Environment). Mit dem Bereich Programmieren ist VisuStruct eine kleine IDE mit eingebautem Struktogramm. +Profis nennen ein Programm, in dem man Code schreibt, ausführt und Fehler sucht, eine **IDE** (Integrated Development Environment). Mit dem Bereich Code ist VisuStruct eine kleine IDE mit eingebautem Struktogramm. ::: ## Fehler suchen mit dem Debugger @@ -6521,7 +6521,7 @@ Das ist ein Schreibtischtest, nur dass der Computer für dich mitschreibt. Über ## Übung: Erst Code, dann Struktogramm -Diesmal zeichnest du nicht. Öffne den Bereich Programmieren und tippe diesen Java-Code ab: +Diesmal zeichnest du nicht. Öffne den Bereich Code und tippe diesen Java-Code ab: \`\`\` System.out.println("Startzahl?"); @@ -6535,13 +6535,14 @@ System.out.println("Start!"); ::: übung l20-countdown titel: Countdown -auftrag: Tippe den Java-Code oben im Bereich Programmieren ab. Führe ihn mit ▶︎ aus und gib in der Konsole eine Startzahl ein. +bereich: beide +auftrag: Tippe den Java-Code oben im Bereich Code ab. Führe ihn mit ▶︎ aus und gib in der Konsole eine Startzahl ein. Sieh dir dann das Struktogramm an, das dabei entstanden ist, und klicke auf Prüfen. test: 3 -> 3 | 2 | 1 | Start! test: 1 -> 1 | Start! test: 0 -> Start! braucht: whileSchleife -tipp: Öffne den Bereich Programmieren mit der schmalen Leiste ganz rechts und tippe einfach los. +tipp: Öffne den Bereich Code mit der schmalen Leiste ganz rechts und tippe einfach los. tipp: Achte auf das Semikolon am Ende jeder Anweisung und auf die geschweiften Klammern der While-Schleife. Unter dem Code steht ein Hinweis, wenn noch etwas fehlt. lösung: l20-countdown-loesung.visustruct ::: @@ -6562,6 +6563,7 @@ System.out.println(fakultaet); ::: übung l17-fakultaet titel: Fakultät aus Java +bereich: beide auftrag: Baue den Java-Code oben als Struktogramm nach. Das Programm liest eine Zahl n ein und gibt das Produkt 1 · 2 · … · n aus. Kontrolliere am Ende in der Code-Ansicht, ob dein Java-Code genauso aussieht. test: 3 -> 6 @@ -6681,7 +6683,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann Ausgabe, Eingabe, Verzweigung und Schleifen in Java erkennen. → Die Elemente in Java - Ich kann den Unterschied zwischen Snippet und Class erklären. → Snippet oder Class - Ich kann ein kurzes Java-Programm als Struktogramm nachbauen. → Übung: Java als Struktogramm -- Ich kann im Bereich Programmieren Java tippen und das entstehende Struktogramm lesen. → Java direkt schreiben +- Ich kann im Bereich Code Java tippen und das entstehende Struktogramm lesen. → Java direkt schreiben - Ich kann ein Programm mit ▶︎ ausführen und Ein- und Ausgaben in der Konsole nutzen. → Das Programm ausführen - Ich kann Haltepunkte setzen und ein Programm im Einzelschritt verfolgen. → Fehler suchen mit dem Debugger ::: @@ -6961,7 +6963,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Es wird Summe: ausgegeben. > Mit str(summe) wird aus der Zahl ein Text. ::: -`,jx=`--- +`,Dx=`--- titel: Wenn das Programm abstürzt: try und catch bereich: Fehler abfangen kurz: Mit echtem Java Fehlermeldungen lesen und Abstürze mit try und catch abfangen. @@ -6970,7 +6972,7 @@ kurz: Mit echtem Java Fehlermeldungen lesen und Abstürze mit try und catch abfa ## Diese Kompetenzen erwerbe ich jetzt ::: kompetenzen -- echtes Java im Bereich Programmieren einschalten +- echtes Java im Bereich Code einschalten - aus einer Fehlermeldung die Exception und die Zeile ablesen - eine Exception mit try und catch auffangen - Text mit Integer.parseInt in eine Zahl umwandeln und die NumberFormatException abfangen @@ -6979,7 +6981,7 @@ kurz: Mit echtem Java Fehlermeldungen lesen und Abstürze mit try und catch abfa ## Abgestürzt! -Dieses Programm soll drei Noten ausgeben. Tippe es im Bereich [Programmieren](#zeige-codelive) ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): +Dieses Programm soll drei Noten ausgeben. Tippe es im Bereich [Code](#zeige-codelive) ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): \`\`\`java int[] noten = {2, 3, 1}; @@ -7000,7 +7002,7 @@ Ist dir das auch schon passiert? Ein kleiner Fehler, und das ganze Programm ist ## Echtes Java einschalten -Der Bereich Programmieren rechnet normalerweise mit derselben Simulation wie das Struktogramm. Die hält bei einem Fehler einfach an. Um zu sehen, was echtes Java macht, schaltest du echtes Java ein: +Der Bereich Code rechnet normalerweise mit derselben Simulation wie das Struktogramm. Die hält bei einem Fehler einfach an. Um zu sehen, was echtes Java macht, schaltest du echtes Java ein: 1. Klicke oben rechts auf das [Zahnrad](#zeige-einstellungen) und wähle als **Programmiersprache** Java. 2. Setze im Abschnitt Java den Haken bei **Echtes Java (mit Swing)**. @@ -7043,7 +7045,7 @@ So eine Meldung sieht erst einmal erschreckend aus. Sie verrät dir aber genau, So einen Fehler zur Laufzeit nennt Java eine **Exception** (englisch für Ausnahme). Man sagt: Java *wirft* eine Exception. Fängt sie niemand auf, bricht das Programm ab. Deshalb erscheint „Fertig!“ nicht. ::: ludwig -Lies Fehlermeldungen immer von oben: Erst der Name der Exception, dann die Zeilennummer. Die Zeilennummern stehen im Bereich Programmieren links neben dem Code. +Lies Fehlermeldungen immer von oben: Erst der Name der Exception, dann die Zeilennummer. Die Zeilennummern stehen im Bereich Code links neben dem Code. ::: ## try und catch @@ -7208,7 +7210,7 @@ Die Exception heißt \`ArithmeticException\`. Schreib in den \`try\`-Block nur d 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. ::: checkliste -- Ich kann echtes Java im Bereich Programmieren einschalten. → Echtes Java einschalten +- Ich kann echtes Java im Bereich Code einschalten. → Echtes Java einschalten - Ich kann aus einer Fehlermeldung die Exception und die Zeile ablesen. → Die Fehlermeldung lesen - Ich kann eine Exception mit try und catch auffangen. → try und catch - Ich kann Text mit Integer.parseInt in eine Zahl umwandeln und die NumberFormatException abfangen. → Text in eine Zahl umwandeln @@ -7244,7 +7246,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = ArithmeticException -> Teilen durch 0 = NumberFormatException -> Text ist keine Zahl ::: -`,Dx=`--- +`,Bx=`--- titel: Text einlesen und speichern bereich: Dateien kurz: Mit Scanner eine Textdatei Zeile für Zeile lesen und mit PrintWriter eine Datei speichern. @@ -7498,7 +7500,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = println(text) -> schreibt eine Zeile = close() -> schließt die Datei ::: -`,Bx=`--- +`,Zx=`--- titel: Zeile für Zeile mit BufferedReader bereich: Dateien kurz: Mit BufferedReader und readLine lesen, bis null kommt, und mit Files eine ganze Datei auf einmal lesen. @@ -7754,7 +7756,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = Files.readString -> kleine Dateien auf einmal = Scanner -> Zahlen und Wörter lesen ::: -`,Zx=`--- +`,Mx=`--- titel: Tabellen als CSV bereich: Dateien kurz: Eine Tabelle als CSV-Datei lesen, jede Zeile mit split zerlegen und mit den Zahlen rechnen. @@ -7978,7 +7980,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = Datensatz -> eine Zeile mit Werten = Trennzeichen -> trennt die Spalten, meist ; ::: -`,Mx=`--- +`,Lx=`--- titel: Daten als JSON bereich: Dateien kurz: JSON-Dateien verstehen, Werte mit indexOf und substring herausholen und selbst JSON schreiben. @@ -8203,7 +8205,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = [ ] -> eine Liste = : -> trennt Schlüssel und Wert ::: -`,Lx=`--- +`,Ex=`--- titel: Formate im Vergleich bereich: Dateien kurz: Dieselben Daten als txt, CSV und JSON vergleichen, das passende Format wählen und eine Datei in ein anderes Format umwandeln. @@ -8378,7 +8380,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = die Notenliste der Klasse -> CSV = ein Spielstand mit Listen -> JSON ::: -`,Ex=`--- +`,Wx=`--- titel: Dein erstes Fenster bereich: Fenster mit Swing kurz: Mit Java und Swing ein eigenes Fenster öffnen, Zeile für Zeile erklärt. @@ -8387,7 +8389,7 @@ kurz: Mit Java und Swing ein eigenes Fenster öffnen, Zeile für Zeile erklärt. ## Diese Kompetenzen erwerbe ich jetzt ::: kompetenzen -- im Bereich Programmieren „Echtes Java“ einschalten +- im Bereich Code „Echtes Java“ einschalten - ein Fenster mit Titel und Größe öffnen - erklären, was jede Zeile des Fensterprogramms macht - erklären, warum setVisible(true) am Ende steht @@ -8399,11 +8401,11 @@ Bisher haben deine Programme Text in die Konsole geschrieben. Die meisten Progra Java bringt dafür einen Werkzeugkasten mit: **Swing**. In VisuStruct schaltest du ihn so ein: -1. Öffne rechts den Bereich [Programmieren](#zeige-codelive). +1. Öffne rechts den Bereich [Code](#zeige-codelive). 2. Klicke oben rechts auf das [Zahnrad](#zeige-einstellungen) und wähle als **Programmiersprache** Java. 3. Setze darunter im Abschnitt Java den Haken bei **Echtes Java (mit Swing)**. -Beim ersten [▶︎ Ausführen](#zeige-ausfuehren) lädt VisuStruct einmalig etwa 40 MB, das dauert einen Moment. Danach läuft dein Code als echtes Java, und deine Fenster erscheinen im Bereich Programmieren im Feld **Java-Fenster** über der Konsole. +Beim ersten [▶︎ Ausführen](#zeige-ausfuehren) lädt VisuStruct einmalig etwa 40 MB, das dauert einen Moment. Danach läuft dein Code als echtes Java, und deine Fenster erscheinen im Bereich Code im Feld **Java-Fenster** über der Konsole. > Mit „Echtes Java“ funktionieren Eingaben über die Konsole (\`Scanner\`) noch nicht. Für Programme mit Eingabe schaltest du den Haken wieder aus. @@ -8413,7 +8415,7 @@ Swing gibt es seit 1998. Davor hatte Java nur das ältere AWT mit einer Klasse \ ## Das ganze Programm -So sieht das kleinste Programm aus, das ein Fenster öffnet. Tippe es im Bereich Programmieren ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): +So sieht das kleinste Programm aus, das ein Fenster öffnet. Tippe es im Bereich Code ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): \`\`\`java import javax.swing.*; @@ -8557,7 +8559,7 @@ frage: Was siehst du? Führe es aus und prüfe alle drei Punkte. ::: ludwig -Du willst nicht so viel tippen? Mit „Echtes Java“ darfst du im Bereich Programmieren auch nur die vier Zeilen aus \`main\` schreiben. VisuStruct packt sie dann selbst in eine Klasse und ergänzt die \`import\`-Zeilen. In einer richtigen Java-Entwicklungsumgebung brauchst du aber das ganze Programm. +Du willst nicht so viel tippen? Mit „Echtes Java“ darfst du im Bereich Code auch nur die vier Zeilen aus \`main\` schreiben. VisuStruct packt sie dann selbst in eine Klasse und ergänzt die \`import\`-Zeilen. In einer richtigen Java-Entwicklungsumgebung brauchst du aber das ganze Programm. ::: ## Checkliste @@ -8565,7 +8567,7 @@ Du willst nicht so viel tippen? Mit „Echtes Java“ darfst du im Bereich Progr 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. ::: checkliste -- Ich kann im Bereich Programmieren „Echtes Java“ einschalten. → Programme mit Fenstern +- Ich kann im Bereich Code „Echtes Java“ einschalten. → Programme mit Fenstern - Ich kann ein Fenster mit Titel und Größe öffnen. → Das ganze Programm - Ich kann erklären, was jede Zeile des Fensterprogramms macht. → Zeile für Zeile - Ich kann erklären, warum setVisible(true) am Ende steht. → Warum setVisible am Ende steht @@ -8600,7 +8602,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Sie stehen in geschweiften Klammern. - [ ] Sie enden mit Window. ::: -`,Wx=`--- +`,Nx=`--- titel: Ein Knopf im Fenster bereich: Fenster mit Swing kurz: Einen Knopf ins Fenster legen und mit einem Layout ordentlich anordnen. @@ -8816,7 +8818,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Auf dem Knopf steht „Ich wurde geklickt“. > Was beim Klick passieren soll, lernst du in der nächsten Lektion. ::: -`,Nx=`--- +`,Fx=`--- titel: Der Knopf reagiert bereich: Fenster mit Swing kurz: Mit einem ActionListener festlegen, was beim Klick passiert. @@ -9158,7 +9160,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = setText -> Beschriftung ändern = setVisible(true) -> Fenster zeigen ::: -`,Fx=`--- +`,Jx=`--- titel: Zahl verdoppeln im Fenster bereich: Fenster mit Swing kurz: Beschriftung, Textfeld und Knopf mit einem GridLayout anordnen und mit dem Text im Textfeld rechnen. @@ -9439,7 +9441,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = JButton -> Knopf = GridLayout -> Anordnung im Gitter ::: -`,Jx=`--- +`,Rx=`--- titel: Klickzähler mit Reset bereich: Fenster mit Swing kurz: Zwei Knöpfe ändern dieselbe Zahl: eine Variable für die ganze Klasse anlegen. @@ -9671,7 +9673,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Es setzt das Fenster in die Mitte des Bildschirms. - [ ] Es macht die Schrift größer. ::: -`,Rx=`--- +`,Gx=`--- titel: Eine Ampel mit Farben bereich: Fenster mit Swing kurz: Hintergrundfarben setzen und mit einer Zustandsvariable eine Ampel weiterschalten. @@ -9947,7 +9949,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] 3 > Nach phase++ ist sie 3, das ist größer als 2, also wird sie 0. ::: -`,Gx=`--- +`,Hx=`--- titel: Notenrechner im Fenster bereich: Fenster mit Swing kurz: Punkte eingeben, mit else if die Note bestimmen und falsche Eingaben abfangen. @@ -10006,7 +10008,7 @@ if (punkte >= 92) { Bei 85 Punkten ist \`punkte >= 92\` falsch, aber \`punkte >= 81\` wahr. Also Note 2, und die restlichen Bedingungen werden gar nicht mehr geprüft. Deshalb reicht jeweils die untere Grenze. ::: -Du kannst diesen Teil ohne Fenster im Bereich [Programmieren](#zeige-codelive) ausprobieren. Schreib \`int punkte = 85;\` davor und \`System.out.println("Note: " + note);\` dahinter. Das Struktogramm zeigt dir die verschachtelten Verzweigungen. +Du kannst diesen Teil ohne Fenster im Bereich [Code](#zeige-codelive) ausprobieren. Schreib \`int punkte = 85;\` davor und \`System.out.println("Note: " + note);\` dahinter. Das Struktogramm zeigt dir die verschachtelten Verzweigungen. ## Das Fenster @@ -10223,7 +10225,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] punkte >= 0 || punkte <= 100 > Eine Zahl kann nicht gleichzeitig kleiner als 0 und größer als 100 sein, deshalb braucht es oder. ::: -`,Hx=`--- +`,Vx=`--- titel: Ein Taschenrechner bereich: Fenster mit Swing kurz: Zwei Spalten mit GridLayout, vier Rechenknöpfe und die Division durch 0 abfangen. @@ -10494,7 +10496,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [ ] Spalte für Spalte, erst ganz links von oben nach unten - [ ] Zufällig ::: -`,Vx=`--- +`,qx=`--- titel: Zahlenraten bereich: Fenster mit Swing kurz: Ein Spiel mit Zufallszahl, Versuchszähler und einem Knopf, der sich am Ende abschaltet. @@ -10534,7 +10536,7 @@ int geheim = (int) (Math.random() * 100) + 1; Ohne \`+ 1\` käme 0 bis 99 heraus. -Probiere es im Bereich [Programmieren](#zeige-codelive) aus: \`int geheim = (int) (Math.random() * 100) + 1;\` und \`System.out.println(geheim);\`. Jedes Ausführen liefert eine andere Zahl. +Probiere es im Bereich [Code](#zeige-codelive) aus: \`int geheim = (int) (Math.random() * 100) + 1;\` und \`System.out.println(geheim);\`. Jedes Ausführen liefert eine andere Zahl. ::: angeberwissen Computer können eigentlich gar nicht würfeln. \`Math.random()\` rechnet mit einer Formel eine lange Folge von Zahlen aus, die nur zufällig **aussehen**. Man nennt sie Pseudozufallszahlen. Für Spiele reicht das völlig. @@ -10650,7 +10652,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - [x] 7 > Jeder Tipp halbiert den Bereich, und 2 hoch 7 = 128 ist größer als 100. ::: -`,qx=`--- +`,Qx=`--- titel: Viele Knöpfe, ein Zuhörer bereich: Fenster mit Swing kurz: Ein Zuhörer für viele Knöpfe, mit getActionCommand und getSource herausfinden, welcher Knopf geklickt wurde. @@ -10955,7 +10957,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = ActionEvent -> das Ereignis e mit den Infos zum Klick = JPanel -> eine Fläche mit eigenem Layout ::: -`,Qx=`--- +`,Ux=`--- titel: Innere Klassen bereich: Fenster mit Swing kurz: Einen Zuhörer als benannte innere Klasse, als anonyme Klasse und als Lambda schreiben und wissen, wer was sehen darf. @@ -11187,7 +11189,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = new ActionListener() { … } -> anonyme Klasse = der Pfeil hinter e -> Lambda ::: -`,Ux=`--- +`,$x=`--- titel: Zwei Reiter bereich: Fenster mit Swing kurz: Ein Fenster mit zwei Reitern bauen, Daten von einem Reiter zum anderen bringen und die Liste als Textdatei speichern. @@ -11468,7 +11470,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = JPanel -> die Fläche eines Reiters = JTextArea -> ein Textbereich mit mehreren Zeilen ::: -`,$x=`--- +`,Yx=`--- titel: Model View Controller bereich: Fenster mit Swing kurz: Den Klickzähler in Model, View und Controller zerlegen und verstehen, wer mit wem redet. @@ -11883,7 +11885,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ = ZahlAnzeige mit aktualisieren(int wert) -> View = der Zuhörer am Knopf -> Controller ::: -`,Yx=`Fachbegriffe für den Lernbereich. Kommt ein Begriff in einem Schritt vor, wird er dort einmal markiert und zeigt beim +`,Xx=`Fachbegriffe für den Lernbereich. Kommt ein Begriff in einem Schritt vor, wird er dort einmal markiert und zeigt beim Hovern oder Antippen seine Erklärung. Steht er im Schritt fett, wird er gerade erklärt und deshalb nicht markiert. \`auch:\` nennt weitere Formen, die ebenfalls erkannt werden. Groß- und Kleinschreibung zählt. @@ -12080,7 +12082,7 @@ Ein fertiger Baustein von Java, der Eingaben über die Tastatur liest, z. B. mit ### import Eine Zeile ganz oben im Java-Code, die einen fertigen Baustein aus einem Paket holt, z. B. \`import java.util.Scanner;\`. Ohne sie kennt Java den Namen nicht. -`,Xx=`## Grundbausteine +`,Kx=`## Grundbausteine ### Anweisung @@ -12220,7 +12222,7 @@ boolean[][] sitze = new boolean[3][5] sitze[1][4] = true output: sitze.length + " Reihen, " + sitze[0].length + " Plätze" \`\`\` -`,Kx=`--- +`,e4=`--- titel: What is a structure chart? bereich: First steps kurz: Show and read algorithms as a series of clear steps. @@ -12607,7 +12609,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] An arrow > Everything between WHILE and END WHILE is indented and is repeated. ::: -`,e4=`--- +`,t4=`--- titel: The editor bereich: First steps kurz: Insert elements, type text, move and delete. @@ -12623,7 +12625,7 @@ kurz: Insert elements, type text, move and delete. ## The screen -VisuStruct has two editors: the [structure chart editor](#zeige-editor), which this lesson is about, and on the right the [Programming](#zeige-codelive) area for Java code (from lesson 4). If the structure chart editor is collapsed, this lesson opens it for you. The blue words show you the areas, even when they are collapsed: move the mouse over one, and the area opens next to the learning area and lights up. Click it (or tap it), and it stays open. +VisuStruct has two editors: the [structure chart editor](#zeige-editor), which this lesson is about, and on the right the [Code](#zeige-codelive) area for Java code (from lesson 4). If the structure chart editor is collapsed, this lesson opens it for you. The blue words show you the areas, even when they are collapsed: move the mouse over one, and the area opens next to the learning area and lights up. Click it (or tap it), and it stays open. The structure chart editor has several areas. Move the mouse over a blue word or tap it, and that area lights up in the editor; collapsed areas such as Elements open. @@ -12633,7 +12635,7 @@ The structure chart editor has several areas. Move the mouse over a blue word or - **In the middle, the [structure chart](#zeige-struktogramm):** A new diagram contains only an empty placeholder, marked with **ø**. - **At the bottom, the [Object Inspector](#zeige-objektinspektor):** Here you edit the text of the selected element. -> You can collapse this learning area at any time with the [sidebar icon](#zeige-lernen) at the top of this area. Then only the slim “🎓 Learn” strip stays on the left; click it to open the area again. It stays open next to the editor so you can try out right away what you read. In the same way there is the [📁 Files](#zeige-dateien) column on the left for your saved programs (lesson 3) and the [Programming](#zeige-codelive) area on the right for Java (from lesson 4). +> You can collapse this learning area at any time with the [sidebar icon](#zeige-lernen) at the top of this area. Then only the slim “🎓 Learn” strip stays on the left; click it to open the area again. It stays open next to the editor so you can try out right away what you read. In the same way there is the [📁 Files](#zeige-dateien) column on the left for your saved programs (lesson 3) and the [Code](#zeige-codelive) area on the right for Java (from lesson 4). ## Insert an element @@ -12793,7 +12795,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] input: "Good morning" > Without quotation marks, Good morning is understood as the name of a variable. ::: -`,t4=`--- +`,n4=`--- titel: Save, open, export bereich: First steps kurz: Keep your files safe, use your workspace, open several diagrams and share them as an image or PDF. @@ -12947,7 +12949,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] Directly in the workspace without a subfolder > VisuStruct automatically creates a date folder for each day. That keeps the programs sorted by lesson. ::: -`,n4=`--- +`,i4=`--- titel: Variables and data types bereich: Basics kurz: Store values, get to know the data types int, double, String and boolean, and calculate. @@ -13145,14 +13147,14 @@ System.out.println("Height: " + height + " m"); - You write \`String\` with a capital letter, \`int\`, \`double\` and \`boolean\` in lowercase. Java tells them apart. - With \`+\` you join text and numbers together. -You type Java in the [Programming](#zeige-codelive) area. The structure chart builds itself as you type. “Open in editor” brings the example into the Programming area. Click “Run” there, then change the name, age or height and try again. +You type Java in the [Code](#zeige-codelive) area. The structure chart builds itself as you type. “Open in editor” brings the example into the Code area. Click “Run” there, then change the name, age or height and try again. ::: übung l04-java-steckbrief titel: Profile in Java code: java auftrag: Write a profile of Ludwig the billy goat. Create three variables: the name **Ludwig**, the age **7** and the height **1.2**. Then output these two lines: **Ludwig is 7 years old.** and **Height: 1.2 m** - “Open in editor” also opens the Programming area on the right. Type your code there; the structure chart builds itself. Then click Check. + “Open in editor” also opens the Code area on the right. Type your code there; the structure chart builds itself. Then click Check. test: - -> Ludwig is 7 years old. | Height: 1.2 m braucht: anweisung tipp: You need a \`String\`, an \`int\` and a \`double\`. Every line ends with a semicolon. @@ -13176,7 +13178,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 Programming 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 “Java”. ::: ## Find the bug: seconds @@ -13185,7 +13187,7 @@ erklärung: Whole numbers are \`int\`, decimal numbers \`double\`, texts \`Strin titel: Fix the seconds code: java auftrag: The program should convert 200 seconds into minutes and seconds and output **3 min 20 s**. But it outputs **20 min 3 s**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l04-java-fehler-start.visustruct test: - -> 3 min 20 s braucht: anweisung @@ -13293,7 +13295,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] Double price = 2.5 > Decimal numbers use a point, and the line ends with a semicolon. ::: -`,i4=`--- +`,a4=`--- titel: Sequence bereich: Basics kurz: Run steps one after another, watch the order and swap values. @@ -13395,13 +13397,13 @@ System.out.println("b = " + b); - Every statement ends with a **semicolon** \`;\`. - An output is called \`System.out.println(…)\` in Java. Mind the capital S in \`System\`: Java tells upper and lower case apart. -You type Java in the [Programming](#zeige-codelive) area to the right of the structure chart. While you type, VisuStruct builds the structure chart along with it. So you see straight away which box belongs to which line. +You type Java in the [Code](#zeige-codelive) area to the right of the structure chart. While you type, VisuStruct builds the structure chart along with it. So you see straight away which box belongs to which line. ::: übung l05-java-kino titel: Cinema tickets in Java code: java auftrag: A cinema ticket costs 9 euros. Write a Java program that calculates the price of 3 tickets and outputs **Total: 27**. - “Open in editor” also opens the Programming area on the right. Type your code there; the structure chart builds itself. Then click Check. + “Open in editor” also opens the Code area on the right. Type your code there; the structure chart builds itself. Then click Check. test: - -> Total: 27 braucht: anweisung tipp: You need three variables: the price, the number of tickets and the result. Every line ends with a semicolon. @@ -13431,7 +13433,7 @@ erklärung: First you save \`a\` in the helper variable, then \`a\` gets the val titel: Fix the credit code: java auftrag: The canteen card holds 20 euros. A meal costs 7 euros. The program should output the credit **after** paying, so **Left: 13**. But it outputs **Left: 20**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l05-java-fehler-start.visustruct test: - -> Left: 13 braucht: anweisung @@ -13530,7 +13532,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] With a colon : > If the semicolon is missing, VisuStruct shows a hint below the code. ::: -`,a4=`--- +`,s4=`--- titel: Input and output bereich: Basics kurz: Ask for values, show results and use the IPO model. @@ -13724,7 +13726,7 @@ erklärung: \`scanner.next()\` reads a word, \`scanner.nextInt()\` a whole numbe titel: Fix the sum code: java auftrag: The program reads two numbers and should output their sum. For 3 and 4, however, it shows **Sum: 34** instead of **Sum: 7**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l06-java-fehler-start.visustruct test: 3, 4 -> Sum: 7 test: 10, 5 -> Sum: 15 @@ -13861,7 +13863,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] A whole sentence > For decimal numbers there is \`scanner.nextDouble()\`, for a word \`scanner.next()\`. ::: -`,s4=`--- +`,r4=`--- titel: Simulation and desk check bereich: Basics kurz: Run a structure chart step by step, work it out by hand and find mistakes. @@ -13904,7 +13906,7 @@ The values of a and b are swapped. The variable temp keeps one value meanwhile. - **Variables:** All variables with their current values. - **Output:** Everything that was output with \`output:\`. -If the [Programming](#zeige-codelive) area is open on the right, the [console](#zeige-konsole) runs along there as well. It is cleared at the start and then shows output and input just as they would appear in the real program. +If the [Code](#zeige-codelive) area is open on the right, the [console](#zeige-konsole) runs along there as well. It is cleared at the start and then shows output and input just as they would appear in the real program. At the end, **Simulation finished.** appears. If something goes wrong, the simulation stops on the faulty box and shows a message, e.g. **Unknown variable: total**. @@ -13985,7 +13987,7 @@ lösung: sim-kino-loesung.visustruct ## Now in Java -You can run Java code step by step too. In the [Programming](#zeige-codelive) area the tool for this is called the **debugger**: +You can run Java code step by step too. In the [Code](#zeige-codelive) area the tool for this is called the **debugger**: - Click a line number on the left. A red dot appears: that is a **breakpoint**. [▶︎ Run](#zeige-ausfuehren) pauses before this line. - The [Step](#zeige-einzelschritt) button runs exactly one line, like **Step** in the simulation. @@ -14017,7 +14019,7 @@ b = a * 2; // b is now [[14]] a = b - a; // a is now [[7]] System.out.println(a + b); // output: [[21]] \`\`\` -erklärung: Each line calculates with the values that are in the variables right now: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, output 7 + 14 = 21. You can check it with Step in the Programming area. +erklärung: Each line calculates with the values that are in the variables right now: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, output 7 + 14 = 21. You can check it with Step in the Code area. ::: ## Find the bug: score @@ -14149,14 +14151,14 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] sum is too big. - [ ] The structure chart has too many boxes. -? What does a red dot in front of a line number in the Programming area do? +? What does a red dot in front of a line number in the Code area do? → Now in Java - [ ] It marks an error. - [x] The program pauses before this line. - [ ] The line is skipped. > That is a breakpoint. ▶︎ or Step carries on. ::: -`,r4=`--- +`,o4=`--- titel: Branch bereich: Basics kurz: Use a condition to decide which of two paths runs. @@ -14288,7 +14290,7 @@ Java has a mascot too: **Duke**, a little black-and-white fellow with a big red titel: Passed in Java code: java auftrag: Write a Java program that asks for the number of points. From 50 points on it outputs **passed**, otherwise **not passed**. - Type the code in the Programming area and then click Check. + Type the code in the Code area and then click Check. test: 50 -> passed test: 49 -> not passed test: 100 -> passed @@ -14325,7 +14327,7 @@ erklärung: \`number % 2\` is the remainder when dividing by 2. If it is 0, the titel: Fix the admission code: java auftrag: At the zoo, children **under** 6 get in for free, everyone else pays 4 euros. But the program also lets six-year-olds in for free. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l08-java-fehler-start.visustruct test: 5 -> Free entry test: 6 -> 4 euros @@ -14491,7 +14493,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] After a semicolon > \`if (age >= 18) { … }\`: the round brackets belong to the condition, the curly ones to the branch. ::: -`,o4=`--- +`,l4=`--- titel: Combining conditions bereich: Basics kurz: Join several conditions with and, or and not, and check ranges of values. @@ -14740,7 +14742,7 @@ erklärung: A grade is valid when **both** conditions are true, so \`&&\`. It is titel: Fix the day off code: java auftrag: The program should output **no school** for day 6 (Saturday) and day 7 (Sunday), otherwise **school**. But it always outputs **school**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l09-java-fehler-start.visustruct test: 6 -> no school test: 7 -> no school @@ -14803,7 +14805,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] if (age >= 12 || age < 18) > Each comparison stands on its own, joined with \`&&\`. ::: -`,l4=`--- +`,u4=`--- titel: Switch bereich: Basics kurz: Run one of many cases, depending on the value of a variable. @@ -14976,7 +14978,7 @@ erklärung: After \`switch\` the variable is in round brackets. Each case starts titel: Fix the calculator code: java auftrag: The calculator reads two numbers and a choice: 1 plus, 2 minus, 3 times. For 7, 3 and choice 2 the result should be **4**, but it calculates **-4**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l10-java-fehler-start.visustruct test: 7, 3, 2 -> 4 test: 7, 3, 1 -> 10 @@ -15117,7 +15119,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [x] default - [ ] case 0 ::: -`,u4=`--- +`,c4=`--- titel: While loop bereich: Basics kurz: Repeat steps as long as a condition is true. @@ -15461,7 +15463,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] while (number > 0); > The condition is in round brackets, then \`{\` opens the body. ::: -`,c4=`--- +`,m4=`--- titel: Do-while loop bereich: Basics kurz: Run first, check afterwards: loops with at least one pass. @@ -15595,7 +15597,7 @@ erklärung: The body is between \`do {\` and \`}\`, the condition only comes aft titel: Fix the halving code: java auftrag: The program reads a start number and keeps dividing it by 2 (whole-number division) with a do-while loop. Every result is output until **0** is reached. For 10 that is 5, 2, 1 and 0. But the 0 is missing. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l12-java-fehler-start.visustruct test: 10 -> 5 | 2 | 1 | 0 test: 1 -> 0 @@ -15724,7 +15726,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] } until (condition); > A semicolon follows the condition. ::: -`,m4=`--- +`,d4=`--- titel: For loop bereich: Basics kurz: Count a fixed number of passes with Init, Condition and Step. @@ -15895,7 +15897,7 @@ erklärung: The round brackets hold the start value, the condition and the step, titel: Fix the times table code: java auftrag: The program asks for a times table and should output it from 1 times to 10 times, for 7 that is 7, 14, … up to 70. But the 70 is missing. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l13-java-fehler-start.visustruct test: 7 -> 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 test: 3 -> 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 @@ -16036,7 +16038,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] i is output. > \`i++\` is short for \`i = i + 1\`. ::: -`,d4=`--- +`,h4=`--- titel: Nesting bereich: Basics kurz: Combine branches inside loops and loops inside loops. @@ -16140,7 +16142,7 @@ for (int i = 1; i <= n; i++) { System.out.println(count); \`\`\` -What is nested in the structure chart is nested in curly brackets in Java. Every level is indented four spaces further. If your code gets messy, the **Indent** button at the top of the Programming area helps. +What is nested in the structure chart is nested in curly brackets in Java. Every level is indented four spaces further. If your code gets messy, the **Indent** button at the top of the Code area helps. \`count++\` is short for \`count = count + 1\`. @@ -16180,7 +16182,7 @@ erklärung: The inner loop builds one line of 4 stars, the outer loop repeats th titel: Fix the counting code: java auftrag: The program should count how many numbers from 1 to \`n\` are divisible by 3 and output the result **once**. For 10 that is just **Count: 3**. But it outputs far too many lines. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l14-java-fehler-start.visustruct test: 10 -> Count: 3 test: 3 -> Count: 1 @@ -16317,7 +16319,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [x] By the curly brackets and the indentation - [ ] By the semicolons ::: -`,h4=`--- +`,g4=`--- titel: Arrays bereich: Basics kurz: Store many values under one name, reach them with the index and go through them with a loop. @@ -16510,7 +16512,7 @@ erklärung: \`int[]\` is an array of whole numbers, \`values.length\` is its len titel: Fix the highest temperature code: java auftrag: In January the temperatures -5, -2, -8 and -3 degrees were measured. The program should output the highest, so **Highest temperature: -2**. But it claims 0 degrees, although it was never that warm. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l15-java-fehler-start.visustruct test: - -> Highest temperature: -2 braucht: forSchleife, verzweigung @@ -16645,7 +16647,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] int numbers = [1, 2, 3]; - [ ] array numbers = (1, 2, 3); ::: -`,g4=`--- +`,p4=`--- titel: Two-dimensional arrays bereich: Basics kurz: Store values in rows and columns, like the seats in a cinema, and go through them with two nested loops. @@ -16816,7 +16818,7 @@ erklärung: \`int[][]\` is a table. \`grid.length\` is the number of rows (2), \ titel: Fix player 2 code: java auftrag: In the table \`points\` each row stands for one player. The program should add up the points of player 2 (row 1), so **Player 2: 11**. Instead it reports an error. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l16-java-fehler-start.visustruct test: - -> Player 2: 11 braucht: forSchleife @@ -16947,7 +16949,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] 5, the number of seats - [ ] 15, all seats together ::: -`,p4=`--- +`,f4=`--- titel: Strings bereich: Basics kurz: Work with text: read single characters, cut out parts, search, compare and split. @@ -17171,7 +17173,7 @@ erklärung: \`length()\` counts the characters, \`toUpperCase()\` makes everythi titel: Fix the initials code: java auftrag: The program reads a first name and a last name and should output the initials. For Ludwig Geißbock that is **L. G.** But it outputs **u. e.** - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l17-java-fehler-start.visustruct test: Ludwig, Geißbock -> L. G. test: Mia, Meyer -> M. M. @@ -17456,7 +17458,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] an error message > parseInt turns the text into a number. After that Java calculates as usual. ::: -`,f4=`--- +`,b4=`--- titel: Call and break bereich: Basics kurz: Split big tasks into subprograms and leave loops early. @@ -17686,7 +17688,7 @@ System.out.println("The square is " + q); - In the header, what the method returns (\`int\`) comes before the name. If it returns nothing, it says \`void\`. - The parameters go in the round brackets with their data type: \`(int x)\`. You separate several with commas. -- In the Programming area you write every method in its own tab, just as every subprogram has its own structure chart. +- In the Code area you write every method in its own tab, just as every subprogram has its own structure chart. - In Java the exit is called \`break\`. With \`while (true)\` you build a loop that only ends through \`break\`. ::: übung l18-java-kasse @@ -17707,7 +17709,7 @@ lösung: l18-java-kasse-loesung.visustruct ::: lückentext titel: Method and exit -auftrag: Fill in the missing words. At the top is the method that calculates a square. Below is the main program that calls it. In the Programming area both are in tabs of their own. +auftrag: Fill in the missing words. At the top is the method that calculates a square. Below is the main program that calls it. In the Code area both are in tabs of their own. \`\`\`java public static [[int]] square(int x) { [[return]] x * x; @@ -17733,7 +17735,7 @@ erklärung: \`int\` before the method name means: the method returns a whole num titel: Fix the try counter code: java auftrag: In this guessing game the secret number is 7. The program keeps asking for a guess until 7 comes, then it outputs the number of tries. For 3, 5 and 7 that was 3 tries, but the program says **Tries: 2**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l18-java-fehler-start.visustruct test: 3, 5, 7 -> Tries: 3 test: 7 -> Tries: 1 @@ -17938,7 +17940,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] return > void means “empty”: the method does something but returns no value. ::: -`,b4=`--- +`,x4=`--- titel: Searching and sorting bereich: Basics kurz: Use playing cards to understand how linear search, binary search and bubble sort work, and why some methods are much faster. @@ -18129,7 +18131,7 @@ erklärung: If a card is larger than its right neighbour, the two are swapped, w titel: Fix the linear search code: java auftrag: The cards {8, 4, 11, 4, 6} are in an array. The program should output the **first** position of the card you are looking for, so for 4 **Position: 1**. But it outputs **Position: 3**. - “Open in editor” shows the code in the Programming area. Find the bug, fix it and click Check. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. start: l19-java-fehler-start.visustruct test: 4 -> Position: 1 test: 6 -> Position: 4 @@ -18274,10 +18276,10 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] A while loop cannot go through arrays. > The card can appear several times. That is why you go through all cards to the end. ::: -`,x4=`--- +`,v4=`--- titel: Structure chart and code bereich: From structure chart to code -kurz: All elements in Java at a glance, generate code, write Java in the Programming area, run it and find mistakes. +kurz: All elements in Java at a glance, generate code, write Java in the Code area, run it and find mistakes. --- ## Skills I will gain now @@ -18287,7 +18289,7 @@ kurz: All elements in Java at a glance, generate code, write Java in the Program - recognise output, input, branches and loops in Java - explain the difference between Snippet and Class - rebuild a short Java program as a structure chart -- type Java in the Programming area and read the structure chart that is built +- type Java in the Code area and read the structure chart that is built - run a program with ▶︎ and use input and output in the console - set breakpoints and follow a program step by step ::: @@ -18394,25 +18396,25 @@ This helps you match the boxes to the Java commands. Your diagram itself stays u ## Write Java directly -So far you drew the structure chart first and then looked at the code. In the [Programming](#zeige-codelive) area it also works the other way round. Click the slim **Programming** strip on the right. Next to the structure chart a column appears where you type Java yourself. +So far you drew the structure chart first and then looked at the code. In the [Code](#zeige-codelive) area it also works the other way round. Click the slim **Code** strip on the right. Next to the structure chart a column appears where you type Java yourself. - **Structure chart to code:** When you change something in the structure chart, the Java code changes right away. - **Code to structure chart:** When you type Java, VisuStruct builds the structure chart as you type. If something is still missing, for example a closing bracket \`}\`, a hint appears below the code. - **Suggestions:** While you type, VisuStruct suggests templates, for example for \`if\`, \`for\` or \`while\`. Press Enter to accept a template. Simply replace the grey placeholders with your own text. -- **Indent:** If your code has got messy, click the **Indent** button at the top of the Programming area. Every level then sits four spaces deeper, as in Eclipse or IntelliJ. If you have selected lines, VisuStruct only indents those. +- **Indent:** If your code has got messy, click the **Indent** button at the top of the Code area. Every level then sits four spaces deeper, as in Eclipse or IntelliJ. If you have selected lines, VisuStruct only indents those. So you can try both ways. Drawing the structure chart first is good for planning a process. Writing code directly is faster when you already know what you want. The structure chart then helps you check your code. ## Run the program -At the top of the Programming area, [▶︎ Run](#zeige-ausfuehren) starts your program and **■ Stop** ends it, for example in an endless loop. What your program outputs appears below in the [console](#zeige-konsole). If it asks for input, type it there and press Enter. +At the top of the Code area, [▶︎ Run](#zeige-ausfuehren) starts your program and **■ Stop** ends it, for example in an endless loop. What your program outputs appears below in the [console](#zeige-konsole). If it asks for input, type it there and press Enter. You can drag the border between code and console up or down with the mouse. -> The Programming area understands the Java commands that also exist as boxes in the structure chart. It does not know your own classes and objects yet. Windows with Swing work anyway: turn on **Real Java (with Swing)** under the gear (lesson “Your first window”). +> The Code area understands the Java commands that also exist as boxes in the structure chart. It does not know your own classes and objects yet. Windows with Swing work anyway: turn on **Real Java (with Swing)** under the gear (lesson “Your first window”). ::: angeberwissen -Professionals call a program where you write code, run it and look for mistakes an **IDE** (Integrated Development Environment). With the Programming area, VisuStruct is a small IDE with a built-in structure chart. +Professionals call a program where you write code, run it and look for mistakes an **IDE** (Integrated Development Environment). With the Code area, VisuStruct is a small IDE with a built-in structure chart. ::: ## Find mistakes with the debugger @@ -18441,7 +18443,7 @@ This is a desk check, except the computer takes the notes for you. Before each s ## Exercise: Code first, then the structure chart -This time you don't draw. Open the Programming area and type in this Java code: +This time you don't draw. Open the Code area and type in this Java code: \`\`\` System.out.println("Start number?"); @@ -18455,13 +18457,14 @@ System.out.println("Start!"); ::: übung l20-countdown titel: Countdown -auftrag: Type the Java code above into the Programming area. Run it with ▶︎ and enter a start number in the console. +bereich: beide +auftrag: Type the Java code above into the Code area. Run it with ▶︎ and enter a start number in the console. Then look at the structure chart that was built and click Check. test: 3 -> 3 | 2 | 1 | Start! test: 1 -> 1 | Start! test: 0 -> Start! braucht: whileSchleife -tipp: Open the Programming area with the slim strip on the far right and just start typing. +tipp: Open the Code area with the slim strip on the far right and just start typing. tipp: Watch out for the semicolon at the end of every statement and the curly brackets of the while loop. A hint below the code tells you when something is still missing. lösung: l20-countdown-loesung.visustruct ::: @@ -18482,6 +18485,7 @@ System.out.println(factorial); ::: übung l17-fakultaet titel: Factorial from Java +bereich: beide auftrag: Rebuild the Java code above as a structure chart. The program reads in a number n and outputs the product 1 · 2 · … · n. At the end, check in the code view whether your Java code looks the same. test: 3 -> 6 @@ -18601,7 +18605,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can recognise output, input, branches and loops in Java. → The elements in Java - I can explain the difference between Snippet and Class. → Snippet or Class - I can rebuild a short Java program as a structure chart. → Exercise: Java as a structure chart -- I can type Java in the Programming area and read the structure chart that is built. → Write Java directly +- I can type Java in the Code area and read the structure chart that is built. → Write Java directly - I can run a program with ▶︎ and use input and output in the console. → Run the program - I can set breakpoints and follow a program step by step. → Find mistakes with the debugger ::: @@ -18643,7 +18647,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] The line contains a mistake. > That is a breakpoint. Continue with ▶︎ or Step. ::: -`,v4=`--- +`,y4=`--- titel: Python and JavaScript bereich: From structure chart to code kurz: Generate Python and JavaScript code from the structure chart and run JavaScript straight in the browser. @@ -18881,7 +18885,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] Sum: is output. > str(sum) turns the number into text. ::: -`,y4=`--- +`,w4=`--- titel: When the program crashes: try and catch bereich: Catching errors kurz: Use real Java to read error messages and catch crashes with try and catch. @@ -18890,7 +18894,7 @@ kurz: Use real Java to read error messages and catch crashes with try and catch. ## Skills I will gain now ::: kompetenzen -- switch on real Java in the Programming area +- switch on real Java in the Code area - read the exception and the line from an error message - catch an exception with try and catch - turn text into a number with Integer.parseInt and catch the NumberFormatException @@ -18899,7 +18903,7 @@ kurz: Use real Java to read error messages and catch crashes with try and catch. ## Crashed! -This program should print three grades. Type it into the [Programming](#zeige-codelive) area and click [▶︎ Run](#zeige-ausfuehren): +This program should print three grades. Type it into the [Code](#zeige-codelive) area and click [▶︎ Run](#zeige-ausfuehren): \`\`\`java int[] grades = {2, 3, 1}; @@ -18920,7 +18924,7 @@ In 1947 Grace Hopper's team found a moth in the Mark II computer at Harvard Univ ## Switching on real Java -The Programming area normally calculates with the same simulation as the structure chart. It simply stops when there is an error. To see what real Java does, switch on real Java: +The Code area normally calculates with the same simulation as the structure chart. It simply stops when there is an error. To see what real Java does, switch on real Java: 1. Click the [gear](#zeige-einstellungen) at the top right and choose Java as the **Programming language**. 2. In the Java section, tick **Real Java (with Swing)**. @@ -18963,7 +18967,7 @@ A message like this looks scary at first. But it tells you exactly what is going Java calls an error like this, at run time, an **exception**. We say: Java *throws* an exception. If nobody catches it, the program stops. That is why “Done!” does not appear. ::: ludwig -Always read error messages from the top: first the name of the exception, then the line number. In the Programming area the line numbers are on the left next to the code. +Always read error messages from the top: first the name of the exception, then the line number. In the Code area the line numbers are on the left next to the code. ::: ## try and catch @@ -19128,7 +19132,7 @@ The exception is called \`ArithmeticException\`. Only put the line that can cras 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. ::: checkliste -- I can switch on real Java in the Programming area. → Switching on real Java +- I can switch on real Java in the Code area. → Switching on real Java - I can read the exception and the line from an error message. → Reading the error message - I can catch an exception with try and catch. → try and catch - I can turn text into a number with Integer.parseInt and catch the NumberFormatException. → Turning text into a number @@ -19164,7 +19168,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = ArithmeticException -> dividing by 0 = NumberFormatException -> text is not a number ::: -`,w4=`--- +`,z4=`--- titel: Reading and saving text bereich: Files kurz: Read a text file line by line with Scanner and save a file with PrintWriter. @@ -19418,7 +19422,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = println(text) -> writes a line = close() -> closes the file ::: -`,z4=`--- +`,I4=`--- titel: Line by line with BufferedReader bereich: Files kurz: Read with BufferedReader and readLine until null comes, and read a whole file at once with Files. @@ -19674,7 +19678,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = Files.readString -> small files all at once = Scanner -> reading numbers and words ::: -`,I4=`--- +`,k4=`--- titel: Tables as CSV bereich: Files kurz: Read a table as a CSV file, split each line with split and calculate with the numbers. @@ -19898,7 +19902,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = record -> a line with values = separator -> separates the columns, often ; ::: -`,k4=`--- +`,S4=`--- titel: Data as JSON bereich: Files kurz: Understand JSON files, get values out with indexOf and substring, and write JSON yourself. @@ -20123,7 +20127,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = [ ] -> a list = : -> separates key and value ::: -`,S4=`--- +`,T4=`--- titel: Comparing formats bereich: Files kurz: Compare the same data as txt, CSV and JSON, choose the right format and convert a file into another format. @@ -20298,7 +20302,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = the class grade list -> CSV = a game save with lists -> JSON ::: -`,T4=`--- +`,_4=`--- titel: Your first window bereich: Windows with Swing kurz: Open your own window with Java and Swing, explained line by line. @@ -20307,7 +20311,7 @@ kurz: Open your own window with Java and Swing, explained line by line. ## Skills I will gain now ::: kompetenzen -- switch on “Real Java” in the Programming area +- switch on “Real Java” in the Code area - open a window with a title and a size - explain what each line of the window program does - explain why setVisible(true) comes last @@ -20319,11 +20323,11 @@ So far your programs have written text to the console. Most programs you know, h Java comes with a toolbox for this: **Swing**. In VisuStruct you switch it on like this: -1. Open the [Programming](#zeige-codelive) area on the right. +1. Open the [Code](#zeige-codelive) area on the right. 2. Click the [gear](#zeige-einstellungen) at the top right and choose Java as the **Programming language**. 3. Below that, in the Java section, tick **Real Java (with Swing)**. -The first time you click [▶︎ Run](#zeige-ausfuehren), VisuStruct downloads about 40 MB once, which takes a moment. After that your code runs as real Java, and your windows appear in the Programming area in the **Java windows** box above the console. +The first time you click [▶︎ Run](#zeige-ausfuehren), VisuStruct downloads about 40 MB once, which takes a moment. After that your code runs as real Java, and your windows appear in the Code area in the **Java windows** box above the console. > With “Real Java”, input from the console (\`Scanner\`) does not work yet. For programs with input, untick the box again. @@ -20333,7 +20337,7 @@ Swing has been around since 1998. Before that, Java only had the older AWT with ## The whole program -This is the smallest program that opens a window. Type it into the Programming area and click [▶︎ Run](#zeige-ausfuehren): +This is the smallest program that opens a window. Type it into the Code area and click [▶︎ Run](#zeige-ausfuehren): \`\`\`java import javax.swing.*; @@ -20477,7 +20481,7 @@ Change the program so that Run it and check all three points. ::: ludwig -Don't feel like typing so much? With “Real Java” you may type just the four lines from \`main\` into the Programming area. VisuStruct then wraps them in a class itself and adds the \`import\` lines. In a real Java development environment, though, you need the whole program. +Don't feel like typing so much? With “Real Java” you may type just the four lines from \`main\` into the Code area. VisuStruct then wraps them in a class itself and adds the \`import\` lines. In a real Java development environment, though, you need the whole program. ::: ## Checklist @@ -20485,7 +20489,7 @@ Don't feel like typing so much? With “Real Java” you may type just the four 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. ::: checkliste -- I can switch on “Real Java” in the Programming area. → Programs with windows +- I can switch on “Real Java” in the Code area. → Programs with windows - I can open a window with a title and a size. → The whole program - I can explain what each line of the window program does. → Line by line - I can explain why setVisible(true) comes last. → Why setVisible comes last @@ -20520,7 +20524,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] They are in curly brackets. - [ ] They end in Window. ::: -`,_4=`--- +`,O4=`--- titel: A button in the window bereich: Windows with Swing kurz: Put a button into the window and arrange it neatly with a layout. @@ -20736,7 +20740,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] The button says “I was clicked”. > What should happen on a click is what you learn in the next lesson. ::: -`,O4=`--- +`,A4=`--- titel: The button reacts bereich: Windows with Swing kurz: Use an ActionListener to decide what happens on a click. @@ -21078,7 +21082,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = setText -> change the label = setVisible(true) -> show the window ::: -`,A4=`--- +`,C4=`--- titel: Doubling a number in a window bereich: Windows with Swing kurz: Arrange a label, a text field and a button with a GridLayout and calculate with the text in the text field. @@ -21359,7 +21363,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = JButton -> button = GridLayout -> arrangement in a grid ::: -`,C4=`--- +`,j4=`--- titel: Click counter with reset bereich: Windows with Swing kurz: Two buttons change the same number: create a variable for the whole class. @@ -21867,7 +21871,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] 3 > After phase++ it is 3, which is greater than 2, so it becomes 0. ::: -`,j4=`--- +`,D4=`--- titel: Grade calculator in a window bereich: Windows with Swing kurz: Enter points, work out the grade with else if and catch wrong input. @@ -21923,7 +21927,7 @@ if (points >= 90) { With 85 points, \`points >= 90\` is false, but \`points >= 80\` is true. So grade B, and the remaining conditions are not checked at all. That is why the lower limit is enough each time. ::: -You can try this part without a window in the [Programming](#zeige-codelive) area. Put \`int points = 85;\` in front of it and \`System.out.println("Grade: " + grade);\` after it. The structure chart shows you the nested branches. +You can try this part without a window in the [Code](#zeige-codelive) area. Put \`int points = 85;\` in front of it and \`System.out.println("Grade: " + grade);\` after it. The structure chart shows you the nested branches. ## The window @@ -22138,7 +22142,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] points >= 0 || points <= 100 > A number can't be smaller than 0 and bigger than 100 at the same time, so you need or. ::: -`,D4=`--- +`,B4=`--- titel: A calculator bereich: Windows with Swing kurz: Two columns with GridLayout, four arithmetic buttons and catching division by 0. @@ -22409,7 +22413,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [ ] Column by column, starting top to bottom on the far left - [ ] Randomly ::: -`,B4=`--- +`,Z4=`--- titel: Guess the number bereich: Windows with Swing kurz: A game with a random number, a counter for the guesses and a button that switches itself off at the end. @@ -22449,7 +22453,7 @@ int secret = (int) (Math.random() * 100) + 1; Without \`+ 1\` you would get 0 to 99. -Try it in the [Programming](#zeige-codelive) area: \`int secret = (int) (Math.random() * 100) + 1;\` and \`System.out.println(secret);\`. Every run gives a different number. +Try it in the [Code](#zeige-codelive) area: \`int secret = (int) (Math.random() * 100) + 1;\` and \`System.out.println(secret);\`. Every run gives a different number. ::: angeberwissen Computers can't actually roll dice. \`Math.random()\` uses a formula to calculate a long sequence of numbers that only **look** random. They are called pseudo-random numbers. For games that is perfectly fine. @@ -22565,7 +22569,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - [x] 7 > Each guess halves the range, and 2 to the power of 7 = 128 is bigger than 100. ::: -`,Z4=`--- +`,M4=`--- titel: Many buttons, one listener bereich: Windows with Swing kurz: One listener for many buttons, and finding out with getActionCommand and getSource which button was clicked. @@ -22869,7 +22873,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = ActionEvent -> the event e with the information about the click = JPanel -> an area with its own layout ::: -`,M4=`--- +`,L4=`--- titel: Inner classes bereich: Windows with Swing kurz: Write a listener as a named inner class, as an anonymous class and as a lambda, and know who can see what. @@ -23101,7 +23105,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = new ActionListener() { … } -> anonymous class = the arrow after e -> lambda ::: -`,L4=`--- +`,E4=`--- titel: Two tabs bereich: Windows with Swing kurz: Build a window with two tabs, bring data from one tab to the other and save the list as a text file. @@ -23382,7 +23386,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = JPanel -> the area of a tab = JTextArea -> a text area with several lines ::: -`,E4=`--- +`,W4=`--- titel: Model View Controller bereich: Windows with Swing kurz: Split the click counter into model, view and controller and understand who talks to whom. @@ -23797,7 +23801,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can = NumberView with update(int value) -> view = the listener at the button -> controller ::: -`,W4=`Technical terms for the learning area. When a term appears in a step, it is marked there once and shows its explanation +`,N4=`Technical terms for the learning area. When a term appears in a step, it is marked there once and shows its explanation on hover or tap. If it is in bold in that step, it is being explained right there and is not marked. \`also:\` lists other forms that are recognised too. Upper and lower case matter. @@ -23999,7 +24003,7 @@ A ready-made Java building block that reads input from the keyboard, for example ### import A line at the very top of Java code that fetches a ready-made building block from a package, for example \`import java.util.Scanner;\`. Without it, Java doesn't know the name. -`,N4=`## Basics +`,F4=`## Basics ### Statement @@ -24139,7 +24143,7 @@ boolean[][] seats = new boolean[3][5] seats[1][4] = true output: seats.length + " rows, " + seats[0].length + " seats" \`\`\` -`,F4=`--- +`,J4=`--- titel: O que é um estrutograma? bereich: Primeiros passos kurz: Mostrar e ler algoritmos como uma série de passos claros. @@ -24533,7 +24537,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Uma seta > Tudo o que está entre ENQUANTO e FIM ENQUANTO está recuado e é repetido. ::: -`,J4=`--- +`,R4=`--- titel: O editor bereich: Primeiros passos kurz: Inserir elementos, escrever texto, mover e eliminar. @@ -24549,7 +24553,7 @@ kurz: Inserir elementos, escrever texto, mover e eliminar. ## O ecrã -O VisuStruct tem dois editores: o [editor de estrutogramas](#zeige-editor), de que trata esta lição, e à direita a área [Programação](#zeige-codelive) para código Java (a partir da lição 4). Se o editor de estrutogramas estiver recolhido, esta lição abre-o sozinha. As palavras azuis mostram-te as áreas, mesmo que estejam recolhidas: passa o rato por cima de uma, e a área abre-se ao lado da área de aprendizagem e acende-se. Se clicares nela (ou tocares nela), fica aberta. +O VisuStruct tem dois editores: o [editor de estrutogramas](#zeige-editor), de que trata esta lição, e à direita a área [Código](#zeige-codelive) para código Java (a partir da lição 4). Se o editor de estrutogramas estiver recolhido, esta lição abre-o sozinha. As palavras azuis mostram-te as áreas, mesmo que estejam recolhidas: passa o rato por cima de uma, e a área abre-se ao lado da área de aprendizagem e acende-se. Se clicares nela (ou tocares nela), fica aberta. O editor de estrutogramas tem várias áreas. Passa o rato por cima de uma palavra azul ou toca nela, e essa área acende-se no editor; as áreas recolhidas, como os Elementos, abrem-se. @@ -24559,7 +24563,7 @@ O editor de estrutogramas tem várias áreas. Passa o rato por cima de uma palav - **Ao meio, o [estrutograma](#zeige-struktogramm):** Um diagrama novo contém apenas um marcador vazio, assinalado com **ø**. - **Em baixo, o [Inspetor de objetos](#zeige-objektinspektor):** Aqui editas o texto do elemento selecionado. -> Podes recolher esta área de aprendizagem a qualquer momento com o [ícone da barra lateral](#zeige-lernen) no topo desta área. Fica só a barra estreita “🎓 Aprender” à esquerda; um clique abre-a de novo. Ela fica aberta ao lado do editor, para poderes experimentar logo o que lês. Da mesma forma, há à esquerda a coluna [📁 Ficheiros](#zeige-dateien) para os teus programas guardados (lição 3) e à direita a área [Programação](#zeige-codelive) para Java (a partir da lição 4). +> Podes recolher esta área de aprendizagem a qualquer momento com o [ícone da barra lateral](#zeige-lernen) no topo desta área. Fica só a barra estreita “🎓 Aprender” à esquerda; um clique abre-a de novo. Ela fica aberta ao lado do editor, para poderes experimentar logo o que lês. Da mesma forma, há à esquerda a coluna [📁 Ficheiros](#zeige-dateien) para os teus programas guardados (lição 3) e à direita a área [Código](#zeige-codelive) para Java (a partir da lição 4). ## Inserir um elemento @@ -24719,7 +24723,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] input: "Bom dia" > Sem aspas, Bom dia é entendido como o nome de uma variável. ::: -`,R4=`--- +`,G4=`--- titel: Guardar, abrir, exportar bereich: Primeiros passos kurz: Guardar os teus ficheiros em segurança, usar o teu espaço de trabalho, abrir vários diagramas e partilhá-los como imagem ou PDF. @@ -24873,7 +24877,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Diretamente no espaço de trabalho, sem subpasta > O VisuStruct cria automaticamente uma pasta com a data de cada dia. Assim os programas ficam ordenados por aula. ::: -`,G4=`--- +`,H4=`--- titel: Variáveis e tipos de dados bereich: Fundamentos kurz: Guardar valores, conhecer os tipos de dados int, double, String e boolean, e fazer contas. @@ -25071,14 +25075,14 @@ System.out.println("Altura: " + altura + " m"); - \`String\` escreve-se com maiúscula, \`int\`, \`double\` e \`boolean\` com minúscula. O Java distingue-os. - Com \`+\` juntas texto e números. -Escreves Java na área [Programação](#zeige-codelive). O estrutograma constrói-se sozinho enquanto escreves. “Abrir no editor” leva o exemplo para a área Programação. Clica aí em “Executar”, depois muda o nome, a idade ou a altura e experimenta outra vez. +Escreves Java na área [Código](#zeige-codelive). O estrutograma constrói-se sozinho enquanto escreves. “Abrir no editor” leva o exemplo para a área Código. Clica aí em “Executar”, depois muda o nome, a idade ou a altura e experimenta outra vez. ::: übung l04-java-steckbrief titel: Ficha em Java code: java auftrag: Escreve a ficha do Ludwig, o bode. Cria três variáveis: o nome **Ludwig**, a idade **7** e a altura **1.2**. Depois mostra estas duas linhas: **Ludwig tem 7 anos.** e **Altura: 1.2 m** - “Abrir no editor” abre também a área Programação à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. + “Abrir no editor” abre também a área Código à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. test: - -> Ludwig tem 7 anos. | Altura: 1.2 m braucht: anweisung tipp: Precisas de uma \`String\`, um \`int\` e um \`double\`. Cada linha termina com ponto e vírgula. @@ -25102,7 +25106,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 Programação 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 “Java”. ::: ## Encontra o erro: segundos @@ -25111,7 +25115,7 @@ erklärung: Números inteiros são \`int\`, números decimais \`double\`, textos titel: Corrigir os segundos code: java auftrag: O programa deve converter 200 segundos em minutos e segundos e mostrar **3 min 20 s**. Mas mostra **20 min 3 s**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l04-java-fehler-start.visustruct test: - -> 3 min 20 s braucht: anweisung @@ -25219,7 +25223,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Double preco = 2.5 > Os números decimais escrevem-se com ponto, e no fim há um ponto e vírgula. ::: -`,H4=`--- +`,V4=`--- titel: Sequência bereich: Fundamentos kurz: Executar passos um a seguir ao outro, prestar atenção à ordem e trocar valores. @@ -25321,13 +25325,13 @@ System.out.println("b = " + b); - No fim de cada instrução há um **ponto e vírgula** \`;\`. - Uma saída chama-se \`System.out.println(…)\` em Java. Atenção ao S maiúsculo de \`System\`: o Java distingue maiúsculas de minúsculas. -Escreves Java na área [Programação](#zeige-codelive), à direita do estrutograma. Enquanto escreves, o VisuStruct constrói o estrutograma ao mesmo tempo. Assim vês logo que bloco pertence a que linha. +Escreves Java na área [Código](#zeige-codelive), à direita do estrutograma. Enquanto escreves, o VisuStruct constrói o estrutograma ao mesmo tempo. Assim vês logo que bloco pertence a que linha. ::: übung l05-java-kino titel: Bilhetes de cinema em Java code: java auftrag: Um bilhete de cinema custa 9 euros. Escreve um programa em Java que calcula o preço de 3 bilhetes e mostra **Total: 27**. - “Abrir no editor” abre também a área Programação à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. + “Abrir no editor” abre também a área Código à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. test: - -> Total: 27 braucht: anweisung tipp: Precisas de três variáveis: o preço, a quantidade e o resultado. Cada linha termina com ponto e vírgula. @@ -25357,7 +25361,7 @@ erklärung: Primeiro guardas \`a\` na variável auxiliar, depois \`a\` recebe o titel: Corrigir o saldo code: java auftrag: O cartão da cantina tem 20 euros. Uma refeição custa 7 euros. O programa deve mostrar o saldo **depois** de pagar, ou seja, **Resta: 13**. Mas mostra **Resta: 20**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l05-java-fehler-start.visustruct test: - -> Resta: 13 braucht: anweisung @@ -25456,7 +25460,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Com dois pontos : > Se faltar o ponto e vírgula, o VisuStruct mostra uma indicação por baixo do código. ::: -`,V4=`--- +`,q4=`--- titel: Entrada e saída bereich: Fundamentos kurz: Pedir valores, mostrar resultados e usar o modelo EPS. @@ -25650,7 +25654,7 @@ erklärung: \`scanner.next()\` lê uma palavra, \`scanner.nextInt()\` um número titel: Corrigir a soma code: java auftrag: O programa lê dois números e deve mostrar a soma. Mas com 3 e 4 aparece **Soma: 34** em vez de **Soma: 7**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l06-java-fehler-start.visustruct test: 3, 4 -> Soma: 7 test: 10, 5 -> Soma: 15 @@ -25787,7 +25791,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Uma frase inteira > Para números decimais há \`scanner.nextDouble()\`, para uma palavra \`scanner.next()\`. ::: -`,q4=`--- +`,Q4=`--- titel: Simulação e teste de secretária bereich: Fundamentos kurz: Executar um estrutograma passo a passo, segui-lo à mão e encontrar erros. @@ -25830,7 +25834,7 @@ Os valores de a e b são trocados. A variável aux guarda um dos valores entreta - **Variáveis:** Todas as variáveis com os seus valores atuais. - **Saída:** Tudo o que foi mostrado com \`output:\`. -Se a área [Programação](#zeige-codelive) estiver aberta à direita, a [consola](#zeige-konsole) também acompanha lá. É limpa no início e depois mostra as saídas e entradas tal como apareceriam no programa real. +Se a área [Código](#zeige-codelive) estiver aberta à direita, a [consola](#zeige-konsole) também acompanha lá. É limpa no início e depois mostra as saídas e entradas tal como apareceriam no programa real. No fim aparece **Simulação terminada.** Se algo correr mal, a simulação para no bloco com erro e mostra uma mensagem, p. ex. **Variável desconhecida: total**. @@ -25911,7 +25915,7 @@ lösung: sim-kino-loesung.visustruct ## Agora em Java -Também podes executar código Java passo a passo. Na área [Programação](#zeige-codelive), a ferramenta para isso chama-se **depurador** (debugger): +Também podes executar código Java passo a passo. Na área [Código](#zeige-codelive), a ferramenta para isso chama-se **depurador** (debugger): - Clica num número de linha à esquerda. Aparece um ponto vermelho: é um **ponto de paragem**. [▶︎ Executar](#zeige-ausfuehren) para antes dessa linha. - O botão [Passo a passo](#zeige-einzelschritt) executa exatamente uma linha, como **Passo** na simulação. @@ -25943,7 +25947,7 @@ b = a * 2; // b vale agora [[14]] a = b - a; // a vale agora [[7]] System.out.println(a + b); // saída: [[21]] \`\`\` -erklärung: Cada linha calcula com os valores que estão nesse momento nas variáveis: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, saída 7 + 14 = 21. Podes confirmar com Passo a passo na área Programação. +erklärung: Cada linha calcula com os valores que estão nesse momento nas variáveis: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, saída 7 + 14 = 21. Podes confirmar com Passo a passo na área Código. ::: ## Encontra o erro: pontuação @@ -26075,14 +26079,14 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] soma é demasiado grande. - [ ] O estrutograma tem demasiados blocos. -? O que faz um ponto vermelho antes de um número de linha na área Programação? +? O que faz um ponto vermelho antes de um número de linha na área Código? → Agora em Java - [ ] Marca um erro. - [x] O programa para antes dessa linha. - [ ] A linha é saltada. > É um ponto de paragem. Continuas com ▶︎ ou com Passo a passo. ::: -`,Q4=`--- +`,U4=`--- titel: Decisão bereich: Fundamentos kurz: Usar uma condição para decidir qual de dois ramos é executado. @@ -26214,7 +26218,7 @@ O Java também tem uma mascote: o **Duke**, um bonequinho preto e branco com um titel: Aprovado em Java code: java auftrag: Escreve um programa em Java que pergunta pela pontuação. A partir de 50 pontos mostra **aprovado**, senão **reprovado**. - Escreve o código na área Programação e depois clica em Verificar. + Escreve o código na área Código e depois clica em Verificar. test: 50 -> aprovado test: 49 -> reprovado test: 100 -> aprovado @@ -26251,7 +26255,7 @@ erklärung: \`numero % 2\` é o resto da divisão por 2. Se for 0, o número é titel: Corrigir a entrada code: java auftrag: No jardim zoológico, as crianças com **menos** de 6 anos entram de graça, todos os outros pagam 4 euros. Mas o programa também deixa entrar de graça as crianças de seis anos. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l08-java-fehler-start.visustruct test: 5 -> Entrada gratuita test: 6 -> 4 euros @@ -26417,7 +26421,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Depois de um ponto e vírgula > \`if (idade >= 18) { … }\`: os parênteses curvos pertencem à condição, as chavetas ao ramo. ::: -`,U4=`--- +`,$4=`--- titel: Combinar condições bereich: Fundamentos kurz: Juntar várias condições com e, ou e não, e verificar intervalos de valores. @@ -26666,7 +26670,7 @@ erklärung: Uma nota é válida quando **as duas** condições são verdadeiras, titel: Corrigir o dia sem escola code: java auftrag: O programa deve mostrar **sem escola** para o dia 6 (sábado) e o dia 7 (domingo), e **escola** nos outros dias. Mas mostra sempre **escola**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l09-java-fehler-start.visustruct test: 6 -> sem escola test: 7 -> sem escola @@ -26729,7 +26733,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] if (idade >= 12 || idade < 18) > Cada comparação fica sozinha, ligada com \`&&\`. ::: -`,$4=`--- +`,Y4=`--- titel: Seleção bereich: Fundamentos kurz: Executar um de vários casos, consoante o valor de uma variável. @@ -26902,7 +26906,7 @@ erklärung: Depois de \`switch\` vem a variável entre parênteses. Cada caso co titel: Corrigir a calculadora code: java auftrag: A calculadora lê dois números e uma opção: 1 mais, 2 menos, 3 vezes. Com 7, 3 e a opção 2 devia dar **4**, mas dá **-4**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l10-java-fehler-start.visustruct test: 7, 3, 2 -> 4 test: 7, 3, 1 -> 10 @@ -27043,7 +27047,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [x] default - [ ] case 0 ::: -`,Y4=`--- +`,X4=`--- titel: Ciclo while bereich: Fundamentos kurz: Repetir passos enquanto uma condição for verdadeira. @@ -27387,7 +27391,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] while (numero > 0); > A condição fica entre parênteses curvos, depois \`{\` abre o corpo. ::: -`,X4=`--- +`,K4=`--- titel: Ciclo do-while bereich: Fundamentos kurz: Primeiro executar, depois verificar: ciclos com pelo menos uma iteração. @@ -27521,7 +27525,7 @@ erklärung: O corpo fica entre \`do {\` e \`}\`, a condição só vem depois. No titel: Corrigir a divisão ao meio code: java auftrag: O programa lê um número inicial e, com um ciclo do-while, divide-o repetidamente por 2 (divisão inteira). Cada resultado é mostrado até chegar a **0**. Para 10 são 5, 2, 1 e 0. Mas falta o 0. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l12-java-fehler-start.visustruct test: 10 -> 5 | 2 | 1 | 0 test: 1 -> 0 @@ -27650,7 +27654,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] } until (condicao); > Depois da condição vem um ponto e vírgula. ::: -`,K4=`--- +`,ev=`--- titel: Ciclo for bereich: Fundamentos kurz: Contar um número fixo de iterações com Início, Condição e Passo. @@ -27821,7 +27825,7 @@ erklärung: Entre os parênteses ficam o valor inicial, a condição e o passo, titel: Corrigir a tabuada code: java auftrag: O programa pergunta que tabuada queres e deve mostrá-la de 1 vez até 10 vezes, para o 7 são 7, 14, … até 70. Mas falta o 70. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l13-java-fehler-start.visustruct test: 7 -> 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 test: 3 -> 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 @@ -27962,7 +27966,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] i é mostrado. > \`i++\` é a forma curta de \`i = i + 1\`. ::: -`,ev=`--- +`,tv=`--- titel: Encaixar bereich: Fundamentos kurz: Combinar decisões dentro de ciclos e ciclos dentro de ciclos. @@ -28066,7 +28070,7 @@ for (int i = 1; i <= n; i++) { System.out.println(quantidade); \`\`\` -O que no estrutograma está encaixado, em Java está encaixado entre chavetas. Cada nível fica quatro espaços mais para dentro. Se o teu código ficar desarrumado, ajuda o botão **Indentar** em cima na área Programação. +O que no estrutograma está encaixado, em Java está encaixado entre chavetas. Cada nível fica quatro espaços mais para dentro. Se o teu código ficar desarrumado, ajuda o botão **Indentar** em cima na área Código. \`quantidade++\` é a forma curta de \`quantidade = quantidade + 1\`. @@ -28106,7 +28110,7 @@ erklärung: O ciclo de dentro constrói uma linha de 4 estrelas, o de fora repet titel: Corrigir a contagem code: java auftrag: O programa deve contar quantos números de 1 a \`n\` são divisíveis por 3 e mostrar o resultado **uma vez**. Para 10 é só **Quantidade: 3**. Mas mostra linhas a mais. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l14-java-fehler-start.visustruct test: 10 -> Quantidade: 3 test: 3 -> Quantidade: 1 @@ -28243,7 +28247,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [x] Pelas chavetas e pela indentação - [ ] Pelos pontos e vírgulas ::: -`,tv=`--- +`,nv=`--- titel: Arrays bereich: Fundamentos kurz: Guardar muitos valores com um só nome, chegar a eles com o índice e percorrê-los com um ciclo. @@ -28436,7 +28440,7 @@ erklärung: \`int[]\` é um array de números inteiros, \`valores.length\` é o titel: Corrigir a temperatura mais alta code: java auftrag: Em janeiro mediram-se as temperaturas -5, -2, -8 e -3 graus. O programa deve mostrar a mais alta, ou seja, **Temperatura mais alta: -2**. Mas diz 0 graus, embora nunca tenha estado tão quente. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l15-java-fehler-start.visustruct test: - -> Temperatura mais alta: -2 braucht: forSchleife, verzweigung @@ -28571,7 +28575,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] int numeros = [1, 2, 3]; - [ ] array numeros = (1, 2, 3); ::: -`,nv=`--- +`,iv=`--- titel: Arrays bidimensionais bereich: Fundamentos kurz: Guardar valores em linhas e colunas, como os lugares de um cinema, e percorrê-los com dois ciclos encaixados. @@ -28742,7 +28746,7 @@ erklärung: \`int[][]\` é uma tabela. \`campo.length\` é o número de linhas ( titel: Corrigir o jogador 2 code: java auftrag: Na tabela \`pontos\`, cada linha corresponde a um jogador. O programa deve somar os pontos do jogador 2 (linha 1), ou seja, **Jogador 2: 11**. Em vez disso, dá um erro. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l16-java-fehler-start.visustruct test: - -> Jogador 2: 11 braucht: forSchleife @@ -28873,7 +28877,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] 5, o número de lugares - [ ] 15, todos os lugares juntos ::: -`,iv=`--- +`,av=`--- titel: Strings bereich: Fundamentos kurz: Trabalhar com texto: ler caracteres, recortar partes, pesquisar, comparar e dividir. @@ -29097,7 +29101,7 @@ erklärung: \`length()\` conta os carateres, \`toUpperCase()\` põe tudo em mai titel: Corrigir as iniciais code: java auftrag: O programa lê o nome próprio e o apelido e deve mostrar as iniciais. Para Ludwig Geißbock é **L. G.** Mas mostra **u. e.** - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l17-java-fehler-start.visustruct test: Ludwig, Geißbock -> L. G. test: Mia, Meyer -> M. M. @@ -29384,7 +29388,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] uma mensagem de erro > parseInt transforma o texto num número. Depois o Java faz a conta normalmente. ::: -`,av=`--- +`,sv=`--- titel: Chamada e interrupção bereich: Fundamentos kurz: Dividir tarefas grandes em subprogramas e sair mais cedo dos ciclos. @@ -29614,7 +29618,7 @@ System.out.println("O quadrado é " + q); - No cabeçalho, antes do nome, fica o que o método devolve (\`int\`). Se não devolver nada, fica \`void\`. - Os parâmetros ficam entre parênteses curvos, com o tipo de dados: \`(int x)\`. Separas vários com vírgulas. -- Na área Programação escreves cada método no seu próprio separador, tal como cada subprograma tem o seu próprio estrutograma. +- Na área Código escreves cada método no seu próprio separador, tal como cada subprograma tem o seu próprio estrutograma. - Em Java, a saída chama-se \`break\`. Com \`while (true)\` constróis um ciclo que só termina com \`break\`. ::: übung l18-java-kasse @@ -29635,7 +29639,7 @@ lösung: l18-java-kasse-loesung.visustruct ::: lückentext titel: Método e saída -auftrag: Preenche as palavras que faltam. Em cima está o método que calcula um quadrado. Por baixo está o programa principal, que o chama. Na área Programação, cada um fica no seu separador. +auftrag: Preenche as palavras que faltam. Em cima está o método que calcula um quadrado. Por baixo está o programa principal, que o chama. Na área Código, cada um fica no seu separador. \`\`\`java public static [[int]] quadrado(int x) { [[return]] x * x; @@ -29661,7 +29665,7 @@ erklärung: \`int\` antes do nome do método quer dizer que o método devolve um titel: Corrigir a contagem de tentativas code: java auftrag: Neste jogo de adivinhar, o número secreto é 7. O programa pede um palpite até aparecer o 7 e depois mostra o número de tentativas. Com 3, 5 e 7 foram 3 tentativas, mas o programa diz **Tentativas: 2**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l18-java-fehler-start.visustruct test: 3, 5, 7 -> Tentativas: 3 test: 7 -> Tentativas: 1 @@ -29866,7 +29870,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] return > void significa “vazio”: o método faz alguma coisa, mas não devolve nenhum valor. ::: -`,sv=`--- +`,rv=`--- titel: Pesquisar e ordenar bereich: Fundamentos kurz: Perceber com cartas de jogar como funcionam a pesquisa linear, a pesquisa binária e o bubble sort, e porque é que alguns métodos são muito mais rápidos. @@ -30057,7 +30061,7 @@ erklärung: Se uma carta for maior do que a vizinha da direita, as duas trocam d titel: Corrigir a pesquisa linear code: java auftrag: As cartas {8, 4, 11, 4, 6} estão num array. O programa deve mostrar a **primeira** posição da carta procurada, para o 4 é **Posição: 1**. Mas mostra **Posição: 3**. - “Abrir no editor” mostra o código na área Programação. Encontra o erro, corrige-o e carrega em Verificar. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. start: l19-java-fehler-start.visustruct test: 4 -> Posição: 1 test: 6 -> Posição: 4 @@ -30202,10 +30206,10 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Um ciclo while não consegue percorrer arrays. > A carta pode aparecer várias vezes. Por isso percorres todas as cartas até ao fim. ::: -`,rv=`--- +`,ov=`--- titel: Estrutograma e código bereich: Do estrutograma ao código -kurz: Todos os elementos em Java num relance, gerar código, escrever Java na área Programação, executá-lo e procurar erros. +kurz: Todos os elementos em Java num relance, gerar código, escrever Java na área Código, executá-lo e procurar erros. --- ## Competências que vou adquirir agora @@ -30215,7 +30219,7 @@ kurz: Todos os elementos em Java num relance, gerar código, escrever Java na á - reconhecer em Java a saída, a entrada, as decisões e os ciclos - explicar a diferença entre Excerto e Classe - reconstruir um programa Java curto como estrutograma -- escrever Java na área Programação e ler o estrutograma que é construído +- escrever Java na área Código e ler o estrutograma que é construído - executar um programa com ▶︎ e usar entradas e saídas na consola - pôr pontos de paragem e seguir um programa passo a passo ::: @@ -30322,25 +30326,25 @@ Isto ajuda-te a associar os blocos aos comandos Java. O teu diagrama em si fica ## Escrever Java diretamente -Até agora desenhaste primeiro o estrutograma e depois viste o código. Na área [Programação](#zeige-codelive) também funciona ao contrário. Clica na barra estreita **Programação** à direita. Ao lado do estrutograma aparece uma coluna onde escreves tu mesmo o Java. +Até agora desenhaste primeiro o estrutograma e depois viste o código. Na área [Código](#zeige-codelive) também funciona ao contrário. Clica na barra estreita **Código** à direita. Ao lado do estrutograma aparece uma coluna onde escreves tu mesmo o Java. - **Do estrutograma para o código:** Quando alteras alguma coisa no estrutograma, o código Java muda logo. - **Do código para o estrutograma:** Quando escreves Java, o VisuStruct constrói o estrutograma enquanto escreves. Se ainda faltar alguma coisa, por exemplo uma chaveta de fecho \`}\`, aparece uma indicação por baixo do código. - **Sugestões:** Enquanto escreves, o VisuStruct sugere modelos, por exemplo para \`if\`, \`for\` ou \`while\`. Com Enter aceitas um modelo. Substitui simplesmente os marcadores cinzentos pelo teu texto. -- **Indentar:** Se o teu código ficou desarrumado, clica no botão **Indentar** em cima na área Programação. Cada nível fica então quatro espaços mais para dentro, como no Eclipse ou no IntelliJ. Se tiveres linhas selecionadas, o VisuStruct só indenta essas. +- **Indentar:** Se o teu código ficou desarrumado, clica no botão **Indentar** em cima na área Código. Cada nível fica então quatro espaços mais para dentro, como no Eclipse ou no IntelliJ. Se tiveres linhas selecionadas, o VisuStruct só indenta essas. Assim podes experimentar os dois caminhos. Desenhar primeiro o estrutograma é bom para planear um processo. Escrever o código diretamente é mais rápido quando já sabes o que queres. O estrutograma ajuda-te depois a verificar o teu código. ## Executar o programa -Em cima, na área Programação, [▶︎ Executar](#zeige-ausfuehren) inicia o teu programa e **■ Parar** termina-o, por exemplo num ciclo infinito. O que o teu programa mostra aparece em baixo na [consola](#zeige-konsole). Se pedir uma entrada, escreve-a lá e carrega em Enter. +Em cima, na área Código, [▶︎ Executar](#zeige-ausfuehren) inicia o teu programa e **■ Parar** termina-o, por exemplo num ciclo infinito. O que o teu programa mostra aparece em baixo na [consola](#zeige-konsole). Se pedir uma entrada, escreve-a lá e carrega em Enter. Podes arrastar com o rato a fronteira entre o código e a consola para cima ou para baixo. -> A área Programação entende os comandos Java que também existem como blocos no estrutograma. Ainda não conhece classes próprias nem objetos. Janelas com Swing funcionam na mesma: liga o **Java verdadeiro (com Swing)** na roda dentada (lição “A tua primeira janela”). +> A área Código entende os comandos Java que também existem como blocos no estrutograma. Ainda não conhece classes próprias nem objetos. Janelas com Swing funcionam na mesma: liga o **Java verdadeiro (com Swing)** na roda dentada (lição “A tua primeira janela”). ::: angeberwissen -Os profissionais chamam **IDE** (Integrated Development Environment) a um programa onde se escreve código, se executa e se procuram erros. Com a área Programação, o VisuStruct é um pequeno IDE com estrutograma incluído. +Os profissionais chamam **IDE** (Integrated Development Environment) a um programa onde se escreve código, se executa e se procuram erros. Com a área Código, o VisuStruct é um pequeno IDE com estrutograma incluído. ::: ## Encontrar erros com o depurador @@ -30369,7 +30373,7 @@ System.out.println("Soma: " + soma); ## Exercício: Primeiro o código, depois o estrutograma -Desta vez não desenhas. Abre a área Programação e escreve este código Java: +Desta vez não desenhas. Abre a área Código e escreve este código Java: \`\`\` System.out.println("Número inicial?"); @@ -30383,13 +30387,14 @@ System.out.println("Start!"); ::: übung l20-countdown titel: Contagem decrescente -auftrag: Escreve o código Java acima na área Programação. Executa-o com ▶︎ e introduz um número inicial na consola. +bereich: beide +auftrag: Escreve o código Java acima na área Código. Executa-o com ▶︎ e introduz um número inicial na consola. Depois observa o estrutograma que foi construído e clica em Verificar. test: 3 -> 3 | 2 | 1 | Start! test: 1 -> 1 | Start! test: 0 -> Start! braucht: whileSchleife -tipp: Abre a área Programação com a barra estreita mais à direita e começa simplesmente a escrever. +tipp: Abre a área Código com a barra estreita mais à direita e começa simplesmente a escrever. tipp: Atenção ao ponto e vírgula no fim de cada instrução e às chavetas do ciclo while. Por baixo do código aparece uma indicação quando ainda falta alguma coisa. lösung: l20-countdown-loesung.visustruct ::: @@ -30410,6 +30415,7 @@ System.out.println(fatorial); ::: übung l17-fakultaet titel: Fatorial a partir de Java +bereich: beide auftrag: Reconstrói o código Java de cima como estrutograma. O programa lê um número n e mostra o produto 1 · 2 · … · n. No fim, confirma na vista de código se o teu código Java fica igual. test: 3 -> 6 @@ -30529,7 +30535,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - Consigo reconhecer em Java a saída, a entrada, as decisões e os ciclos. → Os elementos em Java - Consigo explicar a diferença entre Excerto e Classe. → Excerto ou Classe - Consigo reconstruir um programa Java curto como estrutograma. → Exercício: Java como estrutograma -- Consigo escrever Java na área Programação e ler o estrutograma que é construído. → Escrever Java diretamente +- Consigo escrever Java na área Código e ler o estrutograma que é construído. → Escrever Java diretamente - Consigo executar um programa com ▶︎ e usar entradas e saídas na consola. → Executar o programa - Consigo pôr pontos de paragem e seguir um programa passo a passo. → Encontrar erros com o depurador ::: @@ -30571,7 +30577,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] A linha tem um erro. > É um ponto de paragem. Continua-se com ▶︎ ou com Passo a passo. ::: -`,ov=`--- +`,lv=`--- titel: Python e JavaScript bereich: Do estrutograma ao código kurz: Gerar código Python e JavaScript a partir do estrutograma e executar JavaScript diretamente no navegador. @@ -30809,7 +30815,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] É mostrado Soma:. > str(soma) transforma o número em texto. ::: -`,lv=`--- +`,uv=`--- titel: Quando o programa falha: try e catch bereich: Apanhar erros kurz: Ler mensagens de erro com Java verdadeiro e apanhar falhas com try e catch. @@ -30818,7 +30824,7 @@ kurz: Ler mensagens de erro com Java verdadeiro e apanhar falhas com try e catch ## Competências que vou adquirir agora ::: kompetenzen -- ligar o Java verdadeiro na área Programação +- ligar o Java verdadeiro na área Código - ler numa mensagem de erro a exceção e a linha - apanhar uma exceção com try e catch - transformar texto num número com Integer.parseInt e apanhar a NumberFormatException @@ -30827,7 +30833,7 @@ kurz: Ler mensagens de erro com Java verdadeiro e apanhar falhas com try e catch ## Falhou! -Este programa deve escrever três notas. Escreve-o na área [Programação](#zeige-codelive) e clica em [▶︎ Executar](#zeige-ausfuehren): +Este programa deve escrever três notas. Escreve-o na área [Código](#zeige-codelive) e clica em [▶︎ Executar](#zeige-ausfuehren): \`\`\`java int[] notas = {2, 3, 1}; @@ -30848,7 +30854,7 @@ Em 1947, a equipa de Grace Hopper encontrou no computador Mark II da Universidad ## Ligar o Java verdadeiro -Normalmente a área Programação calcula com a mesma simulação que o estrutograma. Quando há um erro, ela simplesmente para. Para veres o que faz o Java verdadeiro, liga o Java verdadeiro: +Normalmente a área Código calcula com a mesma simulação que o estrutograma. Quando há um erro, ela simplesmente para. Para veres o que faz o Java verdadeiro, liga o Java verdadeiro: 1. Clica na [roda dentada](#zeige-einstellungen) em cima à direita e escolhe Java como **Linguagem de programação**. 2. Na secção Java, marca **Java verdadeiro (com Swing)**. @@ -30891,7 +30897,7 @@ Uma mensagem destas assusta à primeira vista. Mas diz-te exatamente o que se pa O Java chama a um erro destes, durante a execução, uma **exceção** (em inglês *exception*). Diz-se: o Java *lança* uma exceção. Se ninguém a apanhar, o programa para. É por isso que “Pronto!” não aparece. ::: ludwig -Lê as mensagens de erro sempre de cima: primeiro o nome da exceção, depois o número da linha. Na área Programação, os números das linhas estão à esquerda do código. +Lê as mensagens de erro sempre de cima: primeiro o nome da exceção, depois o número da linha. Na área Código, os números das linhas estão à esquerda do código. ::: ## try e catch @@ -31056,7 +31062,7 @@ A exceção chama-se \`ArithmeticException\`. Põe no bloco \`try\` só a linha 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. ::: checkliste -- Consigo ligar o Java verdadeiro na área Programação. → Ligar o Java verdadeiro +- Consigo ligar o Java verdadeiro na área Código. → Ligar o Java verdadeiro - Consigo ler numa mensagem de erro a exceção e a linha. → Ler a mensagem de erro - Consigo apanhar uma exceção com try e catch. → try e catch - Consigo transformar texto num número com Integer.parseInt e apanhar a NumberFormatException. → Transformar texto num número @@ -31092,7 +31098,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = ArithmeticException -> divisão por 0 = NumberFormatException -> o texto não é um número ::: -`,uv=`--- +`,cv=`--- titel: Ler e guardar texto bereich: Ficheiros kurz: Ler um ficheiro de texto linha a linha com Scanner e guardar um ficheiro com PrintWriter. @@ -31346,7 +31352,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = println(texto) -> escreve uma linha = close() -> fecha o ficheiro ::: -`,cv=`--- +`,mv=`--- titel: Linha a linha com BufferedReader bereich: Ficheiros kurz: Ler com BufferedReader e readLine até chegar null, e ler um ficheiro inteiro de uma vez com Files. @@ -31602,7 +31608,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = Files.readString -> ficheiros pequenos de uma vez = Scanner -> ler números e palavras ::: -`,mv=`--- +`,dv=`--- titel: Tabelas em CSV bereich: Ficheiros kurz: Ler uma tabela num ficheiro CSV, dividir cada linha com split e fazer contas com os números. @@ -31826,7 +31832,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = registo -> uma linha com valores = separador -> separa as colunas, muitas vezes ; ::: -`,dv=`--- +`,hv=`--- titel: Dados em JSON bereich: Ficheiros kurz: Perceber ficheiros JSON, tirar valores com indexOf e substring e escrever JSON tu mesmo. @@ -32051,7 +32057,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = [ ] -> uma lista = : -> separa a chave do valor ::: -`,hv=`--- +`,gv=`--- titel: Comparar formatos bereich: Ficheiros kurz: Comparar os mesmos dados em txt, CSV e JSON, escolher o formato certo e converter um ficheiro noutro formato. @@ -32226,7 +32232,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = a pauta de notas da turma -> CSV = um jogo guardado com listas -> JSON ::: -`,gv=`--- +`,pv=`--- titel: A tua primeira janela bereich: Janelas com Swing kurz: Abrir uma janela tua com Java e Swing, explicado linha a linha. @@ -32235,7 +32241,7 @@ kurz: Abrir uma janela tua com Java e Swing, explicado linha a linha. ## Competências que vou adquirir agora ::: kompetenzen -- ligar o “Java verdadeiro” na área Programação +- ligar o “Java verdadeiro” na área Código - abrir uma janela com título e tamanho - explicar o que faz cada linha do programa com janela - explicar porque é que setVisible(true) fica no fim @@ -32247,11 +32253,11 @@ Até agora os teus programas escreviam texto na consola. Mas a maioria dos progr O Java traz uma caixa de ferramentas para isso: o **Swing**. No VisuStruct ligas o Swing assim: -1. Abre à direita a área [Programação](#zeige-codelive). +1. Abre à direita a área [Código](#zeige-codelive). 2. Clica na [roda dentada](#zeige-einstellungen) em cima à direita e escolhe Java como **Linguagem de programação**. 3. Por baixo, na secção Java, marca **Java verdadeiro (com Swing)**. -Na primeira vez que clicas em [▶︎ Executar](#zeige-ausfuehren), o VisuStruct descarrega uma única vez cerca de 40 MB, o que demora um pouco. Depois disso o teu código corre como Java verdadeiro, e as tuas janelas aparecem na área Programação na área **Janelas Java**, por cima da consola. +Na primeira vez que clicas em [▶︎ Executar](#zeige-ausfuehren), o VisuStruct descarrega uma única vez cerca de 40 MB, o que demora um pouco. Depois disso o teu código corre como Java verdadeiro, e as tuas janelas aparecem na área Código na área **Janelas Java**, por cima da consola. > Com o “Java verdadeiro”, as entradas pela consola (\`Scanner\`) ainda não funcionam. Para programas com entradas, desliga outra vez a opção. @@ -32261,7 +32267,7 @@ O Swing existe desde 1998. Antes disso, o Java só tinha o AWT, mais antigo, com ## O programa completo -Este é o programa mais pequeno que abre uma janela. Escreve-o na área Programação e clica em [▶︎ Executar](#zeige-ausfuehren): +Este é o programa mais pequeno que abre uma janela. Escreve-o na área Código e clica em [▶︎ Executar](#zeige-ausfuehren): \`\`\`java import javax.swing.*; @@ -32405,7 +32411,7 @@ Altera o programa de forma que Executa-o e verifica os três pontos. ::: ludwig -Não te apetece escrever tanto? Com o “Java verdadeiro” podes escrever na área Programação só as quatro linhas de \`main\`. O VisuStruct põe-nas sozinho dentro de uma classe e acrescenta as linhas \`import\`. Num ambiente de desenvolvimento Java a sério precisas, no entanto, do programa completo. +Não te apetece escrever tanto? Com o “Java verdadeiro” podes escrever na área Código só as quatro linhas de \`main\`. O VisuStruct põe-nas sozinho dentro de uma classe e acrescenta as linhas \`import\`. Num ambiente de desenvolvimento Java a sério precisas, no entanto, do programa completo. ::: ## Lista de verificação @@ -32413,7 +32419,7 @@ Não te apetece escrever tanto? Com o “Java verdadeiro” podes escrever na á 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. ::: checkliste -- Consigo ligar o “Java verdadeiro” na área Programação. → Programas com janelas +- Consigo ligar o “Java verdadeiro” na área Código. → Programas com janelas - Consigo abrir uma janela com título e tamanho. → O programa completo - Consigo explicar o que faz cada linha do programa com janela. → Linha a linha - Consigo explicar porque é que setVisible(true) fica no fim. → Porque é que setVisible fica no fim @@ -32448,7 +32454,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Estão entre chavetas. - [ ] Terminam em Window. ::: -`,pv=`--- +`,fv=`--- titel: Um botão na janela bereich: Janelas com Swing kurz: Pôr um botão na janela e arrumá-lo bem com um layout. @@ -32664,7 +32670,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] No botão aparece “Fui clicado”. > O que deve acontecer com um clique aprendes na próxima lição. ::: -`,fv=`--- +`,bv=`--- titel: O botão reage bereich: Janelas com Swing kurz: Com um ActionListener decides o que acontece com um clique. @@ -33006,7 +33012,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = setText -> mudar o texto = setVisible(true) -> mostrar a janela ::: -`,bv=`--- +`,xv=`--- titel: Duplicar um número na janela bereich: Janelas com Swing kurz: Arrumar uma etiqueta, um campo de texto e um botão com um GridLayout e calcular com o texto do campo de texto. @@ -33287,7 +33293,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = JButton -> botão = GridLayout -> arrumação em grelha ::: -`,xv=`--- +`,vv=`--- titel: Contador de cliques com reset bereich: Janelas com Swing kurz: Dois botões alteram o mesmo número: criar uma variável para a classe toda. @@ -33519,7 +33525,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Põe a janela no meio do ecrã. - [ ] Aumenta a letra. ::: -`,vv=`--- +`,yv=`--- titel: Um semáforo com cores bereich: Janelas com Swing kurz: Definir cores de fundo e mudar um semáforo com uma variável de estado. @@ -33795,7 +33801,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] 3 > Depois de fase++ é 3, que é maior do que 2, por isso passa a 0. ::: -`,yv=`--- +`,wv=`--- titel: Calculadora de notas na janela bereich: Janelas com Swing kurz: Escrever a percentagem, determinar o nível com else if e apanhar entradas erradas. @@ -33851,7 +33857,7 @@ if (percentagem >= 90) { Com 75 %, \`percentagem >= 90\` é falso, mas \`percentagem >= 70\` é verdadeiro. Portanto nível 4, e as restantes condições já nem são verificadas. É por isso que basta sempre o limite de baixo. ::: -Podes experimentar esta parte sem janela na área [Programação](#zeige-codelive). Escreve \`int percentagem = 75;\` antes e \`System.out.println("Nível: " + nivel);\` depois. O estrutograma mostra-te as decisões encaixadas. +Podes experimentar esta parte sem janela na área [Código](#zeige-codelive). Escreve \`int percentagem = 75;\` antes e \`System.out.println("Nível: " + nivel);\` depois. O estrutograma mostra-te as decisões encaixadas. ## A janela @@ -34066,7 +34072,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] percentagem >= 0 || percentagem <= 100 > Um número não pode ser ao mesmo tempo menor do que 0 e maior do que 100, por isso é preciso o ou. ::: -`,wv=`--- +`,zv=`--- titel: Uma calculadora bereich: Janelas com Swing kurz: Duas colunas com GridLayout, quatro botões de cálculo e apanhar a divisão por 0. @@ -34337,7 +34343,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [ ] Coluna a coluna, começando de cima para baixo na coluna da esquerda - [ ] Ao acaso ::: -`,zv=`--- +`,Iv=`--- titel: Adivinha o número bereich: Janelas com Swing kurz: Um jogo com número aleatório, contagem de tentativas e um botão que se desliga no fim. @@ -34377,7 +34383,7 @@ int secreto = (int) (Math.random() * 100) + 1; Sem o \`+ 1\` sairia de 0 a 99. -Experimenta na área [Programação](#zeige-codelive): \`int secreto = (int) (Math.random() * 100) + 1;\` e \`System.out.println(secreto);\`. Cada execução dá um número diferente. +Experimenta na área [Código](#zeige-codelive): \`int secreto = (int) (Math.random() * 100) + 1;\` e \`System.out.println(secreto);\`. Cada execução dá um número diferente. ::: angeberwissen Na verdade, os computadores não sabem lançar dados. O \`Math.random()\` calcula com uma fórmula uma longa sequência de números que só **parecem** aleatórios. Chamam-se números pseudoaleatórios. Para jogos chega perfeitamente. @@ -34493,7 +34499,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ - [x] 7 > Cada palpite corta o intervalo a meio, e 2 elevado a 7 = 128 é maior do que 100. ::: -`,Iv=`--- +`,kv=`--- titel: Muitos botões, um ouvinte bereich: Janelas com Swing kurz: Um ouvinte para muitos botões e descobrir com getActionCommand e getSource qual foi o botão clicado. @@ -34797,7 +34803,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = ActionEvent -> o evento e com a informação sobre o clique = JPanel -> uma área com o seu próprio layout ::: -`,kv=`--- +`,Sv=`--- titel: Classes internas bereich: Janelas com Swing kurz: Escrever um ouvinte como classe interna com nome, como classe anónima e como lambda, e saber quem vê o quê. @@ -35029,7 +35035,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = new ActionListener() { … } -> classe anónima = a seta depois de e -> lambda ::: -`,Sv=`--- +`,Tv=`--- titel: Dois separadores bereich: Janelas com Swing kurz: Construir uma janela com dois separadores, levar dados de um separador para o outro e guardar a lista num ficheiro de texto. @@ -35310,7 +35316,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = JPanel -> a área de um separador = JTextArea -> uma área de texto com várias linhas ::: -`,Tv=`--- +`,_v=`--- titel: Model View Controller bereich: Janelas com Swing kurz: Dividir o contador de cliques em model, view e controller e perceber quem fala com quem. @@ -35725,7 +35731,7 @@ Avalia-te com honestidade em cada ponto: ☂️ ainda não, ⛅ em parte, ☀️ = VistaNumero com atualizar(int valor) -> view = o ouvinte do botão -> controller ::: -`,_v=`Termos técnicos da área de aprendizagem. Quando um termo aparece num passo, fica marcado uma vez e mostra a sua +`,Ov=`Termos técnicos da área de aprendizagem. Quando um termo aparece num passo, fica marcado uma vez e mostra a sua explicação ao passar o rato ou ao tocar. Se estiver a negrito nesse passo, é explicado ali mesmo e não é marcado. \`auch:\` indica outras formas que também são reconhecidas. Maiúsculas e minúsculas contam. @@ -35931,7 +35937,7 @@ Um bloco pronto do Java que lê entradas do teclado, por exemplo um número com ### import Uma linha mesmo no início do código Java que vai buscar um bloco pronto a um pacote, por exemplo \`import java.util.Scanner;\`. Sem ela, o Java não conhece o nome. -`,Ov=`## Elementos básicos +`,Av=`## Elementos básicos ### Instrução @@ -36071,7 +36077,7 @@ boolean[][] lugares = new boolean[3][5] lugares[1][4] = true output: lugares.length + " filas, " + lugares[0].length + " lugares" \`\`\` -`,Av=`--- +`,Cv=`--- titel: Alter im Unterprogramm nach: 18 stufe: 2 @@ -36092,7 +36098,7 @@ tipp: Öffne die Übung im Editor und baue dort das Hauptprogramm mit dem Aufruf lösung: aufgabe-alter-haupt-loesung.visustruct unterprogramm: aufgabe-alter-unterprogramm-loesung.visustruct ::: -`,Cv=`--- +`,jv=`--- titel: Ballwurf auswerten nach: 25 stufe: 2 @@ -36155,7 +36161,7 @@ tipp: Lies jede Zahl erst in eine Variable ein und schreibe sie dann ins Array: tipp: Der Tausch braucht auch in Java eine Hilfsvariable: \`int hilf = punkte[i]; punkte[i] = punkte[i + 1]; punkte[i + 1] = hilf;\`. lösung: aufgabe-bestenliste-loesung.visustruct ::: -`,jv=`--- +`,Dv=`--- titel: Binärzahl nach: 11 stufe: 3 @@ -36197,7 +36203,7 @@ tipp: Fang mit \`String binaer = "";\` an. Die Schleife läuft mit \`while (zahl tipp: Im Rumpf: \`int rest = zahl % 2;\`, dann \`binaer = rest + binaer;\` und \`zahl = zahl / 2;\`. Weil \`binaer\` ein String ist, hängt \`+\` den Rest vorne an. lösung: aufgabe-binaer-loesung.visustruct ::: -`,Dv=`--- +`,Bv=`--- titel: Caesar-Verschlüsselung nach: 17 stufe: 3 @@ -36331,7 +36337,7 @@ lösung: aufgabe-caesar-entschluesseln-loesung.visustruct ::: angeberwissen Sicher ist Caesar leider nicht. Es gibt nur 25 Schlüssel, die kann man in ein paar Minuten alle ausprobieren. Noch schneller geht es mit einem Trick: Im Deutschen ist E der häufigste Buchstabe. Kommt im Geheimtext H am häufigsten vor, war der Schlüssel wohl 3. Im Internet gibt es übrigens ROT13, das ist Caesar mit dem Schlüssel 13. Zweimal ROT13 ergibt wieder den Klartext, weil 13 + 13 = 26. ::: -`,Bv=`--- +`,Zv=`--- titel: Collatz-Folge nach: 11 stufe: 2 @@ -36375,7 +36381,7 @@ lösung: aufgabe-collatz-loesung.visustruct ::: angeberwissen Mit dieser Aufgabe kann man reich werden! Der Mathematiker Paul Erdős setzte für einen Beweis 500 Dollar aus. 2021 legte die japanische Firma Bakuage noch einiges drauf: 120 Millionen Yen, damals umgerechnet rund eine Million Dollar, für einen Beweis oder ein Gegenbeispiel. Abgeholt hat das Geld bis heute niemand. Erfunden hat das Rätsel übrigens der deutsche Mathematiker Lothar Collatz im Jahr 1937. Ich rechne gleich mal los, für so viel Geld gibt es eine Menge Heu. ::: -`,Zv=`--- +`,Mv=`--- titel: Einheitenrechner nach: 35 stufe: 2 @@ -36424,7 +36430,7 @@ Zusatz: Ein vierter Knopf **in Fuß** rechnet in die englische Einheit um. Ein F ::: ludwig Tick im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** an. Für „abc“ im Feld brauchst du in jedem Zuhörer ein try/catch mit \`NumberFormatException\`, wie beim Taschenrechner. ::: -`,Mv=`--- +`,Lv=`--- titel: Fibonacci-Zahlen nach: 13 stufe: 2 @@ -36478,7 +36484,7 @@ lösung: aufgabe-fibonacci-loesung.visustruct - [ ] Die Reihenfolge ist egal > Andersherum hätten zahl1 und zahl2 danach denselben Wert. Wie beim Tauschen gilt: Erst retten, dann überschreiben. ::: -`,Lv=`--- +`,Ev=`--- titel: Gerade oder ungerade nach: 8 stufe: 1 @@ -36514,7 +36520,7 @@ tipp: Eine Zahl liest du mit \`int zahl = scanner.nextInt();\` ein. Vorher frags tipp: \`if (zahl % 2 == 0) { … } else { … }\`. Die Ausgabe ist \`System.out.println(zahl + " ist gerade");\`. lösung: aufgabe-gerade-loesung.visustruct ::: -`,Ev=`--- +`,Wv=`--- titel: Mehrwertsteuer nach: 6 stufe: 1 @@ -36555,7 +36561,7 @@ lösung: aufgabe-mehrwertsteuer-loesung.visustruct - [ ] Weil man Kommazahlen nur als Konstante speichern kann > Eine Konstante behält ihren Wert. Ändert sich der Steuersatz einmal, passt du nur die eine Zeile mit \`const\` an. ::: -`,Wv=`--- +`,Nv=`--- titel: Notendurchschnitt nach: 13 stufe: 2 @@ -36590,7 +36596,7 @@ tipp: \`for (int i = 0; i < anzahl; i++)\` liest genau so viele Noten ein, wie v tipp: Teile mit \`double schnitt = summe * 1.0 / anzahl;\`. Ohne \`* 1.0\` teilt Java zwei \`int\` ganzzahlig, und aus 1.5 wird 1. lösung: aufgabe-durchschnitt-loesung.visustruct ::: -`,Nv=`--- +`,Fv=`--- titel: PIN prüfen nach: 12 stufe: 2 @@ -36630,7 +36636,7 @@ tipp: \`do { … } while (…);\` fragt mindestens einmal. Hinter \`while (…)\ tipp: Lege vorher \`int pin = 0;\` und \`int versuche = 0;\` an. In der Schleife: \`int eingabe = scanner.nextInt();\`, \`pin = eingabe;\` und \`versuche++;\`. Die Bedingung ist \`pin != 1234 && versuche < 3\`. lösung: aufgabe-pin-java-loesung.visustruct ::: -`,Fv=`--- +`,Jv=`--- titel: Schiffe versenken nach: 16 stufe: 2 @@ -36667,7 +36673,7 @@ tipp: Zwei \`for\`-Schleifen ineinander: außen die Reihe, innen die Spalte, bei tipp: \`if (meer[reihe][spalte]) { System.out.println(spalten[spalte] + (reihe + 1)); }\`. Die Klammer um \`reihe + 1\` sorgt dafür, dass Java erst rechnet. lösung: aufgabe-schiffe-loesung.visustruct ::: -`,Jv=`--- +`,Rv=`--- titel: Speisekarte nach: 10 stufe: 1 @@ -36703,7 +36709,7 @@ tipp: In Java ist das eine Fallauswahl mit \`switch (nummer) { … }\`. tipp: Jeder Fall sieht so aus: \`case 1 -> { System.out.println("…"); }\`. Für alle anderen Nummern gibt es \`default -> { … }\`. lösung: aufgabe-speisekarte-loesung.visustruct ::: -`,Rv=`--- +`,Gv=`--- titel: Summe bilden nach: 2 stufe: 1 @@ -36719,7 +36725,7 @@ tipp: Du brauchst drei Variablen: zwei für die Zahlen und eine für das Ergebni tipp: Eine Variable legst du mit einer Anweisung wie \`int zahl1 = 4\` fest. Für die Ausgabe schreibst du den Namen der Variablen ohne Anführungszeichen. lösung: aufgabe-summe-loesung.visustruct ::: -`,Gv=`--- +`,Hv=`--- titel: Tafeldienst auslosen nach: 15 stufe: 2 @@ -36756,7 +36762,7 @@ lösung: aufgabe-tafeldienst-loesung.visustruct ::: > Mit \`int nummer = (int) (Math.random() * 5) + 1\` kannst du die Losnummer auch vom Zufall ziehen lassen. Für die automatische Prüfung brauchen wir aber eine feste Eingabe. -`,Hv=`--- +`,Vv=`--- titel: Taschenrechner nach: 10 stufe: 2 @@ -36792,7 +36798,7 @@ tipp: Das Rechenzeichen ist ein Text. Du liest es mit \`String zeichen = scanner tipp: \`switch (zeichen) { case "+" -> { … } … default -> { … } }\`. Bei Texten stehen die Fälle in Anführungszeichen. lösung: aufgabe-rechner-loesung.visustruct ::: -`,Vv=`--- +`,qv=`--- titel: Verleih-Menü nach: 18 stufe: 2 @@ -36827,7 +36833,7 @@ tipp: \`while (true) { … }\` läuft endlos, bis ein \`break;\` kommt. tipp: Nimm in Java hier \`if\`/\`else if\` statt \`switch\`: Ein \`break;\` in einem \`switch\` verlässt nur den \`switch\`, nicht die Schleife. \`if (wahl == 0) { System.out.println("Tschüss"); break; } else if (wahl == 1) { … }\`. lösung: aufgabe-verleih-java-loesung.visustruct ::: -`,qv=`--- +`,Qv=`--- titel: Vokabeltrainer nach: 27 stufe: 3 @@ -36862,7 +36868,7 @@ tipp: Überspringe die Kopfzeile. In der Schleife zerlegst du jede Zeile mit \`s tipp: Texte vergleichst du mit \`antwort.equals(teile[1])\`, nicht mit \`==\`. Zähle vor der Schleife mit \`int richtig = 0;\` und \`int anzahl = 0;\` mit. lösung: aufgabe-vokabeln-loesung.visustruct ::: -`,Qv=`--- +`,Uv=`--- titel: Volljährig? nach: 8 stufe: 1 @@ -36898,7 +36904,7 @@ tipp: Lies das Alter mit \`int alter = scanner.nextInt();\` ein. tipp: \`if (alter >= 18) { … } else { … }\`, in jedem Zweig ein \`System.out.println(…)\`. lösung: aufgabe-volljaehrig-loesung.visustruct ::: -`,Uv=`--- +`,$v=`--- titel: Würfeln mit MVC nach: 40 stufe: 3 @@ -36936,7 +36942,7 @@ Zusatz: Ein Knopf **Neues Spiel** setzt alles auf Anfang. Die Methode dafür geh ::: ludwig Denk an die Regel aus Lektion 40: Im Model steht kein einziges \`JLabel\`. Wenn du beim Würfeln die Schriftgröße änderst, gehört das in die View. ::: -`,$v=`--- +`,Yv=`--- titel: Zahl verdoppeln nach: 2 stufe: 1 @@ -36952,7 +36958,7 @@ tipp: Verdoppeln heißt: mal 2. Das Ergebnis speicherst du wieder in derselben V tipp: \`zahl = zahl * 2\` rechnet mit dem alten Wert und speichert das Ergebnis wieder in \`zahl\`. Text und Variable verbindest du mit \`+\`. lösung: aufgabe-verdoppeln-loesung.visustruct ::: -`,Yv=`--- +`,Xv=`--- titel: Age in a subprogram nach: 18 stufe: 2 @@ -36973,7 +36979,7 @@ tipp: Open the exercise in the editor and build the main program there with the lösung: aufgabe-alter-haupt-loesung.visustruct unterprogramm: aufgabe-alter-unterprogramm-loesung.visustruct ::: -`,Xv=`--- +`,Kv=`--- titel: Ball throw results nach: 25 stufe: 2 @@ -37002,7 +37008,7 @@ tipp: You need four variables before the loop: the count, the sum as a \`double\ tipp: In the loop: \`String[] parts = line.split(";");\` and \`int distance = Integer.parseInt(parts[1]);\`. If \`distance > bestDistance\`, remember the distance and the name. To save: \`PrintWriter out = new PrintWriter("winner.txt");\`, \`out.println(…)\` and \`out.close();\`. lösung: aufgabe-ballwurf-loesung.visustruct ::: -`,Kv=`--- +`,ey=`--- titel: Leaderboard nach: 19 stufe: 2 @@ -37036,7 +37042,7 @@ tipp: Read each number into a variable first and then put it into the array: \`i tipp: The swap needs a temporary variable in Java too: \`int temp = points[i]; points[i] = points[i + 1]; points[i + 1] = temp;\`. lösung: aufgabe-bestenliste-loesung.visustruct ::: -`,ey=`--- +`,ty=`--- titel: Binary number nach: 11 stufe: 3 @@ -37078,7 +37084,7 @@ tipp: Start with \`String binary = "";\`. The loop runs with \`while (number > 0 tipp: In the body: \`int remainder = number % 2;\`, then \`binary = remainder + binary;\` and \`number = number / 2;\`. Because \`binary\` is a String, \`+\` puts the remainder at the front. lösung: aufgabe-binaer-loesung.visustruct ::: -`,ty=`--- +`,ny=`--- titel: Caesar cipher nach: 17 stufe: 3 @@ -37212,7 +37218,7 @@ lösung: aufgabe-caesar-entschluesseln-loesung.visustruct ::: angeberwissen Unfortunately, Caesar is not secure. There are only 25 keys, and you can try them all in a few minutes. It is even quicker with a trick: in English, E is the most common letter. If H is the most common letter in the secret text, the key was probably 3. On the internet there is also ROT13, which is Caesar with the key 13. Applying ROT13 twice gives you the plain text again, because 13 + 13 = 26. ::: -`,ny=`--- +`,iy=`--- titel: Collatz sequence nach: 11 stufe: 2 @@ -37256,7 +37262,7 @@ lösung: aufgabe-collatz-loesung.visustruct ::: angeberwissen This task could make you rich! The mathematician Paul Erdős offered 500 dollars for a proof. In 2021 the Japanese company Bakuage added quite a bit more: 120 million yen, about a million dollars at the time, for a proof or a counterexample. Nobody has collected the money yet. By the way, the puzzle was invented by the German mathematician Lothar Collatz in 1937. I am going to start calculating right now; that much money buys a lot of hay. ::: -`,iy=`--- +`,ay=`--- titel: Unit converter nach: 35 stufe: 2 @@ -37305,7 +37311,7 @@ Extra: a fourth button **in feet** converts to the imperial unit. One foot is 0. ::: ludwig Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). For "abc" in the field, every listener needs a try/catch with \`NumberFormatException\`, just like the calculator. ::: -`,ay=`--- +`,sy=`--- titel: Fibonacci numbers nach: 13 stufe: 2 @@ -37359,7 +37365,7 @@ lösung: aufgabe-fibonacci-loesung.visustruct - [ ] The order does not matter > The other way round, number1 and number2 would have the same value afterwards. Just like swapping: first save, then overwrite. ::: -`,sy=`--- +`,ry=`--- titel: Even or odd nach: 8 stufe: 1 @@ -37395,7 +37401,7 @@ tipp: Read a number with \`int number = scanner.nextInt();\`. Ask with \`System. tipp: \`if (number % 2 == 0) { … } else { … }\`. The output is \`System.out.println(number + " is even");\`. lösung: aufgabe-gerade-loesung.visustruct ::: -`,ry=`--- +`,oy=`--- titel: Sales tax nach: 6 stufe: 1 @@ -37436,7 +37442,7 @@ lösung: aufgabe-mehrwertsteuer-loesung.visustruct - [ ] Because decimal numbers can only be stored as constants > A constant keeps its value. If the tax rate ever changes, you only change the one line with \`const\`. ::: -`,oy=`--- +`,ly=`--- titel: Grade average nach: 13 stufe: 2 @@ -37471,7 +37477,7 @@ tipp: \`for (int i = 0; i < count; i++)\` reads exactly as many grades as were g tipp: Divide with \`double average = sum * 1.0 / count;\`. Without \`* 1.0\`, Java divides two \`int\` values as whole numbers, and 1.5 becomes 1. lösung: aufgabe-durchschnitt-loesung.visustruct ::: -`,ly=`--- +`,uy=`--- titel: Check the PIN nach: 12 stufe: 2 @@ -37511,7 +37517,7 @@ tipp: \`do { … } while (…);\` asks at least once. There is a semicolon after tipp: Create \`int pin = 0;\` and \`int attempts = 0;\` first. In the loop: \`int entered = scanner.nextInt();\`, \`pin = entered;\` and \`attempts++;\`. The condition is \`pin != 1234 && attempts < 3\`. lösung: aufgabe-pin-java-loesung.visustruct ::: -`,uy=`--- +`,cy=`--- titel: Battleship nach: 16 stufe: 2 @@ -37548,7 +37554,7 @@ tipp: Two \`for\` loops inside each other: the row outside, the column inside, b tipp: \`if (sea[row][column]) { System.out.println(columns[column] + (row + 1)); }\`. The brackets around \`row + 1\` make Java calculate first. lösung: aufgabe-schiffe-loesung.visustruct ::: -`,cy=`--- +`,my=`--- titel: Menu nach: 10 stufe: 1 @@ -37584,7 +37590,7 @@ tipp: In Java this is a switch: \`switch (pick) { … }\`. tipp: Every case looks like this: \`case 1 -> { System.out.println("…"); }\`. All other numbers go to \`default -> { … }\`. lösung: aufgabe-speisekarte-loesung.visustruct ::: -`,my=`--- +`,dy=`--- titel: Add up nach: 2 stufe: 1 @@ -37600,7 +37606,7 @@ tipp: You need three variables: two for the numbers and one for the result. tipp: You set a variable with a statement such as \`int number1 = 4\`. For the output you write the name of the variable without quotation marks. lösung: aufgabe-summe-loesung.visustruct ::: -`,dy=`--- +`,hy=`--- titel: Draw for board duty nach: 15 stufe: 2 @@ -37637,7 +37643,7 @@ lösung: aufgabe-tafeldienst-loesung.visustruct ::: > With \`int pick = (int) (Math.random() * 5) + 1\` you can also let chance draw the number. But for the automatic check we need a fixed input. -`,hy=`--- +`,gy=`--- titel: Calculator nach: 10 stufe: 2 @@ -37673,7 +37679,7 @@ tipp: The operator is a text. Read it with \`String operator = scanner.next();\` tipp: \`switch (operator) { case "+" -> { … } … default -> { … } }\`. With texts, the cases are in quotation marks. lösung: aufgabe-rechner-loesung.visustruct ::: -`,gy=`--- +`,py=`--- titel: Rental menu nach: 18 stufe: 2 @@ -37708,7 +37714,7 @@ tipp: \`while (true) { … }\` runs forever until a \`break;\` comes. tipp: In Java, use \`if\`/\`else if\` here instead of \`switch\`: a \`break;\` inside a \`switch\` only leaves the \`switch\`, not the loop. \`if (choice == 0) { System.out.println("Bye"); break; } else if (choice == 1) { … }\`. lösung: aufgabe-verleih-java-loesung.visustruct ::: -`,py=`--- +`,fy=`--- titel: Vocabulary trainer nach: 27 stufe: 3 @@ -37743,7 +37749,7 @@ tipp: Skip the header line. In the loop, split every line with \`split(";")\`: \ tipp: Compare texts with \`answer.equals(parts[1])\`, not with \`==\`. Count along with \`int right = 0;\` and \`int count = 0;\` before the loop. lösung: aufgabe-vokabeln-loesung.visustruct ::: -`,fy=`--- +`,by=`--- titel: Adult? nach: 8 stufe: 1 @@ -37779,7 +37785,7 @@ tipp: Read the age with \`int age = scanner.nextInt();\`. tipp: \`if (age >= 18) { … } else { … }\`, with a \`System.out.println(…)\` in each branch. lösung: aufgabe-volljaehrig-loesung.visustruct ::: -`,by=`--- +`,xy=`--- titel: Rolling dice with MVC nach: 40 stufe: 3 @@ -37817,7 +37823,7 @@ Extra: a button **New game** resets everything. The method for that belongs in t ::: ludwig Remember the rule from lesson 40: there isn't a single \`JLabel\` in the model. If you change the font size when rolling, that belongs in the view. ::: -`,xy=`--- +`,vy=`--- titel: Double a number nach: 2 stufe: 1 @@ -37833,7 +37839,7 @@ tipp: Doubling means: times 2. You store the result in the same variable again. tipp: \`number = number * 2\` calculates with the old value and stores the result in \`number\` again. You join text and a variable with \`+\`. lösung: aufgabe-verdoppeln-loesung.visustruct ::: -`,vy=`--- +`,yy=`--- titel: Idade num subprograma nach: 18 stufe: 2 @@ -37854,7 +37860,7 @@ tipp: Abre o exercício no editor e constrói lá o programa principal com a cha lösung: aufgabe-alter-haupt-loesung.visustruct unterprogramm: aufgabe-alter-unterprogramm-loesung.visustruct ::: -`,yy=`--- +`,wy=`--- titel: Avaliar o lançamento da bola nach: 25 stufe: 2 @@ -37883,7 +37889,7 @@ tipp: Precisas de quatro variáveis antes do ciclo: a contagem, a soma como \`do tipp: No ciclo: \`String[] partes = linha.split(";");\` e \`int distancia = Integer.parseInt(partes[1]);\`. Se \`distancia > melhorDistancia\`, guarda a distância e o nome. Para guardar: \`PrintWriter saida = new PrintWriter("vencedor.txt");\`, \`saida.println(…)\` e \`saida.close();\`. lösung: aufgabe-ballwurf-loesung.visustruct ::: -`,wy=`--- +`,zy=`--- titel: Classificação nach: 19 stufe: 2 @@ -37917,7 +37923,7 @@ tipp: Lê cada número primeiro para uma variável e depois põe-no no array: \` tipp: A troca também precisa de uma variável auxiliar em Java: \`int aux = pontos[i]; pontos[i] = pontos[i + 1]; pontos[i + 1] = aux;\`. lösung: aufgabe-bestenliste-loesung.visustruct ::: -`,zy=`--- +`,Iy=`--- titel: Número binário nach: 11 stufe: 3 @@ -37959,7 +37965,7 @@ tipp: Começa com \`String binario = "";\`. O ciclo corre com \`while (numero > tipp: No corpo: \`int resto = numero % 2;\`, depois \`binario = resto + binario;\` e \`numero = numero / 2;\`. Como \`binario\` é uma String, o \`+\` põe o resto à frente. lösung: aufgabe-binaer-loesung.visustruct ::: -`,Iy=`--- +`,ky=`--- titel: Cifra de César nach: 17 stufe: 3 @@ -38093,7 +38099,7 @@ lösung: aufgabe-caesar-entschluesseln-loesung.visustruct ::: angeberwissen Infelizmente, a cifra de César não é segura. Há apenas 25 chaves, e é possível experimentá-las todas em poucos minutos. Com um truque é ainda mais rápido: em português, as letras mais frequentes são o A e o E. Se no texto cifrado o H aparecer muitas vezes, a chave foi provavelmente 3. Na internet existe ainda o ROT13, que é a cifra de César com a chave 13. Aplicar ROT13 duas vezes devolve o texto simples, porque 13 + 13 = 26. ::: -`,ky=`--- +`,Sy=`--- titel: Sequência de Collatz nach: 11 stufe: 2 @@ -38137,7 +38143,7 @@ lösung: aufgabe-collatz-loesung.visustruct ::: angeberwissen Esta tarefa pode tornar-te rico! O matemático Paul Erdős ofereceu 500 dólares por uma demonstração. Em 2021, a empresa japonesa Bakuage juntou bastante mais: 120 milhões de ienes, na altura cerca de um milhão de dólares, por uma demonstração ou um contraexemplo. Ainda ninguém foi buscar o dinheiro. Já agora, o enigma foi inventado pelo matemático alemão Lothar Collatz em 1937. Vou já começar a fazer contas; com tanto dinheiro compra-se muito feno. ::: -`,Sy=`--- +`,Ty=`--- titel: Conversor de unidades nach: 35 stufe: 2 @@ -38186,7 +38192,7 @@ Extra: um quarto botão **em pés** converte para a unidade inglesa. Um pé são ::: ludwig Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). Para "abc" no campo, cada ouvinte precisa de um try/catch com \`NumberFormatException\`, tal como na calculadora. ::: -`,Ty=`--- +`,_y=`--- titel: Números de Fibonacci nach: 13 stufe: 2 @@ -38240,7 +38246,7 @@ lösung: aufgabe-fibonacci-loesung.visustruct - [ ] A ordem não importa > Ao contrário, numero1 e numero2 ficariam depois com o mesmo valor. Tal como na troca: primeiro guardar, depois substituir. ::: -`,_y=`--- +`,Oy=`--- titel: Par ou ímpar nach: 8 stufe: 1 @@ -38276,7 +38282,7 @@ tipp: Lês um número com \`int numero = scanner.nextInt();\`. Antes disso pergu tipp: \`if (numero % 2 == 0) { … } else { … }\`. A saída é \`System.out.println(numero + " é par");\`. lösung: aufgabe-gerade-loesung.visustruct ::: -`,Oy=`--- +`,Ay=`--- titel: IVA nach: 6 stufe: 1 @@ -38317,7 +38323,7 @@ lösung: aufgabe-mehrwertsteuer-loesung.visustruct - [ ] Porque os números decimais só podem ser guardados como constantes > Uma constante mantém o seu valor. Se a taxa alguma vez mudar, só alteras a linha com \`const\`. ::: -`,Ay=`--- +`,Cy=`--- titel: Média das notas nach: 13 stufe: 2 @@ -38352,7 +38358,7 @@ tipp: \`for (int i = 0; i < quantidade; i++)\` lê exatamente as notas que foram tipp: Divide com \`double media = soma * 1.0 / quantidade;\`. Sem \`* 1.0\`, o Java divide dois \`int\` como inteiros, e 1.5 passa a 1. lösung: aufgabe-durchschnitt-loesung.visustruct ::: -`,Cy=`--- +`,jy=`--- titel: Verificar o PIN nach: 12 stufe: 2 @@ -38429,7 +38435,7 @@ tipp: Dois ciclos \`for\` um dentro do outro: fora a fila, dentro a coluna, ambo tipp: \`if (mar[fila][coluna]) { System.out.println(colunas[coluna] + (fila + 1)); }\`. Os parênteses à volta de \`fila + 1\` fazem o Java calcular primeiro. lösung: aufgabe-schiffe-loesung.visustruct ::: -`,jy=`--- +`,Dy=`--- titel: Ementa nach: 10 stufe: 1 @@ -38465,7 +38471,7 @@ tipp: Em Java isto é uma seleção com \`switch (prato) { … }\`. tipp: Cada caso é assim: \`case 1 -> { System.out.println("…"); }\`. Para todos os outros números há \`default -> { … }\`. lösung: aufgabe-speisekarte-loesung.visustruct ::: -`,Dy=`--- +`,By=`--- titel: Somar nach: 2 stufe: 1 @@ -38481,7 +38487,7 @@ tipp: Precisas de três variáveis: duas para os números e uma para o resultado tipp: Defines uma variável com uma instrução como \`int numero1 = 4\`. Na saída escreves o nome da variável sem aspas. lösung: aufgabe-summe-loesung.visustruct ::: -`,By=`--- +`,Zy=`--- titel: Sortear quem limpa o quadro nach: 15 stufe: 2 @@ -38518,7 +38524,7 @@ lösung: aufgabe-tafeldienst-loesung.visustruct ::: > Com \`int sorteado = (int) (Math.random() * 5) + 1\` também podes deixar o acaso sortear o número. Mas para a verificação automática precisamos de uma entrada fixa. -`,Zy=`--- +`,My=`--- titel: Calculadora nach: 10 stufe: 2 @@ -38554,7 +38560,7 @@ tipp: O operador é um texto. Lês com \`String operador = scanner.next();\`. tipp: \`switch (operador) { case "+" -> { … } … default -> { … } }\`. Com textos, os casos ficam entre aspas. lösung: aufgabe-rechner-loesung.visustruct ::: -`,My=`--- +`,Ly=`--- titel: Menu de aluguer nach: 18 stufe: 2 @@ -38589,7 +38595,7 @@ tipp: \`while (true) { … }\` corre sem fim até aparecer um \`break;\`. tipp: Em Java usa aqui \`if\`/\`else if\` em vez de \`switch\`: um \`break;\` dentro de um \`switch\` só sai do \`switch\`, não do ciclo. \`if (escolha == 0) { System.out.println("Adeus"); break; } else if (escolha == 1) { … }\`. lösung: aufgabe-verleih-java-loesung.visustruct ::: -`,Ly=`--- +`,Ey=`--- titel: Treino de vocabulário nach: 27 stufe: 3 @@ -38624,7 +38630,7 @@ tipp: Salta a linha de cabeçalho. No ciclo, divide cada linha com \`split(";")\ tipp: Os textos comparam-se com \`resposta.equals(partes[1])\`, não com \`==\`. Conta com \`int certas = 0;\` e \`int contagem = 0;\` antes do ciclo. lösung: aufgabe-vokabeln-loesung.visustruct ::: -`,Ey=`--- +`,Wy=`--- titel: Maior de idade? nach: 8 stufe: 1 @@ -38660,7 +38666,7 @@ tipp: Lê a idade com \`int idade = scanner.nextInt();\`. tipp: \`if (idade >= 18) { … } else { … }\`, com um \`System.out.println(…)\` em cada ramo. lösung: aufgabe-volljaehrig-loesung.visustruct ::: -`,Wy=`--- +`,Ny=`--- titel: Lançar o dado com MVC nach: 40 stufe: 3 @@ -38698,7 +38704,7 @@ Extra: um botão **Novo jogo** põe tudo no início. O método para isso pertenc ::: ludwig Lembra-te da regra da lição 40: no model não há um único \`JLabel\`. Se mudares o tamanho da letra ao lançar, isso pertence à view. ::: -`,Ny=`--- +`,Fy=`--- titel: Duplicar um número nach: 2 stufe: 1 @@ -38714,7 +38720,7 @@ tipp: Duplicar quer dizer: vezes 2. Guardas o resultado outra vez na mesma vari tipp: \`numero = numero * 2\` calcula com o valor antigo e volta a guardar o resultado em \`numero\`. Juntas texto e uma variável com \`+\`. lösung: aufgabe-verdoppeln-loesung.visustruct ::: -`,Fy=`--- +`,Jy=`--- titel: Der mBot2 bereich: VisuBot kurz: Lerne den Roboter kennen, den du gleich programmierst. @@ -39046,7 +39052,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann den echten mBot2 per USB-C verbinden und wieder trennen. → Den echten mBot2 verbinden - Ich kann prüfen, ob alle Sensoren und Aktoren funktionieren. → Den mBot2 testen ::: -`,Jy=`--- +`,Ry=`--- titel: Das Quadrat bereich: VisuBot kurz: Vom langen Struktogramm zur dreifach verschachtelten Schleife. @@ -39183,7 +39189,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann drei Schleifen ineinander schachteln. → Vier Quadrate - Ich kann mein Programm auf den mBot2 übertragen und ohne Kabel mit Taste A starten. → Ohne Kabel fahren ::: -`,Ry='---\ntitel: Variablen und Ausgabe\nbereich: VisuBot\nkurz: Werte in Variablen speichern, den mBot2 damit fahren lassen und Ergebnisse ausgeben.\n---\n\n## Diese Kompetenzen erwerbe ich jetzt\n\n::: kompetenzen\n- eine Variable anlegen und benutzen\n- die Datentypen `int`, `double`, `String` und `boolean` unterscheiden\n- mit zwei Variablen ein Rechteck in Java fahren\n- mit `System.out.println` etwas ausgeben\n:::\n\n## Eine Variable für die Seite\n\nMit `mbot.forward(30)` fährt der mBot2 30 cm am Stück. Fährst du damit ein Quadrat ohne Schleife, steht die 30 aber viermal im Programm. Soll das Quadrat größer werden, musst du sie an vier Stellen ändern. Besser ist es, die Seitenlänge **einmal** zu speichern und dann überall zu benutzen.\n\nDafür gibt es **Variablen**. Eine Variable ist ein Kästchen mit einem Namen, in dem ein Wert liegt:\n\n```java\nint seite = 30;\nmbot.forward(seite);\n```\n\n- `int` ist der **Datentyp**: eine ganze Zahl.\n- `seite` ist der **Name**. Du darfst ihn selbst wählen.\n- `30` ist der **Wert**. Das `=` legt ihn in das Kästchen.\n\nWo danach `seite` steht, setzt der Computer den Wert ein. `mbot.forward(seite)` fährt also 30 cm.\n\n::: übung vb-variable-seite\ntitel: Quadrat mit Variable\nauftrag: Lege in einer Anweisung die Variable `int seite = 30` an. Danach fährt der mBot2 ein Quadrat: viermal `seite` Zentimeter vor und nach rechts drehen.\nfahrt: 4 x (forward 30, turnRight)\nbraucht: forSchleife\ntipp: Die erste Anweisung ist `int seite = 30`. Darunter kommt eine For-Schleife, die viermal läuft.\ntipp: In der Schleife stehen `mbot.forward(seite)` und `mbot.turnRight()`.\nlösung: vb-variable-seite-loesung.visustruct\n:::\n\n> Ändere jetzt nur die 30 in eine 60 und starte die Simulation. Das ganze Quadrat wird doppelt so groß.\n\n## Welche Datentypen gibt es?\n\nJede Variable hat einen Datentyp. Er legt fest, welche Werte hineinpassen:\n\n| Datentyp | Was passt hinein? | Beispiel |\n|---|---|---|\n| `int` | ganze Zahlen | `int seite = 30;` |\n| `double` | Kommazahlen, mit Punkt geschrieben | `double tempo = 1.5;` |\n| `String` | Text in Anführungszeichen | `String name = "Visu";` |\n| `boolean` | wahr oder falsch | `boolean fertig = false;` |\n\nMit Variablen kannst du auch rechnen: `int strecke = 4 * seite;` rechnet die ganze Strecke des Quadrats aus.\n\n## Jetzt in Java: Rechteck\n\nEin Rechteck hat zwei verschiedene Seiten. Also brauchst du zwei Variablen.\n\n::: übung vb-java-rechteck\ntitel: Rechteck mit Variablen\ncode: java\nauftrag: Schreibe in Java: Lege `int laenge = 60` und `int breite = 30` an. Der mBot2 fährt ein Rechteck: Länge, rechts drehen, Breite, rechts drehen, und das zweimal.\nfahrt: 2 x (forward 60, turnRight, forward 30, turnRight)\nbraucht: forSchleife\ntipp: Zwei Variablen oben: `int laenge = 60;` und `int breite = 30;`. Darunter eine For-Schleife, die zweimal läuft.\ntipp: In der Schleife: `mbot.forward(laenge);`, `mbot.turnRight();`, `mbot.forward(breite);`, `mbot.turnRight();`\nlösung: vb-java-rechteck-loesung.visustruct\n:::\n\n## Jetzt ohne Roboter: Ausgabe\n\nNicht jedes Ergebnis muss der Roboter fahren. Mit `System.out.println(…)` gibt ein Java-Programm Text in der [Konsole](#zeige-konsole) aus. Mit `+` hängst du Text und Werte aneinander:\n\n```java\nint seite = 30;\nint strecke = 4 * seite;\nSystem.out.println("Strecke: " + strecke + " cm");\n```\n\nDie Konsole zeigt dann **Strecke: 120 cm**.\n\n::: übung vb-ohne-strecke\ntitel: Wie weit fährt er?\ncode: java\nauftrag: Ein Rechteck ist 60 cm lang und 30 cm breit. Lege `laenge` und `breite` als Variablen an. Berechne in einer Variablen `strecke`, wie weit der mBot2 einmal ganz herum fährt, und gib **Strecke: 180 cm** aus. Ganz ohne `mbot`!\ntest: - -> Strecke: 180 cm\nbraucht: anweisung\ntipp: Einmal herum sind zweimal die Länge und zweimal die Breite.\ntipp: `int strecke = 2 * laenge + 2 * breite;` und dann `System.out.println("Strecke: " + strecke + " cm");`\nlösung: vb-ohne-strecke-loesung.visustruct\n:::\n\n::: quiz\n? Was fährt `mbot.forward(seite)`, wenn vorher `int seite = 40;` steht?\n→ Eine Variable für die Seite\n- [ ] 4 cm\n- [x] 40 cm\n- [ ] gar nichts, `seite` ist kein Befehl\n> Wo `seite` steht, setzt Java den Wert 40 ein.\n? Welcher Datentyp passt zu `"Visu"`?\n→ Welche Datentypen gibt es?\n- [ ] `int`\n- [ ] `double`\n- [x] `String`\n> Text in Anführungszeichen ist ein `String`.\n? Was gibt `System.out.println("Seite: " + 30);` aus?\n→ Jetzt ohne Roboter: Ausgabe\n- [x] Seite: 30\n- [ ] "Seite: " + 30\n- [ ] 30\n> Das `+` hängt den Text und die Zahl aneinander.\n:::\n\nSchä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.\n\n::: checkliste\n- Ich kann eine Variable anlegen und benutzen. → Eine Variable für die Seite\n- Ich kann die Datentypen `int`, `double`, `String` und `boolean` unterscheiden. → Welche Datentypen gibt es?\n- Ich kann mit zwei Variablen ein Rechteck in Java fahren. → Jetzt in Java: Rechteck\n- Ich kann mit `System.out.println` etwas ausgeben. → Jetzt ohne Roboter: Ausgabe\n:::\n',Gy=`--- +`,Gy='---\ntitel: Variablen und Ausgabe\nbereich: VisuBot\nkurz: Werte in Variablen speichern, den mBot2 damit fahren lassen und Ergebnisse ausgeben.\n---\n\n## Diese Kompetenzen erwerbe ich jetzt\n\n::: kompetenzen\n- eine Variable anlegen und benutzen\n- die Datentypen `int`, `double`, `String` und `boolean` unterscheiden\n- mit zwei Variablen ein Rechteck in Java fahren\n- mit `System.out.println` etwas ausgeben\n:::\n\n## Eine Variable für die Seite\n\nMit `mbot.forward(30)` fährt der mBot2 30 cm am Stück. Fährst du damit ein Quadrat ohne Schleife, steht die 30 aber viermal im Programm. Soll das Quadrat größer werden, musst du sie an vier Stellen ändern. Besser ist es, die Seitenlänge **einmal** zu speichern und dann überall zu benutzen.\n\nDafür gibt es **Variablen**. Eine Variable ist ein Kästchen mit einem Namen, in dem ein Wert liegt:\n\n```java\nint seite = 30;\nmbot.forward(seite);\n```\n\n- `int` ist der **Datentyp**: eine ganze Zahl.\n- `seite` ist der **Name**. Du darfst ihn selbst wählen.\n- `30` ist der **Wert**. Das `=` legt ihn in das Kästchen.\n\nWo danach `seite` steht, setzt der Computer den Wert ein. `mbot.forward(seite)` fährt also 30 cm.\n\n::: übung vb-variable-seite\ntitel: Quadrat mit Variable\nauftrag: Lege in einer Anweisung die Variable `int seite = 30` an. Danach fährt der mBot2 ein Quadrat: viermal `seite` Zentimeter vor und nach rechts drehen.\nfahrt: 4 x (forward 30, turnRight)\nbraucht: forSchleife\ntipp: Die erste Anweisung ist `int seite = 30`. Darunter kommt eine For-Schleife, die viermal läuft.\ntipp: In der Schleife stehen `mbot.forward(seite)` und `mbot.turnRight()`.\nlösung: vb-variable-seite-loesung.visustruct\n:::\n\n> Ändere jetzt nur die 30 in eine 60 und starte die Simulation. Das ganze Quadrat wird doppelt so groß.\n\n## Welche Datentypen gibt es?\n\nJede Variable hat einen Datentyp. Er legt fest, welche Werte hineinpassen:\n\n| Datentyp | Was passt hinein? | Beispiel |\n|---|---|---|\n| `int` | ganze Zahlen | `int seite = 30;` |\n| `double` | Kommazahlen, mit Punkt geschrieben | `double tempo = 1.5;` |\n| `String` | Text in Anführungszeichen | `String name = "Visu";` |\n| `boolean` | wahr oder falsch | `boolean fertig = false;` |\n\nMit Variablen kannst du auch rechnen: `int strecke = 4 * seite;` rechnet die ganze Strecke des Quadrats aus.\n\n## Jetzt in Java: Rechteck\n\nEin Rechteck hat zwei verschiedene Seiten. Also brauchst du zwei Variablen.\n\n::: übung vb-java-rechteck\ntitel: Rechteck mit Variablen\ncode: java\nauftrag: Schreibe in Java: Lege `int laenge = 60` und `int breite = 30` an. Der mBot2 fährt ein Rechteck: Länge, rechts drehen, Breite, rechts drehen, und das zweimal.\nfahrt: 2 x (forward 60, turnRight, forward 30, turnRight)\nbraucht: forSchleife\ntipp: Zwei Variablen oben: `int laenge = 60;` und `int breite = 30;`. Darunter eine For-Schleife, die zweimal läuft.\ntipp: In der Schleife: `mbot.forward(laenge);`, `mbot.turnRight();`, `mbot.forward(breite);`, `mbot.turnRight();`\nlösung: vb-java-rechteck-loesung.visustruct\n:::\n\n## Jetzt ohne Roboter: Ausgabe\n\nNicht jedes Ergebnis muss der Roboter fahren. Mit `System.out.println(…)` gibt ein Java-Programm Text in der [Konsole](#zeige-konsole) aus. Mit `+` hängst du Text und Werte aneinander:\n\n```java\nint seite = 30;\nint strecke = 4 * seite;\nSystem.out.println("Strecke: " + strecke + " cm");\n```\n\nDie Konsole zeigt dann **Strecke: 120 cm**.\n\n::: übung vb-ohne-strecke\ntitel: Wie weit fährt er?\ncode: java\nauftrag: Ein Rechteck ist 60 cm lang und 30 cm breit. Lege `laenge` und `breite` als Variablen an. Berechne in einer Variablen `strecke`, wie weit der mBot2 einmal ganz herum fährt, und gib **Strecke: 180 cm** aus. Ganz ohne `mbot`!\ntest: - -> Strecke: 180 cm\nbraucht: anweisung\ntipp: Einmal herum sind zweimal die Länge und zweimal die Breite.\ntipp: `int strecke = 2 * laenge + 2 * breite;` und dann `System.out.println("Strecke: " + strecke + " cm");`\nlösung: vb-ohne-strecke-loesung.visustruct\n:::\n\n::: quiz\n? Was fährt `mbot.forward(seite)`, wenn vorher `int seite = 40;` steht?\n→ Eine Variable für die Seite\n- [ ] 4 cm\n- [x] 40 cm\n- [ ] gar nichts, `seite` ist kein Befehl\n> Wo `seite` steht, setzt Java den Wert 40 ein.\n? Welcher Datentyp passt zu `"Visu"`?\n→ Welche Datentypen gibt es?\n- [ ] `int`\n- [ ] `double`\n- [x] `String`\n> Text in Anführungszeichen ist ein `String`.\n? Was gibt `System.out.println("Seite: " + 30);` aus?\n→ Jetzt ohne Roboter: Ausgabe\n- [x] Seite: 30\n- [ ] "Seite: " + 30\n- [ ] 30\n> Das `+` hängt den Text und die Zahl aneinander.\n:::\n\nSchä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.\n\n::: checkliste\n- Ich kann eine Variable anlegen und benutzen. → Eine Variable für die Seite\n- Ich kann die Datentypen `int`, `double`, `String` und `boolean` unterscheiden. → Welche Datentypen gibt es?\n- Ich kann mit zwei Variablen ein Rechteck in Java fahren. → Jetzt in Java: Rechteck\n- Ich kann mit `System.out.println` etwas ausgeben. → Jetzt ohne Roboter: Ausgabe\n:::\n',Hy=`--- titel: Sensoren abfragen bereich: VisuBot kurz: Der mBot2 misst etwas, und dein Programm entscheidet. @@ -39264,7 +39270,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann den Unterschied zwischen Befehl und Sensor erklären. → Befehle und Sensoren - Ich kann einen Sensor in eine Bedingung einbauen. → Wand vorn? ::: -`,Hy=`--- +`,Vy=`--- titel: Bis zur Wand bereich: VisuBot kurz: Der mBot2 misst den Abstand und hält rechtzeitig an. @@ -39351,7 +39357,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann entscheiden, wann ich eine While-Schleife statt einer For-Schleife nehme. → Drei Welten, ein Programm - Ich kann mit dem Liniensensor ein Ziel finden. → Bis zum Ziel ::: -`,Vy=`--- +`,qy=`--- titel: Der Ultraschallsensor bereich: VisuBot kurz: Abstand messen, Abstand halten und das Ganze in Java. @@ -39402,7 +39408,7 @@ lösung: vb-abstand-halten-loesung.visustruct ## Jetzt in Java -Im Bereich [Programmieren](#zeige-codelive) siehst du dein Struktogramm schon als Java-Code. Eine Verzweigung heißt dort \`if\`, der Nein-Zweig \`else\`: +Im Bereich [Code](#zeige-codelive) siehst du dein Struktogramm schon als Java-Code. Eine Verzweigung heißt dort \`if\`, der Nein-Zweig \`else\`: \`\`\`java if (mbot.getDistance() < 10) { @@ -39449,7 +39455,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann zwei Verzweigungen ineinander bauen. → Abstand halten im Struktogramm - Ich kann eine While-Schleife mit dem Abstand in Java schreiben. → Jetzt in Java ::: -`,qy=`--- +`,Qy=`--- titel: Der Liniensensor bereich: VisuBot kurz: Dunkle Linien auf dem Boden erkennen und nicht vom Tisch fallen. @@ -39543,7 +39549,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann bis zu einer Linie fahren. → Am Rand umkehren im Struktogramm - Ich kann in Java mit einer Variable Schritte zählen. → Jetzt in Java: hin und zurück ::: -`,Qy=`--- +`,Uy=`--- titel: Farben erkennen bereich: VisuBot kurz: Der Quad-RGB-Sensor sagt, auf welcher Farbe der mBot2 steht. @@ -39633,7 +39639,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann mit \`!\` eine Bedingung umdrehen. → Fahre bis Rot im Struktogramm - Ich kann eine Verzweigung in eine Schleife schreiben. → Jetzt in Java: bei Grün piepen ::: -`,Uy=`--- +`,$y=`--- titel: Fallauswahl mit Farben bereich: VisuBot kurz: Je nach Farbe oder Linie etwas anderes tun, mit einer Fallauswahl statt vieler Verzweigungen. @@ -39755,7 +39761,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann eine Fallauswahl mit Zahlen in Java schreiben. → Jetzt in Java: Linienmuster - Ich kann eine Zahl einlesen und je nach Wert etwas ausgeben. → Jetzt ohne Roboter: Noten in Worten ::: -`,$y=`--- +`,Yy=`--- titel: Tasten und Joystick bereich: VisuBot kurz: Der mBot2 wartet auf dich und lässt sich fernsteuern. @@ -39844,7 +39850,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann auf eine Taste warten. → Warten auf Taste A im Struktogramm - Ich kann den mBot2 mit dem Joystick steuern. → Jetzt in Java: Fernsteuerung ::: -`,Yy=`--- +`,Xy=`--- titel: Der Lichtsensor bereich: VisuBot kurz: Hell oder dunkel? Der mBot2 wird zum Nachtlicht. @@ -39924,7 +39930,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann mit einer Verzweigung die LEDs schalten. → Nachtlicht im Struktogramm - Ich kann mehrere Befehle in einen Zweig schreiben. → Jetzt in Java: Nachtlicht mit Ton ::: -`,Xy=`--- +`,Ky=`--- titel: Das Mikrofon bereich: VisuBot kurz: Klatschen zum Losfahren und eine Lärmampel für das Klassenzimmer. @@ -40001,7 +40007,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann warten, bis etwas passiert. → Klatschen zum Losfahren im Struktogramm - Ich kann eine Lärmampel in Java schreiben. → Jetzt in Java: Lärmampel ::: -`,Ky=`--- +`,ew=`--- titel: Der Lagesensor bereich: VisuBot kurz: Neigung messen und Schütteln erkennen. @@ -40087,7 +40093,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann zwei Bedingungen mit „oder“ verbinden. → Schräglage-Warnung im Struktogramm - Ich kann mehrere Bedingungen mit „und“ verbinden. → Jetzt in Java: Wasserwaage ::: -`,ew=`--- +`,tw=`--- titel: Die LEDs bereich: VisuBot kurz: Farben mischen, eine Ampel bauen und blinken lassen. @@ -40174,7 +40180,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann Farben mit Pausen nacheinander zeigen. → Ampel im Struktogramm - Ich kann die LEDs in Java blinken lassen. → Jetzt in Java: Blaulicht ::: -`,tw=`--- +`,nw=`--- titel: Einzelne LEDs bereich: VisuBot kurz: Jede der fünf LEDs bekommt ihre eigene Farbe, bis zum Lauflicht. @@ -40261,7 +40267,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann einzelne LEDs in verschiedenen Farben leuchten lassen. → Drei Lichter im Struktogramm - Ich kann mit einer Schleife ein Lauflicht bauen. → Jetzt in Java: Lauflicht ::: -`,nw=`--- +`,iw=`--- titel: Der Lautsprecher bereich: VisuBot kurz: Töne, eine Tonleiter und eine Sirene. @@ -40365,7 +40371,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann in Java mit der Zählvariable rechnen. → Jetzt in Java: immer höher - Ich kann den mBot2 ein Gefühl zeigen lassen. → Gefühle zeigen ::: -`,iw=`--- +`,aw=`--- titel: Arrays und Melodien bereich: VisuBot kurz: Viele Werte in einem Array speichern und mit einer Schleife abarbeiten. @@ -40464,7 +40470,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann ein Array mit Texten in Java benutzen. → Jetzt in Java: Regenbogen - Ich kann alle Werte eines Arrays zusammenzählen. → Jetzt ohne Roboter: Summe der Noten ::: -`,aw=`--- +`,sw=`--- titel: Der Bildschirm bereich: VisuBot kurz: Text, Zahlen und Messwerte auf dem CyberPi anzeigen. @@ -40552,7 +40558,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann Zahlen und Messwerte anzeigen. → Zahlen und Messwerte - Ich kann einen Countdown in Java schreiben. → Jetzt in Java: Countdown ::: -`,sw=`--- +`,rw=`--- titel: Zeichenketten bereich: VisuBot kurz: Mit Texten rechnen, Buchstaben herausholen und auf dem Bildschirm zeigen. @@ -40646,7 +40652,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann Texte und Zahlen mit \`+\` verbinden. → Jetzt in Java: Text und Länge - Ich kann mit \`charAt(…)\` einzelne Zeichen holen. → Jetzt ohne Roboter: rückwärts lesen ::: -`,rw=`--- +`,ow=`--- titel: Motoren und Geschwindigkeit bereich: VisuBot kurz: Gas geben, lenken und einer Linie folgen. @@ -40748,7 +40754,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann fahren, bis ein Sensor etwas meldet. → Gas geben bis zur Wand im Struktogramm - Ich kann einen Linienfolger in Java schreiben. → Jetzt in Java: Linienfolger ::: -`,ow=`--- +`,lw=`--- titel: Stoppuhr und Akku bereich: VisuBot kurz: Zeit messen und den Akku im Blick behalten. @@ -40839,7 +40845,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann eine bestimmte Zeit lang fahren. → Zwei Sekunden fahren im Struktogramm - Ich kann den Akkustand anzeigen. → Jetzt in Java: Akku-Anzeige ::: -`,lw=`--- +`,uw=`--- titel: Eigene Methoden bereich: VisuBot kurz: Eigene Befehle mit Parametern und Rückgabewert schreiben und aufrufen. @@ -40894,7 +40900,7 @@ public class Quadrate { } \`\`\` -Im Bereich [Programmieren](#zeige-codelive) siehst du jede Methode in ihrem eigenen Reiter, so wie im Struktogramm. +Im Bereich [Code](#zeige-codelive) siehst du jede Methode in ihrem eigenen Reiter, so wie im Struktogramm. ::: quiz ? Was bedeutet \`void\` in \`void quadrat(int seite)\`? @@ -40941,7 +40947,7 @@ Schätze dich bei jedem Punkt ehrlich ein: ☂️ noch nicht, ⛅ teilweise, ☀ - Ich kann Methoden in Java erkennen. → Methoden in Java - Ich kann eine Methode mit Rückgabewert schreiben. → Jetzt ohne Roboter: Methode mit Rückgabe ::: -`,uw=`## 🤖 mBot2-Befehle +`,cw=`## 🤖 mBot2-Befehle Ein Befehl sagt dem mBot2, was er **tun** soll. Jeder Befehl beginnt mit \`mbot.\` und endet mit Klammern. In die Klammern schreibst du oft eine Zahl. @@ -41093,7 +41099,7 @@ Mit **🔌 mBot2** neben „Simulation starten“ verbindest du den echten Robot ### Ohne Kabel fahren Mit **⬆ Übertragen** speicherst du dein Programm fest auf dem mBot2. Danach Kabel ab, mBot2 an den Start und **Taste A** drücken: Er fährt dein Programm allein. Es bleibt gespeichert, bis du ein neues überträgst. Eingaben mit der Tastatur gehen am mBot2 nicht. -`,cw=`--- +`,mw=`--- titel: The mBot2 bereich: VisuBot kurz: Get to know the robot you are about to program. @@ -41425,7 +41431,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can connect the real mBot2 with USB-C and disconnect it again. → Connecting the real mBot2 - I can check that all sensors and actuators work. → Testing the mBot2 ::: -`,mw=`--- +`,dw=`--- titel: The square bereich: VisuBot kurz: From a long structure chart to a triple nested loop. @@ -41562,7 +41568,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can nest three loops. → Four squares - I can upload my program to the mBot2 and start it with button A without a cable. → Driving without a cable ::: -`,dw='---\ntitel: Variables and output\nbereich: VisuBot\nkurz: Store values in variables, drive the mBot2 with them and print results.\n---\n\n## Skills I will gain now\n\n::: kompetenzen\n- create and use a variable\n- tell the data types `int`, `double`, `String` and `boolean` apart\n- drive a rectangle in Java with two variables\n- print something with `System.out.println`\n:::\n\n## A variable for the side\n\nWith `mbot.forward(30)` the mBot2 drives 30 cm in one go. If you drive a square with it and no loop, the 30 appears four times in your program. To make the square bigger, you have to change it in four places. It is better to store the side length **once** and then use it everywhere.\n\nThat is what **variables** are for. A variable is a box with a name that holds a value:\n\n```java\nint side = 30;\nmbot.forward(side);\n```\n\n- `int` is the **data type**: a whole number.\n- `side` is the **name**. You may choose it yourself.\n- `30` is the **value**. The `=` puts it into the box.\n\nWherever `side` appears afterwards, the computer uses its value. So `mbot.forward(side)` drives 30 cm.\n\n::: übung vb-variable-seite\ntitel: Square with a variable\nauftrag: In one statement, create the variable `int side = 30`. After that the mBot2 drives a square: four times `side` centimetres forward and turn right.\nfahrt: 4 x (forward 30, turnRight)\nbraucht: forSchleife\ntipp: The first statement is `int side = 30`. Below it comes a for loop that runs four times.\ntipp: Inside the loop are `mbot.forward(side)` and `mbot.turnRight()`.\nlösung: vb-variable-seite-loesung.visustruct\n:::\n\n> Now change only the 30 to 60 and start the simulation. The whole square becomes twice as big.\n\n## Which data types are there?\n\nEvery variable has a data type. It decides which values fit inside:\n\n| Data type | What fits inside? | Example |\n|---|---|---|\n| `int` | whole numbers | `int side = 30;` |\n| `double` | decimal numbers, written with a point | `double speed = 1.5;` |\n| `String` | text in quotation marks | `String name = "Visu";` |\n| `boolean` | true or false | `boolean done = false;` |\n\nYou can also calculate with variables: `int distance = 4 * side;` works out the whole distance around the square.\n\n## Now in Java: rectangle\n\nA rectangle has two different sides. So you need two variables.\n\n::: übung vb-java-rechteck\ntitel: Rectangle with variables\ncode: java\nauftrag: Write in Java: create `int length = 60` and `int width = 30`. The mBot2 drives a rectangle: length, turn right, width, turn right, and all that twice.\nfahrt: 2 x (forward 60, turnRight, forward 30, turnRight)\nbraucht: forSchleife\ntipp: Two variables at the top: `int length = 60;` and `int width = 30;`. Below them a for loop that runs twice.\ntipp: Inside the loop: `mbot.forward(length);`, `mbot.turnRight();`, `mbot.forward(width);`, `mbot.turnRight();`\nlösung: vb-java-rechteck-loesung.visustruct\n:::\n\n## Now without the robot: output\n\nNot every result has to be driven by the robot. With `System.out.println(…)` a Java program prints text in the [console](#zeige-konsole). With `+` you join text and values:\n\n```java\nint side = 30;\nint distance = 4 * side;\nSystem.out.println("Distance: " + distance + " cm");\n```\n\nThe console then shows **Distance: 120 cm**.\n\n::: übung vb-ohne-strecke\ntitel: How far does it drive?\ncode: java\nauftrag: A rectangle is 60 cm long and 30 cm wide. Create `length` and `width` as variables. Calculate in a variable `distance` how far the mBot2 drives once all the way round, and print **Distance: 180 cm**. No `mbot` at all!\ntest: - -> Distance: 180 cm\nbraucht: anweisung\ntipp: Once round is twice the length plus twice the width.\ntipp: `int distance = 2 * length + 2 * width;` and then `System.out.println("Distance: " + distance + " cm");`\nlösung: vb-ohne-strecke-loesung.visustruct\n:::\n\n::: quiz\n? What does `mbot.forward(side)` drive if `int side = 40;` comes first?\n→ A variable for the side\n- [ ] 4 cm\n- [x] 40 cm\n- [ ] nothing, `side` is not a command\n> Wherever `side` appears, Java uses the value 40.\n? Which data type fits `"Visu"`?\n→ Which data types are there?\n- [ ] `int`\n- [ ] `double`\n- [x] `String`\n> Text in quotation marks is a `String`.\n? What does `System.out.println("Side: " + 30);` print?\n→ Now without the robot: output\n- [x] Side: 30\n- [ ] "Side: " + 30\n- [ ] 30\n> The `+` joins the text and the number.\n:::\n\nRate 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.\n\n::: checkliste\n- I can create and use a variable. → A variable for the side\n- I can tell the data types `int`, `double`, `String` and `boolean` apart. → Which data types are there?\n- I can drive a rectangle in Java with two variables. → Now in Java: rectangle\n- I can print something with `System.out.println`. → Now without the robot: output\n:::\n',hw=`--- +`,hw='---\ntitel: Variables and output\nbereich: VisuBot\nkurz: Store values in variables, drive the mBot2 with them and print results.\n---\n\n## Skills I will gain now\n\n::: kompetenzen\n- create and use a variable\n- tell the data types `int`, `double`, `String` and `boolean` apart\n- drive a rectangle in Java with two variables\n- print something with `System.out.println`\n:::\n\n## A variable for the side\n\nWith `mbot.forward(30)` the mBot2 drives 30 cm in one go. If you drive a square with it and no loop, the 30 appears four times in your program. To make the square bigger, you have to change it in four places. It is better to store the side length **once** and then use it everywhere.\n\nThat is what **variables** are for. A variable is a box with a name that holds a value:\n\n```java\nint side = 30;\nmbot.forward(side);\n```\n\n- `int` is the **data type**: a whole number.\n- `side` is the **name**. You may choose it yourself.\n- `30` is the **value**. The `=` puts it into the box.\n\nWherever `side` appears afterwards, the computer uses its value. So `mbot.forward(side)` drives 30 cm.\n\n::: übung vb-variable-seite\ntitel: Square with a variable\nauftrag: In one statement, create the variable `int side = 30`. After that the mBot2 drives a square: four times `side` centimetres forward and turn right.\nfahrt: 4 x (forward 30, turnRight)\nbraucht: forSchleife\ntipp: The first statement is `int side = 30`. Below it comes a for loop that runs four times.\ntipp: Inside the loop are `mbot.forward(side)` and `mbot.turnRight()`.\nlösung: vb-variable-seite-loesung.visustruct\n:::\n\n> Now change only the 30 to 60 and start the simulation. The whole square becomes twice as big.\n\n## Which data types are there?\n\nEvery variable has a data type. It decides which values fit inside:\n\n| Data type | What fits inside? | Example |\n|---|---|---|\n| `int` | whole numbers | `int side = 30;` |\n| `double` | decimal numbers, written with a point | `double speed = 1.5;` |\n| `String` | text in quotation marks | `String name = "Visu";` |\n| `boolean` | true or false | `boolean done = false;` |\n\nYou can also calculate with variables: `int distance = 4 * side;` works out the whole distance around the square.\n\n## Now in Java: rectangle\n\nA rectangle has two different sides. So you need two variables.\n\n::: übung vb-java-rechteck\ntitel: Rectangle with variables\ncode: java\nauftrag: Write in Java: create `int length = 60` and `int width = 30`. The mBot2 drives a rectangle: length, turn right, width, turn right, and all that twice.\nfahrt: 2 x (forward 60, turnRight, forward 30, turnRight)\nbraucht: forSchleife\ntipp: Two variables at the top: `int length = 60;` and `int width = 30;`. Below them a for loop that runs twice.\ntipp: Inside the loop: `mbot.forward(length);`, `mbot.turnRight();`, `mbot.forward(width);`, `mbot.turnRight();`\nlösung: vb-java-rechteck-loesung.visustruct\n:::\n\n## Now without the robot: output\n\nNot every result has to be driven by the robot. With `System.out.println(…)` a Java program prints text in the [console](#zeige-konsole). With `+` you join text and values:\n\n```java\nint side = 30;\nint distance = 4 * side;\nSystem.out.println("Distance: " + distance + " cm");\n```\n\nThe console then shows **Distance: 120 cm**.\n\n::: übung vb-ohne-strecke\ntitel: How far does it drive?\ncode: java\nauftrag: A rectangle is 60 cm long and 30 cm wide. Create `length` and `width` as variables. Calculate in a variable `distance` how far the mBot2 drives once all the way round, and print **Distance: 180 cm**. No `mbot` at all!\ntest: - -> Distance: 180 cm\nbraucht: anweisung\ntipp: Once round is twice the length plus twice the width.\ntipp: `int distance = 2 * length + 2 * width;` and then `System.out.println("Distance: " + distance + " cm");`\nlösung: vb-ohne-strecke-loesung.visustruct\n:::\n\n::: quiz\n? What does `mbot.forward(side)` drive if `int side = 40;` comes first?\n→ A variable for the side\n- [ ] 4 cm\n- [x] 40 cm\n- [ ] nothing, `side` is not a command\n> Wherever `side` appears, Java uses the value 40.\n? Which data type fits `"Visu"`?\n→ Which data types are there?\n- [ ] `int`\n- [ ] `double`\n- [x] `String`\n> Text in quotation marks is a `String`.\n? What does `System.out.println("Side: " + 30);` print?\n→ Now without the robot: output\n- [x] Side: 30\n- [ ] "Side: " + 30\n- [ ] 30\n> The `+` joins the text and the number.\n:::\n\nRate 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.\n\n::: checkliste\n- I can create and use a variable. → A variable for the side\n- I can tell the data types `int`, `double`, `String` and `boolean` apart. → Which data types are there?\n- I can drive a rectangle in Java with two variables. → Now in Java: rectangle\n- I can print something with `System.out.println`. → Now without the robot: output\n:::\n',gw=`--- titel: Reading sensors bereich: VisuBot kurz: The mBot2 measures something, and your program decides. @@ -41643,7 +41649,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can explain the difference between a command and a sensor. → Commands and sensors - I can build a sensor into a condition. → Wall ahead? ::: -`,gw=`--- +`,pw=`--- titel: Up to the wall bereich: VisuBot kurz: The mBot2 measures the distance and stops in time. @@ -41730,7 +41736,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can decide when to use a while loop instead of a for loop. → Three worlds, one program - I can find a goal with the line sensor. → To the goal ::: -`,pw=`--- +`,fw=`--- titel: The ultrasonic sensor bereich: VisuBot kurz: Measure the distance, keep your distance, and do it all in Java. @@ -41781,7 +41787,7 @@ lösung: vb-abstand-halten-loesung.visustruct ## Now in Java -In the [Programming](#zeige-codelive) area you already see your structure chart as Java code. A branch is called \`if\` there, the No branch is \`else\`: +In the [Code](#zeige-codelive) area you already see your structure chart as Java code. A branch is called \`if\` there, the No branch is \`else\`: \`\`\`java if (mbot.getDistance() < 10) { @@ -41828,7 +41834,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can put one branch inside another. → Keep your distance in the structure chart - I can write a while loop with the distance in Java. → Now in Java ::: -`,fw=`--- +`,bw=`--- titel: The line sensor bereich: VisuBot kurz: Detect dark lines on the floor and don't fall off the table. @@ -41922,7 +41928,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can drive up to a line. → Turn round at the edge in the structure chart - I can count steps with a variable in Java. → Now in Java: there and back ::: -`,bw=`--- +`,xw=`--- titel: Recognising colours bereich: VisuBot kurz: The quad RGB sensor tells you which colour the mBot2 is standing on. @@ -42012,7 +42018,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can turn a condition round with \`!\`. → Drive to red in the structure chart - I can put a branch inside a loop. → Now in Java: beep on green ::: -`,xw=`--- +`,vw=`--- titel: Case selection with colours bereich: VisuBot kurz: Do something different for each colour or line, with one case selection instead of many branches. @@ -42134,7 +42140,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can write a case selection with numbers in Java. → Now in Java: line patterns - I can read a number and print something depending on its value. → Now without the robot: grades in words ::: -`,vw=`--- +`,yw=`--- titel: Buttons and joystick bereich: VisuBot kurz: The mBot2 waits for you and can be remote controlled. @@ -42223,7 +42229,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can wait for a button. → Waiting for button A in the structure chart - I can steer the mBot2 with the joystick. → Now in Java: remote control ::: -`,yw=`--- +`,ww=`--- titel: The light sensor bereich: VisuBot kurz: Bright or dark? The mBot2 becomes a night light. @@ -42303,7 +42309,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can switch the LEDs with a branch. → Night light in the structure chart - I can write several commands in one branch. → Now in Java: night light with sound ::: -`,ww=`--- +`,zw=`--- titel: The microphone bereich: VisuBot kurz: Clap to start, and a noise light for the classroom. @@ -42380,7 +42386,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can wait until something happens. → Clap to start in the structure chart - I can write a noise light in Java. → Now in Java: noise light ::: -`,zw=`--- +`,Iw=`--- titel: The motion sensor bereich: VisuBot kurz: Measure tilt and detect shaking. @@ -42466,7 +42472,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can join two conditions with “or”. → Tilt warning in the structure chart - I can join several conditions with “and”. → Now in Java: spirit level ::: -`,Iw=`--- +`,kw=`--- titel: The LEDs bereich: VisuBot kurz: Mix colours, build a traffic light and make it blink. @@ -42553,7 +42559,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can show colours one after the other with pauses. → Traffic light in the structure chart - I can make the LEDs blink in Java. → Now in Java: blue light ::: -`,kw=`--- +`,Sw=`--- titel: Single LEDs bereich: VisuBot kurz: Each of the five LEDs gets its own colour, all the way to a running light. @@ -42640,7 +42646,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can make single LEDs light up in different colours. → Three lights in the structogram - I can build a running light with a loop. → Now in Java: running light ::: -`,Sw=`--- +`,Tw=`--- titel: The speaker bereich: VisuBot kurz: Tones, a scale and a siren. @@ -42744,7 +42750,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can calculate with the counting variable in Java. → Now in Java: higher and higher - I can make the mBot2 show a feeling. → Showing feelings ::: -`,Tw=`--- +`,_w=`--- titel: Arrays and melodies bereich: VisuBot kurz: Store many values in one array and work through them with a loop. @@ -42843,7 +42849,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can use an array of texts in Java. → Now in Java: rainbow - I can add up all values of an array. → Now without the robot: sum of the grades ::: -`,_w=`--- +`,Ow=`--- titel: The screen bereich: VisuBot kurz: Show text, numbers and sensor values on the CyberPi. @@ -42931,7 +42937,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can show numbers and sensor values. → Numbers and sensor values - I can write a countdown in Java. → Now in Java: countdown ::: -`,Ow=`--- +`,Aw=`--- titel: Strings bereich: VisuBot kurz: Work with texts, pick out letters and show them on the screen. @@ -43025,7 +43031,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can join texts and numbers with \`+\`. → Now in Java: text and length - I can get single characters with \`charAt(…)\`. → Now without the robot: read it backwards ::: -`,Aw=`--- +`,Cw=`--- titel: Motors and speed bereich: VisuBot kurz: Step on the gas, steer and follow a line. @@ -43127,7 +43133,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can drive until a sensor reports something. → Full speed to the wall in the structure chart - I can write a line follower in Java. → Now in Java: line follower ::: -`,Cw=`--- +`,jw=`--- titel: Stopwatch and battery bereich: VisuBot kurz: Measure time and keep an eye on the battery. @@ -43273,7 +43279,7 @@ public class Squares { } \`\`\` -In [Programming](#zeige-codelive) you see each method in its own tab, just like in the structogram. +In [Code](#zeige-codelive) you see each method in its own tab, just like in the structogram. ::: quiz ? What does \`void\` mean in \`void square(int side)\`? @@ -43320,7 +43326,7 @@ Rate yourself honestly for each point: ☂️ not yet, ⛅ partly, ☀️ I can - I can recognise methods in Java. → Methods in Java - I can write a method with a return value. → Now without the robot: a method with a return value ::: -`,jw=`## 🤖 mBot2 commands +`,Dw=`## 🤖 mBot2 commands A command tells the mBot2 what to **do**. Every command starts with \`mbot.\` and ends with brackets. Often you write a number in the brackets. @@ -43472,7 +43478,7 @@ With **🔌 mBot2** next to "Start simulation" you connect the real robot with t ### Driving without a cable With **⬆ Upload** you save your program on the mBot2. Then unplug the cable, put the mBot2 at the start and press **button A**: it drives your program on its own. It stays saved until you upload a new one. Keyboard inputs do not work on the mBot2. -`,Dw=`--- +`,Bw=`--- titel: Die Alarmanlage nach: 16 stufe: 2 @@ -43491,7 +43497,7 @@ tipp: Außen steht eine While-Schleife mit \`!mbot.isButtonB()\`. Darin eine Ver tipp: Die Bedingung der Verzweigung: \`mbot.getDistance() < 20 || mbot.getLoudness() > 60\`. Im Ja-Zweig \`mbot.setLed(255, 0, 0)\` und \`mbot.playTone(880, 200)\`, im Nein-Zweig \`mbot.ledOff()\`. lösung: vb-alarmanlage-loesung.visustruct ::: -`,Bw=`--- +`,Zw=`--- titel: Labyrinth mit Ausgängen nach: 5 stufe: 3 @@ -43510,7 +43516,7 @@ tipp: In jedem Durchlauf dreht sich der mBot2 zuerst nach links und misst. Ist o tipp: Durch die Lücke sind es zwei Felder bis in den nächsten Gang. Danach soll er wieder nach rechts schauen. Ist oben eine Wand, dreht er sich zurück und fährt ein Feld weiter. lösung: vb-ausgang-loesung.visustruct ::: -`,Zw=`--- +`,Mw=`--- titel: Binär zählen nach: 15 stufe: 3 @@ -43535,7 +43541,7 @@ tipp: Ob LED 0 an ist, verrät der Rest beim Teilen durch 2: \`zahl % 2 == 1\`. tipp: In der Schleife stehen drei Verzweigungen und danach **kurz warten**. Im Ja-Zweig zum Beispiel \`mbot.led(0).setColor("grün")\`, im Nein-Zweig \`mbot.led(0).setColor("aus")\`. lösung: vb-binaer-zaehlen-loesung.visustruct ::: -`,Mw=`--- +`,Lw=`--- titel: Das Dreieck nach: 2 stufe: 1 @@ -43558,7 +43564,7 @@ lösung: vb-dreieck-loesung.visustruct ::: angeberwissen Die Idee, mit einem fahrenden Roboter Figuren zu zeichnen, ist über 50 Jahre alt: Ende der 1960er-Jahre entstand die Sprache **Logo**. Kinder steuerten damit eine „Schildkröte“, die mit einem Stift über das Papier fuhr. ::: -`,Lw=`--- +`,Ew=`--- titel: Rückwärts einparken nach: 16 stufe: 2 @@ -43578,7 +43584,7 @@ tipp: Zwei While-Schleifen hintereinander: erst \`!mbot.getColor().equals("blau" tipp: Am Ende: \`mbot.setLed(0, 255, 0)\` und \`mbot.showText("Geparkt!")\`. lösung: vb-einparken-loesung.visustruct ::: -`,Ew='---\ntitel: Hindernis ausweichen\nnach: 16\nstufe: 2\n---\n\nAuf dem Weg zum roten Feld stehen Klötze im Weg. Der mBot2 fährt in 10-cm-Schritten vor. Taucht ein Klotz auf (näher als 20 cm), warnt er mit Licht und Ton und fährt außen herum: nach rechts drehen, 30 cm vor, nach links drehen. Dann geht es weiter geradeaus.\n\n::: übung vb-hindernis\ntitel: Hindernis ausweichen\nauftrag: Der mBot2 fährt, solange er nicht auf Rot steht. Ist ein Klotz näher als 20 cm, leuchten die LEDs orange (`mbot.setLed(255, 128, 0)`), er piept und weicht aus. Danach gehen die LEDs aus. Sonst fährt er 10 cm vor. Es gibt zwei Welten.\nwelt: hindernis-1 -> tone\nwelt: hindernis-2 -> tone\nbraucht: whileSchleife, verzweigung\ntipp: Außen eine While-Schleife mit `!mbot.getColor().equals("rot")`, darin eine Verzweigung mit `mbot.getDistance() < 20`.\ntipp: Im Ja-Zweig: `mbot.setLed(255, 128, 0)`, `mbot.playTone(880, 200)`, `mbot.turnRight()`, `mbot.forward(30)`, `mbot.turnLeft()`, `mbot.ledOff()`. Im Nein-Zweig: `mbot.forward()`.\nlösung: vb-hindernis-loesung.visustruct\n:::\n',Ww=`--- +`,Ww='---\ntitel: Hindernis ausweichen\nnach: 16\nstufe: 2\n---\n\nAuf dem Weg zum roten Feld stehen Klötze im Weg. Der mBot2 fährt in 10-cm-Schritten vor. Taucht ein Klotz auf (näher als 20 cm), warnt er mit Licht und Ton und fährt außen herum: nach rechts drehen, 30 cm vor, nach links drehen. Dann geht es weiter geradeaus.\n\n::: übung vb-hindernis\ntitel: Hindernis ausweichen\nauftrag: Der mBot2 fährt, solange er nicht auf Rot steht. Ist ein Klotz näher als 20 cm, leuchten die LEDs orange (`mbot.setLed(255, 128, 0)`), er piept und weicht aus. Danach gehen die LEDs aus. Sonst fährt er 10 cm vor. Es gibt zwei Welten.\nwelt: hindernis-1 -> tone\nwelt: hindernis-2 -> tone\nbraucht: whileSchleife, verzweigung\ntipp: Außen eine While-Schleife mit `!mbot.getColor().equals("rot")`, darin eine Verzweigung mit `mbot.getDistance() < 20`.\ntipp: Im Ja-Zweig: `mbot.setLed(255, 128, 0)`, `mbot.playTone(880, 200)`, `mbot.turnRight()`, `mbot.forward(30)`, `mbot.turnLeft()`, `mbot.ledOff()`. Im Nein-Zweig: `mbot.forward()`.\nlösung: vb-hindernis-loesung.visustruct\n:::\n',Nw=`--- titel: Knight Rider nach: 15 stufe: 2 @@ -43595,7 +43601,7 @@ tipp: Die erste Schleife zählt \`i\` von 0 bis 4 hoch. Die zweite startet bei 3 tipp: In beiden Schleifen: \`mbot.led(i).setColor("rot")\`, \`mbot.pause(100)\`, \`mbot.led(i).setColor("aus")\`. lösung: vb-knight-rider-loesung.visustruct ::: -`,Nw=`--- +`,Fw=`--- titel: Das Labyrinth nach: 5 stufe: 2 @@ -43620,7 +43626,7 @@ lösung: vb-labyrinth-loesung.visustruct ::: angeberwissen Mit der Regel „Hand immer an der Wand“ findet man aus jedem Labyrinth, dessen Wände alle zusammenhängen. Schon die Griechen erzählten von Theseus, der sich im Labyrinth des Minotaurus mit einem Wollfaden half. ::: -`,Fw='---\ntitel: Linienfolger mit Stopp\nnach: 20\nstufe: 3\n---\n\nDer mBot2 folgt einer schwarzen Linie und hält am roten Feld an ihrem Ende an.\n\nDafür gibt er mit **Räder einzeln** Gas: `mbot.drive(40, 40)` lässt beide Räder gleich schnell drehen, er fährt geradeaus weiter, bis ein anderer Fahrbefehl kommt. `mbot.drive(10, 40)` macht eine Linkskurve, `mbot.drive(40, 10)` eine Rechtskurve. `mbot.stop()` hält ihn an.\n\nDie beiden mittleren Fühler des Liniensensors fragst du mit `mbot.isLineLeft()` und `mbot.isLineRight()` ab. Sehen beide die Linie, fährt er geradeaus. Sieht nur der linke sie, lenkt er nach links, sieht nur der rechte sie, nach rechts.\n\n::: übung vb-linienfolger-stopp\ntitel: Linienfolger mit Stopp\nauftrag: Solange der mBot2 nicht auf Rot steht, folgt er der Linie. Danach hält er an. In der zweiten Welt schlängelt sich die Linie.\nwelt: linie-rot-1, linie-rot-2\nbraucht: whileSchleife, verzweigung\ntipp: Außen eine While-Schleife mit `!mbot.getColor().equals("rot")`, danach **anhalten**.\ntipp: In der Schleife: Sind `mbot.isLineLeft() && mbot.isLineRight()`, dann `mbot.drive(40, 40)`. Sonst, wenn `mbot.isLineLeft()`, dann `mbot.drive(10, 40)`. Sonst, wenn `mbot.isLineRight()`, dann `mbot.drive(40, 10)`.\nlösung: vb-linienfolger-stopp-loesung.visustruct\n:::\n',Jw=`--- +`,Jw='---\ntitel: Linienfolger mit Stopp\nnach: 20\nstufe: 3\n---\n\nDer mBot2 folgt einer schwarzen Linie und hält am roten Feld an ihrem Ende an.\n\nDafür gibt er mit **Räder einzeln** Gas: `mbot.drive(40, 40)` lässt beide Räder gleich schnell drehen, er fährt geradeaus weiter, bis ein anderer Fahrbefehl kommt. `mbot.drive(10, 40)` macht eine Linkskurve, `mbot.drive(40, 10)` eine Rechtskurve. `mbot.stop()` hält ihn an.\n\nDie beiden mittleren Fühler des Liniensensors fragst du mit `mbot.isLineLeft()` und `mbot.isLineRight()` ab. Sehen beide die Linie, fährt er geradeaus. Sieht nur der linke sie, lenkt er nach links, sieht nur der rechte sie, nach rechts.\n\n::: übung vb-linienfolger-stopp\ntitel: Linienfolger mit Stopp\nauftrag: Solange der mBot2 nicht auf Rot steht, folgt er der Linie. Danach hält er an. In der zweiten Welt schlängelt sich die Linie.\nwelt: linie-rot-1, linie-rot-2\nbraucht: whileSchleife, verzweigung\ntipp: Außen eine While-Schleife mit `!mbot.getColor().equals("rot")`, danach **anhalten**.\ntipp: In der Schleife: Sind `mbot.isLineLeft() && mbot.isLineRight()`, dann `mbot.drive(40, 40)`. Sonst, wenn `mbot.isLineLeft()`, dann `mbot.drive(10, 40)`. Sonst, wenn `mbot.isLineRight()`, dann `mbot.drive(40, 10)`.\nlösung: vb-linienfolger-stopp-loesung.visustruct\n:::\n',Rw=`--- titel: Morsen nach: 15 stufe: 2 @@ -43637,7 +43643,7 @@ tipp: Drei For-Schleifen hintereinander, jede läuft dreimal. Dazwischen steht j tipp: In der ersten und dritten Schleife: \`mbot.led(2).setColor("weiß")\`, \`mbot.pause(200)\`, \`mbot.led(2).setColor("aus")\`, \`mbot.pause(200)\`. In der mittleren wartet er nach dem Einschalten 600. lösung: vb-morsen-loesung.visustruct ::: -`,Rw=`--- +`,Gw=`--- titel: Der Nachtwächter nach: 18 stufe: 1 @@ -43655,7 +43661,7 @@ tipp: Eine While-Schleife mit \`mbot.getBrightness() < 20\`. Darin \`mbot.forwar tipp: Nach der Schleife steht \`mbot.showText("Zzz")\`. lösung: vb-nachtwaechter-loesung.visustruct ::: -`,Gw=`--- +`,Hw=`--- titel: Slalom nach: 2 stufe: 2 @@ -43674,7 +43680,7 @@ tipp: Überlege zuerst, wie der mBot2 oben um einen einzigen Pylon herumfährt: tipp: Unten herum geht genauso, nur mit links und rechts vertauscht. „Oben herum, dann unten herum“ wiederholt sich zweimal. lösung: vb-slalom-loesung.visustruct ::: -`,Hw=`--- +`,Vw=`--- titel: Die Spirale nach: 2 stufe: 2 @@ -43693,7 +43699,7 @@ tipp: Lass die Zählvariable von 1 bis 8 laufen. Wie lang ist dann die Seite in tipp: In der Klammer von **fahre vor** steht eine Rechnung mit der Zählvariable. lösung: vb-spirale-loesung.visustruct ::: -`,Vw=`--- +`,qw=`--- titel: Die Treppe nach: 2 stufe: 1 @@ -43710,7 +43716,7 @@ tipp: Schreib zuerst eine Stufe auf. Dann packst du sie in eine For-Schleife, di tipp: In der Schleife: \`mbot.forward(20)\`, \`mbot.turnLeft()\`, \`mbot.forward(20)\`, \`mbot.turnRight()\`. lösung: vb-treppe-loesung.visustruct ::: -`,qw=`--- +`,Qw=`--- titel: Der Tunnelsucher nach: 5 stufe: 3 @@ -43731,7 +43737,7 @@ tipp: In jedem Durchlauf fährt der mBot2 ein Feld vor und schaut sich dann nach tipp: Hier passt eine Schleife, die erst fährt und danach prüft. Sie läuft weiter, solange links **oder** rechts mindestens 20 cm frei ist: \`links >= 20 || rechts >= 20\`. lösung: vb-tunnel-loesung.visustruct ::: -`,Qw=`--- +`,Uw=`--- titel: Kleeblatt im Wald nach: 5 stufe: 2 @@ -43750,7 +43756,7 @@ tipp: Wie bei „Fahre bis zum Ziel“ läuft außen eine Schleife, bis der Lini tipp: Um einen Baum herum: nach links drehen, ein Feld vor, nach rechts drehen, zwei Felder vor, nach rechts drehen, ein Feld vor, nach links drehen. lösung: vb-wald-loesung.visustruct ::: -`,Uw=`--- +`,$w=`--- titel: The alarm system nach: 16 stufe: 2 @@ -43769,7 +43775,7 @@ tipp: On the outside is a while loop with \`!mbot.isButtonB()\`. Inside a branch tipp: The condition of the branch: \`mbot.getDistance() < 20 || mbot.getLoudness() > 60\`. In the yes branch \`mbot.setLed(255, 0, 0)\` and \`mbot.playTone(880, 200)\`, in the no branch \`mbot.ledOff()\`. lösung: vb-alarmanlage-loesung.visustruct ::: -`,$w=`--- +`,Yw=`--- titel: Maze with exits nach: 5 stufe: 3 @@ -43788,7 +43794,7 @@ tipp: In each pass the mBot2 first turns left and measures. If the way up is fre tipp: Through the gap it is two squares into the next corridor. Afterwards it should face right again. If there is a wall above, it turns back and drives one square further. lösung: vb-ausgang-loesung.visustruct ::: -`,Yw=`--- +`,Xw=`--- titel: Counting in binary nach: 15 stufe: 3 @@ -43813,7 +43819,7 @@ tipp: Whether LED 0 is on is given by the remainder when dividing by 2: \`number tipp: The loop contains three branches and then **wait a moment**. In the yes branch, for example, \`mbot.led(0).setColor("green")\`, in the no branch \`mbot.led(0).setColor("off")\`. lösung: vb-binaer-zaehlen-loesung.visustruct ::: -`,Xw=`--- +`,Kw=`--- titel: The triangle nach: 2 stufe: 1 @@ -43836,7 +43842,7 @@ lösung: vb-dreieck-loesung.visustruct ::: angeberwissen The idea of drawing shapes with a driving robot is more than 50 years old: the language **Logo** was created in the late 1960s. Children used it to steer a "turtle" that rolled across paper with a pen. ::: -`,Kw=`--- +`,e9=`--- titel: Reverse parking nach: 16 stufe: 2 @@ -43856,7 +43862,7 @@ tipp: Two while loops one after the other: first \`!mbot.getColor().equals("blue tipp: At the end: \`mbot.setLed(0, 255, 0)\` and \`mbot.showText("Parked!")\`. lösung: vb-einparken-loesung.visustruct ::: -`,e9='---\ntitel: Avoid obstacles\nnach: 16\nstufe: 2\n---\n\nOn the way to the red field there are blocks in the way. The mBot2 drives forward in steps of 10 cm. If a block shows up (closer than 20 cm), it warns with light and sound and drives around it: turn right, 30 cm forward, turn left. Then it carries on straight ahead.\n\n::: übung vb-hindernis\ntitel: Avoid obstacles\nauftrag: The mBot2 drives as long as it is not on red. If a block is closer than 20 cm, the LEDs light up orange (`mbot.setLed(255, 128, 0)`), it beeps and drives around it. Then the LEDs go off. Otherwise it drives forward 10 cm. There are two worlds.\nwelt: hindernis-1 -> tone\nwelt: hindernis-2 -> tone\nbraucht: whileSchleife, verzweigung\ntipp: On the outside a while loop with `!mbot.getColor().equals("red")`, inside a branch with `mbot.getDistance() < 20`.\ntipp: In the yes branch: `mbot.setLed(255, 128, 0)`, `mbot.playTone(880, 200)`, `mbot.turnRight()`, `mbot.forward(30)`, `mbot.turnLeft()`, `mbot.ledOff()`. In the no branch: `mbot.forward()`.\nlösung: vb-hindernis-loesung.visustruct\n:::\n',t9=`--- +`,t9='---\ntitel: Avoid obstacles\nnach: 16\nstufe: 2\n---\n\nOn the way to the red field there are blocks in the way. The mBot2 drives forward in steps of 10 cm. If a block shows up (closer than 20 cm), it warns with light and sound and drives around it: turn right, 30 cm forward, turn left. Then it carries on straight ahead.\n\n::: übung vb-hindernis\ntitel: Avoid obstacles\nauftrag: The mBot2 drives as long as it is not on red. If a block is closer than 20 cm, the LEDs light up orange (`mbot.setLed(255, 128, 0)`), it beeps and drives around it. Then the LEDs go off. Otherwise it drives forward 10 cm. There are two worlds.\nwelt: hindernis-1 -> tone\nwelt: hindernis-2 -> tone\nbraucht: whileSchleife, verzweigung\ntipp: On the outside a while loop with `!mbot.getColor().equals("red")`, inside a branch with `mbot.getDistance() < 20`.\ntipp: In the yes branch: `mbot.setLed(255, 128, 0)`, `mbot.playTone(880, 200)`, `mbot.turnRight()`, `mbot.forward(30)`, `mbot.turnLeft()`, `mbot.ledOff()`. In the no branch: `mbot.forward()`.\nlösung: vb-hindernis-loesung.visustruct\n:::\n',n9=`--- titel: Knight Rider nach: 15 stufe: 2 @@ -43873,7 +43879,7 @@ tipp: The first loop counts \`i\` up from 0 to 4. The second starts at 3 and cou tipp: In both loops: \`mbot.led(i).setColor("red")\`, \`mbot.pause(100)\`, \`mbot.led(i).setColor("off")\`. lösung: vb-knight-rider-loesung.visustruct ::: -`,n9=`--- +`,i9=`--- titel: The maze nach: 5 stufe: 2 @@ -43898,7 +43904,7 @@ lösung: vb-labyrinth-loesung.visustruct ::: angeberwissen With the rule "always keep one hand on the wall" you get out of any maze whose walls are all connected. The ancient Greeks already told of Theseus, who found his way through the Minotaur's labyrinth with a ball of thread. ::: -`,i9='---\ntitel: Line follower with stop\nnach: 20\nstufe: 3\n---\n\nThe mBot2 follows a black line and stops at the red field at its end.\n\nFor this it steps on the gas with **wheels separately**: `mbot.drive(40, 40)` turns both wheels equally fast, it keeps driving straight ahead until another driving command comes. `mbot.drive(10, 40)` makes a left curve, `mbot.drive(40, 10)` a right curve. `mbot.stop()` stops it.\n\nYou ask the two middle probes of the line sensor with `mbot.isLineLeft()` and `mbot.isLineRight()`. If both see the line, it drives straight ahead. If only the left one sees it, it steers left, if only the right one sees it, right.\n\n::: übung vb-linienfolger-stopp\ntitel: Line follower with stop\nauftrag: As long as the mBot2 is not on red, it follows the line. Then it stops. In the second world the line winds about.\nwelt: linie-rot-1, linie-rot-2\nbraucht: whileSchleife, verzweigung\ntipp: On the outside a while loop with `!mbot.getColor().equals("red")`, after it **stop**.\ntipp: Inside the loop: if `mbot.isLineLeft() && mbot.isLineRight()`, then `mbot.drive(40, 40)`. Otherwise, if `mbot.isLineLeft()`, then `mbot.drive(10, 40)`. Otherwise, if `mbot.isLineRight()`, then `mbot.drive(40, 10)`.\nlösung: vb-linienfolger-stopp-loesung.visustruct\n:::\n',a9=`--- +`,a9='---\ntitel: Line follower with stop\nnach: 20\nstufe: 3\n---\n\nThe mBot2 follows a black line and stops at the red field at its end.\n\nFor this it steps on the gas with **wheels separately**: `mbot.drive(40, 40)` turns both wheels equally fast, it keeps driving straight ahead until another driving command comes. `mbot.drive(10, 40)` makes a left curve, `mbot.drive(40, 10)` a right curve. `mbot.stop()` stops it.\n\nYou ask the two middle probes of the line sensor with `mbot.isLineLeft()` and `mbot.isLineRight()`. If both see the line, it drives straight ahead. If only the left one sees it, it steers left, if only the right one sees it, right.\n\n::: übung vb-linienfolger-stopp\ntitel: Line follower with stop\nauftrag: As long as the mBot2 is not on red, it follows the line. Then it stops. In the second world the line winds about.\nwelt: linie-rot-1, linie-rot-2\nbraucht: whileSchleife, verzweigung\ntipp: On the outside a while loop with `!mbot.getColor().equals("red")`, after it **stop**.\ntipp: Inside the loop: if `mbot.isLineLeft() && mbot.isLineRight()`, then `mbot.drive(40, 40)`. Otherwise, if `mbot.isLineLeft()`, then `mbot.drive(10, 40)`. Otherwise, if `mbot.isLineRight()`, then `mbot.drive(40, 10)`.\nlösung: vb-linienfolger-stopp-loesung.visustruct\n:::\n',s9=`--- titel: Morse code nach: 15 stufe: 2 @@ -43915,7 +43921,7 @@ tipp: Three for loops one after the other, each runs three times. Between them t tipp: In the first and third loop: \`mbot.led(2).setColor("white")\`, \`mbot.pause(200)\`, \`mbot.led(2).setColor("off")\`, \`mbot.pause(200)\`. In the middle one it waits 600 after switching on. lösung: vb-morsen-loesung.visustruct ::: -`,s9=`--- +`,r9=`--- titel: The night watchman nach: 18 stufe: 1 @@ -43933,7 +43939,7 @@ tipp: A while loop with \`mbot.getBrightness() < 20\`. Inside \`mbot.forward(30) tipp: After the loop is \`mbot.showText("Zzz")\`. lösung: vb-nachtwaechter-loesung.visustruct ::: -`,r9=`--- +`,o9=`--- titel: Slalom nach: 2 stufe: 2 @@ -43952,7 +43958,7 @@ tipp: First think about how the mBot2 drives around a single cone on the top sid tipp: Around the bottom works the same way, only with left and right swapped. "Top, then bottom" repeats twice. lösung: vb-slalom-loesung.visustruct ::: -`,o9=`--- +`,l9=`--- titel: The spiral nach: 2 stufe: 2 @@ -43971,7 +43977,7 @@ tipp: Let the counter variable run from 1 to 8. How long is the side in each pas tipp: The brackets of **drive forward** contain a calculation with the counter variable. lösung: vb-spirale-loesung.visustruct ::: -`,l9=`--- +`,u9=`--- titel: The staircase nach: 2 stufe: 1 @@ -43988,7 +43994,7 @@ tipp: Write down one step first. Then put it into a for loop that runs three tim tipp: Inside the loop: \`mbot.forward(20)\`, \`mbot.turnLeft()\`, \`mbot.forward(20)\`, \`mbot.turnRight()\`. lösung: vb-treppe-loesung.visustruct ::: -`,u9=`--- +`,c9=`--- titel: The tunnel finder nach: 5 stufe: 3 @@ -44009,7 +44015,7 @@ tipp: In each pass the mBot2 drives one square forward and then looks left and r tipp: A loop that drives first and checks afterwards fits here. It keeps going as long as at least 20 cm are free on the left **or** on the right: \`left >= 20 || right >= 20\`. lösung: vb-tunnel-loesung.visustruct ::: -`,c9=`--- +`,m9=`--- titel: Clover in the forest nach: 5 stufe: 2 @@ -44028,7 +44034,7 @@ tipp: As in "Drive to the goal", a loop on the outside runs until the line senso tipp: Around a tree: turn left, one square forward, turn right, two squares forward, turn right, one square forward, turn left. lösung: vb-wald-loesung.visustruct ::: -`,m9=` +`,d9=` 111;117;116;112;117;116;58;32;34;87;105;108;108;107;111;109;109;101;110;34; @@ -44040,7 +44046,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;117;102;32;87;105;101;100;101;114;115;101;104;101;110;34; -`,d9=` +`,h9=` 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; @@ -44059,7 +44065,7 @@ lösung: vb-wald-loesung.visustruct -`,h9=` +`,g9=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;98;97;108;108;119;117;114;102;46;99;115;118;34;41;41; @@ -44140,7 +44146,7 @@ lösung: vb-wald-loesung.visustruct 97;117;115;46;99;108;111;115;101;40;41; -`,g9=` +`,p9=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;98;97;108;108;119;117;114;102;46;99;115;118;34;41;41; @@ -44149,7 +44155,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,p9=` +`,f9=` 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -44214,7 +44220,7 @@ lösung: vb-wald-loesung.visustruct -`,f9=` +`,b9=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;71;97;110;122;101;32;90;97;104;108;32;101;105;110;103;101;98;101;110;34; @@ -44240,7 +44246,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98;105;110;97;101;114; -`,b9=` +`,x9=` 99;104;97;114;91;93;32;97;108;112;104;97;98;101;116;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; @@ -44294,13 +44300,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;103;101;104;101;105;109; -`,x9=` +`,v9=` 99;104;97;114;91;93;32;97;108;112;104;97;98;101;116;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; -`,v9=` +`,y9=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;116;32;34;87;101;108;99;104;101;115;32;87;111;114;116;32;40;110;117;114;32;71;114;111;223;98;117;99;104;115;116;97;98;101;110;41;63;34; @@ -44331,7 +44337,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;103;101;104;101;105;109; -`,y9=` +`,w9=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;103;101;104;101;105;109;32;34;87;101;108;99;104;101;114;32;71;101;104;101;105;109;116;101;120;116;63;34; @@ -44362,7 +44368,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;107;108;97;114;116;101;120;116; -`,w9=` +`,z9=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;32;101;105;110;103;101;98;101;110;34; @@ -44398,7 +44404,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;99;104;114;105;116;116;101;58;32;34;32;43;32;115;99;104;114;105;116;116;101; -`,z9=` +`,I9=` 105;110;112;117;116;58;32;105;110;116;32;97;110;122;97;104;108;32;34;87;105;101;32;118;105;101;108;101;32;78;111;116;101;110;63;34; @@ -44426,7 +44432,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;99;104;110;105;116;116; -`,I9=` +`,k9=` 105;110;112;117;116;58;32;105;110;116;32;97;110;122;97;104;108;32;34;87;105;101;32;118;105;101;108;101;32;90;97;104;108;101;110;63;34; @@ -44463,7 +44469,7 @@ lösung: vb-wald-loesung.visustruct -`,k9=` +`,S9=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;34; @@ -44482,7 +44488,7 @@ lösung: vb-wald-loesung.visustruct -`,S9=` +`,T9=` 99;111;110;115;116;32;100;111;117;98;108;101;32;77;87;83;84;32;61;32;48;46;49;57; @@ -44503,7 +44509,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98;114;117;116;116;111;112;114;101;105;115; -`,T9=` +`,_9=` 105;110;116;32;112;105;110;32;61;32;48; @@ -44539,7 +44545,7 @@ lösung: vb-wald-loesung.visustruct -`,_9=` +`,O9=` 99;111;110;115;116;32;105;110;116;32;80;73;78;32;61;32;49;50;51;52; @@ -44575,7 +44581,7 @@ lösung: vb-wald-loesung.visustruct -`,O9=` +`,A9=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;49;32;34;69;114;115;116;101;32;90;97;104;108;34; @@ -44619,7 +44625,7 @@ lösung: vb-wald-loesung.visustruct -`,A9=` +`,C9=` 98;111;111;108;101;97;110;91;93;91;93;32;109;101;101;114;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; @@ -44673,7 +44679,7 @@ lösung: vb-wald-loesung.visustruct -`,C9=` +`,j9=` 98;111;111;108;101;97;110;91;93;91;93;32;109;101;101;114;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; @@ -44729,7 +44735,7 @@ lösung: vb-wald-loesung.visustruct -`,j9=` +`,D9=` 105;110;116;32;122;97;104;108;49;32;61;32;52; @@ -44744,7 +44750,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109;109;101; -`,D9=` +`,B9=` 83;116;114;105;110;103;91;93;32;110;97;109;101;110;32;61;32;110;101;119;32;83;116;114;105;110;103;91;53;93; @@ -44766,7 +44772,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;97;102;101;108;100;105;101;110;115;116;58;32;34;32;43;32;110;97;109;101;110;91;110;117;109;109;101;114;32;45;32;49;93; -`,B9=` +`,Z9=` 105;110;116;32;122;97;104;108;32;61;32;52; @@ -44778,7 +44784,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;86;101;114;100;111;112;112;101;108;116;101;32;90;97;104;108;58;32;34;32;43;32;122;97;104;108; -`,Z9=` +`,M9=` -1; @@ -44825,7 +44831,7 @@ lösung: vb-wald-loesung.visustruct -`,M9=` +`,L9=` @@ -44862,7 +44868,7 @@ lösung: vb-wald-loesung.visustruct -`,L9=` +`,E9=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;118;111;107;97;98;101;108;110;46;99;115;118;34;41;41; @@ -44922,7 +44928,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;114;105;99;104;116;105;103;32;43;32;34;32;118;111;110;32;34;32;43;32;97;110;122;97;104;108;32;43;32;34;32;114;105;99;104;116;105;103;34; -`,E9=` +`,W9=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;118;111;107;97;98;101;108;110;46;99;115;118;34;41;41; @@ -44931,7 +44937,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,W9=` +`,N9=` 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; @@ -44950,7 +44956,7 @@ lösung: vb-wald-loesung.visustruct -`,N9=` +`,F9=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; @@ -44973,7 +44979,7 @@ lösung: vb-wald-loesung.visustruct 108;101;115;101;114;46;99;108;111;115;101;40;41; -`,F9=` +`,J9=` 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;34;90;111;114;97;59;49;59;50;59;50;34; @@ -44991,7 +44997,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;97;109;101;32;43;32;34;32;104;97;116;32;105;110;32;77;97;116;104;101;32;101;105;110;101;32;34;32;43;32;109;97;116;104;101; -`,J9=` +`,R9=` 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;34;123;92;34;110;97;109;101;92;34;58;32;92;34;90;111;114;97;92;34;44;32;92;34;97;114;116;92;34;58;32;92;34;90;105;101;103;101;92;34;44;32;92;34;97;108;116;101;114;92;34;58;32;54;125;44;34; @@ -45009,7 +45015,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;97;109;101; -`,R9=` +`,G9=` 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; @@ -45029,7 +45035,7 @@ lösung: vb-wald-loesung.visustruct 100;97;116;101;105;46;99;108;111;115;101;40;41; -`,G9=` +`,H9=` 111;117;116;112;117;116;58;32;34;87;101;108;99;111;109;101;34; @@ -45041,7 +45047,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;111;111;100;98;121;101;34; -`,H9=` +`,V9=` 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; @@ -45060,7 +45066,7 @@ lösung: vb-wald-loesung.visustruct -`,V9=` +`,q9=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;104;114;111;119;46;99;115;118;34;41;41; @@ -45141,7 +45147,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;46;99;108;111;115;101;40;41; -`,q9=` +`,Q9=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;104;114;111;119;46;99;115;118;34;41;41; @@ -45150,7 +45156,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,Q9=` +`,U9=` 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -45215,7 +45221,7 @@ lösung: vb-wald-loesung.visustruct -`,U9=` +`,$9=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;119;104;111;108;101;32;110;117;109;98;101;114;34; @@ -45241,7 +45247,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98;105;110;97;114;121; -`,$9=` +`,Y9=` 99;104;97;114;91;93;32;97;108;112;104;97;98;101;116;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; @@ -45295,13 +45301,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;101;99;114;101;116; -`,Y9=` +`,X9=` 99;104;97;114;91;93;32;97;108;112;104;97;98;101;116;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; -`,X9=` +`,K9=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;100;32;34;87;104;105;99;104;32;119;111;114;100;32;40;99;97;112;105;116;97;108;32;108;101;116;116;101;114;115;32;111;110;108;121;41;63;34; @@ -45332,7 +45338,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;101;99;114;101;116; -`,K9=` +`,e5=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;115;101;99;114;101;116;32;34;87;104;105;99;104;32;115;101;99;114;101;116;32;116;101;120;116;63;34; @@ -45363,7 +45369,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;112;108;97;105;110; -`,e5=` +`,t5=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;115;116;97;114;116;32;110;117;109;98;101;114;34; @@ -45399,7 +45405,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;116;101;112;115;58;32;34;32;43;32;115;116;101;112;115; -`,t5=` +`,n5=` 105;110;112;117;116;58;32;105;110;116;32;99;111;117;110;116;32;34;72;111;119;32;109;97;110;121;32;103;114;97;100;101;115;63;34; @@ -45427,7 +45433,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;118;101;114;97;103;101; -`,n5=` +`,i5=` 105;110;112;117;116;58;32;105;110;116;32;99;111;117;110;116;32;34;72;111;119;32;109;97;110;121;32;110;117;109;98;101;114;115;63;34; @@ -45464,7 +45470,7 @@ lösung: vb-wald-loesung.visustruct -`,i5=` +`,a5=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;34; @@ -45483,7 +45489,7 @@ lösung: vb-wald-loesung.visustruct -`,a5=` +`,s5=` 99;111;110;115;116;32;100;111;117;98;108;101;32;86;65;84;32;61;32;48;46;49;57; @@ -45504,7 +45510,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;103;114;111;115;115;80;114;105;99;101; -`,s5=` +`,r5=` 105;110;116;32;112;105;110;32;61;32;48; @@ -45540,7 +45546,7 @@ lösung: vb-wald-loesung.visustruct -`,r5=` +`,o5=` 99;111;110;115;116;32;105;110;116;32;80;73;78;32;61;32;49;50;51;52; @@ -45576,7 +45582,7 @@ lösung: vb-wald-loesung.visustruct -`,o5=` +`,l5=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;49;32;34;70;105;114;115;116;32;110;117;109;98;101;114;34; @@ -45620,7 +45626,7 @@ lösung: vb-wald-loesung.visustruct -`,l5=` +`,u5=` 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; @@ -45674,7 +45680,7 @@ lösung: vb-wald-loesung.visustruct -`,u5=` +`,c5=` 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; @@ -45701,7 +45707,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;91;93;32;99;111;108;117;109;110;115;32;61;32;123;34;65;34;44;32;34;66;34;44;32;34;67;34;44;32;34;68;34;44;32;34;69;34;125; -`,c5=` +`,m5=` 105;110;112;117;116;58;32;105;110;116;32;112;105;99;107;32;34;87;104;105;99;104;32;100;105;115;104;63;32;40;49;44;32;50;32;111;114;32;51;41;34; @@ -45730,7 +45736,7 @@ lösung: vb-wald-loesung.visustruct -`,m5=` +`,d5=` 105;110;116;32;110;117;109;98;101;114;49;32;61;32;52; @@ -45745,7 +45751,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109; -`,d5=` +`,h5=` 83;116;114;105;110;103;91;93;32;110;97;109;101;115;32;61;32;110;101;119;32;83;116;114;105;110;103;91;53;93; @@ -45767,7 +45773,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;66;111;97;114;100;32;100;117;116;121;58;32;34;32;43;32;110;97;109;101;115;91;112;105;99;107;32;45;32;49;93; -`,h5=` +`,g5=` 105;110;116;32;110;117;109;98;101;114;32;61;32;52; @@ -45779,7 +45785,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;111;117;98;108;101;100;32;110;117;109;98;101;114;58;32;34;32;43;32;110;117;109;98;101;114; -`,g5=` +`,p5=` -1; @@ -45826,7 +45832,7 @@ lösung: vb-wald-loesung.visustruct -`,p5=` +`,f5=` @@ -45863,7 +45869,7 @@ lösung: vb-wald-loesung.visustruct -`,f5=` +`,b5=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;119;111;114;100;115;46;99;115;118;34;41;41; @@ -45923,7 +45929,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;114;105;103;104;116;32;43;32;34;32;111;102;32;34;32;43;32;99;111;117;110;116;32;43;32;34;32;114;105;103;104;116;34; -`,b5=` +`,x5=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;119;111;114;100;115;46;99;115;118;34;41;41; @@ -45932,7 +45938,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,x5=` +`,v5=` 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; @@ -45951,7 +45957,7 @@ lösung: vb-wald-loesung.visustruct -`,v5=` +`,y5=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; @@ -45974,7 +45980,7 @@ lösung: vb-wald-loesung.visustruct 114;101;97;100;101;114;46;99;108;111;115;101;40;41; -`,y5=` +`,w5=` 83;116;114;105;110;103;32;108;105;110;101;32;61;32;34;90;111;114;97;59;49;59;50;59;50;34; @@ -45992,7 +45998,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;97;109;101;32;43;32;34;32;103;111;116;32;97;32;34;32;43;32;109;97;116;104;115;32;43;32;34;32;105;110;32;109;97;116;104;115;34; -`,w5=` +`,z5=` 83;116;114;105;110;103;32;108;105;110;101;32;61;32;34;123;92;34;110;97;109;101;92;34;58;32;92;34;90;111;114;97;92;34;44;32;92;34;115;112;101;99;105;101;115;92;34;58;32;92;34;103;111;97;116;92;34;44;32;92;34;97;103;101;92;34;58;32;54;125;44;34; @@ -46010,7 +46016,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;97;109;101; -`,z5=` +`,I5=` 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; @@ -46030,7 +46036,7 @@ lösung: vb-wald-loesung.visustruct 102;105;108;101;46;99;108;111;115;101;40;41; -`,I5=` +`,k5=` 105;110;116;91;93;91;93;32;116;97;98;108;101;32;61;32;110;101;119;32;105;110;116;91;49;48;93;91;49;48;93; @@ -46062,7 +46068,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;32;43;32;34;32;183;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;116;97;98;108;101;91;97;32;45;32;49;93;91;98;32;45;32;49;93; -`,k5=` +`,S5=` 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -46110,7 +46116,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;70;114;101;101;58;32;34;32;43;32;102;114;101;101; -`,S5=` +`,T5=` 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -46125,7 +46131,7 @@ lösung: vb-wald-loesung.visustruct 115;101;97;116;115;91;50;93;91;51;93;32;61;32;116;114;117;101; -`,T5=` +`,_5=` 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -46159,7 +46165,7 @@ lösung: vb-wald-loesung.visustruct -`,_5=` +`,O5=` 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -46177,7 +46183,7 @@ lösung: vb-wald-loesung.visustruct 105;110;112;117;116;58;32;105;110;116;32;115;101;97;116;32;34;83;101;97;116;34; -`,O5=` +`,A5=` 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -46225,7 +46231,7 @@ lösung: vb-wald-loesung.visustruct -`,A5=` +`,C5=` 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -46249,7 +46255,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;82;111;119;32;49;44;32;115;101;97;116;32;50;32;115;111;108;100;63;32;34;32;43;32;115;101;97;116;115;91;49;93;91;50;93; -`,C5=` +`,j5=` 105;110;116;32;115;101;99;111;110;100;115;32;61;32;50;48;48; @@ -46279,7 +46285,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;101;115;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;32;43;32;34;32;115;34; -`,j5=` +`,D5=` 83;116;114;105;110;103;32;110;97;109;101;32;61;32;34;76;117;100;119;105;103;34; @@ -46297,7 +46303,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;101;105;103;104;116;58;32;34;32;43;32;104;101;105;103;104;116;32;43;32;34;32;109;34; -`,D5=` +`,B5=` 105;110;116;32;110;117;109;98;101;114;32;61;32;51; @@ -46312,7 +46318,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;117;109;98;101;114; -`,B5=` +`,Z5=` 105;110;116;32;110;117;109;98;101;114;32;61;32;50; @@ -46327,7 +46333,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;117;109;98;101;114; -`,Z5=` +`,M5=` 111;117;116;112;117;116;58;32;110;117;109;98;101;114; @@ -46342,7 +46348,7 @@ lösung: vb-wald-loesung.visustruct 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;43;32;51; -`,M5=` +`,L5=` 83;116;114;105;110;103;32;108;101;102;116;32;61;32;34;106;117;105;99;101;34; @@ -46366,7 +46372,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;82;105;103;104;116;58;32;34;32;43;32;114;105;103;104;116; -`,L5=` +`,E5=` 83;116;114;105;110;103;32;108;101;102;116;32;61;32;34;106;117;105;99;101;34; @@ -46381,7 +46387,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;82;105;103;104;116;58;32;34;32;43;32;114;105;103;104;116; -`,E5=` +`,W5=` 105;110;116;32;97;32;61;32;53; @@ -46405,7 +46411,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; -`,W5=` +`,N5=` 105;110;116;32;97;103;101;32;61;32;49;52; @@ -46423,7 +46429,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;101;105;103;104;116;58;32;34;32;43;32;104;101;105;103;104;116;32;43;32;34;32;109;34; -`,N5=` +`,F5=` 105;110;116;32;109;105;110;117;116;101;115;32;61;32;49;51;53; @@ -46438,7 +46444,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;104;111;117;114;115;32;43;32;34;32;104;111;117;114;115;32;97;110;100;32;34;32;43;32;114;101;109;97;105;110;100;101;114;32;43;32;34;32;109;105;110;117;116;101;115;34; -`,F5=` +`,J5=` 105;110;116;32;99;111;117;110;116;32;61;32;51; @@ -46453,7 +46459,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108;80;114;105;99;101;32;43;32;34;32;101;117;114;111;115;34; -`,J5=` +`,R5=` 105;110;116;32;99;114;101;100;105;116;32;61;32;50;48; @@ -46468,7 +46474,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;76;101;102;116;58;32;34;32;43;32;99;114;101;100;105;116; -`,R5=` +`,G5=` 105;110;116;32;99;114;101;100;105;116;32;61;32;50;48; @@ -46483,7 +46489,7 @@ lösung: vb-wald-loesung.visustruct 99;114;101;100;105;116;32;61;32;99;114;101;100;105;116;32;45;32;112;114;105;99;101; -`,G5=` +`,H5=` 105;110;116;32;112;114;105;99;101;32;61;32;57; @@ -46498,7 +46504,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; -`,H5=` +`,V5=` 105;110;116;32;108;101;110;103;116;104;32;61;32;55; @@ -46519,7 +46525,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;101;114;105;109;101;116;101;114;58;32;34;32;43;32;112;101;114;105;109;101;116;101;114; -`,V5=` +`,q5=` 105;110;116;32;115;101;99;111;110;100;115;32;61;32;50;48;48; @@ -46534,7 +46540,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;101;115;32;43;32;34;32;109;105;110;117;116;101;115;32;97;110;100;32;34;32;43;32;114;101;109;97;105;110;100;101;114;32;43;32;34;32;115;101;99;111;110;100;115;34; -`,q5=` +`,Q5=` 105;110;116;32;115;101;99;111;110;100;115;32;61;32;50;48;48; @@ -46543,7 +46549,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;101;115;32;43;32;34;32;109;105;110;117;116;101;115;32;97;110;100;32;34;32;43;32;114;101;109;97;105;110;100;101;114;32;43;32;34;32;115;101;99;111;110;100;115;34; -`,Q5=` +`,U5=` 105;110;116;32;108;101;110;103;116;104;32;61;32;53; @@ -46558,7 +46564,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;114;101;97; -`,U5=` +`,$5=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;97;109;101;32;34;87;104;97;116;32;105;115;32;121;111;117;114;32;110;97;109;101;63;34; @@ -46567,7 +46573,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;101;108;108;111;32;34;32;43;32;110;97;109;101;32;43;32;34;33;34; -`,$5=` +`,Y5=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; @@ -46582,7 +46588,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; -`,Y5=` +`,X5=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; @@ -46594,7 +46600,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;40;97;32;43;32;98;41; -`,X5=` +`,K5=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; @@ -46606,7 +46612,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;97;32;43;32;98; -`,K5=` +`,ez=` 105;110;112;117;116;58;32;105;110;116;32;121;101;97;114;115;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; @@ -46618,7 +46624,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;104;97;116;32;105;115;32;97;98;111;117;116;32;34;32;43;32;100;97;121;115;32;43;32;34;32;100;97;121;115;46;34; -`,ez=` +`,tz=` 105;110;112;117;116;58;32;100;111;117;98;108;101;32;120;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; @@ -46633,7 +46639,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;101;97;110;58;32;34;32;43;32;109;101;97;110; -`,tz=` +`,nz=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; @@ -46654,7 +46660,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;114;111;100;117;99;116;58;32;34;32;43;32;112;114;111;100;117;99;116; -`,nz=` +`,iz=` 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; @@ -46673,7 +46679,7 @@ lösung: vb-wald-loesung.visustruct -`,iz=` +`,az=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;78;117;109;98;101;114;63;34; @@ -46695,7 +46701,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;117;109;98;101;114; -`,az=` +`,sz=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;78;117;109;98;101;114;63;34; @@ -46714,7 +46720,7 @@ lösung: vb-wald-loesung.visustruct -`,sz=` +`,rz=` 105;110;116;32;112;111;105;110;116;115;32;61;32;48; @@ -46732,7 +46738,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;105;110;116;115;58;32;34;32;43;32;112;111;105;110;116;115; -`,rz=` +`,oz=` 105;110;116;32;112;111;105;110;116;115;32;61;32;48; @@ -46750,7 +46756,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;105;110;116;115;58;32;34;32;43;32;112;111;105;110;116;115; -`,oz=` +`,lz=` 105;110;116;32;112;114;105;99;101;32;61;32;56; @@ -46768,7 +46774,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; -`,lz=` +`,uz=` 105;110;116;32;112;114;105;99;101;32;61;32;56; @@ -46786,7 +46792,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; -`,uz=` +`,cz=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; @@ -46808,7 +46814,7 @@ lösung: vb-wald-loesung.visustruct -`,cz=` +`,mz=` 105;110;112;117;116;58;32;100;111;117;98;108;101;32;112;114;105;99;101;32;34;80;114;105;99;101;32;105;110;32;101;117;114;111;115;63;34; @@ -46830,7 +46836,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;32;112;97;121;58;32;34;32;43;32;112;114;105;99;101;32;43;32;34;32;101;117;114;111;115;34; -`,mz=` +`,dz=` 105;110;112;117;116;58;32;105;110;116;32;103;114;97;100;101;32;34;71;114;97;100;101;63;34; @@ -46849,7 +46855,7 @@ lösung: vb-wald-loesung.visustruct -`,dz=` +`,hz=` 105;110;112;117;116;58;32;105;110;116;32;112;111;105;110;116;115;32;34;72;111;119;32;109;97;110;121;32;112;111;105;110;116;115;63;34; @@ -46868,7 +46874,7 @@ lösung: vb-wald-loesung.visustruct -`,hz=` +`,gz=` 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; @@ -46887,7 +46893,7 @@ lösung: vb-wald-loesung.visustruct -`,gz=` +`,pz=` 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; @@ -46906,7 +46912,7 @@ lösung: vb-wald-loesung.visustruct -`,pz=` +`,fz=` 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; @@ -46925,7 +46931,7 @@ lösung: vb-wald-loesung.visustruct -`,fz=` +`,bz=` 105;110;112;117;116;58;32;105;110;116;32;103;114;97;100;101;32;34;71;114;97;100;101;63;34; @@ -46944,7 +46950,7 @@ lösung: vb-wald-loesung.visustruct -`,bz=` +`,xz=` 105;110;112;117;116;58;32;105;110;116;32;121;101;97;114;32;34;89;101;97;114;63;34; @@ -46963,7 +46969,7 @@ lösung: vb-wald-loesung.visustruct -`,xz=` +`,vz=` 105;110;112;117;116;58;32;105;110;116;32;100;97;121;32;34;68;97;121;32;40;49;32;116;111;32;55;41;63;34; @@ -46982,7 +46988,7 @@ lösung: vb-wald-loesung.visustruct -`,vz=` +`,yz=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;99;111;108;111;114;32;34;87;104;97;116;32;99;111;108;111;114;32;105;115;32;116;104;101;32;116;114;97;102;102;105;99;32;108;105;103;104;116;63;34; @@ -47011,7 +47017,7 @@ lösung: vb-wald-loesung.visustruct -`,yz=` +`,wz=` 105;110;112;117;116;58;32;105;110;116;32;99;104;111;105;99;101;32;34;49;32;119;97;116;101;114;44;32;50;32;106;117;105;99;101;44;32;51;32;99;111;99;111;97;34; @@ -47040,7 +47046,7 @@ lösung: vb-wald-loesung.visustruct -`,wz=` +`,zz=` 105;110;112;117;116;58;32;105;110;116;32;100;97;121;32;34;87;104;105;99;104;32;100;97;121;32;40;49;32;116;111;32;55;41;63;34; @@ -47059,7 +47065,7 @@ lösung: vb-wald-loesung.visustruct -`,zz=` +`,Iz=` 105;110;112;117;116;58;32;105;110;116;32;100;97;121;32;34;87;104;105;99;104;32;100;97;121;32;40;49;32;116;111;32;55;41;63;34; @@ -47078,7 +47084,7 @@ lösung: vb-wald-loesung.visustruct -`,Iz=` +`,kz=` 105;110;112;117;116;58;32;105;110;116;32;104;111;117;114;32;34;87;104;97;116;32;116;105;109;101;32;105;115;32;105;116;32;40;106;117;115;116;32;116;104;101;32;104;111;117;114;41;63;34; @@ -47097,7 +47103,7 @@ lösung: vb-wald-loesung.visustruct -`,kz=` +`,Sz=` 105;110;112;117;116;58;32;105;110;116;32;103;114;97;100;101;32;34;87;104;105;99;104;32;103;114;97;100;101;63;34; @@ -47141,7 +47147,7 @@ lösung: vb-wald-loesung.visustruct -`,Sz=` +`,Tz=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;34; @@ -47188,7 +47194,7 @@ lösung: vb-wald-loesung.visustruct -`,Tz=` +`,_z=` 105;110;112;117;116;58;32;105;110;116;32;99;104;111;105;99;101;32;34;49;32;119;97;116;101;114;44;32;50;32;106;117;105;99;101;44;32;51;32;99;111;99;111;97;34; @@ -47227,7 +47233,7 @@ lösung: vb-wald-loesung.visustruct -`,_z=` +`,Oz=` 80;117;116;32;97;32;99;117;112;32;111;110;32;116;104;101;32;116;97;98;108;101; @@ -47257,7 +47263,7 @@ lösung: vb-wald-loesung.visustruct 68;114;105;110;107;32;116;104;101;32;116;101;97; -`,Oz=` +`,Az=` 71;101;116;32;117;112; @@ -47272,7 +47278,7 @@ lösung: vb-wald-loesung.visustruct 72;97;118;101;32;98;114;101;97;107;102;97;115;116; -`,Az=` +`,Cz=` 70;105;108;108;32;116;104;101;32;107;101;116;116;108;101;32;119;105;116;104;32;119;97;116;101;114; @@ -47293,7 +47299,7 @@ lösung: vb-wald-loesung.visustruct 84;97;107;101;32;111;117;116;32;116;104;101;32;116;101;97;32;98;97;103; -`,Cz=` +`,jz=` 73;115;32;105;116;32;114;97;105;110;105;110;103;63; @@ -47326,7 +47332,7 @@ lösung: vb-wald-loesung.visustruct 67;108;101;97;114;32;116;104;101;32;112;108;97;116;101; -`,jz=` +`,Dz=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;67;111;117;110;116;32;117;112;32;116;111;63;34; @@ -47346,7 +47352,7 @@ lösung: vb-wald-loesung.visustruct -`,Dz=` +`,Bz=` 105;110;116;32;110;117;109;98;101;114;32;61;32;51; @@ -47366,7 +47372,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; -`,Bz=` +`,Zz=` 105;110;116;32;110;117;109;98;101;114;32;61;32;51; @@ -47383,7 +47389,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; -`,Zz=` +`,Mz=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;70;97;99;116;111;114;105;97;108;32;111;102;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -47409,7 +47415,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;32;43;32;34;33;32;61;32;34;32;43;32;102;97;99;116;111;114;105;97;108; -`,Mz=` +`,Lz=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; @@ -47444,7 +47450,7 @@ lösung: vb-wald-loesung.visustruct -`,Lz=` +`,Ez=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; @@ -47479,7 +47485,7 @@ lösung: vb-wald-loesung.visustruct -`,Ez=` +`,Wz=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;87;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -47508,7 +47514,7 @@ lösung: vb-wald-loesung.visustruct -`,Wz=` +`,Nz=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;110;117;109;98;101;114;34; @@ -47531,7 +47537,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;116;101;112;115; -`,Nz=` +`,Fz=` 105;110;116;32;110;117;109;98;101;114;32;61;32;48; @@ -47548,7 +47554,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;104;97;110;107;32;121;111;117;33;34; -`,Fz=` +`,Jz=` 105;110;116;32;105;32;61;32;49;48; @@ -47565,7 +47571,7 @@ lösung: vb-wald-loesung.visustruct -`,Jz=` +`,Rz=` 105;110;112;117;116;58;32;105;110;116;32;103;111;97;108;32;34;83;97;118;105;110;103;115;32;103;111;97;108;63;34; @@ -47591,7 +47597,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;87;101;101;107;115;58;32;34;32;43;32;119;101;101;107;115; -`,Rz=` +`,Gz=` 105;110;112;117;116;58;32;105;110;116;32;103;111;97;108;32;34;83;97;118;105;110;103;115;32;103;111;97;108;63;34; @@ -47617,7 +47623,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;87;101;101;107;115;58;32;34;32;43;32;119;101;101;107;115; -`,Gz=` +`,Hz=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;101;114;101;63;34; @@ -47637,7 +47643,7 @@ lösung: vb-wald-loesung.visustruct -`,Hz=` +`,Vz=` 105;110;116;32;103;114;97;100;101;32;61;32;48; @@ -47654,7 +47660,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;89;111;117;114;32;103;114;97;100;101;58;32;34;32;43;32;103;114;97;100;101; -`,Vz=` +`,qz=` 105;110;116;32;115;117;109;32;61;32;48; @@ -47677,7 +47683,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109; -`,qz=` +`,Qz=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;83;116;97;114;116;32;110;117;109;98;101;114;34; @@ -47696,7 +47702,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;111;33;34; -`,Qz=` +`,Uz=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;87;104;105;99;104;32;116;105;109;101;115;32;116;97;98;108;101;63;34; @@ -47715,7 +47721,7 @@ lösung: vb-wald-loesung.visustruct -`,Uz=` +`,$z=` 105;110;116;32;105;32;61;32;49; @@ -47728,7 +47734,7 @@ lösung: vb-wald-loesung.visustruct -`,$z=` +`,Yz=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;110;117;109;98;101;114;63;34; @@ -47745,7 +47751,7 @@ lösung: vb-wald-loesung.visustruct -`,Yz=` +`,Xz=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;110;117;109;98;101;114;63;34; @@ -47762,7 +47768,7 @@ lösung: vb-wald-loesung.visustruct -`,Xz=` +`,Kz=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;110;117;109;98;101;114;63;34; @@ -47779,7 +47785,7 @@ lösung: vb-wald-loesung.visustruct -`,Kz=` +`,e6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -47801,7 +47807,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109; -`,e6=` +`,t6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;72;111;119;32;109;97;110;121;32;108;105;110;101;115;63;34; @@ -47830,7 +47836,7 @@ lösung: vb-wald-loesung.visustruct -`,t6=` +`,n6=` 105;110;116;32;99;111;117;110;116;32;61;32;48; @@ -47862,7 +47868,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;99;111;117;110;116; -`,n6=` +`,i6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -47894,7 +47900,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;99;111;117;110;116; -`,i6=` +`,a6=` 105;110;112;117;116;58;32;105;110;116;32;114;111;119;32;34;87;104;105;99;104;32;116;105;109;101;115;32;116;97;98;108;101;63;34; @@ -47910,7 +47916,7 @@ lösung: vb-wald-loesung.visustruct -`,a6=` +`,s6=` 105;110;112;117;116;58;32;105;110;116;32;114;111;119;32;34;87;104;105;99;104;32;116;105;109;101;115;32;116;97;98;108;101;63;34; @@ -47926,7 +47932,7 @@ lösung: vb-wald-loesung.visustruct -`,s6=` +`,r6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -47942,7 +47948,7 @@ lösung: vb-wald-loesung.visustruct -`,r6=` +`,o6=` 105;110;112;117;116;58;32;105;110;116;32;119;105;100;116;104;32;34;87;105;100;116;104;34; @@ -47974,7 +47980,7 @@ lösung: vb-wald-loesung.visustruct -`,o6=` +`,l6=` 105;110;116;91;93;32;110;117;109;98;101;114;115;32;61;32;123;50;44;32;52;44;32;54;44;32;56;44;32;49;48;125; @@ -47990,7 +47996,7 @@ lösung: vb-wald-loesung.visustruct -`,l6=` +`,u6=` 105;110;116;91;93;32;118;97;108;117;101;115;32;61;32;123;52;44;32;56;44;32;49;53;44;32;49;54;44;32;50;51;44;32;52;50;125; @@ -48005,7 +48011,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;118;97;108;117;101;115;46;108;101;110;103;116;104; -`,u6=` +`,c6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -48037,7 +48043,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;67;111;117;110;116;58;32;34;32;43;32;99;111;117;110;116; -`,c6=` +`,m6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -48069,7 +48075,7 @@ lösung: vb-wald-loesung.visustruct -`,m6=` +`,d6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;72;111;119;32;109;97;110;121;32;115;116;101;112;115;63;34; @@ -48098,7 +48104,7 @@ lösung: vb-wald-loesung.visustruct -`,d6=` +`,h6=` 83;116;114;105;110;103;91;93;32;110;97;109;101;115;32;61;32;110;101;119;32;83;116;114;105;110;103;91;51;93; @@ -48117,7 +48123,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;70;105;114;115;116;32;110;97;109;101;58;32;34;32;43;32;110;97;109;101;115;91;48;93; -`,h6=` +`,g6=` 105;110;116;91;93;32;110;117;109;98;101;114;115;32;61;32;110;101;119;32;105;110;116;91;52;93; @@ -48143,7 +48149,7 @@ lösung: vb-wald-loesung.visustruct -`,g6=` +`,p6=` 105;110;116;91;93;32;110;117;109;98;101;114;115;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -48194,7 +48200,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;97;120;105;109;117;109;58;32;34;32;43;32;109;97;120; -`,p6=` +`,f6=` 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;123;49;50;44;32;55;44;32;49;57;44;32;52;125; @@ -48235,7 +48241,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;97;120;105;109;117;109;58;32;34;32;43;32;109;97;120; -`,f6=` +`,b6=` 105;110;116;32;115;117;109;32;61;32;48; @@ -48258,7 +48264,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; -`,b6=` +`,x6=` 105;110;116;32;115;117;109;32;61;32;48; @@ -48288,7 +48294,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; -`,x6=` +`,v6=` 105;110;112;117;116;58;32;105;110;116;32;108;101;110;103;116;104;32;34;76;101;110;103;116;104;63;34; @@ -48303,13 +48309,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;114;101;97;58;32;34;32;43;32;102; -`,v6=` +`,y6=` 114;101;116;117;114;110;32;97;32;42;32;98; -`,y6=` +`,w6=` 115;104;111;119;71;114;101;101;116;105;110;103;40;41; @@ -48321,7 +48327,7 @@ lösung: vb-wald-loesung.visustruct 115;104;111;119;82;101;115;117;108;116;40;41; -`,w6=` +`,z6=` 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;101;115;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; @@ -48353,7 +48359,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;105;103;104;101;115;116;32;116;101;109;112;101;114;97;116;117;114;101;58;32;34;32;43;32;109;97;120; -`,z6=` +`,I6=` 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;101;115;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; @@ -48385,7 +48391,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;105;103;104;101;115;116;32;116;101;109;112;101;114;97;116;117;114;101;58;32;34;32;43;32;109;97;120; -`,I6=` +`,k6=` 105;110;116;91;93;32;103;114;97;100;101;115;32;61;32;123;50;44;32;51;44;32;49;44;32;52;125; @@ -48407,7 +48413,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; -`,k6=` +`,S6=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;87;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -48419,7 +48425,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;104;101;32;115;113;117;97;114;101;32;105;115;32;34;32;43;32;113; -`,S6=` +`,T6=` 105;110;116;32;114;101;115;117;108;116;32;61;32;120;32;42;32;120; @@ -48428,7 +48434,7 @@ lösung: vb-wald-loesung.visustruct 114;101;116;117;114;110;32;114;101;115;117;108;116; -`,T6=` +`,_6=` 115;104;111;119;84;105;116;108;101;40;41; @@ -48440,7 +48446,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;101;108;108;111;32;34;32;43;32;110;97;109;101; -`,_6=` +`,O6=` 111;117;116;112;117;116;58;32;34;87;101;108;99;111;109;101;32;116;111;32;116;104;101;32;113;117;105;122;33;34; @@ -48449,7 +48455,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;89;111;117;32;103;101;116;32;116;104;114;101;101;32;113;117;101;115;116;105;111;110;115;46;34; -`,O6=` +`,A6=` 115;104;111;119;83;117;109;40;51;44;32;52;41; @@ -48461,7 +48467,7 @@ lösung: vb-wald-loesung.visustruct 115;104;111;119;83;117;109;40;120;44;32;120;32;43;32;49;41; -`,A6=` +`,C6=` 105;110;116;32;115;117;109;32;61;32;97;32;43;32;98; @@ -48470,7 +48476,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;32;43;32;34;32;43;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;115;117;109; -`,C6=` +`,j6=` 105;110;112;117;116;58;32;105;110;116;32;115;116;97;114;116;32;34;83;116;97;114;116;32;118;97;108;117;101;34; @@ -48516,7 +48522,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;111;34; -`,j6=` +`,D6=` 105;110;116;91;93;91;93;32;112;111;105;110;116;115;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; @@ -48538,7 +48544,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;108;97;121;101;114;32;50;58;32;34;32;43;32;116;111;116;97;108; -`,D6=` +`,B6=` 105;110;116;91;93;91;93;32;112;111;105;110;116;115;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; @@ -48560,7 +48566,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;108;97;121;101;114;32;50;58;32;34;32;43;32;116;111;116;97;108; -`,B6=` +`,Z6=` 105;110;116;91;93;91;93;32;112;111;105;110;116;115;32;61;32;123;123;51;44;32;53;125;44;32;123;52;44;32;49;125;44;32;123;50;44;32;50;125;125; @@ -48589,7 +48595,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; -`,Z6=` +`,M6=` 105;110;116;32;115;117;109;32;61;32;48; @@ -48612,7 +48618,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109; -`,M6=` +`,L6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -48634,7 +48640,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109; -`,L6=` +`,E6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -48656,7 +48662,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109; -`,E6=` +`,W6=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;87;104;105;99;104;32;116;105;109;101;115;32;116;97;98;108;101;63;34; @@ -48688,7 +48694,7 @@ lösung: vb-wald-loesung.visustruct -`,W6=` +`,N6=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;34; @@ -48710,7 +48716,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;102;97;99;116;111;114;105;97;108; -`,N6=` +`,F6=` 83;116;114;105;110;103;32;108;101;116;116;101;114;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;101;116;116;101;114;46;116;120;116;34;41;41; @@ -48742,13 +48748,13 @@ lösung: vb-wald-loesung.visustruct -`,F6=` +`,J6=` 83;116;114;105;110;103;32;108;101;116;116;101;114;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;101;116;116;101;114;46;116;120;116;34;41;41; -`,J6=` +`,R6=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;105;114;115;116;32;34;70;105;114;115;116;32;110;97;109;101;63;34; @@ -48760,7 +48766,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;102;105;114;115;116;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;108;97;115;116;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; -`,R6=` +`,G6=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;105;114;115;116;32;34;70;105;114;115;116;32;110;97;109;101;63;34; @@ -48772,7 +48778,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;102;105;114;115;116;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;32;34;32;43;32;108;97;115;116;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;34; -`,G6=` +`,H6=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;105;110;112;117;116;32;34;80;97;115;115;119;111;114;100;63;34; @@ -48791,7 +48797,7 @@ lösung: vb-wald-loesung.visustruct -`,H6=` +`,V6=` 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; @@ -48820,7 +48826,7 @@ lösung: vb-wald-loesung.visustruct -`,V6=` +`,q6=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;118;97;108;117;101;63;34; @@ -48840,7 +48846,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;69;110;100;34; -`,q6=` +`,Q6=` 105;110;116;32;116;114;105;101;115;32;61;32;48; @@ -48873,7 +48879,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;114;105;101;115;58;32;34;32;43;32;116;114;105;101;115; -`,Q6=` +`,U6=` 105;110;116;32;116;114;105;101;115;32;61;32;48; @@ -48906,7 +48912,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;114;105;101;115;58;32;34;32;43;32;116;114;105;101;115; -`,U6=` +`,$6=` 105;110;116;32;115;117;109;32;61;32;48; @@ -48948,7 +48954,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;115;117;109; -`,$6=` +`,Y6=` 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; @@ -48970,7 +48976,7 @@ lösung: vb-wald-loesung.visustruct -`,Y6=` +`,X6=` 105;110;112;117;116;58;32;105;110;116;32;108;105;109;105;116;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; @@ -48986,7 +48992,7 @@ lösung: vb-wald-loesung.visustruct -`,X6=` +`,K6=` 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -49025,7 +49031,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; -`,K6=` +`,e7=` 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -49064,7 +49070,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; -`,e7=` +`,t7=` 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -49099,7 +49105,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;67;111;117;110;116;58;32;34;32;43;32;99;111;117;110;116; -`,t7=` +`,n7=` 111;117;116;112;117;116;58;32;34;71;111;111;100;32;109;111;114;110;105;110;103;34; @@ -49108,13 +49114,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;100;97;121;32;119;101;32;108;101;97;114;110;32;115;116;114;117;99;116;117;114;101;32;99;104;97;114;116;115;46;34; -`,n7=` +`,i7=` 111;117;116;112;117;116;58;32;34;72;101;108;108;111;32;87;111;114;108;100;34; -`,i7=` +`,a7=` 111;117;116;112;117;116;58;32;34;72;101;108;108;111;34; @@ -49123,7 +49129,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;73;32;97;109;32;108;101;97;114;110;105;110;103;32;115;116;114;117;99;116;117;114;101;32;99;104;97;114;116;115;34; -`,a7=` +`,s7=` 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; @@ -49164,7 +49170,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;99;111;117;110;116;32;43;32;34;32;108;105;110;101;115;32;115;97;118;101;100;34; -`,s7=` +`,r7=` 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; @@ -49173,7 +49179,7 @@ lösung: vb-wald-loesung.visustruct 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;115;104;111;112;112;105;110;103;45;110;101;119;46;116;120;116;34;41; -`,r7=` +`,o7=` 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; @@ -49199,13 +49205,13 @@ lösung: vb-wald-loesung.visustruct 102;105;108;101;46;99;108;111;115;101;40;41; -`,o7=` +`,l7=` 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; -`,l7=` +`,u7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; @@ -49244,7 +49250,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;70;111;120;58;32;34;32;43;32;99;111;117;110;116; -`,u7=` +`,c7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; @@ -49253,7 +49259,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,c7=` +`,m7=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; @@ -49288,7 +49294,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;76;111;110;103;101;115;116;32;101;110;116;114;121;58;32;34;32;43;32;108;111;110;103;101;115;116; -`,m7=` +`,d7=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; @@ -49297,7 +49303,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;91;93;32;108;105;110;101;115;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; -`,d7=` +`,h7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;99;108;97;115;115;46;99;115;118;34;41;41; @@ -49351,7 +49357,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;66;101;115;116;32;103;114;97;100;101;32;105;110;32;69;110;103;108;105;115;104;58;32;34;32;43;32;98;101;115;116;78;97;109;101;32;43;32;34;32;40;34;32;43;32;98;101;115;116;71;114;97;100;101;32;43;32;34;41;34; -`,h7=` +`,g7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;99;108;97;115;115;46;99;115;118;34;41;41; @@ -49360,7 +49366,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,g7=` +`,p7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;99;108;97;115;115;46;99;115;118;34;41;41; @@ -49401,7 +49407,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;97;116;104;115;32;97;118;101;114;97;103;101;58;32;34;32;43;32;115;117;109;32;47;32;99;111;117;110;116; -`,p7=` +`,f7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;99;108;97;115;115;46;99;115;118;34;41;41; @@ -49410,7 +49416,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,f7=` +`,b7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; @@ -49449,7 +49455,7 @@ lösung: vb-wald-loesung.visustruct 114;101;97;100;101;114;46;99;108;111;115;101;40;41; -`,b7=` +`,x7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; @@ -49458,7 +49464,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,x7=` +`,v7=` 83;116;114;105;110;103;91;93;32;110;97;109;101;115;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;70;111;120;34;125; @@ -49508,7 +49514,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;97;109;101;115;46;108;101;110;103;116;104;32;43;32;34;32;101;110;116;114;105;101;115;32;115;97;118;101;100;34; -`,v7=` +`,y7=` 83;116;114;105;110;103;91;93;32;110;97;109;101;115;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;70;111;120;34;125; @@ -49526,7 +49532,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;46;99;108;111;115;101;40;41; -`,y7=` +`,w7=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;97;110;105;109;97;108;115;46;99;115;118;34;41;41; @@ -49579,7 +49585,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;40;108;105;110;101;115;46;108;101;110;103;116;104;32;45;32;49;41;32;43;32;34;32;97;110;105;109;97;108;115;32;115;97;118;101;100;34; -`,w7=` +`,z7=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;97;110;105;109;97;108;115;46;99;115;118;34;41;41; @@ -49600,7 +49606,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;46;99;108;111;115;101;40;41; -`,z7=` +`,I7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;97;110;105;109;97;108;115;46;99;115;118;34;41;41; @@ -49644,7 +49650,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;99;111;117;110;116;32;43;32;34;32;115;101;110;116;101;110;99;101;115;32;115;97;118;101;100;34; -`,I7=` +`,k7=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;97;110;105;109;97;108;115;46;99;115;118;34;41;41; @@ -49665,7 +49671,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;46;99;108;111;115;101;40;41; -`,k7=` +`,S7=` 105;110;112;117;116;58;32;105;110;116;32;99;111;117;110;116;32;34;72;111;119;32;109;97;110;121;32;116;105;99;107;101;116;115;63;34; @@ -49677,7 +49683,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; -`,S7=` +`,T7=` 105;110;112;117;116;58;32;105;110;116;32;99;111;117;110;116;32;34;72;111;119;32;109;97;110;121;32;116;105;99;107;101;116;115;63;34; @@ -49689,7 +49695,7 @@ lösung: vb-wald-loesung.visustruct 100;111;117;98;108;101;32;116;111;116;97;108;32;61;32;99;111;117;110;116;32;42;32;56;46;53; -`,T7=` +`,_7=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;34; @@ -49713,7 +49719,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98; -`,_7=` +`,O7=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;34; @@ -49734,7 +49740,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98; -`,O7=` +`,A7=` 105;110;116;32;97;32;61;32;51; @@ -49758,7 +49764,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; -`,A7=` +`,C7=` 105;110;116;91;93;32;99;97;114;100;115;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -49817,7 +49823,7 @@ lösung: vb-wald-loesung.visustruct -`,C7=` +`,j7=` 105;110;116;91;93;32;99;97;114;100;115;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -49950,7 +49956,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;67;111;109;112;97;114;105;115;111;110;115;58;32;34;32;43;32;99;111;109;112;97;114;105;115;111;110;115; -`,j7=` +`,D7=` 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;55;44;32;51;44;32;49;48;44;32;53;44;32;50;125; @@ -49999,7 +50005,7 @@ lösung: vb-wald-loesung.visustruct -`,D7=` +`,B7=` 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -50048,7 +50054,7 @@ lösung: vb-wald-loesung.visustruct -`,B7=` +`,Z7=` 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; @@ -50106,7 +50112,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;67;111;109;112;97;114;105;115;111;110;115;58;32;34;32;43;32;99;111;109;112;97;114;105;115;111;110;115; -`,Z7=` +`,M7=` 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;123;51;44;32;53;44;32;56;125; @@ -50125,7 +50131,7 @@ lösung: vb-wald-loesung.visustruct -`,M7=` +`,L7=` 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;123;51;44;32;53;44;32;56;125; @@ -50144,7 +50150,7 @@ lösung: vb-wald-loesung.visustruct -`,L7=` +`,E7=` 105;110;116;32;105;32;61;32;48; @@ -50157,7 +50163,7 @@ lösung: vb-wald-loesung.visustruct -`,E7=` +`,W7=` 105;110;116;32;110;117;109;98;101;114;32;61;32;53; @@ -50181,7 +50187,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;102;116;101;114;58;32;34;32;43;32;114;111;119;91;48;93;32;43;32;34;44;32;34;32;43;32;114;111;119;91;49;93; -`,W7=` +`,N7=` 105;110;116;32;105;32;61;32;48; @@ -50194,7 +50200,7 @@ lösung: vb-wald-loesung.visustruct -`,N7=` +`,F7=` 120;32;61;32;120;32;42;32;50; @@ -50203,7 +50209,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;73;110;32;116;104;101;32;115;117;98;112;114;111;103;114;97;109;58;32;120;32;61;32;34;32;43;32;120; -`,F7=` +`,J7=` 105;110;116;32;100;105;115;116;97;110;99;101;32;61;32;109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41; @@ -50212,7 +50218,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;68;105;115;116;97;110;99;101;58;32;34;32;43;32;100;105;115;116;97;110;99;101;32;43;32;34;32;99;109;34;41; -`,J7=` +`,R7=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;49;48; @@ -50238,7 +50244,7 @@ lösung: vb-wald-loesung.visustruct -`,R7=` +`,G7=` 33;109;98;111;116;46;105;115;66;117;116;116;111;110;66;40;41; @@ -50265,7 +50271,7 @@ lösung: vb-wald-loesung.visustruct -`,G7=` +`,H7=` 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; @@ -50283,7 +50289,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;50;53;53;44;32;48;41; -`,H7=` +`,V7=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -50313,7 +50319,7 @@ lösung: vb-wald-loesung.visustruct -`,V7=` +`,q7=` 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;72;101;108;108;111;33;34;41; @@ -50325,7 +50331,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;73;32;97;109;32;86;105;115;117;66;111;116;34;41; -`,q7=` +`,Q7=` 105;110;116;32;110;117;109;98;101;114;32;61;32;48; @@ -50377,7 +50383,7 @@ lösung: vb-wald-loesung.visustruct -`,Q7=` +`,U7=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;101;100;34;41; @@ -50388,7 +50394,7 @@ lösung: vb-wald-loesung.visustruct -`,U7=` +`,$7=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; @@ -50399,7 +50405,7 @@ lösung: vb-wald-loesung.visustruct -`,$7=` +`,Y7=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -50410,7 +50416,7 @@ lösung: vb-wald-loesung.visustruct -`,Y7=` +`,X7=` 83;116;114;105;110;103;32;119;111;114;100;32;61;32;34;86;105;115;117;66;111;116;34; @@ -50429,7 +50435,7 @@ lösung: vb-wald-loesung.visustruct -`,X7=` +`,K7=` 109;98;111;116;46;108;101;100;40;48;41;46;115;101;116;67;111;108;111;114;40;34;114;101;100;34;41; @@ -50441,7 +50447,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;108;101;100;40;52;41;46;115;101;116;67;111;108;111;114;40;34;103;114;101;101;110;34;41; -`,K7=` +`,eI=` 105;110;116;32;105;32;61;32;48; @@ -50457,7 +50463,7 @@ lösung: vb-wald-loesung.visustruct -`,eI=` +`,tI=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;98;108;117;101;34;41; @@ -50485,7 +50491,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;80;97;114;107;101;100;33;34;41; -`,tI=` +`,nI=` 83;116;114;105;110;103;91;93;32;99;111;108;111;117;114;115;32;61;32;123;34;114;101;100;34;44;32;34;121;101;108;108;111;119;34;44;32;34;103;114;101;101;110;34;44;32;34;98;108;117;101;34;44;32;34;112;117;114;112;108;101;34;125; @@ -50501,7 +50507,7 @@ lösung: vb-wald-loesung.visustruct -`,nI=` +`,iI=` 109;98;111;116;46;103;101;116;67;111;108;111;114;40;41; @@ -50527,7 +50533,7 @@ lösung: vb-wald-loesung.visustruct -`,iI=` +`,aI=` 109;98;111;116;46;100;114;105;118;101;40;53;48;44;32;53;48;41; @@ -50544,7 +50550,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;116;111;112;40;41; -`,aI=` +`,sI=` 109;98;111;116;46;102;111;114;119;97;114;100;40;41; @@ -50562,7 +50568,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;102;111;114;119;97;114;100;40;41; -`,sI=` +`,rI=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;101;100;34;41; @@ -50598,7 +50604,7 @@ lösung: vb-wald-loesung.visustruct -`,rI=` +`,oI=` 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;66;97;116;116;101;114;121;58;32;34;32;43;32;109;98;111;116;46;103;101;116;66;97;116;116;101;114;121;40;41;32;43;32;34;32;37;34;41; @@ -50617,7 +50623,7 @@ lösung: vb-wald-loesung.visustruct -`,oI=` +`,lI=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;98;108;117;101;34;41; @@ -50641,7 +50647,7 @@ lösung: vb-wald-loesung.visustruct -`,lI=` +`,uI=` 105;110;116;32;105;32;61;32;48; @@ -50663,7 +50669,7 @@ lösung: vb-wald-loesung.visustruct -`,uI=` +`,cI=` 105;110;116;32;105;32;61;32;51; @@ -50682,7 +50688,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;71;111;33;34;41; -`,cI=` +`,mI=` 105;110;116;32;105;32;61;32;49; @@ -50695,7 +50701,7 @@ lösung: vb-wald-loesung.visustruct -`,mI=` +`,dI=` 105;110;116;32;105;32;61;32;48; @@ -50728,7 +50734,7 @@ lösung: vb-wald-loesung.visustruct -`,dI=` +`,hI=` 109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;62;32;54;48; @@ -50744,7 +50750,7 @@ lösung: vb-wald-loesung.visustruct -`,hI=` +`,gI=` 105;110;116;32;105;32;61;32;48; @@ -50763,7 +50769,7 @@ lösung: vb-wald-loesung.visustruct -`,gI=` +`,pI=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; @@ -50807,7 +50813,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;116;111;112;40;41; -`,pI=` +`,fI=` 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;51;48; @@ -50826,7 +50832,7 @@ lösung: vb-wald-loesung.visustruct -`,fI=` +`,bI=` 105;110;116;32;115;116;101;112;115;32;61;32;48; @@ -50856,7 +50862,7 @@ lösung: vb-wald-loesung.visustruct -`,bI=` +`,xI=` 105;110;116;32;108;101;110;103;116;104;32;61;32;54;48; @@ -50884,7 +50890,7 @@ lösung: vb-wald-loesung.visustruct -`,xI=` +`,vI=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;34;72;101;108;108;111;32;99;108;97;115;115;34; @@ -50893,7 +50899,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;116;101;120;116;32;43;32;34;32;40;34;32;43;32;116;101;120;116;46;108;101;110;103;116;104;40;41;32;43;32;34;41;34;41; -`,vI=` +`,yI=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; @@ -50907,7 +50913,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;112;108;97;121;84;111;110;101;40;52;52;48;44;32;51;48;48;41; -`,yI=` +`,wI=` 109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;62;32;45;53;32;38;38;32;109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;60;32;53;32;38;38;32;109;98;111;116;46;103;101;116;82;111;108;108;40;41;32;62;32;45;53;32;38;38;32;109;98;111;116;46;103;101;116;82;111;108;108;40;41;32;60;32;53; @@ -50923,7 +50929,7 @@ lösung: vb-wald-loesung.visustruct -`,wI=` +`,zI=` 109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;60;32;53;48; @@ -50937,7 +50943,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; -`,zI=` +`,II=` 105;110;116;32;105;32;61;32;48; @@ -50972,7 +50978,7 @@ lösung: vb-wald-loesung.visustruct -`,II=` +`,kI=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -51006,7 +51012,7 @@ lösung: vb-wald-loesung.visustruct -`,kI=` +`,SI=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;101;100;34;41; @@ -51050,7 +51056,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;116;111;112;40;41; -`,SI=` +`,TI=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41; @@ -51076,7 +51082,7 @@ lösung: vb-wald-loesung.visustruct -`,TI=` +`,_I=` 105;110;116;91;93;32;116;111;110;101;115;32;61;32;123;50;54;50;44;32;50;57;52;44;32;51;51;48;44;32;51;52;57;44;32;51;57;50;125; @@ -51092,7 +51098,7 @@ lösung: vb-wald-loesung.visustruct -`,_I=` +`,OI=` 105;110;116;32;105;32;61;32;48; @@ -51158,7 +51164,7 @@ lösung: vb-wald-loesung.visustruct -`,OI=` +`,AI=` 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;51;48; @@ -51174,7 +51180,7 @@ lösung: vb-wald-loesung.visustruct -`,AI=` +`,CI=` 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;50;48; @@ -51191,7 +51197,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;90;122;122;34;41; -`,CI=` +`,jI=` 105;110;112;117;116;58;32;105;110;116;32;103;114;97;100;101; @@ -51235,13 +51241,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98; -`,jI=` +`,DI=` 114;101;116;117;114;110;32;120;32;42;32;120; -`,DI=` +`,BI=` 83;116;114;105;110;103;32;119;111;114;100;32;61;32;34;76;117;100;119;105;103;34; @@ -51263,7 +51269,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98;97;99;107;119;97;114;100;115; -`,BI=` +`,ZI=` 105;110;116;32;108;101;110;103;116;104;32;61;32;54;48; @@ -51278,7 +51284,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;105;115;116;97;110;99;101;58;32;34;32;43;32;100;105;115;116;97;110;99;101;32;43;32;34;32;99;109;34; -`,ZI=` +`,MI=` 105;110;116;91;93;32;103;114;97;100;101;115;32;61;32;123;50;44;32;49;44;32;51;44;32;50;125; @@ -51303,7 +51309,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;67;111;117;110;116;58;32;34;32;43;32;103;114;97;100;101;115;46;108;101;110;103;116;104; -`,MI=` +`,LI=` 109;98;111;116;46;102;111;114;119;97;114;100;40;41; @@ -51378,7 +51384,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; -`,LI=` +`,EI=` 115;113;117;97;114;101;40;51;48;41; @@ -51387,7 +51393,7 @@ lösung: vb-wald-loesung.visustruct 115;113;117;97;114;101;40;53;48;41; -`,EI=` +`,WI=` 105;110;116;32;105;32;61;32;48; @@ -51442,7 +51448,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; -`,WI=` +`,NI=` 105;110;116;32;105;32;61;32;48; @@ -51458,7 +51464,7 @@ lösung: vb-wald-loesung.visustruct -`,NI=` +`,FI=` 105;110;116;32;105;32;61;32;48; @@ -51481,7 +51487,7 @@ lösung: vb-wald-loesung.visustruct -`,FI=` +`,JI=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -51495,7 +51501,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; -`,JI=` +`,RI=` 109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;62;32;50;48;32;124;124;32;109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;60;32;45;50;48; @@ -51511,7 +51517,7 @@ lösung: vb-wald-loesung.visustruct -`,RI=` +`,GI=` 105;110;116;32;105;32;61;32;48; @@ -51563,7 +51569,7 @@ lösung: vb-wald-loesung.visustruct -`,GI=` +`,HI=` 105;110;116;32;105;32;61;32;49; @@ -51579,7 +51585,7 @@ lösung: vb-wald-loesung.visustruct -`,HI=` +`,VI=` 33;109;98;111;116;46;105;115;66;117;116;116;111;110;65;40;41; @@ -51593,7 +51599,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; -`,VI=` +`,qI=` 109;98;111;116;46;112;108;97;121;84;111;110;101;40;50;54;50;44;32;51;48;48;41; @@ -51611,7 +51617,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;112;108;97;121;84;111;110;101;40;51;57;50;44;32;51;48;48;41; -`,qI=` +`,QI=` 105;110;116;32;105;32;61;32;48; @@ -51633,7 +51639,7 @@ lösung: vb-wald-loesung.visustruct -`,QI=` +`,UI=` 105;110;116;32;108;101;102;116;32;61;32;57;57; @@ -51665,7 +51671,7 @@ lösung: vb-wald-loesung.visustruct -`,UI=` +`,$I=` 105;110;116;32;115;105;100;101;32;61;32;51;48; @@ -51684,7 +51690,7 @@ lösung: vb-wald-loesung.visustruct -`,$I=` +`,YI=` 105;110;116;32;105;32;61;32;48; @@ -51717,7 +51723,7 @@ lösung: vb-wald-loesung.visustruct -`,YI=` +`,XI=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -51756,7 +51762,7 @@ lösung: vb-wald-loesung.visustruct -`,XI=` +`,KI=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48; @@ -51772,7 +51778,7 @@ lösung: vb-wald-loesung.visustruct -`,KI=` +`,ek=` 109;98;111;116;46;114;101;115;101;116;84;105;109;101;114;40;41; @@ -51792,7 +51798,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;116;111;112;40;41; -`,ek=` +`,tk=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;105;114;115;116;78;97;109;101;32;34;70;105;114;115;116;32;110;97;109;101;34; @@ -51804,7 +51810,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;102;105;114;115;116;78;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;108;97;115;116;78;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; -`,tk=` +`,nk=` 83;116;114;105;110;103;32;119;111;114;100;32;61;32;34;66;105;108;108;121;103;111;97;116;34; @@ -51843,7 +51849,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;116;101;120;116; -`,nk=` +`,ik=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;100;32;34;69;110;116;101;114;32;97;32;119;111;114;100;34; @@ -51865,7 +51871,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98;97;99;107;119;97;114;100;115; -`,ik=` +`,ak=` 83;116;114;105;110;103;32;108;105;110;101;32;61;32;34;76;117;100;119;105;103;59;98;105;108;108;121;32;103;111;97;116;59;55;34; @@ -51884,7 +51890,7 @@ lösung: vb-wald-loesung.visustruct -`,ak=` +`,sk=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;115;101;110;116;101;110;99;101;32;34;69;110;116;101;114;32;97;32;115;101;110;116;101;110;99;101;34; @@ -51896,7 +51902,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;87;111;114;100;115;58;32;34;32;43;32;119;111;114;100;115;46;108;101;110;103;116;104; -`,sk=` +`,rk=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;100;32;34;69;110;116;101;114;32;97;32;119;111;114;100;34; @@ -51928,7 +51934,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;78;117;109;98;101;114;32;111;102;32;101;58;32;34;32;43;32;99;111;117;110;116; -`,rk=` +`,ok=` 83;116;114;105;110;103;32;119;111;114;100;32;61;32;34;66;105;108;108;121;103;111;97;116;34; @@ -51952,7 +51958,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;119;111;114;100;46;116;111;85;112;112;101;114;67;97;115;101;40;41; -`,ok=` +`,lk=` 105;110;116;91;93;91;93;32;116;97;98;101;108;108;101;32;61;32;110;101;119;32;105;110;116;91;49;48;93;91;49;48;93; @@ -51984,7 +51990,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;32;43;32;34;32;183;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;116;97;98;101;108;108;101;91;97;32;45;32;49;93;91;98;32;45;32;49;93; -`,lk=` +`,uk=` 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -52032,7 +52038,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;70;114;101;105;58;32;34;32;43;32;102;114;101;105; -`,uk=` +`,ck=` 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -52047,7 +52053,7 @@ lösung: vb-wald-loesung.visustruct 115;105;116;122;101;91;50;93;91;51;93;32;61;32;116;114;117;101; -`,ck=` +`,mk=` 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -52081,7 +52087,7 @@ lösung: vb-wald-loesung.visustruct -`,mk=` +`,dk=` 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -52099,7 +52105,7 @@ lösung: vb-wald-loesung.visustruct 105;110;112;117;116;58;32;105;110;116;32;112;108;97;116;122;32;34;80;108;97;116;122;34; -`,dk=` +`,hk=` 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -52147,7 +52153,7 @@ lösung: vb-wald-loesung.visustruct -`,hk=` +`,gk=` 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -52171,7 +52177,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;82;101;105;104;101;32;49;44;32;80;108;97;116;122;32;50;32;118;101;114;107;97;117;102;116;63;32;34;32;43;32;115;105;116;122;101;91;49;93;91;50;93; -`,gk=` +`,pk=` 105;110;116;32;115;101;107;117;110;100;101;110;32;61;32;50;48;48; @@ -52186,7 +52192,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;101;110;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;32;43;32;34;32;115;34; -`,pk=` +`,fk=` 105;110;116;32;115;101;107;117;110;100;101;110;32;61;32;50;48;48; @@ -52201,7 +52207,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;101;110;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;32;43;32;34;32;115;34; -`,fk=` +`,bk=` 83;116;114;105;110;103;32;110;97;109;101;32;61;32;34;76;117;100;119;105;103;34; @@ -52219,7 +52225,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;114;246;223;101;58;32;34;32;43;32;103;114;111;101;115;115;101;32;43;32;34;32;109;34; -`,bk=` +`,xk=` 105;110;116;32;122;97;104;108;32;61;32;51; @@ -52234,7 +52240,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;122;97;104;108; -`,xk=` +`,vk=` 105;110;116;32;122;97;104;108;32;61;32;50; @@ -52249,7 +52255,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;122;97;104;108; -`,vk=` +`,yk=` 111;117;116;112;117;116;58;32;122;97;104;108; @@ -52264,7 +52270,7 @@ lösung: vb-wald-loesung.visustruct 122;97;104;108;32;61;32;122;97;104;108;32;43;32;51; -`,yk=` +`,wk=` 83;116;114;105;110;103;32;108;105;110;107;115;32;61;32;34;83;97;102;116;34; @@ -52288,7 +52294,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;82;101;99;104;116;115;58;32;34;32;43;32;114;101;99;104;116;115; -`,wk=` +`,zk=` 83;116;114;105;110;103;32;108;105;110;107;115;32;61;32;34;83;97;102;116;34; @@ -52303,7 +52309,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;82;101;99;104;116;115;58;32;34;32;43;32;114;101;99;104;116;115; -`,zk=` +`,Ik=` 105;110;116;32;97;32;61;32;53; @@ -52327,7 +52333,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; -`,Ik=` +`,kk=` 105;110;116;32;97;108;116;101;114;32;61;32;49;52; @@ -52345,7 +52351,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;114;246;223;101;58;32;34;32;43;32;103;114;111;101;115;115;101;32;43;32;34;32;109;34; -`,kk=` +`,Sk=` 105;110;116;32;109;105;110;117;116;101;110;32;61;32;49;51;53; @@ -52360,7 +52366,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;116;117;110;100;101;110;32;43;32;34;32;83;116;117;110;100;101;110;32;117;110;100;32;34;32;43;32;114;101;115;116;32;43;32;34;32;77;105;110;117;116;101;110;34; -`,Sk=` +`,Tk=` 105;110;116;32;97;110;122;97;104;108;32;61;32;51; @@ -52375,7 +52381,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116;80;114;101;105;115;32;43;32;34;32;69;117;114;111;34; -`,Tk=` +`,_k=` 105;110;116;32;103;117;116;104;97;98;101;110;32;61;32;50;48; @@ -52390,7 +52396,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;220;98;114;105;103;58;32;34;32;43;32;103;117;116;104;97;98;101;110; -`,_k=` +`,Ok=` 105;110;116;32;103;117;116;104;97;98;101;110;32;61;32;50;48; @@ -52405,7 +52411,7 @@ lösung: vb-wald-loesung.visustruct 103;117;116;104;97;98;101;110;32;61;32;103;117;116;104;97;98;101;110;32;45;32;112;114;101;105;115; -`,Ok=` +`,Ak=` 105;110;116;32;112;114;101;105;115;32;61;32;57; @@ -52420,7 +52426,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116; -`,Ak=` +`,Ck=` 105;110;116;32;108;97;101;110;103;101;32;61;32;55; @@ -52441,7 +52447,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;85;109;102;97;110;103;58;32;34;32;43;32;117;109;102;97;110;103; -`,Ck=` +`,jk=` 105;110;116;32;115;101;107;117;110;100;101;110;32;61;32;50;48;48; @@ -52465,7 +52471,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;101;110;32;43;32;34;32;77;105;110;117;116;101;110;32;117;110;100;32;34;32;43;32;114;101;115;116;32;43;32;34;32;83;101;107;117;110;100;101;110;34; -`,jk=` +`,Dk=` 105;110;116;32;108;97;101;110;103;101;32;61;32;53; @@ -52480,7 +52486,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;102;108;97;101;99;104;101; -`,Dk=` +`,Bk=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;97;109;101;32;34;87;105;101;32;104;101;105;223;116;32;100;117;63;34; @@ -52489,7 +52495,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;97;108;108;111;32;34;32;43;32;110;97;109;101;32;43;32;34;33;34; -`,Bk=` +`,Zk=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; @@ -52504,7 +52510,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; -`,Zk=` +`,Mk=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; @@ -52516,7 +52522,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;40;97;32;43;32;98;41; -`,Mk=` +`,Lk=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; @@ -52528,7 +52534,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;97;32;43;32;98; -`,Lk=` +`,Ek=` 105;110;112;117;116;58;32;105;110;116;32;106;97;104;114;101;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; @@ -52540,7 +52546,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;97;115;32;115;105;110;100;32;101;116;119;97;32;34;32;43;32;116;97;103;101;32;43;32;34;32;84;97;103;101;46;34; -`,Ek=` +`,Wk=` 105;110;112;117;116;58;32;100;111;117;98;108;101;32;120;32;34;69;114;115;116;101;32;90;97;104;108;63;34; @@ -52555,7 +52561,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;105;116;116;101;108;119;101;114;116;58;32;34;32;43;32;109;105;116;116;101;108; -`,Wk=` +`,Nk=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; @@ -52576,7 +52582,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;114;111;100;117;107;116;58;32;34;32;43;32;112;114;111;100;117;107;116; -`,Nk=` +`,Fk=` 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; @@ -52595,7 +52601,7 @@ lösung: vb-wald-loesung.visustruct -`,Fk=` +`,Jk=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;90;97;104;108;63;34; @@ -52617,7 +52623,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;122;97;104;108; -`,Jk=` +`,Rk=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;90;97;104;108;63;34; @@ -52636,7 +52642,7 @@ lösung: vb-wald-loesung.visustruct -`,Rk=` +`,Gk=` 105;110;116;32;112;117;110;107;116;101;32;61;32;48; @@ -52654,7 +52660,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;117;110;107;116;101;58;32;34;32;43;32;112;117;110;107;116;101; -`,Gk=` +`,Hk=` 105;110;116;32;112;117;110;107;116;101;32;61;32;48; @@ -52672,7 +52678,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;117;110;107;116;101;58;32;34;32;43;32;112;117;110;107;116;101; -`,Hk=` +`,Vk=` 105;110;116;32;112;114;101;105;115;32;61;32;56; @@ -52690,7 +52696,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116; -`,Vk=` +`,qk=` 105;110;116;32;112;114;101;105;115;32;61;32;56; @@ -52708,7 +52714,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116; -`,qk=` +`,Qk=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; @@ -52730,7 +52736,7 @@ lösung: vb-wald-loesung.visustruct -`,Qk=` +`,Uk=` 105;110;112;117;116;58;32;100;111;117;98;108;101;32;112;114;101;105;115;32;34;80;114;101;105;115;32;105;110;32;69;117;114;111;63;34; @@ -52752,7 +52758,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;90;117;32;122;97;104;108;101;110;58;32;34;32;43;32;112;114;101;105;115;32;43;32;34;32;69;117;114;111;34; -`,Uk=` +`,$k=` 105;110;112;117;116;58;32;105;110;116;32;110;111;116;101;32;34;78;111;116;101;63;34; @@ -52771,7 +52777,7 @@ lösung: vb-wald-loesung.visustruct -`,$k=` +`,Yk=` 105;110;112;117;116;58;32;105;110;116;32;112;117;110;107;116;101;32;34;87;105;101;32;118;105;101;108;101;32;80;117;110;107;116;101;63;34; @@ -52790,7 +52796,7 @@ lösung: vb-wald-loesung.visustruct -`,Yk=` +`,Xk=` 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; @@ -52809,7 +52815,7 @@ lösung: vb-wald-loesung.visustruct -`,Xk=` +`,Kk=` 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; @@ -52828,7 +52834,7 @@ lösung: vb-wald-loesung.visustruct -`,Kk=` +`,e8=` 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; @@ -52847,7 +52853,7 @@ lösung: vb-wald-loesung.visustruct -`,e8=` +`,t8=` 105;110;112;117;116;58;32;105;110;116;32;110;111;116;101;32;34;78;111;116;101;63;34; @@ -52866,7 +52872,7 @@ lösung: vb-wald-loesung.visustruct -`,t8=` +`,n8=` 105;110;112;117;116;58;32;105;110;116;32;106;97;104;114;32;34;74;97;104;114;63;34; @@ -52885,7 +52891,7 @@ lösung: vb-wald-loesung.visustruct -`,n8=` +`,i8=` 105;110;112;117;116;58;32;105;110;116;32;116;97;103;32;34;84;97;103;32;40;49;32;98;105;115;32;55;41;63;34; @@ -52904,7 +52910,7 @@ lösung: vb-wald-loesung.visustruct -`,i8=` +`,a8=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;97;114;98;101;32;34;87;101;108;99;104;101;32;70;97;114;98;101;32;104;97;116;32;100;105;101;32;65;109;112;101;108;63;34; @@ -52933,7 +52939,7 @@ lösung: vb-wald-loesung.visustruct -`,a8=` +`,s8=` 105;110;112;117;116;58;32;105;110;116;32;119;97;104;108;32;34;49;32;87;97;115;115;101;114;44;32;50;32;83;97;102;116;44;32;51;32;75;97;107;97;111;34; @@ -52962,7 +52968,7 @@ lösung: vb-wald-loesung.visustruct -`,s8=` +`,r8=` 105;110;112;117;116;58;32;105;110;116;32;116;97;103;32;34;87;101;108;99;104;101;114;32;84;97;103;32;40;49;32;98;105;115;32;55;41;63;34; @@ -52981,7 +52987,7 @@ lösung: vb-wald-loesung.visustruct -`,r8=` +`,o8=` 105;110;112;117;116;58;32;105;110;116;32;116;97;103;32;34;87;101;108;99;104;101;114;32;84;97;103;32;40;49;32;98;105;115;32;55;41;63;34; @@ -53000,7 +53006,7 @@ lösung: vb-wald-loesung.visustruct -`,o8=` +`,l8=` 105;110;112;117;116;58;32;105;110;116;32;115;116;117;110;100;101;32;34;87;105;101;32;115;112;228;116;32;105;115;116;32;101;115;32;40;110;117;114;32;100;105;101;32;83;116;117;110;100;101;41;63;34; @@ -53019,7 +53025,7 @@ lösung: vb-wald-loesung.visustruct -`,l8=` +`,u8=` 105;110;112;117;116;58;32;105;110;116;32;110;111;116;101;32;34;87;101;108;99;104;101;32;78;111;116;101;63;34; @@ -53063,7 +53069,7 @@ lösung: vb-wald-loesung.visustruct -`,u8=` +`,c8=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;34; @@ -53110,7 +53116,7 @@ lösung: vb-wald-loesung.visustruct -`,c8=` +`,m8=` 105;110;112;117;116;58;32;105;110;116;32;119;97;104;108;32;34;49;32;87;97;115;115;101;114;44;32;50;32;83;97;102;116;44;32;51;32;75;97;107;97;111;34; @@ -53149,7 +53155,7 @@ lösung: vb-wald-loesung.visustruct -`,m8=` +`,d8=` 84;97;115;115;101;32;97;117;102;32;100;101;110;32;84;105;115;99;104;32;115;116;101;108;108;101;110; @@ -53179,7 +53185,7 @@ lösung: vb-wald-loesung.visustruct 84;101;101;32;116;114;105;110;107;101;110; -`,d8=` +`,h8=` 65;117;102;115;116;101;104;101;110; @@ -53194,7 +53200,7 @@ lösung: vb-wald-loesung.visustruct 70;114;252;104;115;116;252;99;107;101;110; -`,h8=` +`,g8=` 87;97;115;115;101;114;32;105;110;32;100;101;110;32;87;97;115;115;101;114;107;111;99;104;101;114;32;102;252;108;108;101;110; @@ -53215,7 +53221,7 @@ lösung: vb-wald-loesung.visustruct 84;101;101;98;101;117;116;101;108;32;104;101;114;97;117;115;110;101;104;109;101;110; -`,g8=` +`,p8=` 82;101;103;110;101;116;32;101;115;63; @@ -53234,7 +53240,7 @@ lösung: vb-wald-loesung.visustruct 76;111;115;103;101;104;101;110; -`,p8=` +`,f8=` 84;101;108;108;101;114;32;110;105;99;104;116;32;108;101;101;114; @@ -53248,7 +53254,7 @@ lösung: vb-wald-loesung.visustruct 84;101;108;108;101;114;32;97;98;114;228;117;109;101;110; -`,f8=` +`,b8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;119;111;104;105;110;32;122;228;104;108;101;110;63;34; @@ -53268,7 +53274,7 @@ lösung: vb-wald-loesung.visustruct -`,b8=` +`,x8=` 105;110;116;32;122;97;104;108;32;61;32;51; @@ -53288,7 +53294,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; -`,x8=` +`,v8=` 105;110;116;32;122;97;104;108;32;61;32;51; @@ -53305,7 +53311,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; -`,v8=` +`,y8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;70;97;107;117;108;116;228;116;32;118;111;110;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; @@ -53331,7 +53337,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;32;43;32;34;33;32;61;32;34;32;43;32;102;97;107;117;108;116;97;101;116; -`,y8=` +`,w8=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; @@ -53366,7 +53372,7 @@ lösung: vb-wald-loesung.visustruct -`,w8=` +`,z8=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; @@ -53401,7 +53407,7 @@ lösung: vb-wald-loesung.visustruct -`,z8=` +`,I8=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;87;101;108;99;104;101;32;90;97;104;108;63;34; @@ -53430,7 +53436,7 @@ lösung: vb-wald-loesung.visustruct -`,I8=` +`,k8=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;34; @@ -53453,7 +53459,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;99;104;114;105;116;116;101; -`,k8=` +`,S8=` 105;110;116;32;122;97;104;108;32;61;32;48; @@ -53470,7 +53476,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;97;110;107;101;33;34; -`,S8=` +`,T8=` 105;110;116;32;105;32;61;32;49;48; @@ -53487,7 +53493,7 @@ lösung: vb-wald-loesung.visustruct -`,T8=` +`,_8=` 105;110;112;117;116;58;32;105;110;116;32;122;105;101;108;32;34;83;112;97;114;122;105;101;108;63;34; @@ -53513,7 +53519,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;87;111;99;104;101;110;58;32;34;32;43;32;119;111;99;104;101;110; -`,_8=` +`,O8=` 105;110;112;117;116;58;32;105;110;116;32;122;105;101;108;32;34;83;112;97;114;122;105;101;108;63;34; @@ -53539,7 +53545,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;87;111;99;104;101;110;58;32;34;32;43;32;119;111;99;104;101;110; -`,O8=` +`,A8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;119;111;104;105;110;63;34; @@ -53559,7 +53565,7 @@ lösung: vb-wald-loesung.visustruct -`,A8=` +`,C8=` 105;110;116;32;110;111;116;101;32;61;32;48; @@ -53576,7 +53582,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;101;105;110;101;32;78;111;116;101;58;32;34;32;43;32;110;111;116;101; -`,C8=` +`,j8=` 105;110;116;32;115;117;109;109;101;32;61;32;48; @@ -53618,7 +53624,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;76;111;115;33;34; -`,j8=` +`,D8=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;87;101;108;99;104;101;32;82;101;105;104;101;63;34; @@ -53637,7 +53643,7 @@ lösung: vb-wald-loesung.visustruct -`,D8=` +`,B8=` 105;110;116;32;105;32;61;32;49; @@ -53650,7 +53656,7 @@ lösung: vb-wald-loesung.visustruct -`,B8=` +`,Z8=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;63;34; @@ -53667,7 +53673,7 @@ lösung: vb-wald-loesung.visustruct -`,Z8=` +`,M8=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;63;34; @@ -53684,7 +53690,7 @@ lösung: vb-wald-loesung.visustruct -`,M8=` +`,L8=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;63;34; @@ -53701,7 +53707,7 @@ lösung: vb-wald-loesung.visustruct -`,L8=` +`,E8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; @@ -53723,7 +53729,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109;109;101; -`,E8=` +`,W8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;87;105;101;32;118;105;101;108;101;32;90;101;105;108;101;110;63;34; @@ -53752,7 +53758,7 @@ lösung: vb-wald-loesung.visustruct -`,W8=` +`,N8=` 105;110;116;32;97;110;122;97;104;108;32;61;32;48; @@ -53784,7 +53790,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;110;122;97;104;108; -`,N8=` +`,F8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; @@ -53816,7 +53822,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;110;122;97;104;108; -`,F8=` +`,J8=` 105;110;112;117;116;58;32;105;110;116;32;114;101;105;104;101;32;34;87;101;108;99;104;101;32;82;101;105;104;101;63;34; @@ -53832,7 +53838,7 @@ lösung: vb-wald-loesung.visustruct -`,J8=` +`,R8=` 105;110;112;117;116;58;32;105;110;116;32;114;101;105;104;101;32;34;87;101;108;99;104;101;32;82;101;105;104;101;63;34; @@ -53848,7 +53854,7 @@ lösung: vb-wald-loesung.visustruct -`,R8=` +`,G8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; @@ -53864,7 +53870,7 @@ lösung: vb-wald-loesung.visustruct -`,G8=` +`,H8=` 105;110;112;117;116;58;32;105;110;116;32;98;114;101;105;116;101;32;34;66;114;101;105;116;101;34; @@ -53896,7 +53902,7 @@ lösung: vb-wald-loesung.visustruct -`,H8=` +`,V8=` 105;110;116;91;93;32;122;97;104;108;101;110;32;61;32;123;50;44;32;52;44;32;54;44;32;56;44;32;49;48;125; @@ -53912,7 +53918,7 @@ lösung: vb-wald-loesung.visustruct -`,V8=` +`,q8=` 105;110;116;91;93;32;119;101;114;116;101;32;61;32;123;52;44;32;56;44;32;49;53;44;32;49;54;44;32;50;51;44;32;52;50;125; @@ -53927,7 +53933,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;119;101;114;116;101;46;108;101;110;103;116;104; -`,q8=` +`,Q8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; @@ -53959,7 +53965,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;110;122;97;104;108;58;32;34;32;43;32;97;110;122;97;104;108; -`,Q8=` +`,U8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; @@ -53991,7 +53997,7 @@ lösung: vb-wald-loesung.visustruct -`,U8=` +`,$8=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;87;105;101;32;118;105;101;108;101;32;83;116;117;102;101;110;63;34; @@ -54020,7 +54026,7 @@ lösung: vb-wald-loesung.visustruct -`,$8=` +`,Y8=` 83;116;114;105;110;103;91;93;32;110;97;109;101;110;32;61;32;110;101;119;32;83;116;114;105;110;103;91;51;93; @@ -54039,7 +54045,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;69;114;115;116;101;114;32;78;97;109;101;58;32;34;32;43;32;110;97;109;101;110;91;48;93; -`,Y8=` +`,X8=` 105;110;116;91;93;32;122;97;104;108;101;110;32;61;32;110;101;119;32;105;110;116;91;52;93; @@ -54065,7 +54071,7 @@ lösung: vb-wald-loesung.visustruct -`,X8=` +`,K8=` 105;110;116;91;93;32;122;97;104;108;101;110;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -54116,7 +54122,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;97;120;105;109;117;109;58;32;34;32;43;32;109;97;120; -`,K8=` +`,eS=` 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;123;49;50;44;32;55;44;32;49;57;44;32;52;125; @@ -54157,7 +54163,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;97;120;105;109;117;109;58;32;34;32;43;32;109;97;120; -`,eS=` +`,tS=` 105;110;116;32;115;117;109;109;101;32;61;32;48; @@ -54180,7 +54186,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; -`,tS=` +`,nS=` 105;110;116;32;115;117;109;109;101;32;61;32;48; @@ -54210,7 +54216,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; -`,nS=` +`,iS=` 105;110;112;117;116;58;32;105;110;116;32;108;97;101;110;103;101;32;34;76;228;110;103;101;63;34; @@ -54225,13 +54231,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;70;108;228;99;104;101;58;32;34;32;43;32;102; -`,iS=` +`,aS=` 114;101;116;117;114;110;32;97;32;42;32;98; -`,aS=` +`,sS=` 122;101;105;103;101;66;101;103;114;117;101;115;115;117;110;103;40;41; @@ -54243,7 +54249,7 @@ lösung: vb-wald-loesung.visustruct 122;101;105;103;101;69;114;103;101;98;110;105;115;40;41; -`,sS=` +`,rS=` 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;101;110;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; @@ -54275,7 +54281,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;246;99;104;115;116;101;32;84;101;109;112;101;114;97;116;117;114;58;32;34;32;43;32;109;97;120; -`,rS=` +`,oS=` 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;101;110;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; @@ -54307,7 +54313,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;246;99;104;115;116;101;32;84;101;109;112;101;114;97;116;117;114;58;32;34;32;43;32;109;97;120; -`,oS=` +`,lS=` 105;110;116;91;93;32;110;111;116;101;110;32;61;32;123;50;44;32;51;44;32;49;44;32;52;125; @@ -54329,7 +54335,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; -`,lS=` +`,uS=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;87;101;108;99;104;101;32;90;97;104;108;63;34; @@ -54341,7 +54347,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;97;115;32;81;117;97;100;114;97;116;32;105;115;116;32;34;32;43;32;113; -`,uS=` +`,cS=` 105;110;116;32;101;114;103;101;98;110;105;115;32;61;32;120;32;42;32;120; @@ -54350,7 +54356,7 @@ lösung: vb-wald-loesung.visustruct 114;101;116;117;114;110;32;101;114;103;101;98;110;105;115; -`,cS=` +`,mS=` 122;101;105;103;101;84;105;116;101;108;40;41; @@ -54362,7 +54368,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;97;108;108;111;32;34;32;43;32;110;97;109;101; -`,mS=` +`,dS=` 111;117;116;112;117;116;58;32;34;87;105;108;108;107;111;109;109;101;110;32;122;117;109;32;81;117;105;122;33;34; @@ -54371,7 +54377,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;117;32;98;101;107;111;109;109;115;116;32;100;114;101;105;32;70;114;97;103;101;110;46;34; -`,dS=` +`,hS=` 122;101;105;103;101;83;117;109;109;101;40;51;44;32;52;41; @@ -54383,7 +54389,7 @@ lösung: vb-wald-loesung.visustruct 122;101;105;103;101;83;117;109;109;101;40;120;44;32;120;32;43;32;49;41; -`,hS=` +`,gS=` 105;110;116;32;115;117;109;109;101;32;61;32;97;32;43;32;98; @@ -54392,7 +54398,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;32;43;32;34;32;43;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;115;117;109;109;101; -`,gS=` +`,pS=` 105;110;112;117;116;58;32;105;110;116;32;115;116;97;114;116;32;34;83;116;97;114;116;119;101;114;116;34; @@ -54415,7 +54421,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;76;111;115;33;34; -`,pS=` +`,fS=` 105;110;112;117;116;58;32;105;110;116;32;115;116;97;114;116;32;34;83;116;97;114;116;119;101;114;116;34; @@ -54438,7 +54444,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;76;111;115;34; -`,fS=` +`,bS=` 105;110;116;91;93;91;93;32;112;117;110;107;116;101;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; @@ -54460,7 +54466,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;112;105;101;108;101;114;32;50;58;32;34;32;43;32;115;117;109;109;101; -`,bS=` +`,xS=` 105;110;116;91;93;91;93;32;112;117;110;107;116;101;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; @@ -54482,7 +54488,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;112;105;101;108;101;114;32;50;58;32;34;32;43;32;115;117;109;109;101; -`,xS=` +`,vS=` 105;110;116;91;93;91;93;32;112;117;110;107;116;101;32;61;32;123;123;51;44;32;53;125;44;32;123;52;44;32;49;125;44;32;123;50;44;32;50;125;125; @@ -54511,7 +54517,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; -`,vS=` +`,yS=` 105;110;116;32;115;117;109;109;101;32;61;32;48; @@ -54534,7 +54540,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109;109;101; -`,yS=` +`,wS=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;119;111;104;105;110;63;34; @@ -54556,7 +54562,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109;109;101; -`,wS=` +`,zS=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;119;111;104;105;110;63;34; @@ -54578,7 +54584,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;117;109;109;101; -`,zS=` +`,IS=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;87;101;108;99;104;101;32;82;101;105;104;101;63;34; @@ -54610,7 +54616,7 @@ lösung: vb-wald-loesung.visustruct -`,IS=` +`,kS=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;34; @@ -54632,7 +54638,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;102;97;107;117;108;116;97;101;116; -`,kS=` +`,SS=` 83;116;114;105;110;103;32;98;114;105;101;102;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;98;114;105;101;102;46;116;120;116;34;41;41; @@ -54664,13 +54670,13 @@ lösung: vb-wald-loesung.visustruct -`,SS=` +`,TS=` 83;116;114;105;110;103;32;98;114;105;101;102;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;98;114;105;101;102;46;116;120;116;34;41;41; -`,TS=` +`,_S=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;118;111;114;110;97;109;101;32;34;86;111;114;110;97;109;101;63;34; @@ -54682,7 +54688,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;118;111;114;110;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;110;97;99;104;110;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; -`,_S=` +`,OS=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;118;111;114;110;97;109;101;32;34;86;111;114;110;97;109;101;63;34; @@ -54694,7 +54700,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;118;111;114;110;97;109;101;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;32;34;32;43;32;110;97;99;104;110;97;109;101;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;34; -`,OS=` +`,AS=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;101;105;110;103;97;98;101;32;34;80;97;115;115;119;111;114;116;63;34; @@ -54713,7 +54719,7 @@ lösung: vb-wald-loesung.visustruct -`,AS=` +`,CS=` 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; @@ -54742,7 +54748,7 @@ lösung: vb-wald-loesung.visustruct -`,CS=` +`,jS=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;119;101;114;116;63;34; @@ -54795,7 +54801,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;86;101;114;115;117;99;104;101;58;32;34;32;43;32;118;101;114;115;117;99;104;101; -`,jS=` +`,DS=` 105;110;116;32;118;101;114;115;117;99;104;101;32;61;32;48; @@ -54828,7 +54834,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;86;101;114;115;117;99;104;101;58;32;34;32;43;32;118;101;114;115;117;99;104;101; -`,DS=` +`,BS=` 105;110;116;32;115;117;109;109;101;32;61;32;48; @@ -54870,7 +54876,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;115;117;109;109;101; -`,BS=` +`,ZS=` 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; @@ -54892,7 +54898,7 @@ lösung: vb-wald-loesung.visustruct -`,ZS=` +`,MS=` 105;110;112;117;116;58;32;105;110;116;32;103;114;101;110;122;101;32;34;66;105;115;32;119;111;104;105;110;63;34; @@ -54908,7 +54914,7 @@ lösung: vb-wald-loesung.visustruct -`,MS=` +`,LS=` 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -54947,7 +54953,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; -`,LS=` +`,ES=` 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -54986,7 +54992,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; -`,ES=` +`,WS=` 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -55021,7 +55027,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;110;122;97;104;108;58;32;34;32;43;32;97;110;122;97;104;108; -`,WS=` +`,NS=` 111;117;116;112;117;116;58;32;34;71;117;116;101;110;32;77;111;114;103;101;110;34; @@ -55030,13 +55036,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;101;117;116;101;32;108;101;114;110;101;110;32;119;105;114;32;83;116;114;117;107;116;111;103;114;97;109;109;101;46;34; -`,NS=` +`,FS=` 111;117;116;112;117;116;58;32;34;72;97;108;108;111;32;87;101;108;116;34; -`,FS=` +`,JS=` 111;117;116;112;117;116;58;32;34;72;97;108;108;111;34; @@ -55045,7 +55051,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;73;99;104;32;108;101;114;110;101;32;83;116;114;117;107;116;111;103;114;97;109;109;101;34; -`,JS=` +`,RS=` 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;63;34; @@ -55065,7 +55071,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; -`,RS=` +`,GS=` 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; @@ -55106,7 +55112,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;110;122;97;104;108;32;43;32;34;32;90;101;105;108;101;110;32;103;101;115;112;101;105;99;104;101;114;116;34; -`,GS=` +`,HS=` 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; @@ -55115,7 +55121,7 @@ lösung: vb-wald-loesung.visustruct 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;101;105;110;107;97;117;102;45;110;101;117;46;116;120;116;34;41; -`,HS=` +`,VS=` 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; @@ -55141,13 +55147,13 @@ lösung: vb-wald-loesung.visustruct 100;97;116;101;105;46;99;108;111;115;101;40;41; -`,VS=` +`,qS=` 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; -`,qS=` +`,QS=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; @@ -55186,7 +55192,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;70;117;99;104;115;58;32;34;32;43;32;97;110;122;97;104;108; -`,QS=` +`,US=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; @@ -55195,7 +55201,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,US=` +`,$S=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; @@ -55230,7 +55236,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;76;228;110;103;115;116;101;114;32;69;105;110;116;114;97;103;58;32;34;32;43;32;108;97;101;110;103;115;116;101;114; -`,$S=` +`,YS=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; @@ -55239,7 +55245,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;91;93;32;122;101;105;108;101;110;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; -`,YS=` +`,XS=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;107;108;97;115;115;101;46;99;115;118;34;41;41; @@ -55293,7 +55299,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;66;101;115;116;101;32;78;111;116;101;32;105;110;32;69;110;103;108;105;115;99;104;58;32;34;32;43;32;98;101;115;116;101;114;78;97;109;101;32;43;32;34;32;40;34;32;43;32;98;101;115;116;101;78;111;116;101;32;43;32;34;41;34; -`,XS=` +`,KS=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;107;108;97;115;115;101;46;99;115;118;34;41;41; @@ -55302,7 +55308,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,KS=` +`,eT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;107;108;97;115;115;101;46;99;115;118;34;41;41; @@ -55343,7 +55349,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;99;104;110;105;116;116;32;77;97;116;104;101;58;32;34;32;43;32;115;117;109;109;101;32;47;32;97;110;122;97;104;108; -`,eT=` +`,tT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;107;108;97;115;115;101;46;99;115;118;34;41;41; @@ -55352,7 +55358,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,tT=` +`,nT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; @@ -55391,7 +55397,7 @@ lösung: vb-wald-loesung.visustruct 108;101;115;101;114;46;99;108;111;115;101;40;41; -`,nT=` +`,iT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; @@ -55400,7 +55406,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; -`,iT=` +`,aT=` 83;116;114;105;110;103;91;93;32;110;97;109;101;110;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;70;117;99;104;115;34;125; @@ -55450,7 +55456,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;97;109;101;110;46;108;101;110;103;116;104;32;43;32;34;32;69;105;110;116;114;228;103;101;32;103;101;115;112;101;105;99;104;101;114;116;34; -`,aT=` +`,sT=` 83;116;114;105;110;103;91;93;32;110;97;109;101;110;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;70;117;99;104;115;34;125; @@ -55468,7 +55474,7 @@ lösung: vb-wald-loesung.visustruct 97;117;115;46;99;108;111;115;101;40;41; -`,sT=` +`,rT=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;116;105;101;114;101;46;99;115;118;34;41;41; @@ -55521,7 +55527,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;40;122;101;105;108;101;110;46;108;101;110;103;116;104;32;45;32;49;41;32;43;32;34;32;84;105;101;114;101;32;103;101;115;112;101;105;99;104;101;114;116;34; -`,rT=` +`,oT=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;116;105;101;114;101;46;99;115;118;34;41;41; @@ -55542,7 +55548,7 @@ lösung: vb-wald-loesung.visustruct 97;117;115;46;99;108;111;115;101;40;41; -`,oT=` +`,lT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;105;101;114;101;46;99;115;118;34;41;41; @@ -55586,7 +55592,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;110;122;97;104;108;32;43;32;34;32;83;228;116;122;101;32;103;101;115;112;101;105;99;104;101;114;116;34; -`,lT=` +`,uT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;105;101;114;101;46;99;115;118;34;41;41; @@ -55607,7 +55613,7 @@ lösung: vb-wald-loesung.visustruct 97;117;115;46;99;108;111;115;101;40;41; -`,uT=` +`,cT=` 111;117;116;112;117;116;58;32;34;66;101;109;45;118;105;110;100;111;34; @@ -55619,7 +55625,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;100;101;117;115;34; -`,cT=` +`,mT=` 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; @@ -55638,7 +55644,7 @@ lösung: vb-wald-loesung.visustruct -`,mT=` +`,dT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;97;110;99;97;109;101;110;116;111;46;99;115;118;34;41;41; @@ -55719,7 +55725,7 @@ lösung: vb-wald-loesung.visustruct 115;97;105;100;97;46;99;108;111;115;101;40;41; -`,dT=` +`,hT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;97;110;99;97;109;101;110;116;111;46;99;115;118;34;41;41; @@ -55728,7 +55734,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; -`,hT=` +`,gT=` 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -55793,7 +55799,7 @@ lösung: vb-wald-loesung.visustruct -`,gT=` +`,pT=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;32;105;110;116;101;105;114;111;34; @@ -55819,7 +55825,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98;105;110;97;114;105;111; -`,pT=` +`,fT=` 99;104;97;114;91;93;32;97;108;102;97;98;101;116;111;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; @@ -55873,13 +55879,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;101;103;114;101;100;111; -`,fT=` +`,bT=` 99;104;97;114;91;93;32;97;108;102;97;98;101;116;111;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; -`,bT=` +`,xT=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;34;81;117;101;32;112;97;108;97;118;114;97;32;40;115;243;32;109;97;105;250;115;99;117;108;97;115;41;63;34; @@ -55910,7 +55916,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;101;103;114;101;100;111; -`,xT=` +`,vT=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;115;101;103;114;101;100;111;32;34;81;117;97;108;32;233;32;111;32;116;101;120;116;111;32;99;105;102;114;97;100;111;63;34; @@ -55941,7 +55947,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;116;101;120;116;111; -`,vT=` +`,yT=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;32;105;110;105;99;105;97;108;34; @@ -55977,7 +55983,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;97;115;115;111;115;58;32;34;32;43;32;112;97;115;115;111;115; -`,yT=` +`,wT=` 105;110;112;117;116;58;32;105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;34;81;117;97;110;116;97;115;32;110;111;116;97;115;63;34; @@ -56005,7 +56011,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;101;100;105;97; -`,wT=` +`,zT=` 105;110;112;117;116;58;32;105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;110;250;109;101;114;111;115;63;34; @@ -56042,7 +56048,7 @@ lösung: vb-wald-loesung.visustruct -`,zT=` +`,IT=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;34; @@ -56061,7 +56067,7 @@ lösung: vb-wald-loesung.visustruct -`,IT=` +`,kT=` 99;111;110;115;116;32;100;111;117;98;108;101;32;73;86;65;32;61;32;48;46;50;51; @@ -56082,7 +56088,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;112;114;101;99;111;67;111;109;73;118;97; -`,kT=` +`,ST=` 105;110;116;32;112;105;110;32;61;32;48; @@ -56118,7 +56124,7 @@ lösung: vb-wald-loesung.visustruct -`,ST=` +`,TT=` 99;111;110;115;116;32;105;110;116;32;80;73;78;32;61;32;49;50;51;52; @@ -56154,7 +56160,7 @@ lösung: vb-wald-loesung.visustruct -`,TT=` +`,_T=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;49;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;34; @@ -56198,7 +56204,7 @@ lösung: vb-wald-loesung.visustruct -`,_T=` +`,OT=` 98;111;111;108;101;97;110;91;93;91;93;32;109;97;114;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; @@ -56252,7 +56258,7 @@ lösung: vb-wald-loesung.visustruct -`,OT=` +`,AT=` 98;111;111;108;101;97;110;91;93;91;93;32;109;97;114;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; @@ -56279,7 +56285,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;91;93;32;99;111;108;117;110;97;115;32;61;32;123;34;65;34;44;32;34;66;34;44;32;34;67;34;44;32;34;68;34;44;32;34;69;34;125; -`,AT=` +`,CT=` 105;110;112;117;116;58;32;105;110;116;32;112;114;97;116;111;32;34;81;117;101;32;112;114;97;116;111;63;32;40;49;44;32;50;32;111;117;32;51;41;34; @@ -56308,7 +56314,7 @@ lösung: vb-wald-loesung.visustruct -`,CT=` +`,jT=` 105;110;116;32;110;117;109;101;114;111;49;32;61;32;52; @@ -56345,7 +56351,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;76;105;109;112;97;32;111;32;113;117;97;100;114;111;58;32;34;32;43;32;110;111;109;101;115;91;115;111;114;116;101;97;100;111;32;45;32;49;93; -`,jT=` +`,DT=` 105;110;116;32;110;117;109;101;114;111;32;61;32;52; @@ -56357,7 +56363,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;78;250;109;101;114;111;32;100;117;112;108;105;99;97;100;111;58;32;34;32;43;32;110;117;109;101;114;111; -`,DT=` +`,BT=` -1; @@ -56404,7 +56410,7 @@ lösung: vb-wald-loesung.visustruct -`,BT=` +`,ZT=` @@ -56441,7 +56447,7 @@ lösung: vb-wald-loesung.visustruct -`,ZT=` +`,MT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;118;111;99;97;98;117;108;97;114;105;111;46;99;115;118;34;41;41; @@ -56501,7 +56507,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;99;101;114;116;97;115;32;43;32;34;32;100;101;32;34;32;43;32;99;111;110;116;97;103;101;109;32;43;32;34;32;99;101;114;116;97;115;34; -`,MT=` +`,LT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;118;111;99;97;98;117;108;97;114;105;111;46;99;115;118;34;41;41; @@ -56510,7 +56516,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; -`,LT=` +`,ET=` 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; @@ -56529,7 +56535,7 @@ lösung: vb-wald-loesung.visustruct -`,ET=` +`,WT=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; @@ -56552,7 +56558,7 @@ lösung: vb-wald-loesung.visustruct 108;101;105;116;111;114;46;99;108;111;115;101;40;41; -`,WT=` +`,NT=` 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;34;90;111;114;97;59;49;59;50;59;50;34; @@ -56570,7 +56576,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;111;109;101;32;43;32;34;32;116;101;109;32;34;32;43;32;109;97;116;101;109;97;116;105;99;97;32;43;32;34;32;97;32;77;97;116;101;109;225;116;105;99;97;34; -`,NT=` +`,FT=` 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;34;123;92;34;110;111;109;101;92;34;58;32;92;34;90;111;114;97;92;34;44;32;92;34;101;115;112;101;99;105;101;92;34;58;32;92;34;99;97;98;114;97;92;34;44;32;92;34;105;100;97;100;101;92;34;58;32;54;125;44;34; @@ -56588,7 +56594,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;111;109;101; -`,FT=` +`,JT=` 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; @@ -56608,7 +56614,7 @@ lösung: vb-wald-loesung.visustruct 102;105;99;104;101;105;114;111;46;99;108;111;115;101;40;41; -`,JT=` +`,RT=` 105;110;116;91;93;91;93;32;116;97;98;101;108;97;32;61;32;110;101;119;32;105;110;116;91;49;48;93;91;49;48;93; @@ -56640,7 +56646,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;32;43;32;34;32;183;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;116;97;98;101;108;97;91;97;32;45;32;49;93;91;98;32;45;32;49;93; -`,RT=` +`,GT=` 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -56688,7 +56694,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;76;105;118;114;101;115;58;32;34;32;43;32;108;105;118;114;101;115; -`,GT=` +`,HT=` 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -56703,7 +56709,7 @@ lösung: vb-wald-loesung.visustruct 108;117;103;97;114;101;115;91;50;93;91;51;93;32;61;32;116;114;117;101; -`,HT=` +`,VT=` 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -56737,7 +56743,7 @@ lösung: vb-wald-loesung.visustruct -`,VT=` +`,qT=` 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -56755,7 +56761,7 @@ lösung: vb-wald-loesung.visustruct 105;110;112;117;116;58;32;105;110;116;32;108;117;103;97;114;32;34;76;117;103;97;114;34; -`,qT=` +`,QT=` 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -56803,7 +56809,7 @@ lösung: vb-wald-loesung.visustruct -`,QT=` +`,UT=` 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; @@ -56827,7 +56833,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;70;105;108;97;32;49;44;32;108;117;103;97;114;32;50;32;118;101;110;100;105;100;111;63;32;34;32;43;32;108;117;103;97;114;101;115;91;49;93;91;50;93; -`,UT=` +`,$T=` 105;110;116;32;115;101;103;117;110;100;111;115;32;61;32;50;48;48; @@ -56842,7 +56848,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;111;115;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;115;34; -`,$T=` +`,YT=` 105;110;116;32;115;101;103;117;110;100;111;115;32;61;32;50;48;48; @@ -56857,7 +56863,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;111;115;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;115;34; -`,YT=` +`,XT=` 83;116;114;105;110;103;32;110;111;109;101;32;61;32;34;76;117;100;119;105;103;34; @@ -56875,7 +56881,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;108;116;117;114;97;58;32;34;32;43;32;97;108;116;117;114;97;32;43;32;34;32;109;34; -`,XT=` +`,KT=` 105;110;116;32;110;117;109;101;114;111;32;61;32;51; @@ -56890,7 +56896,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;117;109;101;114;111; -`,KT=` +`,e_=` 105;110;116;32;110;117;109;101;114;111;32;61;32;50; @@ -56905,7 +56911,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;117;109;101;114;111; -`,e_=` +`,t_=` 111;117;116;112;117;116;58;32;110;117;109;101;114;111; @@ -56920,7 +56926,7 @@ lösung: vb-wald-loesung.visustruct 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;43;32;51; -`,t_=` +`,n_=` 83;116;114;105;110;103;32;101;115;113;117;101;114;100;97;32;61;32;34;115;117;109;111;34; @@ -56944,7 +56950,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;105;114;101;105;116;97;58;32;34;32;43;32;100;105;114;101;105;116;97; -`,n_=` +`,i_=` 83;116;114;105;110;103;32;101;115;113;117;101;114;100;97;32;61;32;34;115;117;109;111;34; @@ -56959,7 +56965,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;105;114;101;105;116;97;58;32;34;32;43;32;100;105;114;101;105;116;97; -`,i_=` +`,a_=` 105;110;116;32;97;32;61;32;53; @@ -56983,7 +56989,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; -`,a_=` +`,s_=` 105;110;116;32;105;100;97;100;101;32;61;32;49;52; @@ -57001,7 +57007,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;108;116;117;114;97;58;32;34;32;43;32;97;108;116;117;114;97;32;43;32;34;32;109;34; -`,s_=` +`,r_=` 105;110;116;32;109;105;110;117;116;111;115;32;61;32;49;51;53; @@ -57016,7 +57022,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;104;111;114;97;115;32;43;32;34;32;104;111;114;97;115;32;101;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;109;105;110;117;116;111;115;34; -`,r_=` +`,o_=` 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;51; @@ -57031,7 +57037,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;112;114;101;99;111;84;111;116;97;108;32;43;32;34;32;101;117;114;111;115;34; -`,o_=` +`,l_=` 105;110;116;32;115;97;108;100;111;32;61;32;50;48; @@ -57046,7 +57052,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;82;101;115;116;97;58;32;34;32;43;32;115;97;108;100;111; -`,l_=` +`,u_=` 105;110;116;32;115;97;108;100;111;32;61;32;50;48; @@ -57061,7 +57067,7 @@ lösung: vb-wald-loesung.visustruct 115;97;108;100;111;32;61;32;115;97;108;100;111;32;45;32;112;114;101;99;111; -`,u_=` +`,c_=` 105;110;116;32;112;114;101;99;111;32;61;32;57; @@ -57076,7 +57082,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; -`,c_=` +`,m_=` 105;110;116;32;99;111;109;112;114;105;109;101;110;116;111;32;61;32;55; @@ -57097,7 +57103,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;101;114;237;109;101;116;114;111;58;32;34;32;43;32;112;101;114;105;109;101;116;114;111; -`,m_=` +`,d_=` 105;110;116;32;115;101;103;117;110;100;111;115;32;61;32;50;48;48; @@ -57112,7 +57118,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;111;115;32;43;32;34;32;109;105;110;117;116;111;115;32;101;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;115;101;103;117;110;100;111;115;34; -`,d_=` +`,h_=` 105;110;116;32;115;101;103;117;110;100;111;115;32;61;32;50;48;48; @@ -57121,7 +57127,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;109;105;110;117;116;111;115;32;43;32;34;32;109;105;110;117;116;111;115;32;101;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;115;101;103;117;110;100;111;115;34; -`,h_=` +`,g_=` 105;110;116;32;99;111;109;112;114;105;109;101;110;116;111;32;61;32;53; @@ -57136,7 +57142,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;114;101;97; -`,g_=` +`,p_=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;111;109;101;32;34;67;111;109;111;32;116;101;32;99;104;97;109;97;115;63;34; @@ -57145,7 +57151,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;79;108;225;32;34;32;43;32;110;111;109;101;32;43;32;34;33;34; -`,p_=` +`,f_=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; @@ -57160,7 +57166,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; -`,f_=` +`,b_=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; @@ -57172,7 +57178,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;40;97;32;43;32;98;41; -`,b_=` +`,x_=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; @@ -57184,7 +57190,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;97;32;43;32;98; -`,x_=` +`,v_=` 105;110;112;117;116;58;32;105;110;116;32;97;110;111;115;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; @@ -57196,7 +57202,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;227;111;32;99;101;114;99;97;32;100;101;32;34;32;43;32;100;105;97;115;32;43;32;34;32;100;105;97;115;46;34; -`,v_=` +`,y_=` 105;110;112;117;116;58;32;100;111;117;98;108;101;32;120;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; @@ -57211,7 +57217,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;233;100;105;97;58;32;34;32;43;32;109;101;100;105;97; -`,y_=` +`,w_=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; @@ -57232,7 +57238,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;114;111;100;117;116;111;58;32;34;32;43;32;112;114;111;100;117;116;111; -`,w_=` +`,z_=` 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; @@ -57251,7 +57257,7 @@ lösung: vb-wald-loesung.visustruct -`,z_=` +`,I_=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;63;34; @@ -57273,7 +57279,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;117;109;101;114;111; -`,I_=` +`,k_=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;63;34; @@ -57292,7 +57298,7 @@ lösung: vb-wald-loesung.visustruct -`,k_=` +`,S_=` 105;110;116;32;112;111;110;116;111;115;32;61;32;48; @@ -57310,7 +57316,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;110;116;111;115;58;32;34;32;43;32;112;111;110;116;111;115; -`,S_=` +`,T_=` 105;110;116;32;112;111;110;116;111;115;32;61;32;48; @@ -57328,7 +57334,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;110;116;111;115;58;32;34;32;43;32;112;111;110;116;111;115; -`,T_=` +`,__=` 105;110;116;32;112;114;101;99;111;32;61;32;56; @@ -57346,7 +57352,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; -`,__=` +`,O_=` 105;110;116;32;112;114;101;99;111;32;61;32;56; @@ -57364,7 +57370,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; -`,O_=` +`,A_=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; @@ -57386,7 +57392,7 @@ lösung: vb-wald-loesung.visustruct -`,A_=` +`,C_=` 105;110;112;117;116;58;32;100;111;117;98;108;101;32;112;114;101;99;111;32;34;80;114;101;231;111;32;101;109;32;101;117;114;111;115;63;34; @@ -57408,7 +57414,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;32;112;97;103;97;114;58;32;34;32;43;32;112;114;101;99;111;32;43;32;34;32;101;117;114;111;115;34; -`,C_=` +`,j_=` 105;110;112;117;116;58;32;105;110;116;32;110;111;116;97;32;34;78;111;116;97;63;34; @@ -57446,7 +57452,7 @@ lösung: vb-wald-loesung.visustruct -`,j_=` +`,D_=` 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;101;32;105;100;97;100;101;32;116;101;110;115;63;34; @@ -57465,7 +57471,7 @@ lösung: vb-wald-loesung.visustruct -`,D_=` +`,B_=` 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;101;32;105;100;97;100;101;32;116;101;110;115;63;34; @@ -57484,7 +57490,7 @@ lösung: vb-wald-loesung.visustruct -`,B_=` +`,Z_=` 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; @@ -57503,7 +57509,7 @@ lösung: vb-wald-loesung.visustruct -`,Z_=` +`,M_=` 105;110;112;117;116;58;32;105;110;116;32;110;111;116;97;32;34;78;111;116;97;63;34; @@ -57522,7 +57528,7 @@ lösung: vb-wald-loesung.visustruct -`,M_=` +`,L_=` 105;110;112;117;116;58;32;105;110;116;32;97;110;111;32;34;65;110;111;63;34; @@ -57541,7 +57547,7 @@ lösung: vb-wald-loesung.visustruct -`,L_=` +`,E_=` 105;110;112;117;116;58;32;105;110;116;32;100;105;97;32;34;68;105;97;32;40;49;32;97;32;55;41;63;34; @@ -57560,7 +57566,7 @@ lösung: vb-wald-loesung.visustruct -`,E_=` +`,W_=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;99;111;114;32;34;68;101;32;113;117;101;32;99;111;114;32;101;115;116;225;32;111;32;115;101;109;225;102;111;114;111;63;34; @@ -57589,7 +57595,7 @@ lösung: vb-wald-loesung.visustruct -`,W_=` +`,N_=` 105;110;112;117;116;58;32;105;110;116;32;101;115;99;111;108;104;97;32;34;49;32;225;103;117;97;44;32;50;32;115;117;109;111;44;32;51;32;99;104;111;99;111;108;97;116;101;32;113;117;101;110;116;101;34; @@ -57618,7 +57624,7 @@ lösung: vb-wald-loesung.visustruct -`,N_=` +`,F_=` 105;110;112;117;116;58;32;105;110;116;32;100;105;97;32;34;81;117;101;32;100;105;97;32;40;49;32;97;32;55;41;63;34; @@ -57637,7 +57643,7 @@ lösung: vb-wald-loesung.visustruct -`,F_=` +`,J_=` 105;110;112;117;116;58;32;105;110;116;32;100;105;97;32;34;81;117;101;32;100;105;97;32;40;49;32;97;32;55;41;63;34; @@ -57656,7 +57662,7 @@ lösung: vb-wald-loesung.visustruct -`,J_=` +`,R_=` 105;110;112;117;116;58;32;105;110;116;32;104;111;114;97;32;34;81;117;101;32;104;111;114;97;115;32;115;227;111;32;40;115;243;32;97;32;104;111;114;97;41;63;34; @@ -57675,7 +57681,7 @@ lösung: vb-wald-loesung.visustruct -`,R_=` +`,G_=` 105;110;112;117;116;58;32;105;110;116;32;110;111;116;97;32;34;81;117;101;32;110;111;116;97;63;34; @@ -57714,7 +57720,7 @@ lösung: vb-wald-loesung.visustruct -`,G_=` +`,H_=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;34; @@ -57761,7 +57767,7 @@ lösung: vb-wald-loesung.visustruct -`,H_=` +`,V_=` 105;110;112;117;116;58;32;105;110;116;32;101;115;99;111;108;104;97;32;34;49;32;225;103;117;97;44;32;50;32;115;117;109;111;44;32;51;32;99;104;111;99;111;108;97;116;101;32;113;117;101;110;116;101;34; @@ -57800,7 +57806,7 @@ lösung: vb-wald-loesung.visustruct -`,V_=` +`,q_=` 80;244;114;32;117;109;97;32;99;104;225;118;101;110;97;32;110;97;32;109;101;115;97; @@ -57830,7 +57836,7 @@ lösung: vb-wald-loesung.visustruct 66;101;98;101;114;32;111;32;99;104;225; -`,q_=` +`,Q_=` 76;101;118;97;110;116;97;114; @@ -57845,7 +57851,7 @@ lösung: vb-wald-loesung.visustruct 84;111;109;97;114;32;111;32;112;101;113;117;101;110;111;45;97;108;109;111;231;111; -`,Q_=` +`,U_=` 69;110;99;104;101;114;32;97;32;99;104;97;108;101;105;114;97;32;99;111;109;32;225;103;117;97; @@ -57866,7 +57872,7 @@ lösung: vb-wald-loesung.visustruct 84;105;114;97;114;32;97;32;115;97;113;117;101;116;97;32;100;101;32;99;104;225; -`,U_=` +`,$_=` 69;115;116;225;32;97;32;99;104;111;118;101;114;63; @@ -57885,7 +57891,7 @@ lösung: vb-wald-loesung.visustruct 83;97;105;114; -`,$_=` +`,Y_=` 80;114;97;116;111;32;110;227;111;32;118;97;122;105;111; @@ -57899,7 +57905,7 @@ lösung: vb-wald-loesung.visustruct 76;101;118;97;110;116;97;114;32;111;32;112;114;97;116;111; -`,Y_=` +`,X_=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;67;111;110;116;97;114;32;97;116;233;63;34; @@ -57919,7 +57925,7 @@ lösung: vb-wald-loesung.visustruct -`,X_=` +`,K_=` 105;110;116;32;110;117;109;101;114;111;32;61;32;51; @@ -57939,7 +57945,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;97;114;116;105;100;97;33;34; -`,K_=` +`,eO=` 105;110;116;32;110;117;109;101;114;111;32;61;32;51; @@ -57956,7 +57962,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;97;114;116;105;100;97;33;34; -`,eO=` +`,tO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;70;97;116;111;114;105;97;108;32;100;101;32;113;117;101;32;110;250;109;101;114;111;63;34; @@ -57982,7 +57988,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;32;43;32;34;33;32;61;32;34;32;43;32;102;97;116;111;114;105;97;108; -`,tO=` +`,nO=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; @@ -58017,7 +58023,7 @@ lösung: vb-wald-loesung.visustruct -`,nO=` +`,iO=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; @@ -58052,7 +58058,7 @@ lösung: vb-wald-loesung.visustruct -`,iO=` +`,aO=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;81;117;101;32;110;250;109;101;114;111;63;34; @@ -58081,7 +58087,7 @@ lösung: vb-wald-loesung.visustruct -`,aO=` +`,sO=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;34; @@ -58104,7 +58110,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;112;97;115;115;111;115; -`,sO=` +`,rO=` 105;110;116;32;110;117;109;101;114;111;32;61;32;48; @@ -58121,7 +58127,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;79;98;114;105;103;97;100;111;33;34; -`,rO=` +`,oO=` 105;110;116;32;105;32;61;32;49;48; @@ -58138,7 +58144,7 @@ lösung: vb-wald-loesung.visustruct -`,oO=` +`,lO=` 105;110;112;117;116;58;32;105;110;116;32;111;98;106;101;116;105;118;111;32;34;79;98;106;101;116;105;118;111;63;34; @@ -58164,7 +58170,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;101;109;97;110;97;115;58;32;34;32;43;32;115;101;109;97;110;97;115; -`,lO=` +`,uO=` 105;110;112;117;116;58;32;105;110;116;32;111;98;106;101;116;105;118;111;32;34;79;98;106;101;116;105;118;111;63;34; @@ -58190,7 +58196,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;101;109;97;110;97;115;58;32;34;32;43;32;115;101;109;97;110;97;115; -`,uO=` +`,cO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;111;110;100;101;63;34; @@ -58210,7 +58216,7 @@ lösung: vb-wald-loesung.visustruct -`,cO=` +`,mO=` 105;110;116;32;110;111;116;97;32;61;32;48; @@ -58227,7 +58233,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;32;116;117;97;32;110;111;116;97;58;32;34;32;43;32;110;111;116;97; -`,mO=` +`,dO=` 105;110;116;32;115;111;109;97;32;61;32;48; @@ -58250,7 +58256,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;111;109;97; -`,dO=` +`,hO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;34; @@ -58269,7 +58275,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;74;225;33;34; -`,hO=` +`,gO=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;81;117;101;32;116;97;98;117;97;100;97;63;34; @@ -58288,7 +58294,7 @@ lösung: vb-wald-loesung.visustruct -`,gO=` +`,pO=` 105;110;116;32;105;32;61;32;49; @@ -58301,7 +58307,7 @@ lösung: vb-wald-loesung.visustruct -`,pO=` +`,fO=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;63;34; @@ -58318,7 +58324,7 @@ lösung: vb-wald-loesung.visustruct -`,fO=` +`,bO=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;63;34; @@ -58335,7 +58341,7 @@ lösung: vb-wald-loesung.visustruct -`,bO=` +`,xO=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;63;34; @@ -58352,7 +58358,7 @@ lösung: vb-wald-loesung.visustruct -`,xO=` +`,vO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; @@ -58374,7 +58380,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;111;109;97; -`,vO=` +`,yO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;81;117;97;110;116;97;115;32;108;105;110;104;97;115;63;34; @@ -58403,7 +58409,7 @@ lösung: vb-wald-loesung.visustruct -`,yO=` +`,wO=` 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; @@ -58435,7 +58441,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;113;117;97;110;116;105;100;97;100;101; -`,wO=` +`,zO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; @@ -58467,7 +58473,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;113;117;97;110;116;105;100;97;100;101; -`,zO=` +`,IO=` 105;110;112;117;116;58;32;105;110;116;32;116;97;98;117;97;100;97;32;34;81;117;101;32;116;97;98;117;97;100;97;63;34; @@ -58483,7 +58489,7 @@ lösung: vb-wald-loesung.visustruct -`,IO=` +`,kO=` 105;110;112;117;116;58;32;105;110;116;32;116;97;98;117;97;100;97;32;34;81;117;101;32;116;97;98;117;97;100;97;63;34; @@ -58499,7 +58505,7 @@ lösung: vb-wald-loesung.visustruct -`,kO=` +`,SO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; @@ -58515,7 +58521,7 @@ lösung: vb-wald-loesung.visustruct -`,SO=` +`,TO=` 105;110;112;117;116;58;32;105;110;116;32;108;97;114;103;117;114;97;32;34;76;97;114;103;117;114;97;34; @@ -58547,7 +58553,7 @@ lösung: vb-wald-loesung.visustruct -`,TO=` +`,_O=` 105;110;116;91;93;32;110;117;109;101;114;111;115;32;61;32;123;50;44;32;52;44;32;54;44;32;56;44;32;49;48;125; @@ -58563,7 +58569,7 @@ lösung: vb-wald-loesung.visustruct -`,_O=` +`,OO=` 105;110;116;91;93;32;118;97;108;111;114;101;115;32;61;32;123;52;44;32;56;44;32;49;53;44;32;49;54;44;32;50;51;44;32;52;50;125; @@ -58578,7 +58584,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;118;97;108;111;114;101;115;46;108;101;110;103;116;104; -`,OO=` +`,AO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; @@ -58610,7 +58616,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;81;117;97;110;116;105;100;97;100;101;58;32;34;32;43;32;113;117;97;110;116;105;100;97;100;101; -`,AO=` +`,CO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; @@ -58642,7 +58648,7 @@ lösung: vb-wald-loesung.visustruct -`,CO=` +`,jO=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;81;117;97;110;116;111;115;32;100;101;103;114;97;117;115;63;34; @@ -58690,7 +58696,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;114;105;109;101;105;114;111;32;110;111;109;101;58;32;34;32;43;32;110;111;109;101;115;91;48;93; -`,jO=` +`,DO=` 105;110;116;91;93;32;110;117;109;101;114;111;115;32;61;32;110;101;119;32;105;110;116;91;52;93; @@ -58716,7 +58722,7 @@ lösung: vb-wald-loesung.visustruct -`,DO=` +`,BO=` 105;110;116;91;93;32;110;117;109;101;114;111;115;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -58767,7 +58773,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;225;120;105;109;111;58;32;34;32;43;32;109;97;120; -`,BO=` +`,ZO=` 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;123;49;50;44;32;55;44;32;49;57;44;32;52;125; @@ -58808,7 +58814,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;225;120;105;109;111;58;32;34;32;43;32;109;97;120; -`,ZO=` +`,MO=` 105;110;116;32;115;111;109;97;32;61;32;48; @@ -58831,7 +58837,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; -`,MO=` +`,LO=` 105;110;116;32;115;111;109;97;32;61;32;48; @@ -58861,7 +58867,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; -`,LO=` +`,EO=` 105;110;112;117;116;58;32;105;110;116;32;99;111;109;112;114;105;109;101;110;116;111;32;34;67;111;109;112;114;105;109;101;110;116;111;63;34; @@ -58876,7 +58882,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;193;114;101;97;58;32;34;32;43;32;102; -`,EO=` +`,WO=` 109;111;115;116;114;97;114;66;111;97;115;86;105;110;100;97;115;40;41; @@ -58888,7 +58894,7 @@ lösung: vb-wald-loesung.visustruct 109;111;115;116;114;97;114;82;101;115;117;108;116;97;100;111;40;41; -`,WO=` +`,NO=` 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;97;115;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; @@ -58920,7 +58926,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;101;109;112;101;114;97;116;117;114;97;32;109;97;105;115;32;97;108;116;97;58;32;34;32;43;32;109;97;120; -`,NO=` +`,FO=` 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;97;115;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; @@ -58952,7 +58958,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;101;109;112;101;114;97;116;117;114;97;32;109;97;105;115;32;97;108;116;97;58;32;34;32;43;32;109;97;120; -`,FO=` +`,JO=` 105;110;116;91;93;32;110;111;116;97;115;32;61;32;123;50;44;32;51;44;32;49;44;32;52;125; @@ -58974,7 +58980,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; -`,JO=` +`,RO=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;81;117;101;32;110;250;109;101;114;111;63;34; @@ -58986,7 +58992,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;79;32;113;117;97;100;114;97;100;111;32;233;32;34;32;43;32;113; -`,RO=` +`,GO=` 105;110;116;32;114;101;115;117;108;116;97;100;111;32;61;32;120;32;42;32;120; @@ -58995,7 +59001,7 @@ lösung: vb-wald-loesung.visustruct 114;101;116;117;114;110;32;114;101;115;117;108;116;97;100;111; -`,GO=` +`,HO=` 109;111;115;116;114;97;114;84;105;116;117;108;111;40;41; @@ -59007,7 +59013,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;79;108;225;32;34;32;43;32;110;111;109;101; -`,HO=` +`,VO=` 111;117;116;112;117;116;58;32;34;66;101;109;45;118;105;110;100;111;32;97;111;32;113;117;105;122;33;34; @@ -59016,7 +59022,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;86;97;105;115;32;116;101;114;32;116;114;234;115;32;112;101;114;103;117;110;116;97;115;46;34; -`,VO=` +`,qO=` 109;111;115;116;114;97;114;83;111;109;97;40;51;44;32;52;41; @@ -59028,7 +59034,7 @@ lösung: vb-wald-loesung.visustruct 109;111;115;116;114;97;114;83;111;109;97;40;120;44;32;120;32;43;32;49;41; -`,qO=` +`,QO=` 105;110;116;32;115;111;109;97;32;61;32;97;32;43;32;98; @@ -59037,7 +59043,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;97;32;43;32;34;32;43;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;115;111;109;97; -`,QO=` +`,UO=` 105;110;112;117;116;58;32;105;110;116;32;105;110;105;99;105;111;32;34;86;97;108;111;114;32;105;110;105;99;105;97;108;34; @@ -59060,7 +59066,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;74;225;33;34; -`,UO=` +`,$O=` 105;110;112;117;116;58;32;105;110;116;32;105;110;105;99;105;111;32;34;86;97;108;111;114;32;105;110;105;99;105;97;108;34; @@ -59083,7 +59089,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;74;225;34; -`,$O=` +`,YO=` 105;110;116;91;93;91;93;32;112;111;110;116;111;115;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; @@ -59105,7 +59111,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;74;111;103;97;100;111;114;32;50;58;32;34;32;43;32;115;111;109;97; -`,YO=` +`,XO=` 105;110;116;91;93;91;93;32;112;111;110;116;111;115;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; @@ -59127,7 +59133,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;74;111;103;97;100;111;114;32;50;58;32;34;32;43;32;115;111;109;97; -`,XO=` +`,KO=` 105;110;116;91;93;91;93;32;112;111;110;116;111;115;32;61;32;123;123;51;44;32;53;125;44;32;123;52;44;32;49;125;44;32;123;50;44;32;50;125;125; @@ -59156,7 +59162,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; -`,KO=` +`,eA=` 105;110;116;32;115;111;109;97;32;61;32;48; @@ -59179,7 +59185,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;111;109;97; -`,eA=` +`,tA=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; @@ -59201,7 +59207,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;111;109;97; -`,tA=` +`,nA=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; @@ -59223,7 +59229,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;115;111;109;97; -`,nA=` +`,iA=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;81;117;101;32;116;97;98;117;97;100;97;63;34; @@ -59255,7 +59261,7 @@ lösung: vb-wald-loesung.visustruct -`,iA=` +`,aA=` 105;110;112;117;116;58;32;105;110;116;32;110;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;34; @@ -59277,7 +59283,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;102;97;116;111;114;105;97;108; -`,aA=` +`,sA=` 83;116;114;105;110;103;32;99;97;114;116;97;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;99;97;114;116;97;46;116;120;116;34;41;41; @@ -59309,13 +59315,13 @@ lösung: vb-wald-loesung.visustruct -`,sA=` +`,rA=` 83;116;114;105;110;103;32;99;97;114;116;97;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;99;97;114;116;97;46;116;120;116;34;41;41; -`,rA=` +`,oA=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;111;109;101;32;34;78;111;109;101;32;112;114;243;112;114;105;111;63;34; @@ -59327,7 +59333,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;111;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;97;112;101;108;105;100;111;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; -`,oA=` +`,lA=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;111;109;101;32;34;78;111;109;101;32;112;114;243;112;114;105;111;63;34; @@ -59339,7 +59345,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;111;109;101;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;32;34;32;43;32;97;112;101;108;105;100;111;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;34; -`,lA=` +`,uA=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;101;110;116;114;97;100;97;32;34;80;97;108;97;118;114;97;45;112;97;115;115;101;63;34; @@ -59358,7 +59364,7 @@ lösung: vb-wald-loesung.visustruct -`,uA=` +`,cA=` 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; @@ -59387,7 +59393,7 @@ lösung: vb-wald-loesung.visustruct -`,cA=` +`,mA=` 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;86;97;108;111;114;32;105;110;105;99;105;97;108;63;34; @@ -59407,7 +59413,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;70;105;109;34; -`,mA=` +`,dA=` 105;110;116;32;116;101;110;116;97;116;105;118;97;115;32;61;32;48; @@ -59440,7 +59446,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;101;110;116;97;116;105;118;97;115;58;32;34;32;43;32;116;101;110;116;97;116;105;118;97;115; -`,dA=` +`,hA=` 105;110;116;32;116;101;110;116;97;116;105;118;97;115;32;61;32;48; @@ -59473,7 +59479,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;101;110;116;97;116;105;118;97;115;58;32;34;32;43;32;116;101;110;116;97;116;105;118;97;115; -`,hA=` +`,gA=` 105;110;116;32;115;111;109;97;32;61;32;48; @@ -59515,7 +59521,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;115;111;109;97; -`,gA=` +`,pA=` 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; @@ -59537,7 +59543,7 @@ lösung: vb-wald-loesung.visustruct -`,pA=` +`,fA=` 105;110;112;117;116;58;32;105;110;116;32;108;105;109;105;116;101;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; @@ -59553,7 +59559,7 @@ lösung: vb-wald-loesung.visustruct -`,fA=` +`,bA=` 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -59592,7 +59598,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;115;105;231;227;111;58;32;34;32;43;32;112;111;115;105;99;97;111; -`,bA=` +`,xA=` 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -59631,7 +59637,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;111;115;105;231;227;111;58;32;34;32;43;32;112;111;115;105;99;97;111; -`,xA=` +`,vA=` 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -59666,7 +59672,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;81;117;97;110;116;105;100;97;100;101;58;32;34;32;43;32;113;117;97;110;116;105;100;97;100;101; -`,vA=` +`,yA=` 111;117;116;112;117;116;58;32;34;66;111;109;32;100;105;97;34; @@ -59675,13 +59681,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;72;111;106;101;32;97;112;114;101;110;100;101;109;111;115;32;101;115;116;114;117;116;111;103;114;97;109;97;115;46;34; -`,yA=` +`,wA=` 111;117;116;112;117;116;58;32;34;79;108;225;32;77;117;110;100;111;34; -`,wA=` +`,zA=` 111;117;116;112;117;116;58;32;34;79;108;225;34; @@ -59690,7 +59696,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;69;115;116;111;117;32;97;32;97;112;114;101;110;100;101;114;32;101;115;116;114;117;116;111;103;114;97;109;97;115;34; -`,zA=` +`,IA=` 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; @@ -59731,7 +59737,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;113;117;97;110;116;105;100;97;100;101;32;43;32;34;32;108;105;110;104;97;115;32;103;117;97;114;100;97;100;97;115;34; -`,IA=` +`,kA=` 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; @@ -59740,7 +59746,7 @@ lösung: vb-wald-loesung.visustruct 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;99;111;109;112;114;97;115;45;110;111;118;97;46;116;120;116;34;41; -`,kA=` +`,SA=` 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; @@ -59766,13 +59772,13 @@ lösung: vb-wald-loesung.visustruct 102;105;99;104;101;105;114;111;46;99;108;111;115;101;40;41; -`,SA=` +`,TA=` 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; -`,TA=` +`,_A=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; @@ -59811,7 +59817,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;82;97;112;111;115;97;58;32;34;32;43;32;113;117;97;110;116;105;100;97;100;101; -`,_A=` +`,OA=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; @@ -59820,7 +59826,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; -`,OA=` +`,AA=` 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; @@ -59855,7 +59861,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;69;110;116;114;97;100;97;32;109;97;105;115;32;108;111;110;103;97;58;32;34;32;43;32;109;97;105;115;76;111;110;103;97; -`,AA=` +`,CA=` 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; @@ -59864,7 +59870,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;91;93;32;108;105;110;104;97;115;32;61;32;116;101;120;116;111;46;115;112;108;105;116;40;34;92;110;34;41; -`,CA=` +`,jA=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;117;114;109;97;46;99;115;118;34;41;41; @@ -59927,7 +59933,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; -`,jA=` +`,DA=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;117;114;109;97;46;99;115;118;34;41;41; @@ -59968,7 +59974,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;77;233;100;105;97;32;100;101;32;77;97;116;101;109;225;116;105;99;97;58;32;34;32;43;32;115;111;109;97;32;47;32;113;117;97;110;116;105;100;97;100;101; -`,DA=` +`,BA=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;117;114;109;97;46;99;115;118;34;41;41; @@ -59977,7 +59983,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; -`,BA=` +`,ZA=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; @@ -60016,7 +60022,7 @@ lösung: vb-wald-loesung.visustruct 108;101;105;116;111;114;46;99;108;111;115;101;40;41; -`,ZA=` +`,MA=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; @@ -60025,7 +60031,7 @@ lösung: vb-wald-loesung.visustruct 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; -`,MA=` +`,LA=` 83;116;114;105;110;103;91;93;32;110;111;109;101;115;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;82;97;112;111;115;97;34;125; @@ -60075,7 +60081,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;111;109;101;115;46;108;101;110;103;116;104;32;43;32;34;32;101;110;116;114;97;100;97;115;32;103;117;97;114;100;97;100;97;115;34; -`,LA=` +`,EA=` 83;116;114;105;110;103;91;93;32;110;111;109;101;115;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;82;97;112;111;115;97;34;125; @@ -60093,7 +60099,7 @@ lösung: vb-wald-loesung.visustruct 115;97;105;100;97;46;99;108;111;115;101;40;41; -`,EA=` +`,WA=` 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;97;110;105;109;97;105;115;46;99;115;118;34;41;41; @@ -60146,7 +60152,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;40;108;105;110;104;97;115;46;108;101;110;103;116;104;32;45;32;49;41;32;43;32;34;32;97;110;105;109;97;105;115;32;103;117;97;114;100;97;100;111;115;34; -`,WA=` +`,NA=` 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;97;110;105;109;97;105;115;46;99;115;118;34;41;41; @@ -60167,7 +60173,7 @@ lösung: vb-wald-loesung.visustruct 115;97;105;100;97;46;99;108;111;115;101;40;41; -`,NA=` +`,FA=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;97;110;105;109;97;105;115;46;99;115;118;34;41;41; @@ -60211,7 +60217,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;113;117;97;110;116;105;100;97;100;101;32;43;32;34;32;102;114;97;115;101;115;32;103;117;97;114;100;97;100;97;115;34; -`,FA=` +`,JA=` 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;97;110;105;109;97;105;115;46;99;115;118;34;41;41; @@ -60232,7 +60238,7 @@ lösung: vb-wald-loesung.visustruct 115;97;105;100;97;46;99;108;111;115;101;40;41; -`,JA=` +`,RA=` 105;110;112;117;116;58;32;105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;98;105;108;104;101;116;101;115;63;34; @@ -60244,7 +60250,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; -`,RA=` +`,GA=` 105;110;112;117;116;58;32;105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;98;105;108;104;101;116;101;115;63;34; @@ -60256,7 +60262,7 @@ lösung: vb-wald-loesung.visustruct 100;111;117;98;108;101;32;116;111;116;97;108;32;61;32;113;117;97;110;116;105;100;97;100;101;32;42;32;56;46;53; -`,GA=` +`,HA=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;34; @@ -60280,7 +60286,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98; -`,HA=` +`,VA=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;34; @@ -60301,7 +60307,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98; -`,VA=` +`,qA=` 105;110;116;32;97;32;61;32;51; @@ -60325,7 +60331,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; -`,qA=` +`,QA=` 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -60384,7 +60390,7 @@ lösung: vb-wald-loesung.visustruct -`,QA=` +`,UA=` 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -60443,7 +60449,7 @@ lösung: vb-wald-loesung.visustruct -`,UA=` +`,$A=` 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; @@ -60517,7 +60523,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;67;111;109;112;97;114;97;231;245;101;115;58;32;34;32;43;32;99;111;109;112;97;114;97;99;111;101;115; -`,$A=` +`,YA=` 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;55;44;32;51;44;32;49;48;44;32;53;44;32;50;125; @@ -60566,7 +60572,7 @@ lösung: vb-wald-loesung.visustruct -`,YA=` +`,XA=` 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -60615,7 +60621,7 @@ lösung: vb-wald-loesung.visustruct -`,XA=` +`,KA=` 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; @@ -60673,7 +60679,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;67;111;109;112;97;114;97;231;245;101;115;58;32;34;32;43;32;99;111;109;112;97;114;97;99;111;101;115; -`,KA=` +`,eC=` 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;123;51;44;32;53;44;32;56;125; @@ -60692,7 +60698,7 @@ lösung: vb-wald-loesung.visustruct -`,eC=` +`,tC=` 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;123;51;44;32;53;44;32;56;125; @@ -60711,7 +60717,7 @@ lösung: vb-wald-loesung.visustruct -`,tC=` +`,nC=` 105;110;116;32;105;32;61;32;48; @@ -60724,7 +60730,7 @@ lösung: vb-wald-loesung.visustruct -`,nC=` +`,iC=` 105;110;116;32;110;117;109;101;114;111;32;61;32;53; @@ -60748,7 +60754,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;68;101;112;111;105;115;58;32;34;32;43;32;102;105;108;97;91;48;93;32;43;32;34;44;32;34;32;43;32;102;105;108;97;91;49;93; -`,iC=` +`,aC=` 105;110;116;32;105;32;61;32;48; @@ -60761,7 +60767,7 @@ lösung: vb-wald-loesung.visustruct -`,aC=` +`,sC=` 120;32;61;32;120;32;42;32;50; @@ -60770,7 +60776,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;78;111;32;115;117;98;112;114;111;103;114;97;109;97;58;32;120;32;61;32;34;32;43;32;120; -`,sC=` +`,rC=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;111;109;101;32;34;78;111;109;101;32;112;114;243;112;114;105;111;34; @@ -60782,7 +60788,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;110;111;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;97;112;101;108;105;100;111;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; -`,rC=` +`,oC=` 83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;61;32;34;80;97;115;115;97;116;101;109;112;111;34; @@ -60821,7 +60827,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;116;101;120;116; -`,oC=` +`,lC=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;34;73;110;116;114;111;100;117;122;32;117;109;97;32;112;97;108;97;118;114;97;34; @@ -60843,7 +60849,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;105;110;118;101;114;116;105;100;97; -`,lC=` +`,uC=` 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;34;76;117;100;119;105;103;59;98;111;100;101;59;55;34; @@ -60862,7 +60868,7 @@ lösung: vb-wald-loesung.visustruct -`,uC=` +`,cC=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;114;97;115;101;32;34;73;110;116;114;111;100;117;122;32;117;109;97;32;102;114;97;115;101;34; @@ -60874,7 +60880,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;80;97;108;97;118;114;97;115;58;32;34;32;43;32;112;97;108;97;118;114;97;115;46;108;101;110;103;116;104; -`,cC=` +`,mC=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;34;73;110;116;114;111;100;117;122;32;117;109;97;32;112;97;108;97;118;114;97;34; @@ -60906,7 +60912,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;78;250;109;101;114;111;32;100;101;32;97;58;32;34;32;43;32;113;117;97;110;116;105;100;97;100;101; -`,mC=` +`,dC=` 83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;61;32;34;80;97;115;115;97;116;101;109;112;111;34; @@ -60930,7 +60936,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;116;111;85;112;112;101;114;67;97;115;101;40;41; -`,dC=` +`,hC=` 105;110;112;117;116;58;32;105;110;116;32;97;110;122;97;104;108;32;34;87;105;101;32;118;105;101;108;101;32;75;97;114;116;101;110;63;34; @@ -60942,7 +60948,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116; -`,hC=` +`,gC=` 105;110;112;117;116;58;32;105;110;116;32;97;110;122;97;104;108;32;34;87;105;101;32;118;105;101;108;101;32;75;97;114;116;101;110;63;34; @@ -60954,7 +60960,7 @@ lösung: vb-wald-loesung.visustruct 100;111;117;98;108;101;32;103;101;115;97;109;116;32;61;32;97;110;122;97;104;108;32;42;32;56;46;53; -`,gC=` +`,pC=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;34; @@ -60978,7 +60984,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98; -`,pC=` +`,fC=` 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;34; @@ -60999,7 +61005,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98; -`,fC=` +`,bC=` 105;110;116;32;97;32;61;32;51; @@ -61023,7 +61029,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; -`,bC=` +`,xC=` 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -61082,7 +61088,7 @@ lösung: vb-wald-loesung.visustruct -`,xC=` +`,vC=` 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;110;101;119;32;105;110;116;91;53;93; @@ -61141,7 +61147,7 @@ lösung: vb-wald-loesung.visustruct -`,vC=` +`,yC=` 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; @@ -61215,7 +61221,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;86;101;114;103;108;101;105;99;104;101;58;32;34;32;43;32;118;101;114;103;108;101;105;99;104;101; -`,yC=` +`,wC=` 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;55;44;32;51;44;32;49;48;44;32;53;44;32;50;125; @@ -61264,7 +61270,7 @@ lösung: vb-wald-loesung.visustruct -`,wC=` +`,zC=` 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; @@ -61313,7 +61319,7 @@ lösung: vb-wald-loesung.visustruct -`,zC=` +`,IC=` 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; @@ -61371,7 +61377,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;86;101;114;103;108;101;105;99;104;101;58;32;34;32;43;32;118;101;114;103;108;101;105;99;104;101; -`,IC=` +`,kC=` 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;123;51;44;32;53;44;32;56;125; @@ -61390,7 +61396,7 @@ lösung: vb-wald-loesung.visustruct -`,kC=` +`,SC=` 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;123;51;44;32;53;44;32;56;125; @@ -61409,7 +61415,7 @@ lösung: vb-wald-loesung.visustruct -`,SC=` +`,TC=` 105;110;116;32;105;32;61;32;48; @@ -61422,7 +61428,7 @@ lösung: vb-wald-loesung.visustruct -`,TC=` +`,_C=` 105;110;116;32;122;97;104;108;32;61;32;53; @@ -61446,7 +61452,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;78;97;99;104;104;101;114;58;32;34;32;43;32;114;101;105;104;101;91;48;93;32;43;32;34;44;32;34;32;43;32;114;101;105;104;101;91;49;93; -`,_C=` +`,OC=` 105;110;116;32;105;32;61;32;48; @@ -61459,7 +61465,7 @@ lösung: vb-wald-loesung.visustruct -`,OC=` +`,AC=` 120;32;61;32;120;32;42;32;50; @@ -61468,7 +61474,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;73;109;32;85;110;116;101;114;112;114;111;103;114;97;109;109;58;32;120;32;61;32;34;32;43;32;120; -`,AC=` +`,CC=` 105;110;116;32;97;98;115;116;97;110;100;32;61;32;109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41; @@ -61477,7 +61483,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;65;98;115;116;97;110;100;58;32;34;32;43;32;97;98;115;116;97;110;100;32;43;32;34;32;99;109;34;41; -`,CC=` +`,jC=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;49;48; @@ -61530,7 +61536,7 @@ lösung: vb-wald-loesung.visustruct -`,jC=` +`,DC=` 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; @@ -61548,7 +61554,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;50;53;53;44;32;48;41; -`,DC=` +`,BC=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -61578,7 +61584,7 @@ lösung: vb-wald-loesung.visustruct -`,BC=` +`,ZC=` 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;72;97;108;108;111;33;34;41; @@ -61590,7 +61596,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;73;99;104;32;98;105;110;32;86;105;115;117;66;111;116;34;41; -`,ZC=` +`,MC=` 105;110;116;32;122;97;104;108;32;61;32;48; @@ -61642,7 +61648,7 @@ lösung: vb-wald-loesung.visustruct -`,MC=` +`,LC=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;111;116;34;41; @@ -61653,7 +61659,7 @@ lösung: vb-wald-loesung.visustruct -`,LC=` +`,EC=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; @@ -61664,7 +61670,7 @@ lösung: vb-wald-loesung.visustruct -`,EC=` +`,WC=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -61675,7 +61681,7 @@ lösung: vb-wald-loesung.visustruct -`,WC=` +`,NC=` 83;116;114;105;110;103;32;119;111;114;116;32;61;32;34;86;105;115;117;66;111;116;34; @@ -61694,7 +61700,7 @@ lösung: vb-wald-loesung.visustruct -`,NC=` +`,FC=` 109;98;111;116;46;108;101;100;40;48;41;46;115;101;116;67;111;108;111;114;40;34;114;111;116;34;41; @@ -61706,7 +61712,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;108;101;100;40;52;41;46;115;101;116;67;111;108;111;114;40;34;103;114;252;110;34;41; -`,FC=` +`,JC=` 105;110;116;32;105;32;61;32;48; @@ -61722,7 +61728,7 @@ lösung: vb-wald-loesung.visustruct -`,JC=` +`,RC=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;98;108;97;117;34;41; @@ -61750,7 +61756,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;71;101;112;97;114;107;116;33;34;41; -`,RC=` +`,GC=` 83;116;114;105;110;103;91;93;32;102;97;114;98;101;110;32;61;32;123;34;114;111;116;34;44;32;34;103;101;108;98;34;44;32;34;103;114;252;110;34;44;32;34;98;108;97;117;34;44;32;34;108;105;108;97;34;125; @@ -61766,7 +61772,7 @@ lösung: vb-wald-loesung.visustruct -`,GC=` +`,HC=` 109;98;111;116;46;103;101;116;67;111;108;111;114;40;41; @@ -61792,7 +61798,7 @@ lösung: vb-wald-loesung.visustruct -`,HC=` +`,VC=` 109;98;111;116;46;100;114;105;118;101;40;53;48;44;32;53;48;41; @@ -61809,7 +61815,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;116;111;112;40;41; -`,VC=` +`,qC=` 109;98;111;116;46;102;111;114;119;97;114;100;40;41; @@ -61827,7 +61833,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;102;111;114;119;97;114;100;40;41; -`,qC=` +`,QC=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;111;116;34;41; @@ -61863,7 +61869,7 @@ lösung: vb-wald-loesung.visustruct -`,QC=` +`,UC=` 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;65;107;107;117;58;32;34;32;43;32;109;98;111;116;46;103;101;116;66;97;116;116;101;114;121;40;41;32;43;32;34;32;37;34;41; @@ -61882,7 +61888,7 @@ lösung: vb-wald-loesung.visustruct -`,UC=` +`,$C=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;98;108;97;117;34;41; @@ -61906,7 +61912,7 @@ lösung: vb-wald-loesung.visustruct -`,$C=` +`,YC=` 105;110;116;32;105;32;61;32;48; @@ -61928,7 +61934,7 @@ lösung: vb-wald-loesung.visustruct -`,YC=` +`,XC=` 105;110;116;32;105;32;61;32;51; @@ -61947,7 +61953,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;76;111;115;33;34;41; -`,XC=` +`,KC=` 105;110;116;32;105;32;61;32;49; @@ -61960,7 +61966,7 @@ lösung: vb-wald-loesung.visustruct -`,KC=` +`,ej=` 105;110;116;32;105;32;61;32;48; @@ -61993,7 +61999,7 @@ lösung: vb-wald-loesung.visustruct -`,eP=` +`,tj=` 109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;62;32;54;48; @@ -62009,7 +62015,7 @@ lösung: vb-wald-loesung.visustruct -`,tP=` +`,nj=` 105;110;116;32;105;32;61;32;48; @@ -62028,7 +62034,7 @@ lösung: vb-wald-loesung.visustruct -`,nP=` +`,ij=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; @@ -62072,7 +62078,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;116;111;112;40;41; -`,iP=` +`,aj=` 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;51;48; @@ -62091,7 +62097,7 @@ lösung: vb-wald-loesung.visustruct -`,aP=` +`,sj=` 105;110;116;32;115;99;104;114;105;116;116;101;32;61;32;48; @@ -62121,7 +62127,7 @@ lösung: vb-wald-loesung.visustruct -`,sP=` +`,rj=` 105;110;116;32;108;97;101;110;103;101;32;61;32;54;48; @@ -62149,7 +62155,7 @@ lösung: vb-wald-loesung.visustruct -`,rP=` +`,oj=` 83;116;114;105;110;103;32;116;101;120;116;32;61;32;34;72;97;108;108;111;32;75;108;97;115;115;101;34; @@ -62158,7 +62164,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;116;101;120;116;32;43;32;34;32;40;34;32;43;32;116;101;120;116;46;108;101;110;103;116;104;40;41;32;43;32;34;41;34;41; -`,oP=` +`,lj=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; @@ -62172,7 +62178,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;112;108;97;121;84;111;110;101;40;52;52;48;44;32;51;48;48;41; -`,lP=` +`,uj=` 109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;62;32;45;53;32;38;38;32;109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;60;32;53;32;38;38;32;109;98;111;116;46;103;101;116;82;111;108;108;40;41;32;62;32;45;53;32;38;38;32;109;98;111;116;46;103;101;116;82;111;108;108;40;41;32;60;32;53; @@ -62188,7 +62194,7 @@ lösung: vb-wald-loesung.visustruct -`,uP=` +`,cj=` 109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;60;32;53;48; @@ -62202,7 +62208,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; -`,cP=` +`,mj=` 105;110;116;32;105;32;61;32;48; @@ -62237,7 +62243,7 @@ lösung: vb-wald-loesung.visustruct -`,mP=` +`,dj=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -62271,7 +62277,7 @@ lösung: vb-wald-loesung.visustruct -`,dP=` +`,hj=` 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;111;116;34;41; @@ -62315,7 +62321,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;116;111;112;40;41; -`,hP=` +`,gj=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41; @@ -62341,7 +62347,7 @@ lösung: vb-wald-loesung.visustruct -`,gP=` +`,pj=` 105;110;116;91;93;32;116;111;101;110;101;32;61;32;123;50;54;50;44;32;50;57;52;44;32;51;51;48;44;32;51;52;57;44;32;51;57;50;125; @@ -62357,7 +62363,7 @@ lösung: vb-wald-loesung.visustruct -`,pP=` +`,fj=` 105;110;116;32;105;32;61;32;48; @@ -62423,7 +62429,7 @@ lösung: vb-wald-loesung.visustruct -`,fP=` +`,bj=` 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;51;48; @@ -62439,7 +62445,7 @@ lösung: vb-wald-loesung.visustruct -`,bP=` +`,xj=` 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;50;48; @@ -62456,7 +62462,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;90;122;122;34;41; -`,xP=` +`,vj=` 105;110;112;117;116;58;32;105;110;116;32;110;111;116;101; @@ -62485,7 +62491,7 @@ lösung: vb-wald-loesung.visustruct -`,vP=` +`,yj=` 105;110;116;32;97;32;61;32;113;117;97;100;114;97;116;122;97;104;108;40;51;41; @@ -62500,13 +62506,13 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;98; -`,yP=` +`,wj=` 114;101;116;117;114;110;32;120;32;42;32;120; -`,wP=` +`,zj=` 83;116;114;105;110;103;32;119;111;114;116;32;61;32;34;76;117;100;119;105;103;34; @@ -62528,7 +62534,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;114;117;101;99;107;119;97;101;114;116;115; -`,zP=` +`,Ij=` 105;110;116;32;108;97;101;110;103;101;32;61;32;54;48; @@ -62543,7 +62549,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;83;116;114;101;99;107;101;58;32;34;32;43;32;115;116;114;101;99;107;101;32;43;32;34;32;99;109;34; -`,IP=` +`,kj=` 105;110;116;91;93;32;110;111;116;101;110;32;61;32;123;50;44;32;49;44;32;51;44;32;50;125; @@ -62568,7 +62574,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;110;122;97;104;108;58;32;34;32;43;32;110;111;116;101;110;46;108;101;110;103;116;104; -`,kP=` +`,Sj=` 109;98;111;116;46;102;111;114;119;97;114;100;40;41; @@ -62643,7 +62649,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; -`,SP=` +`,Tj=` 113;117;97;100;114;97;116;40;51;48;41; @@ -62652,7 +62658,7 @@ lösung: vb-wald-loesung.visustruct 113;117;97;100;114;97;116;40;53;48;41; -`,TP=` +`,_j=` 105;110;116;32;105;32;61;32;48; @@ -62707,7 +62713,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; -`,_P=` +`,Oj=` 105;110;116;32;105;32;61;32;48; @@ -62723,7 +62729,7 @@ lösung: vb-wald-loesung.visustruct -`,OP=` +`,Aj=` 105;110;116;32;105;32;61;32;48; @@ -62746,7 +62752,7 @@ lösung: vb-wald-loesung.visustruct -`,AP=` +`,Cj=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -62760,7 +62766,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; -`,CP=` +`,jj=` 109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;62;32;50;48;32;124;124;32;109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;60;32;45;50;48; @@ -62776,7 +62782,7 @@ lösung: vb-wald-loesung.visustruct -`,PP=` +`,Pj=` 105;110;116;32;105;32;61;32;48; @@ -62828,7 +62834,7 @@ lösung: vb-wald-loesung.visustruct -`,jP=` +`,Dj=` 105;110;116;32;105;32;61;32;49; @@ -62844,7 +62850,7 @@ lösung: vb-wald-loesung.visustruct -`,DP=` +`,Bj=` 33;109;98;111;116;46;105;115;66;117;116;116;111;110;65;40;41; @@ -62858,7 +62864,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; -`,BP=` +`,Zj=` 109;98;111;116;46;112;108;97;121;84;111;110;101;40;50;54;50;44;32;51;48;48;41; @@ -62876,7 +62882,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;112;108;97;121;84;111;110;101;40;51;57;50;44;32;51;48;48;41; -`,ZP=` +`,Mj=` 105;110;116;32;105;32;61;32;48; @@ -62898,7 +62904,7 @@ lösung: vb-wald-loesung.visustruct -`,MP=` +`,Lj=` 105;110;116;32;108;105;110;107;115;32;61;32;57;57; @@ -62930,7 +62936,7 @@ lösung: vb-wald-loesung.visustruct -`,LP=` +`,Ej=` 105;110;116;32;115;101;105;116;101;32;61;32;51;48; @@ -62949,7 +62955,7 @@ lösung: vb-wald-loesung.visustruct -`,EP=` +`,Wj=` 105;110;116;32;105;32;61;32;48; @@ -62982,7 +62988,7 @@ lösung: vb-wald-loesung.visustruct -`,WP=` +`,Nj=` 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; @@ -63021,7 +63027,7 @@ lösung: vb-wald-loesung.visustruct -`,NP=` +`,Fj=` 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48; @@ -63037,7 +63043,7 @@ lösung: vb-wald-loesung.visustruct -`,FP=` +`,Jj=` 109;98;111;116;46;114;101;115;101;116;84;105;109;101;114;40;41; @@ -63057,7 +63063,7 @@ lösung: vb-wald-loesung.visustruct 109;98;111;116;46;115;116;111;112;40;41; -`,JP=` +`,Rj=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;118;111;114;110;97;109;101;32;34;86;111;114;110;97;109;101;34; @@ -63069,7 +63075,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;118;111;114;110;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;110;97;99;104;110;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; -`,RP=` +`,Gj=` 83;116;114;105;110;103;32;119;111;114;116;32;61;32;34;90;105;101;103;101;110;98;111;99;107;34; @@ -63108,7 +63114,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;116;101;120;116; -`,GP=` +`,Hj=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;116;32;34;87;111;114;116;32;101;105;110;103;101;98;101;110;34; @@ -63130,7 +63136,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;114;117;101;99;107;119;97;101;114;116;115; -`,HP=` +`,Vj=` 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;34;76;117;100;119;105;103;59;71;101;105;223;98;111;99;107;59;55;34; @@ -63149,7 +63155,7 @@ lösung: vb-wald-loesung.visustruct -`,VP=` +`,qj=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;115;97;116;122;32;34;83;97;116;122;32;101;105;110;103;101;98;101;110;34; @@ -63161,7 +63167,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;87;246;114;116;101;114;58;32;34;32;43;32;119;111;101;114;116;101;114;46;108;101;110;103;116;104; -`,qP=` +`,Qj=` 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;116;32;34;87;111;114;116;32;101;105;110;103;101;98;101;110;34; @@ -63193,7 +63199,7 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;34;65;110;122;97;104;108;32;101;58;32;34;32;43;32;97;110;122;97;104;108; -`,QP=` +`,Uj=` 83;116;114;105;110;103;32;119;111;114;116;32;61;32;34;71;101;105;223;98;111;99;107;34; @@ -63217,14 +63223,14 @@ lösung: vb-wald-loesung.visustruct 111;117;116;112;117;116;58;32;119;111;114;116;46;116;111;85;112;112;101;114;67;97;115;101;40;41; -`,UP=`// Labyrinth mit Ausgängen (nach Kara): jede Wandreihe hat genau eine Lücke, immer weiter rechts. Ein Zeichen = 30 cm. +`,$j=`// Labyrinth mit Ausgängen (nach Kara): jede Wandreihe hat genau eine Lücke, immer weiter rechts. Ein Zeichen = 30 cm. raster: 3 .......Z #####.## ........ ##.##### >....... -`,$P=`// Labyrinth mit Ausgängen, drei Reihen. Ein Zeichen = 30 cm. +`,Yj=`// Labyrinth mit Ausgängen, drei Reihen. Ein Zeichen = 30 cm. raster: 3 ........Z ######.## @@ -63233,20 +63239,20 @@ raster: 3 ......... .######## >........ -`,YP=`// Um die Ecke (Sequenz im Kurs, Lektion 5): ein Zeichen = 30 cm. +`,Xj=`// Um die Ecke (Sequenz im Kurs, Lektion 5): ein Zeichen = 30 cm. raster: 3 Z.... ###.. ..... ..### ^.... -`,XP=`// Fahre bis Rot: kurzer Weg +`,Kj=`// Fahre bis Rot: kurzer Weg ..... ..r.. ..... ..... ..^.. -`,KP=`// Fahre bis Rot: erst kommt ein grünes Feld +`,eP=`// Fahre bis Rot: erst kommt ein grünes Feld ..... ..r.. ..... @@ -63255,21 +63261,21 @@ Z.... ..... ..... ..^.. -`,ej=`// Bis Blau, bei Grün piepen +`,tP=`// Bis Blau, bei Grün piepen ..... ..b.. ..... ..g.. ..... ..^.. -`,tj=`// Bis Blau, ohne grünes Feld +`,nP=`// Bis Blau, ohne grünes Feld ..... ..b.. ..... ..... ..... ..^.. -`,nj=`// Hindernis ausweichen: ein Klotz im Weg, das rote Feld liegt dahinter. +`,iP=`// Hindernis ausweichen: ein Klotz im Weg, das rote Feld liegt dahinter. ......... .....r... .....o... @@ -63280,7 +63286,7 @@ Z.... ......... ......... ..^...... -`,ij=`// Hindernis ausweichen: zwei Klötze im Weg. +`,aP=`// Hindernis ausweichen: zwei Klötze im Weg. ......... .......r. .......o. @@ -63295,7 +63301,7 @@ Z.... ......... ......... .^....... -`,aj=`// Labyrinth: Gänge 30 cm breit, Wände 10 cm dick. Ziel oben links. +`,sP=`// Labyrinth: Gänge 30 cm breit, Wände 10 cm dick. Ziel oben links. ........... .Z......... ........... @@ -63307,7 +63313,7 @@ Z.... ........... .........<. ........... -`,sj=`// Labyrinth: Gänge 30 cm breit, Wände 10 cm dick. Ziel oben rechts. +`,rP=`// Labyrinth: Gänge 30 cm breit, Wände 10 cm dick. Ziel oben rechts. ........... .........Z. ........... @@ -63319,7 +63325,7 @@ Z.... ........... .>......... ........... -`,rj=`// Linienfolger: Die Linie biegt nach rechts ab und endet vor der Wand. +`,oP=`// Linienfolger: Die Linie biegt nach rechts ab und endet vor der Wand. ######### ......... ......... @@ -63334,7 +63340,7 @@ Z.... ......... ..^...... linie: 2,12 2,8 4,5 4,0.6 -`,oj=`// Linienfolger: Die Linie biegt nach links ab und endet vor der Wand. +`,lP=`// Linienfolger: Die Linie biegt nach links ab und endet vor der Wand. ######### ......... ......... @@ -63349,7 +63355,7 @@ linie: 2,12 2,8 4,5 4,0.6 ......... ......^.. linie: 6,12 6,8 4,5 4,0.6 -`,lj=`// Linienfolger mit Stopp: Am Ende der Linie liegt ein rotes Feld. +`,uP=`// Linienfolger mit Stopp: Am Ende der Linie liegt ein rotes Feld. ......... .....r... .....o... @@ -63363,7 +63369,7 @@ linie: 6,12 6,8 4,5 4,0.6 ......... ..^...... linie: 2,11 2,8 5,4 5,1.5 -`,uj=`// Linienfolger mit Stopp: Die Linie schlängelt sich zum roten Feld. +`,cP=`// Linienfolger mit Stopp: Die Linie schlängelt sich zum roten Feld. ........... ...r....... ...o....... @@ -63379,7 +63385,7 @@ linie: 2,11 2,8 5,4 5,1.5 ........... .......^... linie: 7,13 7,10 5,8 5,7 3,5 3,1.5 -`,cj=`// Einparken: rechts parken Autos (Klötze), die blaue Markierung zeigt die Lücke. +`,mP=`// Einparken: rechts parken Autos (Klötze), die blaue Markierung zeigt die Lücke. #....#### #....#### #....#### @@ -63392,7 +63398,7 @@ linie: 7,13 7,10 5,8 5,7 3,5 3,1.5 #....#### #....#### #..^.#### -`,mj=`// Einparken: Die Lücke liegt weiter vorn. +`,dP=`// Einparken: Die Lücke liegt weiter vorn. #....#### #..b....# #.....o.# @@ -63405,14 +63411,14 @@ linie: 7,13 7,10 5,8 5,7 3,5 3,1.5 #....#### #....#### #..^.#### -`,dj=`// Bis zur Linie: der schwarze Rand ist nah +`,hP=`// Bis zur Linie: der schwarze Rand ist nah ..... ===== ..... ..... ..^.. ..... -`,hj=`// Bis zur Linie: der schwarze Rand ist weiter weg +`,gP=`// Bis zur Linie: der schwarze Rand ist weiter weg ..... ===== ..... @@ -63422,17 +63428,17 @@ linie: 7,13 7,10 5,8 5,7 3,5 3,1.5 ..... ..^.. ..... -`,gj=`// Slalom: ein Zeichen = 30 cm. Vier Pylonen, abwechselnd oben und unten herum, Ziel am Ende. +`,pP=`// Slalom: ein Zeichen = 30 cm. Vier Pylonen, abwechselnd oben und unten herum, Ziel am Ende. raster: 3 ......... >#.#.#.#Z ......... -`,pj=`// Tunnelsucher (nach Kara): Halt im ersten Feld mit Wand links UND rechts (hellgrün). Ein Zeichen = 30 cm. +`,fP=`// Tunnelsucher (nach Kara): Halt im ersten Feld mit Wand links UND rechts (hellgrün). Ein Zeichen = 30 cm. raster: 3 ..#..###. >....o... ....##### -`,fj=`// Tunnelsucher, nach oben. Ein Zeichen = 30 cm. +`,bP=`// Tunnelsucher, nach oben. Ein Zeichen = 30 cm. raster: 3 .#.#. .#o#. @@ -63440,12 +63446,12 @@ raster: 3 .#... ..... ..^.. -`,bj=`// Kleeblatt im Wald (nach Kara): Bäume liegen auf dem Weg zum Ziel, nie zwei nebeneinander. Ein Zeichen = 30 cm. +`,xP=`// Kleeblatt im Wald (nach Kara): Bäume liegen auf dem Weg zum Ziel, nie zwei nebeneinander. Ein Zeichen = 30 cm. raster: 3 .......... >..#.#..#Z .......... -`,xj=`// Kleeblatt im Wald, nach oben. Ein Zeichen = 30 cm. +`,vP=`// Kleeblatt im Wald, nach oben. Ein Zeichen = 30 cm. raster: 3 .Z. .#. @@ -63454,7 +63460,7 @@ raster: 3 ... ... .^. -`,vj=`// Wand vorn? Vor dem mBot2 ist viel Platz. +`,yP=`// Wand vorn? Vor dem mBot2 ist viel Platz. ##### ..... ..... @@ -63464,14 +63470,14 @@ raster: 3 ..... ..^.. ..... -`,yj=`// Bis zur Wand: kurzer Weg +`,wP=`// Bis zur Wand: kurzer Weg ##### ..... ..Z.. ..... ..... ..^.. -`,wj=`// Bis zur Wand: langer Weg +`,zP=`// Bis zur Wand: langer Weg ##### ..... ..Z.. @@ -63487,7 +63493,7 @@ raster: 3 ..... ..... ..^.. -`,zj=`// Bis zur Wand: mittlerer Weg +`,IP=`// Bis zur Wand: mittlerer Weg ##### ..... ..Z.. @@ -63498,26 +63504,26 @@ raster: 3 ..... ..... ..^.. -`,Ij=`// Wand vorn? Die Wand steht direkt vor dem mBot2. +`,kP=`// Wand vorn? Die Wand steht direkt vor dem mBot2. ##### ..... ..^.. ..... -`,kj=`// Zwei Sekunden mit halber Kraft: Wo bleibt er stehen? +`,SP=`// Zwei Sekunden mit halber Kraft: Wo bleibt er stehen? ..... ..... ..... ..o.. ..... ..^.. -`,Sj=`// Fahre bis zum Ziel: kurzer Weg, keine Wand +`,TP=`// Fahre bis zum Ziel: kurzer Weg, keine Wand ..... ..Z.. ..... ..... ..^.. ..... -`,Tj=`// Fahre bis zum Ziel: langer Weg, keine Wand +`,_P=`// Fahre bis zum Ziel: langer Weg, keine Wand ..... ..Z.. ..... @@ -63530,37 +63536,37 @@ raster: 3 ..... ..^.. ..... -`,_j=""+new URL("aufgabe-mehrwertsteuer-C-TFTrWz.svg",import.meta.url).href,Oj=""+new URL("ben-shneiderman-Cev5hrqS.jpg",import.meta.url).href,Aj=""+new URL("caesar-ascii-Bix93F5i.svg",import.meta.url).href,Cj=""+new URL("caesar-scheibe-CMRPZI6Y.svg",import.meta.url).href,Pj=""+new URL("caesar-verschiebung-DIR-lDbs.svg",import.meta.url).href,jj=""+new URL("aufgabe-mehrwertsteuer-CnrZ00ny.svg",import.meta.url).href,Dj=""+new URL("kino-saal-C8zaJk4X.svg",import.meta.url).href,Bj=""+new URL("kino-schleifen-D7sfo9iK.svg",import.meta.url).href,Zj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDkyIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iNDkyIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiPgogICAgPCEtLSBTdGFydCAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMTAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjgiIHJ4PSIxNCIgZmlsbD0iI2QxZjJkOSIvPgogICAgPGxpbmUgeDE9IjE1MCIgeTE9IjM4IiB4Mj0iMTUwIiB5Mj0iNTQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gQW53ZWlzdW5nIC0tPgogICAgPHJlY3QgeD0iNTAiIHk9IjU2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iODYiIHgyPSIxNTAiIHkyPSI5OCIgbWFya2VyLWVuZD0idXJsKCNhKSIvPgogICAgPCEtLSBSYXV0ZSAxIC0tPgogICAgPHBhdGggZD0iTTE1MCAxMDAgTDIzNSAxMjggTDE1MCAxNTYgTDY1IDEyOCBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMTU2IiB4Mj0iMTUwIiB5Mj0iMTcyIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8cmVjdCB4PSI1MCIgeT0iMTc0IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMjA0IiB4Mj0iMTUwIiB5Mj0iMjUwIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIG5laW4tV2VnIHVtIGRlbiBLYXN0ZW4gaGVydW0gLS0+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIyMzUsMTI4IDI4NSwxMjggMjg1LDIyMiAxNTAsMjIyIiBmaWxsPSJub25lIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIFJhdXRlIDIgLS0+CiAgICA8cGF0aCBkPSJNMTUwIDI1MiBMMjM1IDI4MCBMMTUwIDMwOCBMNjUgMjgwIFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxsaW5lIHgxPSIyMzUiIHkxPSIyODAiIHgyPSIyNjgiIHkyPSIyODAiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjI3MCIgeT0iMjY1IiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8IS0tIHp1csO8Y2sgenVyIFByw7xmdW5nIC0tPgogICAgPHBvbHlsaW5lIHBvaW50cz0iMzI3LDI2NSAzMjcsMjM4IDE1MCwyMzgiIGZpbGw9Im5vbmUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzMDgiIHgyPSIxNTAiIHkyPSIzMjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjUwIiB5PSIzMjgiIHdpZHRoPSIyMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNlNWYwZmYiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzNTgiIHgyPSIxNTAiIHkyPSIzNzQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gRW5kZSAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjI4IiByeD0iMTQiIGZpbGw9IiNkMWYyZDkiLz4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSI+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI5Ij5TdGFydDwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iNzYiPlB1dCBhIGN1cCBvbiB0aGUgdGFibGU8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjEzMyI+U3VnYXIgd2FudGVkPzwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTk0Ij5BZGQgc3VnYXI8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI4NSI+VGVhIHN0aWxsIHRvbyBob3Q/PC90ZXh0PgogICAgPHRleHQgeD0iMzI3LjUiIHk9IjI4NSI+V2FpdCAxIG1pbnV0ZTwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzQ4Ij5EcmluayB0aGUgdGVhPC90ZXh0PgogICAgPHRleHQgeD0iMTUwIiB5PSIzOTUiPkVuZDwvdGV4dD4KICA8L2c+CiAgPGcgZm9udC1zaXplPSIxMiIgZm9udC13ZWlnaHQ9IjYwMCI+CiAgICA8dGV4dCB4PSIxNTYiIHk9IjE2OCIgZmlsbD0iIzI0OGEzZCI+eWVzPC90ZXh0PgogICAgPHRleHQgeD0iMjQyIiB5PSIxMjIiIGZpbGw9IiNkNzAwMTUiPm5vPC90ZXh0PgogICAgPHRleHQgeD0iMjQwIiB5PSIyNzQiIGZpbGw9IiMyNDhhM2QiPnllczwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1NiIgeT0iMzIwIiBmaWxsPSIjZDcwMDE1Ij5ubzwvdGV4dD4KICA8L2c+CiAgPCEtLSBMZWdlbmRlIC0tPgogIDxsaW5lIHgxPSIxMCIgeTE9IjQxOCIgeDI9IjM5MCIgeTI9IjQxOCIgc3Ryb2tlPSIjZDFkMWQ2Ii8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuNSI+CiAgICA8cmVjdCB4PSI0MCIgeT0iNDMwIiB3aWR0aD0iMzYiIGhlaWdodD0iMTgiIHJ4PSI5IiBmaWxsPSIjZDFmMmQ5Ii8+CiAgICA8cmVjdCB4PSIyMjAiIHk9IjQzMCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjE4IiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8cGF0aCBkPSJNNTggNDU4IEw3NiA0NjkgTDU4IDQ4MCBMNDAgNDY5IFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxwYXRoIGQ9Ik0yMjYgNDYwIEwyNTYgNDYwIEwyNTAgNDc4IEwyMjAgNDc4IFoiIGZpbGw9IiNmMmU2ZmYiLz4KICA8L2c+CiAgPGcgZm9udC1zaXplPSIxMiIgZmlsbD0iIzNhM2EzYyI+CiAgICA8dGV4dCB4PSI4NiIgeT0iNDQzIj5TdGFydCBvciBlbmQ8L3RleHQ+CiAgICA8dGV4dCB4PSIyNjYiIHk9IjQ0MyI+U3RhdGVtZW50PC90ZXh0PgogICAgPHRleHQgeD0iODYiIHk9IjQ3MyI+RGVjaXNpb248L3RleHQ+CiAgICA8dGV4dCB4PSIyNjYiIHk9IjQ3MyI+SW5wdXQgb3Igb3V0cHV0PC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",Mj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE5MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwIiB5PSIyNCIgZm9udC13ZWlnaHQ9IjYwMCI+V2hlcmUgZG9lcyB0aGUgZWxlbWVudCBsYW5kPzwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iNDAiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkYmVhZmUiLz4KICA8cmVjdCB4PSIyMCIgeT0iNzUiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkY2ZjZTciLz4KICA8bGluZSB4MT0iMjAiIHkxPSI3NSIgeDI9IjIxMCIgeTI9Ijc1IiBzdHJva2U9IiM2ZTZlNzMiIHN0cm9rZS1kYXNoYXJyYXk9IjQgMyIvPgogIDxyZWN0IHg9IjIwIiB5PSI0MCIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjYyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMWQ0ZWQ4Ij50b3AgaGFsZjwvdGV4dD4KICA8dGV4dCB4PSIxMTUiIHk9Ijk3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMTU4MDNkIj5ib3R0b20gaGFsZjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9IjYyIj7ihpIgZ29lcyA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+aW4gZnJvbnQ8L3RzcGFuPjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9Ijk3Ij7ihpIgZ29lcyA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+YWZ0ZXI8L3RzcGFuPjwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iMTMyIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjExNSIgeT0iMTU3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2Ij7DuDwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9IjE1NyI+4oaSIDx0c3BhbiBmb250LXdlaWdodD0iNjAwIj5yZXBsYWNlczwvdHNwYW4+IGl0PC90ZXh0Pgo8L3N2Zz4K",Lj=""+new URL("l03-lochkarte-beschriftet-BjBFZjzb.svg",import.meta.url).href,Ej=""+new URL("l03-lochkarte-BB3rWQOm.svg",import.meta.url).href,Wj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgMjcwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CjxyZWN0IHdpZHRoPSI0NjAiIGhlaWdodD0iMjcwIiBmaWxsPSIjZmZmZmZmIi8+Cjx0ZXh0IHg9IjYyIiB5PSI0NCIgZm9udC1zaXplPSI0MCIgZmlsbD0iIzZlNmU3MyIgdGV4dExlbmd0aD0iMjg4IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmdBbmRHbHlwaHMiPnByaWNlPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPlc8L3RzcGFuPml0aDx0c3BhbiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj5UPC90c3Bhbj5heDwvdGV4dD4KPGxpbmUgeDE9IjE5NCIgeTE9IjU0IiB4Mj0iMTk0IiB5Mj0iODQiIHN0cm9rZT0iIzAwN2FmZiIgc3Ryb2tlLXdpZHRoPSIyLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNCIvPgo8bGluZSB4MT0iMjkwIiB5MT0iNTQiIHgyPSIyOTAiIHkyPSI4NCIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSA0Ii8+CjxwYXRoIGQ9Ik0xNDYgMTg1IEwxNDIgMjE0IEwxNDYgMjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNjOTk5NWIiIHN0cm9rZS13aWR0aD0iMTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTY2IDE4NSBMMTcwIDIxNCBMMTY2IDI0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjEwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTMxOSAxODUgTDMxNSAyMTQgTDMxOSAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2M5OTk1YiIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0zMzkgMTg1IEwzNDMgMjE0IEwzMzkgMjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTI2IDE1MCBDMTEwIDE2MCAxMTAgMTg1IDExOCAxOTgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSI0IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTEzNCAxOTIgQzExOCAxNzggMTE4IDE0NiAxNDAgMTQwIEMxNTggMTM4IDE2NCA4NiAxOTQgODYgQzIyNCA4NiAyMjQgMTM2IDI0MiAxMzQgQzI2MCAxMzYgMjYwIDg2IDI5MCA4NiBDMzIwIDg2IDMxOCAxMzYgMzM1IDE0MCBDMzU1IDE0MiAzNjMgMTE4IDM2OSAxMDAgQzM3MyA4NiAzODMgODAgMzk3IDgwIEM0MTEgODAgNDE5IDg2IDQyMSA5NCBDNDIzIDEwMiA0MTEgMTA2IDM5NSAxMDYgQzM4NyAxMzAgMzc3IDE2OCAzNTMgMTg2IEMyNzIgMjA2IDIxMiAyMDYgMTM0IDE5MiBaIiBmaWxsPSIjYzk5OTViIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0zODUgODQgTDM4MSA3MiBMMzkyIDgxIFoiIGZpbGw9IiNjOTk5NWIiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxjaXJjbGUgY3g9IjQwMyIgY3k9IjkwIiByPSIzLjIiIGZpbGw9IiMxYzFjMWUiLz4KPHBhdGggZD0iTTQxMyAxMDAgUTQxNyAxMDIgNDIwIDk5IiBmaWxsPSJub25lIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0zMCAyNDIgSDQzMCIgc3Ryb2tlPSIjZDFkMWQ2IiBzdHJva2Utd2lkdGg9IjMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K",Nj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjEwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIxMCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjE2Ij5pbnQgYWdlID0gMTQ8L3RleHQ+CiAgPHBhdGggZD0iTTEzMCA3MCBMMTcwIDUwIEwzMDAgNTAgTDI2MCA3MCBaIiBmaWxsPSIjYzk4YTNjIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjE4MCIgeT0iMzQiIHdpZHRoPSI0NCIgaGVpZ2h0PSI1MCIgcng9IjMiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KICA8dGV4dCB4PSIyMDIiIHk9IjYwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjIwIiBmb250LXdlaWdodD0iNzAwIj4xNDwvdGV4dD4KICA8cmVjdCB4PSIxMzAiIHk9IjcwIiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iI2U5Yjg3MiIgc3Ryb2tlPSIjOGE1YTFmIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8cGF0aCBkPSJNMjYwIDcwIEwzMDAgNTAgTDMwMCAxNTAgTDI2MCAxNzAgWiIgZmlsbD0iI2Q0OWE0YyIgc3Ryb2tlPSIjOGE1YTFmIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8cmVjdCB4PSIxNTAiIHk9IjEwMCIgd2lkdGg9IjkwIiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjOGE1YTFmIi8+CiAgPHRleHQgeD0iMTk1IiB5PSIxMjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPmFnZTwvdGV4dD4KICA8cmVjdCB4PSIxMzgiIHk9IjE0MiIgd2lkdGg9IjM0IiBoZWlnaHQ9IjIwIiByeD0iMTAiIGZpbGw9IiMwMDdhZmYiLz4KICA8dGV4dCB4PSIxNTUiIHk9IjE1NiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMiIgZmlsbD0iI2ZmZmZmZiIgZm9udC13ZWlnaHQ9IjYwMCI+aW50PC90ZXh0PgogIDxnIHN0cm9rZT0iIzZlNmU3MyI+CiAgICA8bGluZSB4MT0iMzEwIiB5MT0iNDgiIHgyPSIyMjYiIHkyPSI1MiIvPgogICAgPGxpbmUgeDE9IjMxMCIgeTE9IjExNSIgeDI9IjI0MiIgeTI9IjExNSIvPgogICAgPGxpbmUgeDE9IjgwIiB5MT0iMTUyIiB4Mj0iMTM0IiB5Mj0iMTUyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjMxNiIgeT0iNTIiPlZhbHVlPC90ZXh0PgogIDx0ZXh0IHg9IjMxNiIgeT0iMTE5Ij5OYW1lPC90ZXh0PgogIDx0ZXh0IHg9IjgiIHk9IjE1NiI+RGF0YSB0eXBlPC90ZXh0PgogIDx0ZXh0IHg9IjIwMCIgeT0iMTk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5UaGUgbmFtZSBnZXRzIHlvdSB0byB0aGUgdmFsdWUuPC90ZXh0Pgo8L3N2Zz4K",Fj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiPgogICAgPHRleHQgeD0iNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+cG9pbnRzPC90ZXh0PgogICAgPHRleHQgeD0iMTI1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPj08L3RleHQ+CiAgICA8dGV4dCB4PSIyNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9pbnRzICsgNTwvdGV4dD4KICA8L2c+CiAgPHJlY3QgeD0iMTgwIiB5PSI4NiIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjYwIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPuKRoCB3b3JrIG91dCB0aGUgcmlnaHQ6IDEwICsgNSA9IDE1PC90ZXh0PgogIDxwYXRoIGQ9Ik0yNTAgODIgQzIzMCAzMCwgOTAgMzAsIDY0IDg0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgPHRleHQgeD0iMTYwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiI+4pGhIHN0b3JlIHRoZSByZXN1bHQgb24gdGhlIGxlZnQ8L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjE2NCIgd2lkdGg9IjM2MCIgaGVpZ2h0PSIyNiIgcng9IjYiIGZpbGw9IiNmMmYyZjciLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE4MiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9pbnRzIGJlZm9yZTogPHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiPjEwPC90c3Bhbj4gICDihpIgICBwb2ludHMgYWZ0ZXI6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xNTwvdHNwYW4+PC90ZXh0Pgo8L3N2Zz4K",Jj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjYwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjYwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiPgogICAgPHBhdGggZD0iTTQwIDExMCBMNDggMTgwIEwxMDIgMTgwIEwxMTAgMTEwIi8+CiAgICA8cGF0aCBkPSJNMTY1IDExMCBMMTczIDE4MCBMMjI3IDE4MCBMMjM1IDExMCIvPgogICAgPHBhdGggZD0iTTI5MCAxMTAgTDI5OCAxODAgTDM1MiAxODAgTDM2MCAxMTAiLz4KICA8L2c+CiAgPHBhdGggZD0iTTQ0IDEzNSBMNDggMTgwIEwxMDIgMTgwIEwxMDYgMTM1IFoiIGZpbGw9IiNmZGJhNzQiLz4KICA8cGF0aCBkPSJNMjk0IDEzNSBMMjk4IDE4MCBMMzUyIDE4MCBMMzU2IDEzNSBaIiBmaWxsPSIjOTNjNWZkIi8+CiAgPHRleHQgeD0iNzUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+bGVmdDwvdGV4dD4KICA8dGV4dCB4PSI3NSIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5qdWljZTwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+dGVtcDwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+ZW1wdHk8L3RleHQ+CiAgPHRleHQgeD0iMzI1IiB5PSIyMDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPnJpZ2h0PC90ZXh0PgogIDx0ZXh0IHg9IjMyNSIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj53YXRlcjwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxwYXRoIGQ9Ik04OCAxMDQgQzExMCA3MCwgMTYwIDcwLCAxODYgMTA0Ii8+CiAgICA8cGF0aCBkPSJNMzE4IDEwNCBDMjcwIDE1LCAxMzAgMTUsIDgyIDEwNCIvPgogICAgPHBhdGggZD0iTTIxNCAxMDQgQzI0MCA3MCwgMjkwIDcwLCAzMTIgMTA0Ii8+CiAgPC9nPgogIDxnIGZvbnQtd2VpZ2h0PSI3MDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPGNpcmNsZSBjeD0iMTM3IiBjeT0iODAiIHI9IjExIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz48dGV4dCB4PSIxMzciIHk9Ijg1Ij4xPC90ZXh0PgogICAgPGNpcmNsZSBjeD0iMjAwIiBjeT0iMzgiIHI9IjExIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz48dGV4dCB4PSIyMDAiIHk9IjQzIj4yPC90ZXh0PgogICAgPGNpcmNsZSBjeD0iMjYzIiBjeT0iODAiIHI9IjExIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz48dGV4dCB4PSIyNjMiIHk9Ijg1Ij4zPC90ZXh0PgogIDwvZz4KICA8ZyB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxMiI+CiAgICA8dGV4dCB4PSI3MCIgeT0iMjQ3Ij4xOiB0ZW1wID0gbGVmdDwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMjQ3Ij4yOiBsZWZ0ID0gcmlnaHQ8L3RleHQ+CiAgICA8dGV4dCB4PSIzMzAiIHk9IjI0NyI+MzogcmlnaHQgPSB0ZW1wPC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",Rj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDxyZWN0IHg9IjIwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+PHJlY3QgeD0iMzEwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+CiAgPHJlY3QgeD0iOTAiIHk9IjUwIiB3aWR0aD0iMjIwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZGNmY2U3Ii8+CiAgPGxpbmUgeDE9IjIwIiB5MT0iNzQiIHgyPSIzODAiIHkyPSI3NCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8bGluZSB4MT0iNDYiIHkxPSI2OCIgeDI9IjQ2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iNDYiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4wPC90ZXh0PgogIDxsaW5lIHgxPSI5MCIgeTE9IjY4IiB4Mj0iOTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjE8L3RleHQ+CiAgPGxpbmUgeDE9IjEzNCIgeTE9IjY4IiB4Mj0iMTM0IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTM0IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MjwvdGV4dD4KICA8bGluZSB4MT0iMTc4IiB5MT0iNjgiIHgyPSIxNzgiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIxNzgiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4zPC90ZXh0PgogIDxsaW5lIHgxPSIyMjIiIHkxPSI2OCIgeDI9IjIyMiIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjIyMiIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjQ8L3RleHQ+CiAgPGxpbmUgeDE9IjI2NiIgeTE9IjY4IiB4Mj0iMjY2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjY2IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NTwvdGV4dD4KICA8bGluZSB4MT0iMzEwIiB5MT0iNjgiIHgyPSIzMTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIzMTAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj42PC90ZXh0PgogIDxsaW5lIHgxPSIzNTQiIHkxPSI2OCIgeDI9IjM1NCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjM1NCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjc8L3RleHQ+CiAgPGNpcmNsZSBjeD0iOTAiIGN5PSI3NCIgcj0iNiIgZmlsbD0iIzE1ODAzZCIvPjxjaXJjbGUgY3g9IjMxMCIgY3k9Ijc0IiByPSI2IiBmaWxsPSIjMTU4MDNkIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dmFsaWQ8L3RleHQ+CiAgPHRleHQgeD0iNDAiIHk9IjQwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5pbnZhbGlkPC90ZXh0Pjx0ZXh0IHg9IjM2MCIgeT0iNDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPmludmFsaWQ8L3RleHQ+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPHRleHQgeD0iMjAwIiB5PSIxMjQiIGZpbGw9IiMxNTgwM2QiPmdyYWRlICZndDs9IDEgJmFtcDsmYW1wOyBncmFkZSAmbHQ7PSA2PC90ZXh0PgogICAgPHRleHQgeD0iMjAwIiB5PSIxNDIiIGZpbGw9IiNiOTFjMWMiPmdyYWRlICZsdDsgMSB8fCBncmFkZSAmZ3Q7IDY8L3RleHQ+CiAgPC9nPgo8L3N2Zz4K",Gj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIj5Ib3cgdGhlIHdoaWxlIGxvb3AgcnVuczwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjQ0IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjQwIiByeD0iMjAiIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI2OSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIGNoZWNrIHRoZSBjb25kaXRpb248L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSIxMjgiIHdpZHRoPSIxNjAiIGhlaWdodD0iNDAiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTUzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgcnVuIHRoZSBpbnNpZGU8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iODQiIHgyPSIyMDAiIHkyPSIxMjYiLz4KICAgIDxwYXRoIGQ9Ik0xMjAgMTQ4IEM4MCAxNDgsIDgwIDY0LCAxMTggNjQiLz4KICAgIDxwYXRoIGQ9Ik0yODAgNjQgTDM0MCA2NCBMMzQwIDIwMCBMMjgyIDIwMCIvPgogIDwvZz4KICA8dGV4dCB4PSIyMDgiIHk9IjExMCIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dHJ1ZTwvdGV4dD4KICA8dGV4dCB4PSIzOCIgeT0iMTEwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5iYWNrPC90ZXh0PgogIDx0ZXh0IHg9IjM4IiB5PSIxMjYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPnRvIHRoZSB0b3A8L3RleHQ+CiAgPHRleHQgeD0iMzQ4IiB5PSIxMzQiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPmZhbHNlPC90ZXh0PgogIDx0ZXh0IHg9IjI3NiIgeT0iMjA1IiB0ZXh0LWFuY2hvcj0iZW5kIj5jb250aW51ZSBiZWxvdyB0aGUgbG9vcDwvdGV4dD4KPC9zdmc+Cg==",Hj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+cHJlLXRlc3QgKHdoaWxlKTwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9IjIyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iNjAwIj5wb3N0LXRlc3QgKGRvLXdoaWxlKTwvdGV4dD4KICA8bGluZSB4MT0iMjAwIiB5MT0iMTAiIHgyPSIyMDAiIHkyPSIyMjAiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxyZWN0IHg9IjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iNjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCBjb25kaXRpb248L3RleHQ+CiAgPHJlY3QgeD0iMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIxNDciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoSBpbnNpZGU8L3RleHQ+CiAgPHJlY3QgeD0iMjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIGluc2lkZTwvdGV4dD4KICA8cmVjdCB4PSIyMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjMwMCIgeT0iMTQ3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgY29uZGl0aW9uPC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiPgogICAgPGxpbmUgeDE9IjEwMCIgeTE9IjgwIiB4Mj0iMTAwIiB5Mj0iMTIyIi8+CiAgICA8cGF0aCBkPSJNMzUgMTQyIEM4IDE0MiwgOCA2MiwgMzMgNjIiLz4KICAgIDxsaW5lIHgxPSIzMDAiIHkxPSI4MCIgeDI9IjMwMCIgeTI9IjEyMiIvPgogICAgPHBhdGggZD0iTTM2NSAxNDIgQzM5MiAxNDIsIDM5MiA2MiwgMzY3IDYyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjEwNiIgeT0iMTA2IiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTA2IiB0ZXh0LWFuY2hvcj0iZW5kIiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5JZiB0aGUgY29uZGl0aW9uIGlzIGZhbHNlIGF0IG9uY2UsPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj50aGUgaW5zaWRlIHJ1bnMgPHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPm5ldmVyPC90c3Bhbj4uPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5UaGUgaW5zaWRlIGFsd2F5cyBydW5zPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj48dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+YXQgbGVhc3Qgb25jZTwvdHNwYW4+LjwvdGV4dD4KPC9zdmc+Cg==",Vj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjUwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHJlY3QgeD0iMTIwIiB5PSIxNCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIFN0YXJ0IDx0c3BhbiBmaWxsPSIjNmU2ZTczIj4ob25seSBvbmNlKTwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iNzYiIHdpZHRoPSIxNjAiIGhlaWdodD0iMzQiIHJ4PSIxNyIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjYjQ1MzA5IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgY2hlY2sgdGhlIGNvbmRpdGlvbjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjEzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIxNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoiBydW4gdGhlIGluc2lkZTwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjIwMCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIyMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoyBzdGVwLCBlLmcuIGkrKzwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjIwMCIgeTI9Ijc0Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTEwIiB4Mj0iMjAwIiB5Mj0iMTM2Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTcyIiB4Mj0iMjAwIiB5Mj0iMTk4Ii8+CiAgICA8cGF0aCBkPSJNMTIwIDIxNyBDNjAgMjE3LCA2MCA5MywgMTE4IDkzIi8+CiAgICA8cGF0aCBkPSJNMjgwIDkzIEwzMzAgOTMiLz4KICA8L2c+CiAgPHRleHQgeD0iMjA4IiB5PSIxMjkiIGZpbGw9IiMxNTgwM2QiIGZvbnQtd2VpZ2h0PSI2MDAiPnRydWU8L3RleHQ+CiAgPHRleHQgeD0iNDgiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+YmFjazwvdGV4dD4KICA8dGV4dCB4PSI0OCIgeT0iMTc2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj50byDikaE8L3RleHQ+CiAgPHRleHQgeD0iMzAwIiB5PSI4NCIgZmlsbD0iI2I5MWMxYyIgZm9udC13ZWlnaHQ9IjYwMCI+ZmFsc2U8L3RleHQ+CiAgPHRleHQgeD0iMzM2IiB5PSI5OCI+ZG9uZTwvdGV4dD4KPC9zdmc+Cg==",qj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMTkwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCI+aW50W10gbnVtYmVycyA9IHsyLCA0LCA2LCA4LCAxMH08L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjU0IiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj5JbmRleDwvdGV4dD4KICA8dGV4dCB4PSI5MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjA8L3RleHQ+PHJlY3QgeD0iNjAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iOTAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj4yPC90ZXh0PgogIDx0ZXh0IHg9IjE1MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjE8L3RleHQ+PHJlY3QgeD0iMTIwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjE1MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjQ8L3RleHQ+CiAgPHRleHQgeD0iMjEwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MjwvdGV4dD48cmVjdCB4PSIxODAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjEwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+NjwvdGV4dD4KICA8dGV4dCB4PSIyNzAiIHk9IjU0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj4zPC90ZXh0PjxyZWN0IHg9IjI0MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyNzAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj44PC90ZXh0PgogIDx0ZXh0IHg9IjMzMCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjQ8L3RleHQ+PHJlY3QgeD0iMzAwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjMzMCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjEwPC90ZXh0PgogIDx0ZXh0IHg9IjIwIiB5PSI5MCIgZmlsbD0iIzZlNmU3MyIgZm9udC1zaXplPSIxMiI+VmFsdWU8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+PGxpbmUgeDE9IjkwIiB5MT0iMTQwIiB4Mj0iOTAiIHkyPSIxMTIiLz48bGluZSB4MT0iMzMwIiB5MT0iMTQwIiB4Mj0iMzMwIiB5Mj0iMTEyIi8+PC9nPgogIDxnIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjEzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dGV4dCB4PSI5MCIgeT0iMTU2Ij5udW1iZXJzWzBdIGlzIDI8L3RleHQ+PHRleHQgeD0iMzMwIiB5PSIxNTYiPm51bWJlcnNbNF0gaXMgMTA8L3RleHQ+PC9nPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTgyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj41IHNsb3RzLCBjb3VudGluZyBzdGFydHMgYXQgMDogdGhlIGxhc3QgaW5kZXggaXMgNC48L3RleHQ+Cjwvc3ZnPgo=",Qj=""+new URL("mvc-klick-BIA_bYzu.svg",import.meta.url).href,Uj=""+new URL("ss-binaere-suche-D02W1TH_.svg",import.meta.url).href,$j=""+new URL("ss-bubblesort-CmKEoNfO.svg",import.meta.url).href,Yj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDQgMTk2IiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KPHJlY3Qgd2lkdGg9IjQwNCIgaGVpZ2h0PSIxOTYiIGZpbGw9IiNmZmZmZmYiLz4KPHRleHQgeD0iMTQiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIiBmb250LXNpemU9IjE1Ij5Mb29raW5nIGZvciB0aGUgOS4gVGhlIGNhcmRzIGFyZSBtaXhlZCB1cC48L3RleHQ+CjxnPjxyZWN0IHg9IjE0IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48dGV4dCB4PSIzNC4wIiB5PSI3NS4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZGMyNjI2Ij43PC90ZXh0Pjx0ZXh0IHg9IjM0LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjZGMyNjI2Ij7imaU8L3RleHQ+PC9nPgo8dGV4dCB4PSIzNC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMzQuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj4xLjwvdGV4dD4KPGc+PHJlY3QgeD0iNjIiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjgyLjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjM8L3RleHQ+PHRleHQgeD0iODIuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiMxYzFjMWUiPuKZoDwvdGV4dD48L2c+Cjx0ZXh0IHg9IjgyLjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSI4Mi4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjIuPC90ZXh0Pgo8Zz48cmVjdCB4PSIxMTAiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjEzMC4wIiB5PSI3NS4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZGMyNjI2Ij4xMDwvdGV4dD48dGV4dCB4PSIxMzAuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNkYzI2MjYiPuKZpjwvdGV4dD48L2c+Cjx0ZXh0IHg9IjEzMC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMTMwLjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+My48L3RleHQ+CjxnPjxyZWN0IHg9IjE1OCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iMTc4LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjU8L3RleHQ+PHRleHQgeD0iMTc4LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxYzFlIj7imaM8L3RleHQ+PC9nPgo8dGV4dCB4PSIxNzguMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZGMyNjI2Ij7inJc8L3RleHQ+Cjx0ZXh0IHg9IjE3OC4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjQuPC90ZXh0Pgo8Zz48cmVjdCB4PSIyMDYiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiMxNTgwM2QiIHN0cm9rZS13aWR0aD0iMyIvPjx0ZXh0IHg9IjIyNi4wIiB5PSI3NS4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjMWMxYzFlIj45PC90ZXh0Pjx0ZXh0IHg9IjIyNi4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+4pmgPC90ZXh0PjwvZz4KPHRleHQgeD0iMjI2LjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iIzE1ODAzZCI+4pyTPC90ZXh0Pgo8dGV4dCB4PSIyMjYuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj41LjwvdGV4dD4KPGc+PHJlY3QgeD0iMjU0IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iIzFkNGVkOCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSIyNTgiIHk9IjU0IiB3aWR0aD0iMzIiIGhlaWdodD0iNDgiIHJ4PSIzIiBmaWxsPSJub25lIiBzdHJva2U9IiM5M2M1ZmQiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtZGFzaGFycmF5PSIzIDIiLz48L2c+CjxnPjxyZWN0IHg9IjMwMiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiMxZDRlZDgiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHJlY3QgeD0iMzA2IiB5PSI1NCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjQ4IiByeD0iMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTNjNWZkIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWRhc2hhcnJheT0iMyAyIi8+PC9nPgo8Zz48cmVjdCB4PSIzNTAiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjMWQ0ZWQ4IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjxyZWN0IHg9IjM1NCIgeT0iNTQiIHdpZHRoPSIzMiIgaGVpZ2h0PSI0OCIgcng9IjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzkzYzVmZCIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMiIvPjwvZz4KPHRleHQgeD0iMTQiIHk9IjE2OCIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzZlNmU3MyI+VHVybiB0aGVtIG92ZXIgZnJvbSBsZWZ0IHRvIHJpZ2h0OjwvdGV4dD48dGV4dCB4PSIxNCIgeT0iMTg4IiBmb250LXNpemU9IjE1IiBmaWxsPSIjNmU2ZTczIj5BZnRlciA1IGNvbXBhcmlzb25zIHRoZSA5IGlzIGZvdW5kLjwvdGV4dD4KPC9zdmc+Cg==",Xj=""+new URL("ss-vergleiche-UczNldcC.svg",import.meta.url).href,Kj="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjAgNDUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KPGRlZnM+PG1hcmtlciBpZD0iayIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDEwIDUgTDAgMTAgWiIgZmlsbD0iIzFjMWMxZSIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImIiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjYiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNMCAwIEwxMCA1IEwwIDEwIFoiIGZpbGw9IiMxZDRlZDgiLz48L21hcmtlcj48bWFya2VyIGlkPSJvIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjYjQ1MzA5Ii8+PC9tYXJrZXI+PC9kZWZzPgo8cmVjdCB3aWR0aD0iNDIwIiBoZWlnaHQ9IjQ1MCIgZmlsbD0iI2ZmZmZmZiIvPgo8dGV4dCB4PSIxMCIgeT0iMjIiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI3MDAiPkNhbGwgYnkgdmFsdWU6IGEgY29weTwvdGV4dD4KPHJlY3QgeD0iMTAiIHk9IjM4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9Ijg2IiByeD0iOCIgZmlsbD0iI2VmZjZmZiIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8dGV4dCB4PSIyMCIgeT0iNTgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPk1haW4gcHJvZ3JhbTwvdGV4dD4KPHRleHQgeD0iMTYiIHk9Ijk4IiBmb250LXNpemU9IjEyIj5udW1iZXI8L3RleHQ+CjxyZWN0IHg9IjcwIiB5PSI3OCIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9Ijk4IiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+NTwvdGV4dD4KPHJlY3QgeD0iMjUwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNmZmY3ZWQiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjYwIiB5PSI1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+ZG91YmxlSXQ8L3RleHQ+Cjx0ZXh0IHg9IjI2MCIgeT0iOTgiPng8L3RleHQ+CjxyZWN0IHg9IjI4MCIgeT0iNzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMCIgcng9IjQiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8dGV4dCB4PSIzMjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dHNwYW4gZmlsbD0iIzZlNmU3MyIgdGV4dC1kZWNvcmF0aW9uPSJsaW5lLXRocm91Z2giPjU8L3RzcGFuPiA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCI+MTA8L3RzcGFuPjwvdGV4dD4KPGxpbmUgeDE9IjEyOCIgeTE9IjkzIiB4Mj0iMjQ4IiB5Mj0iOTMiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNCIgbWFya2VyLWVuZD0idXJsKCNrKSIvPgo8dGV4dCB4PSIyMTAiIHk9Ijg0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5jb3B5PC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iMTUwIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj54IGJlY29tZXMgMTAsIGJ1dCBudW1iZXIgc3RheXMgNS48L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxNjgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPkxpa2UgYSBwaG90b2NvcHk6IHdyaXRpbmcgb24gdGhlIGNvcHk8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxODYiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPmRvZXMgbm90IGNoYW5nZSB0aGUgb3JpZ2luYWwuPC90ZXh0Pgo8bGluZSB4MT0iMTAiIHkxPSIyMDgiIHgyPSI0MTAiIHkyPSIyMDgiIHN0cm9rZT0iI2QxZDFkNiIvPgo8dGV4dCB4PSIxMCIgeT0iMjM2IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNzAwIj5DYWxsIGJ5IHJlZmVyZW5jZTogdGhlIHNhbWUgYXJyYXk8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZWZmNmZmIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjIwIiB5PSIyNzIiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPk1haW4gcHJvZ3JhbTwvdGV4dD4KPHRleHQgeD0iMjAiIHk9IjMwMCI+cm93PC90ZXh0Pgo8Y2lyY2xlIGN4PSIxNTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiMxZDRlZDgiLz4KPHJlY3QgeD0iMjUwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZmZmN2VkIiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjI2MCIgeT0iMjcyIiBmb250LXNpemU9IjEzIiBmaWxsPSIjYjQ1MzA5Ij5jbGVhcjwvdGV4dD4KPHRleHQgeD0iMjYwIiB5PSIzMDAiPnNlYXRzPC90ZXh0Pgo8Y2lyY2xlIGN4PSIzOTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiNiNDUzMDkiLz4KPHBhdGggZD0iTTE1MCAzMDAgTDE1MCAzNDAgTDE0MCAzNTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYikiLz4KPHBhdGggZD0iTTM5MCAzMDAgTDM5MCAzNDAgTDMyMiAzNTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjbykiLz4KPHJlY3QgeD0iOTAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHJlY3QgeD0iMTUwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+CjxyZWN0IHg9IjIxMCIgeT0iMzU4IiB3aWR0aD0iNjAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8cmVjdCB4PSIyNzAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHRleHQgeD0iMTIwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxODAiIHk9IjM3OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+ZmFsc2U8L3RleHQ+Cjx0ZXh0IHg9IjI0MCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMzAwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iNDE2IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj5UaGVyZSBpcyBvbmx5IG9uZSBhcnJheS4gV2hhdCBjbGVhciBjaGFuZ2VzIHRocm91Z2ggc2VhdHMsPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iNDM0IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj50aGUgbWFpbiBwcm9ncmFtIHNlZXMgdW5kZXIgcm93LjwvdGV4dD4KPC9zdmc+Cg==",eD=""+new URL("zk-zeichen-CgUEhNoK.svg",import.meta.url).href,tD=""+new URL("ike-nassi-D2w47gvX.jpg",import.meta.url).href,nD=""+new URL("kino-saal-CYMOok4_.svg",import.meta.url).href,iD=""+new URL("kino-schleifen-DrTQV7dq.svg",import.meta.url).href,aD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDkyIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iNDkyIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiPgogICAgPCEtLSBTdGFydCAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMTAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjgiIHJ4PSIxNCIgZmlsbD0iI2QxZjJkOSIvPgogICAgPGxpbmUgeDE9IjE1MCIgeTE9IjM4IiB4Mj0iMTUwIiB5Mj0iNTQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gQW53ZWlzdW5nIC0tPgogICAgPHJlY3QgeD0iNTAiIHk9IjU2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iODYiIHgyPSIxNTAiIHkyPSI5OCIgbWFya2VyLWVuZD0idXJsKCNhKSIvPgogICAgPCEtLSBSYXV0ZSAxIC0tPgogICAgPHBhdGggZD0iTTE1MCAxMDAgTDIzNSAxMjggTDE1MCAxNTYgTDY1IDEyOCBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMTU2IiB4Mj0iMTUwIiB5Mj0iMTcyIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8cmVjdCB4PSI1MCIgeT0iMTc0IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMjA0IiB4Mj0iMTUwIiB5Mj0iMjUwIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIG5laW4tV2VnIHVtIGRlbiBLYXN0ZW4gaGVydW0gLS0+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIyMzUsMTI4IDI4NSwxMjggMjg1LDIyMiAxNTAsMjIyIiBmaWxsPSJub25lIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIFJhdXRlIDIgLS0+CiAgICA8cGF0aCBkPSJNMTUwIDI1MiBMMjM1IDI4MCBMMTUwIDMwOCBMNjUgMjgwIFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxsaW5lIHgxPSIyMzUiIHkxPSIyODAiIHgyPSIyNjgiIHkyPSIyODAiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjI3MCIgeT0iMjY1IiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8IS0tIHp1csO8Y2sgenVyIFByw7xmdW5nIC0tPgogICAgPHBvbHlsaW5lIHBvaW50cz0iMzI3LDI2NSAzMjcsMjM4IDE1MCwyMzgiIGZpbGw9Im5vbmUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzMDgiIHgyPSIxNTAiIHkyPSIzMjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjUwIiB5PSIzMjgiIHdpZHRoPSIyMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNlNWYwZmYiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzNTgiIHgyPSIxNTAiIHkyPSIzNzQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gRW5kZSAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjI4IiByeD0iMTQiIGZpbGw9IiNkMWYyZDkiLz4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSI+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI5Ij5TdGFydDwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iNzYiPlRhc3NlIGF1ZiBkZW4gVGlzY2ggc3RlbGxlbjwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTMzIj5adWNrZXIgZ2V3w7xuc2NodD88L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjE5NCI+WnVja2VyIGhpbmVpbmdlYmVuPC90ZXh0PgogICAgPHRleHQgeD0iMTUwIiB5PSIyODUiPlRlZSBub2NoIHp1IGhlacOfPzwvdGV4dD4KICAgIDx0ZXh0IHg9IjMyNy41IiB5PSIyODUiPjEgTWludXRlIHdhcnRlbjwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzQ4Ij5UZWUgdHJpbmtlbjwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzk1Ij5FbmRlPC90ZXh0PgogIDwvZz4KICA8ZyBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNjAwIj4KICAgIDx0ZXh0IHg9IjE1NiIgeT0iMTY4IiBmaWxsPSIjMjQ4YTNkIj5qYTwvdGV4dD4KICAgIDx0ZXh0IHg9IjI0MiIgeT0iMTIyIiBmaWxsPSIjZDcwMDE1Ij5uZWluPC90ZXh0PgogICAgPHRleHQgeD0iMjQwIiB5PSIyNzQiIGZpbGw9IiMyNDhhM2QiPmphPC90ZXh0PgogICAgPHRleHQgeD0iMTU2IiB5PSIzMjAiIGZpbGw9IiNkNzAwMTUiPm5laW48L3RleHQ+CiAgPC9nPgogIDwhLS0gTGVnZW5kZSAtLT4KICA8bGluZSB4MT0iMTAiIHkxPSI0MTgiIHgyPSIzOTAiIHkyPSI0MTgiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxnIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjUiPgogICAgPHJlY3QgeD0iNDAiIHk9IjQzMCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjE4IiByeD0iOSIgZmlsbD0iI2QxZjJkOSIvPgogICAgPHJlY3QgeD0iMjIwIiB5PSI0MzAiIHdpZHRoPSIzNiIgaGVpZ2h0PSIxOCIgZmlsbD0iI2U1ZjBmZiIvPgogICAgPHBhdGggZD0iTTU4IDQ1OCBMNzYgNDY5IEw1OCA0ODAgTDQwIDQ2OSBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8cGF0aCBkPSJNMjI2IDQ2MCBMMjU2IDQ2MCBMMjUwIDQ3OCBMMjIwIDQ3OCBaIiBmaWxsPSIjZjJlNmZmIi8+CiAgPC9nPgogIDxnIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiMzYTNhM2MiPgogICAgPHRleHQgeD0iODYiIHk9IjQ0MyI+U3RhcnQgb2RlciBFbmRlPC90ZXh0PgogICAgPHRleHQgeD0iMjY2IiB5PSI0NDMiPkFud2Vpc3VuZzwvdGV4dD4KICAgIDx0ZXh0IHg9Ijg2IiB5PSI0NzMiPlZlcnp3ZWlndW5nPC90ZXh0PgogICAgPHRleHQgeD0iMjY2IiB5PSI0NzMiPkVpbi0gb2RlciBBdXNnYWJlPC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",sD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE5MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwIiB5PSIyNCIgZm9udC13ZWlnaHQ9IjYwMCI+V29oaW4gbGFuZGV0IGRhcyBFbGVtZW50PzwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iNDAiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkYmVhZmUiLz4KICA8cmVjdCB4PSIyMCIgeT0iNzUiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkY2ZjZTciLz4KICA8bGluZSB4MT0iMjAiIHkxPSI3NSIgeDI9IjIxMCIgeTI9Ijc1IiBzdHJva2U9IiM2ZTZlNzMiIHN0cm9rZS1kYXNoYXJyYXk9IjQgMyIvPgogIDxyZWN0IHg9IjIwIiB5PSI0MCIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjYyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMWQ0ZWQ4Ij5vYmVyZSBIw6RsZnRlPC90ZXh0PgogIDx0ZXh0IHg9IjExNSIgeT0iOTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPnVudGVyZSBIw6RsZnRlPC90ZXh0PgogIDx0ZXh0IHg9IjIyNCIgeT0iNjIiPuKGkiBrb21tdCA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+ZGF2b3I8L3RzcGFuPjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9Ijk3Ij7ihpIga29tbXQgPHRzcGFuIGZvbnQtd2VpZ2h0PSI2MDAiPmRhaGludGVyPC90c3Bhbj48L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjEzMiIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI0MCIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjE1NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiI+w7g8L3RleHQ+CiAgPHRleHQgeD0iMjI0IiB5PSIxNTciPuKGkiA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+ZXJzZXR6dDwvdHNwYW4+IGRlbiBQbGF0emhhbHRlcjwvdGV4dD4KPC9zdmc+Cg==",rD=""+new URL("l03-lochkarte-beschriftet-7hmU_7ct.svg",import.meta.url).href,oD=""+new URL("l03-lochkarte-gzfFEatc.svg",import.meta.url).href,lD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgMjcwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CjxyZWN0IHdpZHRoPSI0NjAiIGhlaWdodD0iMjcwIiBmaWxsPSIjZmZmZmZmIi8+Cjx0ZXh0IHg9IjYyIiB5PSI0NCIgZm9udC1zaXplPSI0MCIgZmlsbD0iIzZlNmU3MyIgdGV4dExlbmd0aD0iMzM2IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmdBbmRHbHlwaHMiPnByZWlzPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPk08L3RzcGFuPml0PHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPlM8L3RzcGFuPnRldWVyPC90ZXh0Pgo8bGluZSB4MT0iMTk0IiB5MT0iNTQiIHgyPSIxOTQiIHkyPSI4NCIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSA0Ii8+CjxsaW5lIHgxPSIyNjYiIHkxPSI1NCIgeDI9IjI2NiIgeTI9Ijg0IiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtZGFzaGFycmF5PSI1IDQiLz4KPHBhdGggZD0iTTE0NiAxODUgTDE0MiAyMTQgTDE0NiAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2M5OTk1YiIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xNjYgMTg1IEwxNzAgMjE0IEwxNjYgMjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMjk1IDE4NSBMMjkxIDIxNCBMMjk1IDI0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzk5OTViIiBzdHJva2Utd2lkdGg9IjEwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTMxNSAxODUgTDMxOSAyMTQgTDMxNSAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xMjYgMTUwIEMxMTAgMTYwIDExMCAxODUgMTE4IDE5OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTM0IDE5MiBDMTE4IDE3OCAxMTggMTQ2IDE0MCAxNDAgQzE1OCAxMzggMTY0IDg2IDE5NCA4NiBDMjI0IDg2IDIyNCAxMzYgMjMwIDEzNCBDMjM2IDEzNiAyMzYgODYgMjY2IDg2IEMyOTYgODYgMjk0IDEzNiAzMTEgMTQwIEMzMzEgMTQyIDMzOSAxMTggMzQ1IDEwMCBDMzQ5IDg2IDM1OSA4MCAzNzMgODAgQzM4NyA4MCAzOTUgODYgMzk3IDk0IEMzOTkgMTAyIDM4NyAxMDYgMzcxIDEwNiBDMzYzIDEzMCAzNTMgMTY4IDMyOSAxODYgQzI2MCAyMDYgMjAwIDIwNiAxMzQgMTkyIFoiIGZpbGw9IiNjOTk5NWIiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyLjUiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTM2MSA4NCBMMzU3IDcyIEwzNjggODEgWiIgZmlsbD0iI2M5OTk1YiIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPGNpcmNsZSBjeD0iMzc5IiBjeT0iOTAiIHI9IjMuMiIgZmlsbD0iIzFjMWMxZSIvPgo8cGF0aCBkPSJNMzg5IDEwMCBRMzkzIDEwMiAzOTYgOTkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTMwIDI0MiBINDMwIiBzdHJva2U9IiNkMWQxZDYiIHN0cm9rZS13aWR0aD0iMyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=",uD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjYwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CiAgPHJlY3Qgd2lkdGg9IjQwMCIgaGVpZ2h0PSIyNjAiIGZpbGw9IiNmZmZmZmYiLz4KICA8IS0tIERhbXBmIC0tPgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2I4YjhjMCIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbGluZWNhcD0icm91bmQiPgogICAgPHBhdGggZD0iTTE2MCA5MiBDMTQ1IDcyIDE3NSA2MiAxNjAgNDIgQzE1MCAyOCAxNjIgMTggMTY4IDEyIi8+CiAgICA8cGF0aCBkPSJNMTk1IDkwIEMxODAgNjggMjEyIDU4IDE5NiAzNiBDMTg2IDIyIDE5OCAxMiAyMDQgNiIvPgogICAgPHBhdGggZD0iTTIzMCA5MiBDMjE1IDcyIDI0NSA2MiAyMzAgNDIgQzIyMCAyOCAyMzIgMTggMjM4IDEyIi8+CiAgPC9nPgogIDwhLS0gVW50ZXJ0YXNzZSAtLT4KICA8ZWxsaXBzZSBjeD0iMTk1IiBjeT0iMjI2IiByeD0iMTM1IiByeT0iMTgiIGZpbGw9IiNlNWU1ZWEiIHN0cm9rZT0iI2FlYWViMiIgc3Ryb2tlLXdpZHRoPSIyLjUiLz4KICA8IS0tIEhlbmtlbCAtLT4KICA8cGF0aCBkPSJNMjYyIDEzMiBDMzA1IDEyOCAzMTIgMTkwIDI1OCAxOTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2E2NTMyYiIgc3Ryb2tlLXdpZHRoPSIxNiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CiAgPCEtLSBUYXNzZSAtLT4KICA8cGF0aCBkPSJNMTIwIDEwOCBIMjcwIFYxNzggQzI3MCAyMDUgMjQ4IDIyMiAyMjAgMjIyIEgxNzAgQzE0MiAyMjIgMTIwIDIwNSAxMjAgMTc4IFoiIGZpbGw9IiNjODY3M2EiIHN0cm9rZT0iI2E2NTMyYiIgc3Ryb2tlLXdpZHRoPSIzIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CiAgPGVsbGlwc2UgY3g9IjE5NSIgY3k9IjEwOCIgcng9Ijc1IiByeT0iMTMiIGZpbGw9IiM1YjNhMjQiIHN0cm9rZT0iI2E2NTMyYiIgc3Ryb2tlLXdpZHRoPSIzIi8+CiAgPGVsbGlwc2UgY3g9IjE4MCIgY3k9IjEwNiIgcng9IjIyIiByeT0iNCIgZmlsbD0iIzdhNTIzNiIvPgogIDwhLS0gQ29kZSBhdWYgZGVyIFRhc3NlIC0tPgogIDx0ZXh0IHg9IjE5NSIgeT0iMTc4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjQwIiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZmZmZmZmIj57IH08L3RleHQ+Cjwvc3ZnPgo=",cD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjEwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIxMCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjE2Ij5pbnQgYWx0ZXIgPSAxNDwvdGV4dD4KICA8cGF0aCBkPSJNMTMwIDcwIEwxNzAgNTAgTDMwMCA1MCBMMjYwIDcwIFoiIGZpbGw9IiNjOThhM2MiIHN0cm9rZT0iIzhhNWExZiIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHJlY3QgeD0iMTgwIiB5PSIzNCIgd2lkdGg9IjQ0IiBoZWlnaHQ9IjUwIiByeD0iMyIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjEuNSIvPgogIDx0ZXh0IHg9IjIwMiIgeT0iNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI3MDAiPjE0PC90ZXh0PgogIDxyZWN0IHg9IjEzMCIgeT0iNzAiIHdpZHRoPSIxMzAiIGhlaWdodD0iMTAwIiBmaWxsPSIjZTliODcyIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxwYXRoIGQ9Ik0yNjAgNzAgTDMwMCA1MCBMMzAwIDE1MCBMMjYwIDE3MCBaIiBmaWxsPSIjZDQ5YTRjIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjE1MCIgeT0iMTAwIiB3aWR0aD0iOTAiIGhlaWdodD0iMzAiIHJ4PSI0IiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiM4YTVhMWYiLz4KICA8dGV4dCB4PSIxOTUiIHk9IjEyMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+YWx0ZXI8L3RleHQ+CiAgPHJlY3QgeD0iMTM4IiB5PSIxNDIiIHdpZHRoPSIzNCIgaGVpZ2h0PSIyMCIgcng9IjEwIiBmaWxsPSIjMDA3YWZmIi8+CiAgPHRleHQgeD0iMTU1IiB5PSIxNTYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiNmZmZmZmYiIGZvbnQtd2VpZ2h0PSI2MDAiPmludDwvdGV4dD4KICA8ZyBzdHJva2U9IiM2ZTZlNzMiPgogICAgPGxpbmUgeDE9IjMxMCIgeTE9IjQ4IiB4Mj0iMjI2IiB5Mj0iNTIiLz4KICAgIDxsaW5lIHgxPSIzMTAiIHkxPSIxMTUiIHgyPSIyNDIiIHkyPSIxMTUiLz4KICAgIDxsaW5lIHgxPSI4MCIgeTE9IjE1MiIgeDI9IjEzNCIgeTI9IjE1MiIvPgogIDwvZz4KICA8dGV4dCB4PSIzMTYiIHk9IjUyIj5XZXJ0PC90ZXh0PgogIDx0ZXh0IHg9IjMxNiIgeT0iMTE5Ij5OYW1lPC90ZXh0PgogIDx0ZXh0IHg9IjgiIHk9IjE1NiI+RGF0ZW50eXA8L3RleHQ+CiAgPHRleHQgeD0iMjAwIiB5PSIxOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPsOcYmVyIGRlbiBOYW1lbiBrb21tc3QgZHUgYW4gZGVuIFdlcnQuPC90ZXh0Pgo8L3N2Zz4K",mD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiPgogICAgPHRleHQgeD0iNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+cHVua3RlPC90ZXh0PgogICAgPHRleHQgeD0iMTI1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPj08L3RleHQ+CiAgICA8dGV4dCB4PSIyNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cHVua3RlICsgNTwvdGV4dD4KICA8L2c+CiAgPHJlY3QgeD0iMTgwIiB5PSI4NiIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjYwIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPuKRoCByZWNodHMgYXVzcmVjaG5lbjogMTAgKyA1ID0gMTU8L3RleHQ+CiAgPHBhdGggZD0iTTI1MCA4MiBDMjMwIDMwLCA5MCAzMCwgNjQgODQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwN2FmZiIgc3Ryb2tlLXdpZHRoPSIyLjUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICA8dGV4dCB4PSIxNjAiIHk9IjM2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIj7ikaEgRXJnZWJuaXMgbGlua3Mgc3BlaWNoZXJuPC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSIxNjQiIHdpZHRoPSIzNjAiIGhlaWdodD0iMjYiIHJ4PSI2IiBmaWxsPSIjZjJmMmY3Ii8+CiAgPHRleHQgeD0iMjAwIiB5PSIxODIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPnB1bmt0ZSB2b3JoZXI6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xMDwvdHNwYW4+ICAg4oaSICAgcHVua3RlIG5hY2hoZXI6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xNTwvdHNwYW4+PC90ZXh0Pgo8L3N2Zz4K",dD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjYwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjYwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiPgogICAgPHBhdGggZD0iTTQwIDExMCBMNDggMTgwIEwxMDIgMTgwIEwxMTAgMTEwIi8+CiAgICA8cGF0aCBkPSJNMTY1IDExMCBMMTczIDE4MCBMMjI3IDE4MCBMMjM1IDExMCIvPgogICAgPHBhdGggZD0iTTI5MCAxMTAgTDI5OCAxODAgTDM1MiAxODAgTDM2MCAxMTAiLz4KICA8L2c+CiAgPHBhdGggZD0iTTQ0IDEzNSBMNDggMTgwIEwxMDIgMTgwIEwxMDYgMTM1IFoiIGZpbGw9IiNmZGJhNzQiLz4KICA8cGF0aCBkPSJNMjk0IDEzNSBMMjk4IDE4MCBMMzUyIDE4MCBMMzU2IDEzNSBaIiBmaWxsPSIjOTNjNWZkIi8+CiAgPHRleHQgeD0iNzUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+bGlua3M8L3RleHQ+CiAgPHRleHQgeD0iNzUiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+U2FmdDwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+aGlsZjwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+bGVlcjwvdGV4dD4KICA8dGV4dCB4PSIzMjUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+cmVjaHRzPC90ZXh0PgogIDx0ZXh0IHg9IjMyNSIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5XYXNzZXI8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8cGF0aCBkPSJNODggMTA0IEMxMTAgNzAsIDE2MCA3MCwgMTg2IDEwNCIvPgogICAgPHBhdGggZD0iTTMxOCAxMDQgQzI3MCAxNSwgMTMwIDE1LCA4MiAxMDQiLz4KICAgIDxwYXRoIGQ9Ik0yMTQgMTA0IEMyNDAgNzAsIDI5MCA3MCwgMzEyIDEwNCIvPgogIDwvZz4KICA8ZyBmb250LXdlaWdodD0iNzAwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4KICAgIDxjaXJjbGUgY3g9IjEzNyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMTM3IiB5PSI4NSI+MTwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjIwMCIgY3k9IjM4IiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjAwIiB5PSI0MyI+MjwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjI2MyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjYzIiB5PSI4NSI+MzwvdGV4dD4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTIiPgogICAgPHRleHQgeD0iNzAiIHk9IjI0NyI+MTogaGlsZiA9IGxpbmtzPC90ZXh0PgogICAgPHRleHQgeD0iMjAwIiB5PSIyNDciPjI6IGxpbmtzID0gcmVjaHRzPC90ZXh0PgogICAgPHRleHQgeD0iMzMwIiB5PSIyNDciPjM6IHJlY2h0cyA9IGhpbGY8L3RleHQ+CiAgPC9nPgo8L3N2Zz4K",hD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDxyZWN0IHg9IjIwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+PHJlY3QgeD0iMzEwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+CiAgPHJlY3QgeD0iOTAiIHk9IjUwIiB3aWR0aD0iMjIwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZGNmY2U3Ii8+CiAgPGxpbmUgeDE9IjIwIiB5MT0iNzQiIHgyPSIzODAiIHkyPSI3NCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8bGluZSB4MT0iNDYiIHkxPSI2OCIgeDI9IjQ2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iNDYiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4wPC90ZXh0PgogIDxsaW5lIHgxPSI5MCIgeTE9IjY4IiB4Mj0iOTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjE8L3RleHQ+CiAgPGxpbmUgeDE9IjEzNCIgeTE9IjY4IiB4Mj0iMTM0IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTM0IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MjwvdGV4dD4KICA8bGluZSB4MT0iMTc4IiB5MT0iNjgiIHgyPSIxNzgiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIxNzgiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4zPC90ZXh0PgogIDxsaW5lIHgxPSIyMjIiIHkxPSI2OCIgeDI9IjIyMiIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjIyMiIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjQ8L3RleHQ+CiAgPGxpbmUgeDE9IjI2NiIgeTE9IjY4IiB4Mj0iMjY2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjY2IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NTwvdGV4dD4KICA8bGluZSB4MT0iMzEwIiB5MT0iNjgiIHgyPSIzMTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIzMTAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj42PC90ZXh0PgogIDxsaW5lIHgxPSIzNTQiIHkxPSI2OCIgeDI9IjM1NCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjM1NCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjc8L3RleHQ+CiAgPGNpcmNsZSBjeD0iOTAiIGN5PSI3NCIgcj0iNiIgZmlsbD0iIzE1ODAzZCIvPjxjaXJjbGUgY3g9IjMxMCIgY3k9Ijc0IiByPSI2IiBmaWxsPSIjMTU4MDNkIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+Z8O8bHRpZzwvdGV4dD4KICA8dGV4dCB4PSI0MCIgeT0iNDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPnVuZ8O8bHRpZzwvdGV4dD48dGV4dCB4PSIzNjAiIHk9IjQwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj51bmfDvGx0aWc8L3RleHQ+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPHRleHQgeD0iMjAwIiB5PSIxMjQiIGZpbGw9IiMxNTgwM2QiPm5vdGUgJmd0Oz0gMSAmYW1wOyZhbXA7IG5vdGUgJmx0Oz0gNjwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMTQyIiBmaWxsPSIjYjkxYzFjIj5ub3RlICZsdDsgMSB8fCBub3RlICZndDsgNjwvdGV4dD4KICA8L2c+Cjwvc3ZnPgo=",gD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDAgMTkwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+CiAgPHJlY3Qgd2lkdGg9IjQ0MCIgaGVpZ2h0PSIxOTAiIGZpbGw9IiNmZmZmZmYiLz4KICA8cmVjdCB4PSIyMCIgeT0iMTQiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iNjAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPmE8L3RleHQ+CiAgPHJlY3QgeD0iMTAwIiB5PSIxNCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIxNDAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPmI8L3RleHQ+CiAgPHJlY3QgeD0iMTgwIiB5PSIxNCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIyMjAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPmEgJmFtcDsmYW1wOyBiPC90ZXh0PgogIDxyZWN0IHg9IjI2MCIgeT0iMTQiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzAwLjAiIHk9IjM1IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iNzAwIj5hIHx8IGI8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSIxNCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIzODAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPiFhPC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSI0NiIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSI2MC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIxMDAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjE0MC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIxODAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjIyMC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIyNjAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjMwMC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIzNDAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjM4MC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9Ijc4IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjYwLjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMTU4MDNkIj50cnVlPC90ZXh0PgogIDxyZWN0IHg9IjEwMCIgeT0iNzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMTQwLjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIj5mYWxzZTwvdGV4dD4KICA8cmVjdCB4PSIxODAiIHk9Ijc4IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjIyMC4wIiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMjYwIiB5PSI3OCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIzMDAuMCIgeT0iOTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPnRydWU8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSI3OCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmVlMmUyIiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIzODAuMCIgeT0iOTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiPmZhbHNlPC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSIxMTAiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iNjAuMCIgeT0iMTMxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIj5mYWxzZTwvdGV4dD4KICA8cmVjdCB4PSIxMDAiIHk9IjExMCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIxNDAuMCIgeT0iMTMxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMTU4MDNkIj50cnVlPC90ZXh0PgogIDxyZWN0IHg9IjE4MCIgeT0iMTEwIiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjIyMC4wIiB5PSIxMzEiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiPmZhbHNlPC90ZXh0PgogIDxyZWN0IHg9IjI2MCIgeT0iMTEwIiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjMwMC4wIiB5PSIxMzEiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPnRydWU8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSIxMTAiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2RjZmNlNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzgwLjAiIHk9IjEzMSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iMTQyIiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjYwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMTAwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMTQwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMTgwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMjIwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMjYwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzAwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2RjZmNlNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzgwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8bGluZSB4MT0iMTgwIiB5MT0iMTQiIHgyPSIxODAiIHkyPSIxNzQiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIzIi8+Cjwvc3ZnPgo=",pD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIj5BYmxhdWYgZGVyIFdoaWxlLVNjaGxlaWZlPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iNDQiIHdpZHRoPSIxNjAiIGhlaWdodD0iNDAiIHJ4PSIyMCIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjYjQ1MzA5IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjY5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaAgQmVkaW5ndW5nIHByw7xmZW48L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSIxMjgiIHdpZHRoPSIxNjAiIGhlaWdodD0iNDAiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTUzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgSW5oYWx0IGF1c2bDvGhyZW48L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iODQiIHgyPSIyMDAiIHkyPSIxMjYiLz4KICAgIDxwYXRoIGQ9Ik0xMjAgMTQ4IEM4MCAxNDgsIDgwIDY0LCAxMTggNjQiLz4KICAgIDxwYXRoIGQ9Ik0yODAgNjQgTDM0MCA2NCBMMzQwIDIwMCBMMjgyIDIwMCIvPgogIDwvZz4KICA8dGV4dCB4PSIyMDgiIHk9IjExMCIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dHJ1ZTwvdGV4dD4KICA8dGV4dCB4PSIzOCIgeT0iMTEwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj53aWVkZXI8L3RleHQ+CiAgPHRleHQgeD0iMzgiIHk9IjEyNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+bmFjaCBvYmVuPC90ZXh0PgogIDx0ZXh0IHg9IjM0OCIgeT0iMTM0IiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5mYWxzZTwvdGV4dD4KICA8dGV4dCB4PSIyNzYiIHk9IjIwNSIgdGV4dC1hbmNob3I9ImVuZCI+d2VpdGVyIHVudGVyIGRlciBTY2hsZWlmZTwvdGV4dD4KPC9zdmc+Cg==",fD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+a29wZmdlc3RldWVydCAoV2hpbGUpPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPmZ1w59nZXN0ZXVlcnQgKERvLXdoaWxlKTwvdGV4dD4KICA8bGluZSB4MT0iMjAwIiB5MT0iMTAiIHgyPSIyMDAiIHkyPSIyMjAiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxyZWN0IHg9IjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iNjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCBCZWRpbmd1bmc8L3RleHQ+CiAgPHJlY3QgeD0iMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIxNDciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoSBJbmhhbHQ8L3RleHQ+CiAgPHJlY3QgeD0iMjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIEluaGFsdDwvdGV4dD4KICA8cmVjdCB4PSIyMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjMwMCIgeT0iMTQ3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgQmVkaW5ndW5nPC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiPgogICAgPGxpbmUgeDE9IjEwMCIgeTE9IjgwIiB4Mj0iMTAwIiB5Mj0iMTIyIi8+CiAgICA8cGF0aCBkPSJNMzUgMTQyIEM4IDE0MiwgOCA2MiwgMzMgNjIiLz4KICAgIDxsaW5lIHgxPSIzMDAiIHkxPSI4MCIgeDI9IjMwMCIgeTI9IjEyMiIvPgogICAgPHBhdGggZD0iTTM2NSAxNDIgQzM5MiAxNDIsIDM5MiA2MiwgMzY3IDYyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjEwNiIgeT0iMTA2IiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTA2IiB0ZXh0LWFuY2hvcj0iZW5kIiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5Jc3QgZGllIEJlZGluZ3VuZyBnbGVpY2ggZmFsc2UsPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5sw6R1ZnQgZGVyIEluaGFsdCA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+bmllPC90c3Bhbj4uPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5EZXIgSW5oYWx0IGzDpHVmdCBpbW1lcjwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9IjIwNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+PHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPm1pbmRlc3RlbnMgZWlubWFsPC90c3Bhbj4uPC90ZXh0Pgo8L3N2Zz4K",bD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjUwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHJlY3QgeD0iMTIwIiB5PSIxNCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIFN0YXJ0IDx0c3BhbiBmaWxsPSIjNmU2ZTczIj4obnVyIGVpbm1hbCk8L3RzcGFuPjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9Ijc2IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iMTciIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGhIEJlZGluZ3VuZyBwcsO8ZmVuPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iMTM4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iNiIgZmlsbD0iI2RiZWFmZSIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGiIEluaGFsdCBhdXNmw7xocmVuPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iMjAwIiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iNiIgZmlsbD0iI2RjZmNlNyIgc3Ryb2tlPSIjMTU4MDNkIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGjIFNjaHJpdHQsIHouIEIuIGkrKzwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjIwMCIgeTI9Ijc0Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTEwIiB4Mj0iMjAwIiB5Mj0iMTM2Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTcyIiB4Mj0iMjAwIiB5Mj0iMTk4Ii8+CiAgICA8cGF0aCBkPSJNMTIwIDIxNyBDNjAgMjE3LCA2MCA5MywgMTE4IDkzIi8+CiAgICA8cGF0aCBkPSJNMjgwIDkzIEwzMzAgOTMiLz4KICA8L2c+CiAgPHRleHQgeD0iMjA4IiB5PSIxMjkiIGZpbGw9IiMxNTgwM2QiIGZvbnQtd2VpZ2h0PSI2MDAiPnRydWU8L3RleHQ+CiAgPHRleHQgeD0iNDgiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+enVyw7xjazwvdGV4dD4KICA8dGV4dCB4PSI0OCIgeT0iMTc2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj56dSDikaE8L3RleHQ+CiAgPHRleHQgeD0iMzAwIiB5PSI4NCIgZmlsbD0iI2I5MWMxYyIgZm9udC13ZWlnaHQ9IjYwMCI+ZmFsc2U8L3RleHQ+CiAgPHRleHQgeD0iMzM2IiB5PSI5OCI+ZmVydGlnPC90ZXh0Pgo8L3N2Zz4K",xD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMTkwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCI+aW50W10gemFobGVuID0gezIsIDQsIDYsIDgsIDEwfTwvdGV4dD4KICA8dGV4dCB4PSIyMCIgeT0iNTQiIGZpbGw9IiM2ZTZlNzMiIGZvbnQtc2l6ZT0iMTIiPkluZGV4PC90ZXh0PgogIDx0ZXh0IHg9IjkwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MDwvdGV4dD48cmVjdCB4PSI2MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjI8L3RleHQ+CiAgPHRleHQgeD0iMTUwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MTwvdGV4dD48cmVjdCB4PSIxMjAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTUwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+NDwvdGV4dD4KICA8dGV4dCB4PSIyMTAiIHk9IjU0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj4yPC90ZXh0PjxyZWN0IHg9IjE4MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyMTAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj42PC90ZXh0PgogIDx0ZXh0IHg9IjI3MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjM8L3RleHQ+PHJlY3QgeD0iMjQwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjI3MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjg8L3RleHQ+CiAgPHRleHQgeD0iMzMwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+NDwvdGV4dD48cmVjdCB4PSIzMDAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzMwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+MTA8L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjkwIiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj5XZXJ0PC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwN2FmZiIgc3Ryb2tlLXdpZHRoPSIxLjgiIG1hcmtlci1lbmQ9InVybCgjYSkiPjxsaW5lIHgxPSI5MCIgeTE9IjE0MCIgeDI9IjkwIiB5Mj0iMTEyIi8+PGxpbmUgeDE9IjMzMCIgeTE9IjE0MCIgeDI9IjMzMCIgeTI9IjExMiIvPjwvZz4KICA8ZyBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxMyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+PHRleHQgeD0iOTAiIHk9IjE1NiI+emFobGVuWzBdIGlzdCAyPC90ZXh0Pjx0ZXh0IHg9IjMzMCIgeT0iMTU2Ij56YWhsZW5bNF0gaXN0IDEwPC90ZXh0PjwvZz4KICA8dGV4dCB4PSIyMDAiIHk9IjE4MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+NSBGw6RjaGVyLCBnZXrDpGhsdCB3aXJkIGFiIDA6IGRlciBsZXR6dGUgSW5kZXggaXN0IDQuPC90ZXh0Pgo8L3N2Zz4K",vD=""+new URL("mvc-klick-KmFKqxH-.svg",import.meta.url).href,yD=""+new URL("aufgabe-mehrwertsteuer-KUkerRBd.svg",import.meta.url).href,wD=""+new URL("kino-saal-BOvcmdzb.svg",import.meta.url).href,zD=""+new URL("kino-schleifen-Ci9yPnbo.svg",import.meta.url).href,ID="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDkyIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iNDkyIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiPgogICAgPCEtLSBTdGFydCAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMTAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjgiIHJ4PSIxNCIgZmlsbD0iI2QxZjJkOSIvPgogICAgPGxpbmUgeDE9IjE1MCIgeTE9IjM4IiB4Mj0iMTUwIiB5Mj0iNTQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gQW53ZWlzdW5nIC0tPgogICAgPHJlY3QgeD0iNTAiIHk9IjU2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iODYiIHgyPSIxNTAiIHkyPSI5OCIgbWFya2VyLWVuZD0idXJsKCNhKSIvPgogICAgPCEtLSBSYXV0ZSAxIC0tPgogICAgPHBhdGggZD0iTTE1MCAxMDAgTDIzNSAxMjggTDE1MCAxNTYgTDY1IDEyOCBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMTU2IiB4Mj0iMTUwIiB5Mj0iMTcyIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8cmVjdCB4PSI1MCIgeT0iMTc0IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMjA0IiB4Mj0iMTUwIiB5Mj0iMjUwIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIG5laW4tV2VnIHVtIGRlbiBLYXN0ZW4gaGVydW0gLS0+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIyMzUsMTI4IDI4NSwxMjggMjg1LDIyMiAxNTAsMjIyIiBmaWxsPSJub25lIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIFJhdXRlIDIgLS0+CiAgICA8cGF0aCBkPSJNMTUwIDI1MiBMMjM1IDI4MCBMMTUwIDMwOCBMNjUgMjgwIFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxsaW5lIHgxPSIyMzUiIHkxPSIyODAiIHgyPSIyNjgiIHkyPSIyODAiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjI3MCIgeT0iMjY1IiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8IS0tIHp1csO8Y2sgenVyIFByw7xmdW5nIC0tPgogICAgPHBvbHlsaW5lIHBvaW50cz0iMzI3LDI2NSAzMjcsMjM4IDE1MCwyMzgiIGZpbGw9Im5vbmUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzMDgiIHgyPSIxNTAiIHkyPSIzMjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjUwIiB5PSIzMjgiIHdpZHRoPSIyMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNlNWYwZmYiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzNTgiIHgyPSIxNTAiIHkyPSIzNzQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gRW5kZSAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjI4IiByeD0iMTQiIGZpbGw9IiNkMWYyZDkiLz4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSI+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI5Ij5JbsOtY2lvPC90ZXh0PgogICAgPHRleHQgeD0iMTUwIiB5PSI3NiI+UMO0ciB1bWEgY2jDoXZlbmEgbmEgbWVzYTwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTMzIj5RdWVyIGHDp8O6Y2FyPzwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTk0Ij5KdW50YXIgYcOnw7pjYXI8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI4NSI+Q2jDoSBtdWl0byBxdWVudGU/PC90ZXh0PgogICAgPHRleHQgeD0iMzI3LjUiIHk9IjI4NSI+RXNwZXJhciAxIG1pbnV0bzwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzQ4Ij5CZWJlciBvIGNow6E8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjM5NSI+RmltPC90ZXh0PgogIDwvZz4KICA8ZyBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNjAwIj4KICAgIDx0ZXh0IHg9IjE1NiIgeT0iMTY4IiBmaWxsPSIjMjQ4YTNkIj5zaW08L3RleHQ+CiAgICA8dGV4dCB4PSIyNDIiIHk9IjEyMiIgZmlsbD0iI2Q3MDAxNSI+bsOjbzwvdGV4dD4KICAgIDx0ZXh0IHg9IjI0MCIgeT0iMjc0IiBmaWxsPSIjMjQ4YTNkIj5zaW08L3RleHQ+CiAgICA8dGV4dCB4PSIxNTYiIHk9IjMyMCIgZmlsbD0iI2Q3MDAxNSI+bsOjbzwvdGV4dD4KICA8L2c+CiAgPCEtLSBMZWdlbmRlIC0tPgogIDxsaW5lIHgxPSIxMCIgeTE9IjQxOCIgeDI9IjM5MCIgeTI9IjQxOCIgc3Ryb2tlPSIjZDFkMWQ2Ii8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuNSI+CiAgICA8cmVjdCB4PSI0MCIgeT0iNDMwIiB3aWR0aD0iMzYiIGhlaWdodD0iMTgiIHJ4PSI5IiBmaWxsPSIjZDFmMmQ5Ii8+CiAgICA8cmVjdCB4PSIyMjAiIHk9IjQzMCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjE4IiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8cGF0aCBkPSJNNTggNDU4IEw3NiA0NjkgTDU4IDQ4MCBMNDAgNDY5IFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxwYXRoIGQ9Ik0yMjYgNDYwIEwyNTYgNDYwIEwyNTAgNDc4IEwyMjAgNDc4IFoiIGZpbGw9IiNmMmU2ZmYiLz4KICA8L2c+CiAgPGcgZm9udC1zaXplPSIxMiIgZmlsbD0iIzNhM2EzYyI+CiAgICA8dGV4dCB4PSI4NiIgeT0iNDQzIj5JbsOtY2lvIG91IGZpbTwvdGV4dD4KICAgIDx0ZXh0IHg9IjI2NiIgeT0iNDQzIj5JbnN0cnXDp8OjbzwvdGV4dD4KICAgIDx0ZXh0IHg9Ijg2IiB5PSI0NzMiPkRlY2lzw6NvPC90ZXh0PgogICAgPHRleHQgeD0iMjY2IiB5PSI0NzMiPkVudHJhZGEgb3Ugc2HDrWRhPC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",kD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE5MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwIiB5PSIyNCIgZm9udC13ZWlnaHQ9IjYwMCI+T25kZSBmaWNhIG8gZWxlbWVudG8/PC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSI0MCIgd2lkdGg9IjE5MCIgaGVpZ2h0PSIzNSIgZmlsbD0iI2RiZWFmZSIvPgogIDxyZWN0IHg9IjIwIiB5PSI3NSIgd2lkdGg9IjE5MCIgaGVpZ2h0PSIzNSIgZmlsbD0iI2RjZmNlNyIvPgogIDxsaW5lIHgxPSIyMCIgeTE9Ijc1IiB4Mj0iMjEwIiB5Mj0iNzUiIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLWRhc2hhcnJheT0iNCAzIi8+CiAgPHJlY3QgeD0iMjAiIHk9IjQwIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjcwIiBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjExNSIgeT0iNjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxZDRlZDgiPm1ldGFkZSBkZSBjaW1hPC90ZXh0PgogIDx0ZXh0IHg9IjExNSIgeT0iOTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPm1ldGFkZSBkZSBiYWl4bzwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9IjYyIj7ihpIgZmljYSA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+YW50ZXM8L3RzcGFuPjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9Ijk3Ij7ihpIgZmljYSA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+ZGVwb2lzPC90c3Bhbj48L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjEzMiIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI0MCIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjE1NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiI+w7g8L3RleHQ+CiAgPHRleHQgeD0iMjI0IiB5PSIxNTciPuKGkiA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+c3Vic3RpdHVpLW88L3RzcGFuPjwvdGV4dD4KPC9zdmc+Cg==",SD=""+new URL("l03-lochkarte-beschriftet-D1QjqGFo.svg",import.meta.url).href,TD=""+new URL("l03-lochkarte-BSn6oWaS.svg",import.meta.url).href,_D="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgMjcwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CjxyZWN0IHdpZHRoPSI0NjAiIGhlaWdodD0iMjcwIiBmaWxsPSIjZmZmZmZmIi8+Cjx0ZXh0IHg9IjYyIiB5PSI0NCIgZm9udC1zaXplPSI0MCIgZmlsbD0iIzZlNmU3MyIgdGV4dExlbmd0aD0iMjY0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmdBbmRHbHlwaHMiPnByZWNvPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPkM8L3RzcGFuPm9tPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPkk8L3RzcGFuPnZhPC90ZXh0Pgo8bGluZSB4MT0iMTk0IiB5MT0iNTQiIHgyPSIxOTQiIHkyPSI4NCIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSA0Ii8+CjxsaW5lIHgxPSIyNjYiIHkxPSI1NCIgeDI9IjI2NiIgeTI9Ijg0IiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtZGFzaGFycmF5PSI1IDQiLz4KPHBhdGggZD0iTTE0NiAxODUgTDE0MiAyMTQgTDE0NiAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2M5OTk1YiIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xNjYgMTg1IEwxNzAgMjE0IEwxNjYgMjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMjk1IDE4NSBMMjkxIDIxNCBMMjk1IDI0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzk5OTViIiBzdHJva2Utd2lkdGg9IjEwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTMxNSAxODUgTDMxOSAyMTQgTDMxNSAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xMjYgMTUwIEMxMTAgMTYwIDExMCAxODUgMTE4IDE5OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTM0IDE5MiBDMTE4IDE3OCAxMTggMTQ2IDE0MCAxNDAgQzE1OCAxMzggMTY0IDg2IDE5NCA4NiBDMjI0IDg2IDIyNCAxMzYgMjMwIDEzNCBDMjM2IDEzNiAyMzYgODYgMjY2IDg2IEMyOTYgODYgMjk0IDEzNiAzMTEgMTQwIEMzMzEgMTQyIDMzOSAxMTggMzQ1IDEwMCBDMzQ5IDg2IDM1OSA4MCAzNzMgODAgQzM4NyA4MCAzOTUgODYgMzk3IDk0IEMzOTkgMTAyIDM4NyAxMDYgMzcxIDEwNiBDMzYzIDEzMCAzNTMgMTY4IDMyOSAxODYgQzI2MCAyMDYgMjAwIDIwNiAxMzQgMTkyIFoiIGZpbGw9IiNjOTk5NWIiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyLjUiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTM2MSA4NCBMMzU3IDcyIEwzNjggODEgWiIgZmlsbD0iI2M5OTk1YiIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPGNpcmNsZSBjeD0iMzc5IiBjeT0iOTAiIHI9IjMuMiIgZmlsbD0iIzFjMWMxZSIvPgo8cGF0aCBkPSJNMzg5IDEwMCBRMzkzIDEwMiAzOTYgOTkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTMwIDI0MiBINDMwIiBzdHJva2U9IiNkMWQxZDYiIHN0cm9rZS13aWR0aD0iMyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=",OD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjEwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIxMCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjE2Ij5pbnQgaWRhZGUgPSAxNDwvdGV4dD4KICA8cGF0aCBkPSJNMTMwIDcwIEwxNzAgNTAgTDMwMCA1MCBMMjYwIDcwIFoiIGZpbGw9IiNjOThhM2MiIHN0cm9rZT0iIzhhNWExZiIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHJlY3QgeD0iMTgwIiB5PSIzNCIgd2lkdGg9IjQ0IiBoZWlnaHQ9IjUwIiByeD0iMyIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjEuNSIvPgogIDx0ZXh0IHg9IjIwMiIgeT0iNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI3MDAiPjE0PC90ZXh0PgogIDxyZWN0IHg9IjEzMCIgeT0iNzAiIHdpZHRoPSIxMzAiIGhlaWdodD0iMTAwIiBmaWxsPSIjZTliODcyIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxwYXRoIGQ9Ik0yNjAgNzAgTDMwMCA1MCBMMzAwIDE1MCBMMjYwIDE3MCBaIiBmaWxsPSIjZDQ5YTRjIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjE1MCIgeT0iMTAwIiB3aWR0aD0iOTAiIGhlaWdodD0iMzAiIHJ4PSI0IiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiM4YTVhMWYiLz4KICA8dGV4dCB4PSIxOTUiIHk9IjEyMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+aWRhZGU8L3RleHQ+CiAgPHJlY3QgeD0iMTM4IiB5PSIxNDIiIHdpZHRoPSIzNCIgaGVpZ2h0PSIyMCIgcng9IjEwIiBmaWxsPSIjMDA3YWZmIi8+CiAgPHRleHQgeD0iMTU1IiB5PSIxNTYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiNmZmZmZmYiIGZvbnQtd2VpZ2h0PSI2MDAiPmludDwvdGV4dD4KICA8ZyBzdHJva2U9IiM2ZTZlNzMiPgogICAgPGxpbmUgeDE9IjMxMCIgeTE9IjQ4IiB4Mj0iMjI2IiB5Mj0iNTIiLz4KICAgIDxsaW5lIHgxPSIzMTAiIHkxPSIxMTUiIHgyPSIyNDIiIHkyPSIxMTUiLz4KICAgIDxsaW5lIHgxPSI4MCIgeTE9IjE1MiIgeDI9IjEzNCIgeTI9IjE1MiIvPgogIDwvZz4KICA8dGV4dCB4PSIzMTYiIHk9IjUyIj5WYWxvcjwvdGV4dD4KICA8dGV4dCB4PSIzMTYiIHk9IjExOSI+Tm9tZTwvdGV4dD4KICA8dGV4dCB4PSI4IiB5PSIxNTYiPlRpcG8gZGUgZGFkb3M8L3RleHQ+CiAgPHRleHQgeD0iMjAwIiB5PSIxOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPlBlbG8gbm9tZSBjaGVnYXMgYW8gdmFsb3IuPC90ZXh0Pgo8L3N2Zz4K",AD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiPgogICAgPHRleHQgeD0iNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+cG9udG9zPC90ZXh0PgogICAgPHRleHQgeD0iMTI1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPj08L3RleHQ+CiAgICA8dGV4dCB4PSIyNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9udG9zICsgNTwvdGV4dD4KICA8L2c+CiAgPHJlY3QgeD0iMTgwIiB5PSI4NiIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjYwIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPuKRoCBjYWxjdWxhciBhIGRpcmVpdGE6IDEwICsgNSA9IDE1PC90ZXh0PgogIDxwYXRoIGQ9Ik0yNTAgODIgQzIzMCAzMCwgOTAgMzAsIDY0IDg0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgPHRleHQgeD0iMTYwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiI+4pGhIGd1YXJkYXIgbyByZXN1bHRhZG8gw6AgZXNxdWVyZGE8L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjE2NCIgd2lkdGg9IjM2MCIgaGVpZ2h0PSIyNiIgcng9IjYiIGZpbGw9IiNmMmYyZjciLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE4MiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9udG9zIGFudGVzOiA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCI+MTA8L3RzcGFuPiAgIOKGkiAgIHBvbnRvcyBkZXBvaXM6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xNTwvdHNwYW4+PC90ZXh0Pgo8L3N2Zz4K",CD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMzAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMzAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiPgogICAgPHBhdGggZD0iTTQwIDExMCBMNDggMTgwIEwxMDIgMTgwIEwxMTAgMTEwIi8+CiAgICA8cGF0aCBkPSJNMTY1IDExMCBMMTczIDE4MCBMMjI3IDE4MCBMMjM1IDExMCIvPgogICAgPHBhdGggZD0iTTI5MCAxMTAgTDI5OCAxODAgTDM1MiAxODAgTDM2MCAxMTAiLz4KICA8L2c+CiAgPHBhdGggZD0iTTQ0IDEzNSBMNDggMTgwIEwxMDIgMTgwIEwxMDYgMTM1IFoiIGZpbGw9IiNmZGJhNzQiLz4KICA8cGF0aCBkPSJNMjk0IDEzNSBMMjk4IDE4MCBMMzUyIDE4MCBMMzU2IDEzNSBaIiBmaWxsPSIjOTNjNWZkIi8+CiAgPHRleHQgeD0iNzUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+ZXNxdWVyZGE8L3RleHQ+CiAgPHRleHQgeD0iNzUiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+c3VtbzwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+YXV4PC90ZXh0PgogIDx0ZXh0IHg9IjIwMCIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj52YXppbzwvdGV4dD4KICA8dGV4dCB4PSIzMjUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+ZGlyZWl0YTwvdGV4dD4KICA8dGV4dCB4PSIzMjUiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+w6FndWE8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8cGF0aCBkPSJNODggMTA0IEMxMTAgNzAsIDE2MCA3MCwgMTg2IDEwNCIvPgogICAgPHBhdGggZD0iTTMxOCAxMDQgQzI3MCAxNSwgMTMwIDE1LCA4MiAxMDQiLz4KICAgIDxwYXRoIGQ9Ik0yMTQgMTA0IEMyNDAgNzAsIDI5MCA3MCwgMzEyIDEwNCIvPgogIDwvZz4KICA8ZyBmb250LXdlaWdodD0iNzAwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4KICAgIDxjaXJjbGUgY3g9IjEzNyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMTM3IiB5PSI4NSI+MTwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjIwMCIgY3k9IjM4IiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjAwIiB5PSI0MyI+MjwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjI2MyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjYzIiB5PSI4NSI+MzwvdGV4dD4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTIiPgogICAgPHRleHQgeD0iMjAwIiB5PSIyNTAiPjE6IGF1eCA9IGVzcXVlcmRhPC90ZXh0PgogICAgPHRleHQgeD0iMjAwIiB5PSIyNjgiPjI6IGVzcXVlcmRhID0gZGlyZWl0YTwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMjg2Ij4zOiBkaXJlaXRhID0gYXV4PC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",PD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDxyZWN0IHg9IjIwIiB5PSI1MCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+PHJlY3QgeD0iMzAwIiB5PSI1MCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+CiAgPHJlY3QgeD0iMTAwIiB5PSI1MCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyNCIgZmlsbD0iI2RjZmNlNyIvPgogIDxsaW5lIHgxPSIyMCIgeTE9Ijc0IiB4Mj0iMzgwIiB5Mj0iNzQiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPGxpbmUgeDE9IjUwIiB5MT0iNjgiIHgyPSI1MCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjUwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MDwvdGV4dD4KICA8bGluZSB4MT0iMTAwIiB5MT0iNjgiIHgyPSIxMDAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIxMDAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4xPC90ZXh0PgogIDxsaW5lIHgxPSIxNTAiIHkxPSI2OCIgeDI9IjE1MCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjE1MCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjI8L3RleHQ+CiAgPGxpbmUgeDE9IjIwMCIgeTE9IjY4IiB4Mj0iMjAwIiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MzwvdGV4dD4KICA8bGluZSB4MT0iMjUwIiB5MT0iNjgiIHgyPSIyNTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyNTAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj40PC90ZXh0PgogIDxsaW5lIHgxPSIzMDAiIHkxPSI2OCIgeDI9IjMwMCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjMwMCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjU8L3RleHQ+CiAgPGxpbmUgeDE9IjM1MCIgeTE9IjY4IiB4Mj0iMzUwIiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzUwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NjwvdGV4dD4KICA8Y2lyY2xlIGN4PSIxMDAiIGN5PSI3NCIgcj0iNiIgZmlsbD0iIzE1ODAzZCIvPjxjaXJjbGUgY3g9IjMwMCIgY3k9Ijc0IiByPSI2IiBmaWxsPSIjMTU4MDNkIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dsOhbGlkYTwvdGV4dD4KICA8dGV4dCB4PSI1MCIgeT0iNDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPmludsOhbGlkYTwvdGV4dD48dGV4dCB4PSIzNTAiIHk9IjQwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5pbnbDoWxpZGE8L3RleHQ+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPHRleHQgeD0iMjAwIiB5PSIxMjQiIGZpbGw9IiMxNTgwM2QiPm5vdGEgJmd0Oz0gMSAmYW1wOyZhbXA7IG5vdGEgJmx0Oz0gNTwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMTQyIiBmaWxsPSIjYjkxYzFjIj5ub3RhICZsdDsgMSB8fCBub3RhICZndDsgNTwvdGV4dD4KICA8L2c+Cjwvc3ZnPgo=",jD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIj5Db21vIGZ1bmNpb25hIG8gY2ljbG8gd2hpbGU8L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSI0NCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI0MCIgcng9IjIwIiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iNjkiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCB2ZXJpZmljYXIgYSBjb25kacOnw6NvPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iMTI4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjQwIiByeD0iNiIgZmlsbD0iI2RiZWFmZSIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE1MyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGhIGV4ZWN1dGFyIG8gaW50ZXJpb3I8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iODQiIHgyPSIyMDAiIHkyPSIxMjYiLz4KICAgIDxwYXRoIGQ9Ik0xMjAgMTQ4IEM4MCAxNDgsIDgwIDY0LCAxMTggNjQiLz4KICAgIDxwYXRoIGQ9Ik0yODAgNjQgTDM0MCA2NCBMMzQwIDIwMCBMMjgyIDIwMCIvPgogIDwvZz4KICA8dGV4dCB4PSIyMDgiIHk9IjExMCIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dHJ1ZTwvdGV4dD4KICA8dGV4dCB4PSIzOCIgeT0iMTEwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj52b2x0YXI8L3RleHQ+CiAgPHRleHQgeD0iMzgiIHk9IjEyNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+cGFyYSBjaW1hPC90ZXh0PgogIDx0ZXh0IHg9IjM0OCIgeT0iMTM0IiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5mYWxzZTwvdGV4dD4KICA8dGV4dCB4PSIyNzYiIHk9IjIwNSIgdGV4dC1hbmNob3I9ImVuZCI+Y29udGludWFyIHBvciBiYWl4byBkbyBjaWNsbzwvdGV4dD4KPC9zdmc+Cg==",DD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+cHLDqS10ZXN0ZSAod2hpbGUpPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPnDDs3MtdGVzdGUgKGRvLXdoaWxlKTwvdGV4dD4KICA8bGluZSB4MT0iMjAwIiB5MT0iMTAiIHgyPSIyMDAiIHkyPSIyMjAiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxyZWN0IHg9IjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iNjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCBjb25kacOnw6NvPC90ZXh0PgogIDxyZWN0IHg9IjM1IiB5PSIxMjQiIHdpZHRoPSIxMzAiIGhlaWdodD0iMzYiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iMTQ3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgaW50ZXJpb3I8L3RleHQ+CiAgPHJlY3QgeD0iMjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIGludGVyaW9yPC90ZXh0PgogIDxyZWN0IHg9IjIzNSIgeT0iMTI0IiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjM2IiByeD0iMTgiIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSIxNDciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoSBjb25kacOnw6NvPC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiPgogICAgPGxpbmUgeDE9IjEwMCIgeTE9IjgwIiB4Mj0iMTAwIiB5Mj0iMTIyIi8+CiAgICA8cGF0aCBkPSJNMzUgMTQyIEM4IDE0MiwgOCA2MiwgMzMgNjIiLz4KICAgIDxsaW5lIHgxPSIzMDAiIHkxPSI4MCIgeDI9IjMwMCIgeTI9IjEyMiIvPgogICAgPHBhdGggZD0iTTM2NSAxNDIgQzM5MiAxNDIsIDM5MiA2MiwgMzY3IDYyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjEwNiIgeT0iMTA2IiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTA2IiB0ZXh0LWFuY2hvcj0iZW5kIiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5TZSBhIGNvbmRpw6fDo28gZm9yIGxvZ28gZmFsc2EsPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5vIGludGVyaW9yIDx0c3BhbiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjMWMxYzFlIj5udW5jYTwvdHNwYW4+IMOpIGV4ZWN1dGFkby48L3RleHQ+CiAgPHRleHQgeD0iMzAwIiB5PSIxOTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPk8gaW50ZXJpb3Igw6kgc2VtcHJlIGV4ZWN1dGFkbzwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9IjIwNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+PHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPnBlbG8gbWVub3MgdW1hIHZlejwvdHNwYW4+LjwvdGV4dD4KPC9zdmc+Cg==",BD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjUwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHJlY3QgeD0iMTIwIiB5PSIxNCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIEluw61jaW8gPHRzcGFuIGZpbGw9IiM2ZTZlNzMiPihzw7MgdW1hIHZleik8L3RzcGFuPjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9Ijc2IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iMTciIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGhIHZlcmlmaWNhciBhIGNvbmRpw6fDo288L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSIxMzgiIHdpZHRoPSIxNjAiIGhlaWdodD0iMzQiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTYwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaIgZXhlY3V0YXIgbyBpbnRlcmlvcjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjIwMCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIyMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoyBwYXNzbywgcC4gZXguIGkrKzwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjIwMCIgeTI9Ijc0Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTEwIiB4Mj0iMjAwIiB5Mj0iMTM2Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTcyIiB4Mj0iMjAwIiB5Mj0iMTk4Ii8+CiAgICA8cGF0aCBkPSJNMTIwIDIxNyBDNjAgMjE3LCA2MCA5MywgMTE4IDkzIi8+CiAgICA8cGF0aCBkPSJNMjgwIDkzIEwzMzAgOTMiLz4KICA8L2c+CiAgPHRleHQgeD0iMjA4IiB5PSIxMjkiIGZpbGw9IiMxNTgwM2QiIGZvbnQtd2VpZ2h0PSI2MDAiPnRydWU8L3RleHQ+CiAgPHRleHQgeD0iNDgiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+dm9sdGFyPC90ZXh0PgogIDx0ZXh0IHg9IjQ4IiB5PSIxNzYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPmFvIOKRoTwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9Ijg0IiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5mYWxzZTwvdGV4dD4KICA8dGV4dCB4PSIzMzYiIHk9Ijk4Ij5maW08L3RleHQ+Cjwvc3ZnPgo=",ZD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMTkwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCI+aW50W10gbnVtZXJvcyA9IHsyLCA0LCA2LCA4LCAxMH08L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjU0IiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj7DjW5kaWNlPC90ZXh0PgogIDx0ZXh0IHg9IjkwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MDwvdGV4dD48cmVjdCB4PSI2MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjI8L3RleHQ+CiAgPHRleHQgeD0iMTUwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MTwvdGV4dD48cmVjdCB4PSIxMjAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTUwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+NDwvdGV4dD4KICA8dGV4dCB4PSIyMTAiIHk9IjU0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj4yPC90ZXh0PjxyZWN0IHg9IjE4MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyMTAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj42PC90ZXh0PgogIDx0ZXh0IHg9IjI3MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjM8L3RleHQ+PHJlY3QgeD0iMjQwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjI3MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjg8L3RleHQ+CiAgPHRleHQgeD0iMzMwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+NDwvdGV4dD48cmVjdCB4PSIzMDAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzMwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+MTA8L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjkwIiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj5WYWxvcjwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj48bGluZSB4MT0iOTAiIHkxPSIxNDAiIHgyPSI5MCIgeTI9IjExMiIvPjxsaW5lIHgxPSIzMzAiIHkxPSIxNDAiIHgyPSIzMzAiIHkyPSIxMTIiLz48L2c+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjx0ZXh0IHg9IjkwIiB5PSIxNTYiPm51bWVyb3NbMF0gw6kgMjwvdGV4dD48dGV4dCB4PSIzMzAiIHk9IjE1NiI+bnVtZXJvc1s0XSDDqSAxMDwvdGV4dD48L2c+CiAgPHRleHQgeD0iMjAwIiB5PSIxODIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPjUgcG9zacOnw7VlcywgY29udGEtc2UgYSBwYXJ0aXIgZGUgMDogbyDDumx0aW1vIMOtbmRpY2Ugw6kgNC48L3RleHQ+Cjwvc3ZnPgo=",MD=""+new URL("mvc-klick-DKonBpbs.svg",import.meta.url).href,LD=""+new URL("schiffe-versenken-iEBDHIxD.svg",import.meta.url).href,ED=""+new URL("ss-binaere-suche-DVVS2SNc.svg",import.meta.url).href,WD=""+new URL("ss-bubblesort-AFDcFDah.svg",import.meta.url).href,ND="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDQgMTk2IiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KPHJlY3Qgd2lkdGg9IjQwNCIgaGVpZ2h0PSIxOTYiIGZpbGw9IiNmZmZmZmYiLz4KPHRleHQgeD0iMTQiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIiBmb250LXNpemU9IjE1Ij5Qcm9jdXJhLXNlIG8gOS4gQXMgY2FydGFzIGVzdMOjbyBiYXJhbGhhZGFzLjwvdGV4dD4KPGc+PHJlY3QgeD0iMTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjM0LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjc8L3RleHQ+PHRleHQgeD0iMzQuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNkYzI2MjYiPuKZpTwvdGV4dD48L2c+Cjx0ZXh0IHg9IjM0LjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIzNC4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjEuPC90ZXh0Pgo8Zz48cmVjdCB4PSI2MiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iODIuMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+MzwvdGV4dD48dGV4dCB4PSI4Mi4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+4pmgPC90ZXh0PjwvZz4KPHRleHQgeD0iODIuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZGMyNjI2Ij7inJc8L3RleHQ+Cjx0ZXh0IHg9IjgyLjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+Mi48L3RleHQ+CjxnPjxyZWN0IHg9IjExMCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iMTMwLjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjEwPC90ZXh0Pjx0ZXh0IHg9IjEzMC4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iI2RjMjYyNiI+4pmmPC90ZXh0PjwvZz4KPHRleHQgeD0iMTMwLjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIxMzAuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj4zLjwvdGV4dD4KPGc+PHJlY3QgeD0iMTU4IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48dGV4dCB4PSIxNzguMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+NTwvdGV4dD48dGV4dCB4PSIxNzguMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiMxYzFjMWUiPuKZozwvdGV4dD48L2c+Cjx0ZXh0IHg9IjE3OC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMTc4LjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+NC48L3RleHQ+CjxnPjxyZWN0IHg9IjIwNiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIzIi8+PHRleHQgeD0iMjI2LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjk8L3RleHQ+PHRleHQgeD0iMjI2LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxYzFlIj7imaA8L3RleHQ+PC9nPgo8dGV4dCB4PSIyMjYuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjMTU4MDNkIj7inJM8L3RleHQ+Cjx0ZXh0IHg9IjIyNi4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjUuPC90ZXh0Pgo8Zz48cmVjdCB4PSIyNTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjMWQ0ZWQ4IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjxyZWN0IHg9IjI1OCIgeT0iNTQiIHdpZHRoPSIzMiIgaGVpZ2h0PSI0OCIgcng9IjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzkzYzVmZCIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMiIvPjwvZz4KPGc+PHJlY3QgeD0iMzAyIiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iIzFkNGVkOCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSIzMDYiIHk9IjU0IiB3aWR0aD0iMzIiIGhlaWdodD0iNDgiIHJ4PSIzIiBmaWxsPSJub25lIiBzdHJva2U9IiM5M2M1ZmQiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtZGFzaGFycmF5PSIzIDIiLz48L2c+CjxnPjxyZWN0IHg9IjM1MCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiMxZDRlZDgiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHJlY3QgeD0iMzU0IiB5PSI1NCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjQ4IiByeD0iMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTNjNWZkIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWRhc2hhcnJheT0iMyAyIi8+PC9nPgo8dGV4dCB4PSIxNCIgeT0iMTY4IiBmb250LXNpemU9IjE1IiBmaWxsPSIjNmU2ZTczIj5WaXJhciBkYSBlc3F1ZXJkYSBwYXJhIGEgZGlyZWl0YTo8L3RleHQ+PHRleHQgeD0iMTQiIHk9IjE4OCIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzZlNmU3MyI+QXDDs3MgNSBjb21wYXJhw6fDtWVzLCBvIDkgw6kgZW5jb250cmFkby48L3RleHQ+Cjwvc3ZnPgo=",FD=""+new URL("ss-vergleiche-DWgkIvLr.svg",import.meta.url).href,JD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjAgNDUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KPGRlZnM+PG1hcmtlciBpZD0iayIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDEwIDUgTDAgMTAgWiIgZmlsbD0iIzFjMWMxZSIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImIiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjYiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNMCAwIEwxMCA1IEwwIDEwIFoiIGZpbGw9IiMxZDRlZDgiLz48L21hcmtlcj48bWFya2VyIGlkPSJvIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjYjQ1MzA5Ii8+PC9tYXJrZXI+PC9kZWZzPgo8cmVjdCB3aWR0aD0iNDIwIiBoZWlnaHQ9IjQ1MCIgZmlsbD0iI2ZmZmZmZiIvPgo8dGV4dCB4PSIxMCIgeT0iMjIiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI3MDAiPlBhc3NhZ2VtIHBvciB2YWxvcjogdW1hIGPDs3BpYTwvdGV4dD4KPHJlY3QgeD0iMTAiIHk9IjM4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9Ijg2IiByeD0iOCIgZmlsbD0iI2VmZjZmZiIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8dGV4dCB4PSIyMCIgeT0iNTgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPlByb2dyYW1hIHByaW5jaXBhbDwvdGV4dD4KPHRleHQgeD0iMTYiIHk9Ijk4IiBmb250LXNpemU9IjEyIj5udW1lcm88L3RleHQ+CjxyZWN0IHg9IjcwIiB5PSI3OCIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9Ijk4IiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+NTwvdGV4dD4KPHJlY3QgeD0iMjUwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNmZmY3ZWQiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjYwIiB5PSI1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+ZHVwbGljYXI8L3RleHQ+Cjx0ZXh0IHg9IjI2MCIgeT0iOTgiPng8L3RleHQ+CjxyZWN0IHg9IjI4MCIgeT0iNzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMCIgcng9IjQiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8dGV4dCB4PSIzMjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dHNwYW4gZmlsbD0iIzZlNmU3MyIgdGV4dC1kZWNvcmF0aW9uPSJsaW5lLXRocm91Z2giPjU8L3RzcGFuPiA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCI+MTA8L3RzcGFuPjwvdGV4dD4KPGxpbmUgeDE9IjEyOCIgeTE9IjkzIiB4Mj0iMjQ4IiB5Mj0iOTMiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNCIgbWFya2VyLWVuZD0idXJsKCNrKSIvPgo8dGV4dCB4PSIyMTAiIHk9Ijg0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5jw7NwaWE8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxNTAiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPnggcGFzc2EgYSAxMCwgbWFzIG51bWVybyBmaWNhIDUuPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iMTY4IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj5Db21vIHVtYSBmb3RvY8OzcGlhOiBlc2NyZXZlciBuYSBjw7NwaWE8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxODYiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPm7Do28gYWx0ZXJhIG8gb3JpZ2luYWwuPC90ZXh0Pgo8bGluZSB4MT0iMTAiIHkxPSIyMDgiIHgyPSI0MTAiIHkyPSIyMDgiIHN0cm9rZT0iI2QxZDFkNiIvPgo8dGV4dCB4PSIxMCIgeT0iMjM2IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNzAwIj5QYXNzYWdlbSBwb3IgcmVmZXLDqm5jaWE6IG8gbWVzbW8gYXJyYXk8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZWZmNmZmIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjIwIiB5PSIyNzIiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPlByb2dyYW1hIHByaW5jaXBhbDwvdGV4dD4KPHRleHQgeD0iMjAiIHk9IjMwMCI+ZmlsYTwvdGV4dD4KPGNpcmNsZSBjeD0iMTUwIiBjeT0iMjk1IiByPSI1IiBmaWxsPSIjMWQ0ZWQ4Ii8+CjxyZWN0IHg9IjI1MCIgeT0iMjUyIiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjYyIiByeD0iOCIgZmlsbD0iI2ZmZjdlZCIgc3Ryb2tlPSIjYjQ1MzA5IiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8dGV4dCB4PSIyNjAiIHk9IjI3MiIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+bGltcGFyPC90ZXh0Pgo8dGV4dCB4PSIyNjAiIHk9IjMwMCI+bHVnYXJlczwvdGV4dD4KPGNpcmNsZSBjeD0iMzkwIiBjeT0iMjk1IiByPSI1IiBmaWxsPSIjYjQ1MzA5Ii8+CjxwYXRoIGQ9Ik0xNTAgMzAwIEwxNTAgMzQwIEwxNDAgMzUyIiBmaWxsPSJub25lIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41IiBtYXJrZXItZW5kPSJ1cmwoI2IpIi8+CjxwYXRoIGQ9Ik0zOTAgMzAwIEwzOTAgMzQwIEwzMjIgMzU0IiBmaWxsPSJub25lIiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMS41IiBtYXJrZXItZW5kPSJ1cmwoI28pIi8+CjxyZWN0IHg9IjkwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+CjxyZWN0IHg9IjE1MCIgeT0iMzU4IiB3aWR0aD0iNjAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8cmVjdCB4PSIyMTAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHJlY3QgeD0iMjcwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9IjEyMCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMTgwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIyNDAiIHk9IjM3OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+ZmFsc2U8L3RleHQ+Cjx0ZXh0IHg9IjMwMCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjQxNiIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+U8OzIGjDoSB1bSBhcnJheS4gTyBxdWUgbGltcGFyIGFsdGVyYSBhdHJhdsOpcyBkZSBsdWdhcmVzLDwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjQzNCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+byBwcm9ncmFtYSBwcmluY2lwYWwgdsOqIGVtIGZpbGEuPC90ZXh0Pgo8L3N2Zz4K",RD=""+new URL("zk-zeichen-8efNmpGx.svg",import.meta.url).href,GD=""+new URL("schiffe-versenken-CXt1SF0S.svg",import.meta.url).href,HD=""+new URL("ss-binaere-suche-CPsLGldq.svg",import.meta.url).href,VD=""+new URL("ss-bubblesort-Dic2ZfaT.svg",import.meta.url).href,qD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDQgMTk2IiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KPHJlY3Qgd2lkdGg9IjQwNCIgaGVpZ2h0PSIxOTYiIGZpbGw9IiNmZmZmZmYiLz4KPHRleHQgeD0iMTQiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIiBmb250LXNpemU9IjE1Ij5HZXN1Y2h0OiBkaWUgOS4gRGllIEthcnRlbiBzaW5kIGdlbWlzY2h0LjwvdGV4dD4KPGc+PHJlY3QgeD0iMTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjM0LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjc8L3RleHQ+PHRleHQgeD0iMzQuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNkYzI2MjYiPuKZpTwvdGV4dD48L2c+Cjx0ZXh0IHg9IjM0LjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIzNC4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjEuPC90ZXh0Pgo8Zz48cmVjdCB4PSI2MiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iODIuMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+MzwvdGV4dD48dGV4dCB4PSI4Mi4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+4pmgPC90ZXh0PjwvZz4KPHRleHQgeD0iODIuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZGMyNjI2Ij7inJc8L3RleHQ+Cjx0ZXh0IHg9IjgyLjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+Mi48L3RleHQ+CjxnPjxyZWN0IHg9IjExMCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iMTMwLjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjEwPC90ZXh0Pjx0ZXh0IHg9IjEzMC4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iI2RjMjYyNiI+4pmmPC90ZXh0PjwvZz4KPHRleHQgeD0iMTMwLjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIxMzAuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj4zLjwvdGV4dD4KPGc+PHJlY3QgeD0iMTU4IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48dGV4dCB4PSIxNzguMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+NTwvdGV4dD48dGV4dCB4PSIxNzguMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiMxYzFjMWUiPuKZozwvdGV4dD48L2c+Cjx0ZXh0IHg9IjE3OC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMTc4LjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+NC48L3RleHQ+CjxnPjxyZWN0IHg9IjIwNiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIzIi8+PHRleHQgeD0iMjI2LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjk8L3RleHQ+PHRleHQgeD0iMjI2LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxYzFlIj7imaA8L3RleHQ+PC9nPgo8dGV4dCB4PSIyMjYuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjMTU4MDNkIj7inJM8L3RleHQ+Cjx0ZXh0IHg9IjIyNi4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjUuPC90ZXh0Pgo8Zz48cmVjdCB4PSIyNTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjMWQ0ZWQ4IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjxyZWN0IHg9IjI1OCIgeT0iNTQiIHdpZHRoPSIzMiIgaGVpZ2h0PSI0OCIgcng9IjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzkzYzVmZCIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMiIvPjwvZz4KPGc+PHJlY3QgeD0iMzAyIiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iIzFkNGVkOCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSIzMDYiIHk9IjU0IiB3aWR0aD0iMzIiIGhlaWdodD0iNDgiIHJ4PSIzIiBmaWxsPSJub25lIiBzdHJva2U9IiM5M2M1ZmQiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtZGFzaGFycmF5PSIzIDIiLz48L2c+CjxnPjxyZWN0IHg9IjM1MCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiMxZDRlZDgiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHJlY3QgeD0iMzU0IiB5PSI1NCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjQ4IiByeD0iMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTNjNWZkIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWRhc2hhcnJheT0iMyAyIi8+PC9nPgo8dGV4dCB4PSIxNCIgeT0iMTY4IiBmb250LXNpemU9IjE1IiBmaWxsPSIjNmU2ZTczIj5Wb24gbGlua3MgbmFjaCByZWNodHMgdW1kcmVoZW46PC90ZXh0Pjx0ZXh0IHg9IjE0IiB5PSIxODgiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiM2ZTZlNzMiPk5hY2ggNSBWZXJnbGVpY2hlbiBpc3QgZGllIDkgZ2VmdW5kZW4uPC90ZXh0Pgo8L3N2Zz4K",QD=""+new URL("ss-vergleiche-DRqzU2TZ.svg",import.meta.url).href,UD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjAgNDUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KPGRlZnM+PG1hcmtlciBpZD0iayIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDEwIDUgTDAgMTAgWiIgZmlsbD0iIzFjMWMxZSIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImIiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjYiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNMCAwIEwxMCA1IEwwIDEwIFoiIGZpbGw9IiMxZDRlZDgiLz48L21hcmtlcj48bWFya2VyIGlkPSJvIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjYjQ1MzA5Ii8+PC9tYXJrZXI+PC9kZWZzPgo8cmVjdCB3aWR0aD0iNDIwIiBoZWlnaHQ9IjQ1MCIgZmlsbD0iI2ZmZmZmZiIvPgo8dGV4dCB4PSIxMCIgeT0iMjIiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI3MDAiPldlcnTDvGJlcmdhYmU6IGVpbmUgS29waWU8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNlZmY2ZmYiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjAiIHk9IjU4IiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWQ0ZWQ4Ij5IYXVwdHByb2dyYW1tPC90ZXh0Pgo8dGV4dCB4PSIyMCIgeT0iOTgiPnphaGw8L3RleHQ+CjxyZWN0IHg9IjcwIiB5PSI3OCIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9Ijk4IiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+NTwvdGV4dD4KPHJlY3QgeD0iMjUwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNmZmY3ZWQiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjYwIiB5PSI1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+dmVyZG9wcGxlPC90ZXh0Pgo8dGV4dCB4PSIyNjAiIHk9Ijk4Ij54PC90ZXh0Pgo8cmVjdCB4PSIyODAiIHk9Ijc4IiB3aWR0aD0iODAiIGhlaWdodD0iMzAiIHJ4PSI0IiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHRleHQgeD0iMzIwIiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+PHRzcGFuIGZpbGw9IiM2ZTZlNzMiIHRleHQtZGVjb3JhdGlvbj0ibGluZS10aHJvdWdoIj41PC90c3Bhbj4gPHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiPjEwPC90c3Bhbj48L3RleHQ+CjxsaW5lIHgxPSIxMjgiIHkxPSI5MyIgeDI9IjI0OCIgeTI9IjkzIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSI1IDQiIG1hcmtlci1lbmQ9InVybCgjaykiLz4KPHRleHQgeD0iMjEwIiB5PSI4NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+S29waWU8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxNTAiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPnggd2lyZCAxMCwgYWJlciB6YWhsIGJsZWlidCA1LjwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjE2OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+V2llIGJlaSBlaW5lciBGb3Rva29waWU6IFdlciBhdWYgZGVyIEtvcGllIHNjaHJlaWJ0LDwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjE4NiIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+w6RuZGVydCBkYXMgT3JpZ2luYWwgbmljaHQuPC90ZXh0Pgo8bGluZSB4MT0iMTAiIHkxPSIyMDgiIHgyPSI0MTAiIHkyPSIyMDgiIHN0cm9rZT0iI2QxZDFkNiIvPgo8dGV4dCB4PSIxMCIgeT0iMjM2IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNzAwIj5SZWZlcmVuesO8YmVyZ2FiZTogZGFzc2VsYmUgQXJyYXk8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZWZmNmZmIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjIwIiB5PSIyNzIiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPkhhdXB0cHJvZ3JhbW08L3RleHQ+Cjx0ZXh0IHg9IjIwIiB5PSIzMDAiPnJlaWhlPC90ZXh0Pgo8Y2lyY2xlIGN4PSIxNTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiMxZDRlZDgiLz4KPHJlY3QgeD0iMjUwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZmZmN2VkIiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjI2MCIgeT0iMjcyIiBmb250LXNpemU9IjEzIiBmaWxsPSIjYjQ1MzA5Ij5sZWVyZW48L3RleHQ+Cjx0ZXh0IHg9IjI2MCIgeT0iMzAwIj5wbGFldHplPC90ZXh0Pgo8Y2lyY2xlIGN4PSIzOTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiNiNDUzMDkiLz4KPHBhdGggZD0iTTE1MCAzMDAgTDE1MCAzNDAgTDE0MCAzNTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYikiLz4KPHBhdGggZD0iTTM5MCAzMDAgTDM5MCAzNDAgTDMyMiAzNTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjbykiLz4KPHJlY3QgeD0iOTAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHJlY3QgeD0iMTUwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+CjxyZWN0IHg9IjIxMCIgeT0iMzU4IiB3aWR0aD0iNjAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8cmVjdCB4PSIyNzAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHRleHQgeD0iMTIwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxODAiIHk9IjM3OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+ZmFsc2U8L3RleHQ+Cjx0ZXh0IHg9IjI0MCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMzAwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iNDE2IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj5FcyBnaWJ0IG51ciBlaW4gQXJyYXkuIFdhcyBsZWVyZW4gw7xiZXIgcGxhZXR6ZSDDpG5kZXJ0LDwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjQzNCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+c2llaHQgZGFzIEhhdXB0cHJvZ3JhbW0gdW50ZXIgcmVpaGUuPC90ZXh0Pgo8L3N2Zz4K",$D=""+new URL("zk-zeichen-vYvc3iJg.svg",import.meta.url).href;function YD(i){const e=[];for(const t of i.replace(/\r\n/g,` +`,OP=""+new URL("aufgabe-mehrwertsteuer-C-TFTrWz.svg",import.meta.url).href,AP=""+new URL("ben-shneiderman-Cev5hrqS.jpg",import.meta.url).href,CP=""+new URL("caesar-ascii-Bix93F5i.svg",import.meta.url).href,jP=""+new URL("caesar-scheibe-CMRPZI6Y.svg",import.meta.url).href,PP=""+new URL("caesar-verschiebung-DIR-lDbs.svg",import.meta.url).href,DP=""+new URL("aufgabe-mehrwertsteuer-CnrZ00ny.svg",import.meta.url).href,BP=""+new URL("kino-saal-C8zaJk4X.svg",import.meta.url).href,ZP=""+new URL("kino-schleifen-D7sfo9iK.svg",import.meta.url).href,MP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDkyIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iNDkyIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiPgogICAgPCEtLSBTdGFydCAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMTAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjgiIHJ4PSIxNCIgZmlsbD0iI2QxZjJkOSIvPgogICAgPGxpbmUgeDE9IjE1MCIgeTE9IjM4IiB4Mj0iMTUwIiB5Mj0iNTQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gQW53ZWlzdW5nIC0tPgogICAgPHJlY3QgeD0iNTAiIHk9IjU2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iODYiIHgyPSIxNTAiIHkyPSI5OCIgbWFya2VyLWVuZD0idXJsKCNhKSIvPgogICAgPCEtLSBSYXV0ZSAxIC0tPgogICAgPHBhdGggZD0iTTE1MCAxMDAgTDIzNSAxMjggTDE1MCAxNTYgTDY1IDEyOCBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMTU2IiB4Mj0iMTUwIiB5Mj0iMTcyIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8cmVjdCB4PSI1MCIgeT0iMTc0IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMjA0IiB4Mj0iMTUwIiB5Mj0iMjUwIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIG5laW4tV2VnIHVtIGRlbiBLYXN0ZW4gaGVydW0gLS0+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIyMzUsMTI4IDI4NSwxMjggMjg1LDIyMiAxNTAsMjIyIiBmaWxsPSJub25lIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIFJhdXRlIDIgLS0+CiAgICA8cGF0aCBkPSJNMTUwIDI1MiBMMjM1IDI4MCBMMTUwIDMwOCBMNjUgMjgwIFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxsaW5lIHgxPSIyMzUiIHkxPSIyODAiIHgyPSIyNjgiIHkyPSIyODAiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjI3MCIgeT0iMjY1IiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8IS0tIHp1csO8Y2sgenVyIFByw7xmdW5nIC0tPgogICAgPHBvbHlsaW5lIHBvaW50cz0iMzI3LDI2NSAzMjcsMjM4IDE1MCwyMzgiIGZpbGw9Im5vbmUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzMDgiIHgyPSIxNTAiIHkyPSIzMjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjUwIiB5PSIzMjgiIHdpZHRoPSIyMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNlNWYwZmYiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzNTgiIHgyPSIxNTAiIHkyPSIzNzQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gRW5kZSAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjI4IiByeD0iMTQiIGZpbGw9IiNkMWYyZDkiLz4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSI+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI5Ij5TdGFydDwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iNzYiPlB1dCBhIGN1cCBvbiB0aGUgdGFibGU8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjEzMyI+U3VnYXIgd2FudGVkPzwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTk0Ij5BZGQgc3VnYXI8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI4NSI+VGVhIHN0aWxsIHRvbyBob3Q/PC90ZXh0PgogICAgPHRleHQgeD0iMzI3LjUiIHk9IjI4NSI+V2FpdCAxIG1pbnV0ZTwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzQ4Ij5EcmluayB0aGUgdGVhPC90ZXh0PgogICAgPHRleHQgeD0iMTUwIiB5PSIzOTUiPkVuZDwvdGV4dD4KICA8L2c+CiAgPGcgZm9udC1zaXplPSIxMiIgZm9udC13ZWlnaHQ9IjYwMCI+CiAgICA8dGV4dCB4PSIxNTYiIHk9IjE2OCIgZmlsbD0iIzI0OGEzZCI+eWVzPC90ZXh0PgogICAgPHRleHQgeD0iMjQyIiB5PSIxMjIiIGZpbGw9IiNkNzAwMTUiPm5vPC90ZXh0PgogICAgPHRleHQgeD0iMjQwIiB5PSIyNzQiIGZpbGw9IiMyNDhhM2QiPnllczwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1NiIgeT0iMzIwIiBmaWxsPSIjZDcwMDE1Ij5ubzwvdGV4dD4KICA8L2c+CiAgPCEtLSBMZWdlbmRlIC0tPgogIDxsaW5lIHgxPSIxMCIgeTE9IjQxOCIgeDI9IjM5MCIgeTI9IjQxOCIgc3Ryb2tlPSIjZDFkMWQ2Ii8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuNSI+CiAgICA8cmVjdCB4PSI0MCIgeT0iNDMwIiB3aWR0aD0iMzYiIGhlaWdodD0iMTgiIHJ4PSI5IiBmaWxsPSIjZDFmMmQ5Ii8+CiAgICA8cmVjdCB4PSIyMjAiIHk9IjQzMCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjE4IiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8cGF0aCBkPSJNNTggNDU4IEw3NiA0NjkgTDU4IDQ4MCBMNDAgNDY5IFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxwYXRoIGQ9Ik0yMjYgNDYwIEwyNTYgNDYwIEwyNTAgNDc4IEwyMjAgNDc4IFoiIGZpbGw9IiNmMmU2ZmYiLz4KICA8L2c+CiAgPGcgZm9udC1zaXplPSIxMiIgZmlsbD0iIzNhM2EzYyI+CiAgICA8dGV4dCB4PSI4NiIgeT0iNDQzIj5TdGFydCBvciBlbmQ8L3RleHQ+CiAgICA8dGV4dCB4PSIyNjYiIHk9IjQ0MyI+U3RhdGVtZW50PC90ZXh0PgogICAgPHRleHQgeD0iODYiIHk9IjQ3MyI+RGVjaXNpb248L3RleHQ+CiAgICA8dGV4dCB4PSIyNjYiIHk9IjQ3MyI+SW5wdXQgb3Igb3V0cHV0PC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",LP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE5MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwIiB5PSIyNCIgZm9udC13ZWlnaHQ9IjYwMCI+V2hlcmUgZG9lcyB0aGUgZWxlbWVudCBsYW5kPzwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iNDAiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkYmVhZmUiLz4KICA8cmVjdCB4PSIyMCIgeT0iNzUiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkY2ZjZTciLz4KICA8bGluZSB4MT0iMjAiIHkxPSI3NSIgeDI9IjIxMCIgeTI9Ijc1IiBzdHJva2U9IiM2ZTZlNzMiIHN0cm9rZS1kYXNoYXJyYXk9IjQgMyIvPgogIDxyZWN0IHg9IjIwIiB5PSI0MCIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjYyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMWQ0ZWQ4Ij50b3AgaGFsZjwvdGV4dD4KICA8dGV4dCB4PSIxMTUiIHk9Ijk3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMTU4MDNkIj5ib3R0b20gaGFsZjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9IjYyIj7ihpIgZ29lcyA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+aW4gZnJvbnQ8L3RzcGFuPjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9Ijk3Ij7ihpIgZ29lcyA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+YWZ0ZXI8L3RzcGFuPjwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iMTMyIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjExNSIgeT0iMTU3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2Ij7DuDwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9IjE1NyI+4oaSIDx0c3BhbiBmb250LXdlaWdodD0iNjAwIj5yZXBsYWNlczwvdHNwYW4+IGl0PC90ZXh0Pgo8L3N2Zz4K",EP=""+new URL("l03-lochkarte-beschriftet-BjBFZjzb.svg",import.meta.url).href,WP=""+new URL("l03-lochkarte-BB3rWQOm.svg",import.meta.url).href,NP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgMjcwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CjxyZWN0IHdpZHRoPSI0NjAiIGhlaWdodD0iMjcwIiBmaWxsPSIjZmZmZmZmIi8+Cjx0ZXh0IHg9IjYyIiB5PSI0NCIgZm9udC1zaXplPSI0MCIgZmlsbD0iIzZlNmU3MyIgdGV4dExlbmd0aD0iMjg4IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmdBbmRHbHlwaHMiPnByaWNlPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPlc8L3RzcGFuPml0aDx0c3BhbiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj5UPC90c3Bhbj5heDwvdGV4dD4KPGxpbmUgeDE9IjE5NCIgeTE9IjU0IiB4Mj0iMTk0IiB5Mj0iODQiIHN0cm9rZT0iIzAwN2FmZiIgc3Ryb2tlLXdpZHRoPSIyLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNCIvPgo8bGluZSB4MT0iMjkwIiB5MT0iNTQiIHgyPSIyOTAiIHkyPSI4NCIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSA0Ii8+CjxwYXRoIGQ9Ik0xNDYgMTg1IEwxNDIgMjE0IEwxNDYgMjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNjOTk5NWIiIHN0cm9rZS13aWR0aD0iMTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTY2IDE4NSBMMTcwIDIxNCBMMTY2IDI0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjEwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTMxOSAxODUgTDMxNSAyMTQgTDMxOSAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2M5OTk1YiIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0zMzkgMTg1IEwzNDMgMjE0IEwzMzkgMjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTI2IDE1MCBDMTEwIDE2MCAxMTAgMTg1IDExOCAxOTgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSI0IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTEzNCAxOTIgQzExOCAxNzggMTE4IDE0NiAxNDAgMTQwIEMxNTggMTM4IDE2NCA4NiAxOTQgODYgQzIyNCA4NiAyMjQgMTM2IDI0MiAxMzQgQzI2MCAxMzYgMjYwIDg2IDI5MCA4NiBDMzIwIDg2IDMxOCAxMzYgMzM1IDE0MCBDMzU1IDE0MiAzNjMgMTE4IDM2OSAxMDAgQzM3MyA4NiAzODMgODAgMzk3IDgwIEM0MTEgODAgNDE5IDg2IDQyMSA5NCBDNDIzIDEwMiA0MTEgMTA2IDM5NSAxMDYgQzM4NyAxMzAgMzc3IDE2OCAzNTMgMTg2IEMyNzIgMjA2IDIxMiAyMDYgMTM0IDE5MiBaIiBmaWxsPSIjYzk5OTViIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0zODUgODQgTDM4MSA3MiBMMzkyIDgxIFoiIGZpbGw9IiNjOTk5NWIiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxjaXJjbGUgY3g9IjQwMyIgY3k9IjkwIiByPSIzLjIiIGZpbGw9IiMxYzFjMWUiLz4KPHBhdGggZD0iTTQxMyAxMDAgUTQxNyAxMDIgNDIwIDk5IiBmaWxsPSJub25lIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0zMCAyNDIgSDQzMCIgc3Ryb2tlPSIjZDFkMWQ2IiBzdHJva2Utd2lkdGg9IjMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K",FP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjEwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIxMCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjE2Ij5pbnQgYWdlID0gMTQ8L3RleHQ+CiAgPHBhdGggZD0iTTEzMCA3MCBMMTcwIDUwIEwzMDAgNTAgTDI2MCA3MCBaIiBmaWxsPSIjYzk4YTNjIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjE4MCIgeT0iMzQiIHdpZHRoPSI0NCIgaGVpZ2h0PSI1MCIgcng9IjMiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KICA8dGV4dCB4PSIyMDIiIHk9IjYwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjIwIiBmb250LXdlaWdodD0iNzAwIj4xNDwvdGV4dD4KICA8cmVjdCB4PSIxMzAiIHk9IjcwIiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iI2U5Yjg3MiIgc3Ryb2tlPSIjOGE1YTFmIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8cGF0aCBkPSJNMjYwIDcwIEwzMDAgNTAgTDMwMCAxNTAgTDI2MCAxNzAgWiIgZmlsbD0iI2Q0OWE0YyIgc3Ryb2tlPSIjOGE1YTFmIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8cmVjdCB4PSIxNTAiIHk9IjEwMCIgd2lkdGg9IjkwIiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjOGE1YTFmIi8+CiAgPHRleHQgeD0iMTk1IiB5PSIxMjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPmFnZTwvdGV4dD4KICA8cmVjdCB4PSIxMzgiIHk9IjE0MiIgd2lkdGg9IjM0IiBoZWlnaHQ9IjIwIiByeD0iMTAiIGZpbGw9IiMwMDdhZmYiLz4KICA8dGV4dCB4PSIxNTUiIHk9IjE1NiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMiIgZmlsbD0iI2ZmZmZmZiIgZm9udC13ZWlnaHQ9IjYwMCI+aW50PC90ZXh0PgogIDxnIHN0cm9rZT0iIzZlNmU3MyI+CiAgICA8bGluZSB4MT0iMzEwIiB5MT0iNDgiIHgyPSIyMjYiIHkyPSI1MiIvPgogICAgPGxpbmUgeDE9IjMxMCIgeTE9IjExNSIgeDI9IjI0MiIgeTI9IjExNSIvPgogICAgPGxpbmUgeDE9IjgwIiB5MT0iMTUyIiB4Mj0iMTM0IiB5Mj0iMTUyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjMxNiIgeT0iNTIiPlZhbHVlPC90ZXh0PgogIDx0ZXh0IHg9IjMxNiIgeT0iMTE5Ij5OYW1lPC90ZXh0PgogIDx0ZXh0IHg9IjgiIHk9IjE1NiI+RGF0YSB0eXBlPC90ZXh0PgogIDx0ZXh0IHg9IjIwMCIgeT0iMTk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5UaGUgbmFtZSBnZXRzIHlvdSB0byB0aGUgdmFsdWUuPC90ZXh0Pgo8L3N2Zz4K",JP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiPgogICAgPHRleHQgeD0iNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+cG9pbnRzPC90ZXh0PgogICAgPHRleHQgeD0iMTI1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPj08L3RleHQ+CiAgICA8dGV4dCB4PSIyNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9pbnRzICsgNTwvdGV4dD4KICA8L2c+CiAgPHJlY3QgeD0iMTgwIiB5PSI4NiIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjYwIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPuKRoCB3b3JrIG91dCB0aGUgcmlnaHQ6IDEwICsgNSA9IDE1PC90ZXh0PgogIDxwYXRoIGQ9Ik0yNTAgODIgQzIzMCAzMCwgOTAgMzAsIDY0IDg0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgPHRleHQgeD0iMTYwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiI+4pGhIHN0b3JlIHRoZSByZXN1bHQgb24gdGhlIGxlZnQ8L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjE2NCIgd2lkdGg9IjM2MCIgaGVpZ2h0PSIyNiIgcng9IjYiIGZpbGw9IiNmMmYyZjciLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE4MiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9pbnRzIGJlZm9yZTogPHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiPjEwPC90c3Bhbj4gICDihpIgICBwb2ludHMgYWZ0ZXI6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xNTwvdHNwYW4+PC90ZXh0Pgo8L3N2Zz4K",RP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjYwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjYwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiPgogICAgPHBhdGggZD0iTTQwIDExMCBMNDggMTgwIEwxMDIgMTgwIEwxMTAgMTEwIi8+CiAgICA8cGF0aCBkPSJNMTY1IDExMCBMMTczIDE4MCBMMjI3IDE4MCBMMjM1IDExMCIvPgogICAgPHBhdGggZD0iTTI5MCAxMTAgTDI5OCAxODAgTDM1MiAxODAgTDM2MCAxMTAiLz4KICA8L2c+CiAgPHBhdGggZD0iTTQ0IDEzNSBMNDggMTgwIEwxMDIgMTgwIEwxMDYgMTM1IFoiIGZpbGw9IiNmZGJhNzQiLz4KICA8cGF0aCBkPSJNMjk0IDEzNSBMMjk4IDE4MCBMMzUyIDE4MCBMMzU2IDEzNSBaIiBmaWxsPSIjOTNjNWZkIi8+CiAgPHRleHQgeD0iNzUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+bGVmdDwvdGV4dD4KICA8dGV4dCB4PSI3NSIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5qdWljZTwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+dGVtcDwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+ZW1wdHk8L3RleHQ+CiAgPHRleHQgeD0iMzI1IiB5PSIyMDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPnJpZ2h0PC90ZXh0PgogIDx0ZXh0IHg9IjMyNSIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj53YXRlcjwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxwYXRoIGQ9Ik04OCAxMDQgQzExMCA3MCwgMTYwIDcwLCAxODYgMTA0Ii8+CiAgICA8cGF0aCBkPSJNMzE4IDEwNCBDMjcwIDE1LCAxMzAgMTUsIDgyIDEwNCIvPgogICAgPHBhdGggZD0iTTIxNCAxMDQgQzI0MCA3MCwgMjkwIDcwLCAzMTIgMTA0Ii8+CiAgPC9nPgogIDxnIGZvbnQtd2VpZ2h0PSI3MDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPGNpcmNsZSBjeD0iMTM3IiBjeT0iODAiIHI9IjExIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz48dGV4dCB4PSIxMzciIHk9Ijg1Ij4xPC90ZXh0PgogICAgPGNpcmNsZSBjeD0iMjAwIiBjeT0iMzgiIHI9IjExIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz48dGV4dCB4PSIyMDAiIHk9IjQzIj4yPC90ZXh0PgogICAgPGNpcmNsZSBjeD0iMjYzIiBjeT0iODAiIHI9IjExIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz48dGV4dCB4PSIyNjMiIHk9Ijg1Ij4zPC90ZXh0PgogIDwvZz4KICA8ZyB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxMiI+CiAgICA8dGV4dCB4PSI3MCIgeT0iMjQ3Ij4xOiB0ZW1wID0gbGVmdDwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMjQ3Ij4yOiBsZWZ0ID0gcmlnaHQ8L3RleHQ+CiAgICA8dGV4dCB4PSIzMzAiIHk9IjI0NyI+MzogcmlnaHQgPSB0ZW1wPC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",GP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDxyZWN0IHg9IjIwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+PHJlY3QgeD0iMzEwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+CiAgPHJlY3QgeD0iOTAiIHk9IjUwIiB3aWR0aD0iMjIwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZGNmY2U3Ii8+CiAgPGxpbmUgeDE9IjIwIiB5MT0iNzQiIHgyPSIzODAiIHkyPSI3NCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8bGluZSB4MT0iNDYiIHkxPSI2OCIgeDI9IjQ2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iNDYiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4wPC90ZXh0PgogIDxsaW5lIHgxPSI5MCIgeTE9IjY4IiB4Mj0iOTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjE8L3RleHQ+CiAgPGxpbmUgeDE9IjEzNCIgeTE9IjY4IiB4Mj0iMTM0IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTM0IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MjwvdGV4dD4KICA8bGluZSB4MT0iMTc4IiB5MT0iNjgiIHgyPSIxNzgiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIxNzgiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4zPC90ZXh0PgogIDxsaW5lIHgxPSIyMjIiIHkxPSI2OCIgeDI9IjIyMiIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjIyMiIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjQ8L3RleHQ+CiAgPGxpbmUgeDE9IjI2NiIgeTE9IjY4IiB4Mj0iMjY2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjY2IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NTwvdGV4dD4KICA8bGluZSB4MT0iMzEwIiB5MT0iNjgiIHgyPSIzMTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIzMTAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj42PC90ZXh0PgogIDxsaW5lIHgxPSIzNTQiIHkxPSI2OCIgeDI9IjM1NCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjM1NCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjc8L3RleHQ+CiAgPGNpcmNsZSBjeD0iOTAiIGN5PSI3NCIgcj0iNiIgZmlsbD0iIzE1ODAzZCIvPjxjaXJjbGUgY3g9IjMxMCIgY3k9Ijc0IiByPSI2IiBmaWxsPSIjMTU4MDNkIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dmFsaWQ8L3RleHQ+CiAgPHRleHQgeD0iNDAiIHk9IjQwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5pbnZhbGlkPC90ZXh0Pjx0ZXh0IHg9IjM2MCIgeT0iNDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPmludmFsaWQ8L3RleHQ+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPHRleHQgeD0iMjAwIiB5PSIxMjQiIGZpbGw9IiMxNTgwM2QiPmdyYWRlICZndDs9IDEgJmFtcDsmYW1wOyBncmFkZSAmbHQ7PSA2PC90ZXh0PgogICAgPHRleHQgeD0iMjAwIiB5PSIxNDIiIGZpbGw9IiNiOTFjMWMiPmdyYWRlICZsdDsgMSB8fCBncmFkZSAmZ3Q7IDY8L3RleHQ+CiAgPC9nPgo8L3N2Zz4K",HP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIj5Ib3cgdGhlIHdoaWxlIGxvb3AgcnVuczwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjQ0IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjQwIiByeD0iMjAiIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI2OSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIGNoZWNrIHRoZSBjb25kaXRpb248L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSIxMjgiIHdpZHRoPSIxNjAiIGhlaWdodD0iNDAiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTUzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgcnVuIHRoZSBpbnNpZGU8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iODQiIHgyPSIyMDAiIHkyPSIxMjYiLz4KICAgIDxwYXRoIGQ9Ik0xMjAgMTQ4IEM4MCAxNDgsIDgwIDY0LCAxMTggNjQiLz4KICAgIDxwYXRoIGQ9Ik0yODAgNjQgTDM0MCA2NCBMMzQwIDIwMCBMMjgyIDIwMCIvPgogIDwvZz4KICA8dGV4dCB4PSIyMDgiIHk9IjExMCIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dHJ1ZTwvdGV4dD4KICA8dGV4dCB4PSIzOCIgeT0iMTEwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5iYWNrPC90ZXh0PgogIDx0ZXh0IHg9IjM4IiB5PSIxMjYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPnRvIHRoZSB0b3A8L3RleHQ+CiAgPHRleHQgeD0iMzQ4IiB5PSIxMzQiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPmZhbHNlPC90ZXh0PgogIDx0ZXh0IHg9IjI3NiIgeT0iMjA1IiB0ZXh0LWFuY2hvcj0iZW5kIj5jb250aW51ZSBiZWxvdyB0aGUgbG9vcDwvdGV4dD4KPC9zdmc+Cg==",VP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+cHJlLXRlc3QgKHdoaWxlKTwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9IjIyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iNjAwIj5wb3N0LXRlc3QgKGRvLXdoaWxlKTwvdGV4dD4KICA8bGluZSB4MT0iMjAwIiB5MT0iMTAiIHgyPSIyMDAiIHkyPSIyMjAiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxyZWN0IHg9IjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iNjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCBjb25kaXRpb248L3RleHQ+CiAgPHJlY3QgeD0iMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIxNDciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoSBpbnNpZGU8L3RleHQ+CiAgPHJlY3QgeD0iMjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIGluc2lkZTwvdGV4dD4KICA8cmVjdCB4PSIyMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjMwMCIgeT0iMTQ3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgY29uZGl0aW9uPC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiPgogICAgPGxpbmUgeDE9IjEwMCIgeTE9IjgwIiB4Mj0iMTAwIiB5Mj0iMTIyIi8+CiAgICA8cGF0aCBkPSJNMzUgMTQyIEM4IDE0MiwgOCA2MiwgMzMgNjIiLz4KICAgIDxsaW5lIHgxPSIzMDAiIHkxPSI4MCIgeDI9IjMwMCIgeTI9IjEyMiIvPgogICAgPHBhdGggZD0iTTM2NSAxNDIgQzM5MiAxNDIsIDM5MiA2MiwgMzY3IDYyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjEwNiIgeT0iMTA2IiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTA2IiB0ZXh0LWFuY2hvcj0iZW5kIiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5JZiB0aGUgY29uZGl0aW9uIGlzIGZhbHNlIGF0IG9uY2UsPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj50aGUgaW5zaWRlIHJ1bnMgPHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPm5ldmVyPC90c3Bhbj4uPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5UaGUgaW5zaWRlIGFsd2F5cyBydW5zPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj48dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+YXQgbGVhc3Qgb25jZTwvdHNwYW4+LjwvdGV4dD4KPC9zdmc+Cg==",qP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjUwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHJlY3QgeD0iMTIwIiB5PSIxNCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIFN0YXJ0IDx0c3BhbiBmaWxsPSIjNmU2ZTczIj4ob25seSBvbmNlKTwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iNzYiIHdpZHRoPSIxNjAiIGhlaWdodD0iMzQiIHJ4PSIxNyIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjYjQ1MzA5IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgY2hlY2sgdGhlIGNvbmRpdGlvbjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjEzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIxNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoiBydW4gdGhlIGluc2lkZTwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjIwMCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIyMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoyBzdGVwLCBlLmcuIGkrKzwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjIwMCIgeTI9Ijc0Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTEwIiB4Mj0iMjAwIiB5Mj0iMTM2Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTcyIiB4Mj0iMjAwIiB5Mj0iMTk4Ii8+CiAgICA8cGF0aCBkPSJNMTIwIDIxNyBDNjAgMjE3LCA2MCA5MywgMTE4IDkzIi8+CiAgICA8cGF0aCBkPSJNMjgwIDkzIEwzMzAgOTMiLz4KICA8L2c+CiAgPHRleHQgeD0iMjA4IiB5PSIxMjkiIGZpbGw9IiMxNTgwM2QiIGZvbnQtd2VpZ2h0PSI2MDAiPnRydWU8L3RleHQ+CiAgPHRleHQgeD0iNDgiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+YmFjazwvdGV4dD4KICA8dGV4dCB4PSI0OCIgeT0iMTc2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj50byDikaE8L3RleHQ+CiAgPHRleHQgeD0iMzAwIiB5PSI4NCIgZmlsbD0iI2I5MWMxYyIgZm9udC13ZWlnaHQ9IjYwMCI+ZmFsc2U8L3RleHQ+CiAgPHRleHQgeD0iMzM2IiB5PSI5OCI+ZG9uZTwvdGV4dD4KPC9zdmc+Cg==",QP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMTkwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCI+aW50W10gbnVtYmVycyA9IHsyLCA0LCA2LCA4LCAxMH08L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjU0IiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj5JbmRleDwvdGV4dD4KICA8dGV4dCB4PSI5MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjA8L3RleHQ+PHJlY3QgeD0iNjAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iOTAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj4yPC90ZXh0PgogIDx0ZXh0IHg9IjE1MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjE8L3RleHQ+PHJlY3QgeD0iMTIwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjE1MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjQ8L3RleHQ+CiAgPHRleHQgeD0iMjEwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MjwvdGV4dD48cmVjdCB4PSIxODAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjEwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+NjwvdGV4dD4KICA8dGV4dCB4PSIyNzAiIHk9IjU0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj4zPC90ZXh0PjxyZWN0IHg9IjI0MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyNzAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj44PC90ZXh0PgogIDx0ZXh0IHg9IjMzMCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjQ8L3RleHQ+PHJlY3QgeD0iMzAwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjMzMCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjEwPC90ZXh0PgogIDx0ZXh0IHg9IjIwIiB5PSI5MCIgZmlsbD0iIzZlNmU3MyIgZm9udC1zaXplPSIxMiI+VmFsdWU8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+PGxpbmUgeDE9IjkwIiB5MT0iMTQwIiB4Mj0iOTAiIHkyPSIxMTIiLz48bGluZSB4MT0iMzMwIiB5MT0iMTQwIiB4Mj0iMzMwIiB5Mj0iMTEyIi8+PC9nPgogIDxnIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjEzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dGV4dCB4PSI5MCIgeT0iMTU2Ij5udW1iZXJzWzBdIGlzIDI8L3RleHQ+PHRleHQgeD0iMzMwIiB5PSIxNTYiPm51bWJlcnNbNF0gaXMgMTA8L3RleHQ+PC9nPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTgyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj41IHNsb3RzLCBjb3VudGluZyBzdGFydHMgYXQgMDogdGhlIGxhc3QgaW5kZXggaXMgNC48L3RleHQ+Cjwvc3ZnPgo=",UP=""+new URL("mvc-klick-BIA_bYzu.svg",import.meta.url).href,$P=""+new URL("ss-binaere-suche-D02W1TH_.svg",import.meta.url).href,YP=""+new URL("ss-bubblesort-CmKEoNfO.svg",import.meta.url).href,XP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDQgMTk2IiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KPHJlY3Qgd2lkdGg9IjQwNCIgaGVpZ2h0PSIxOTYiIGZpbGw9IiNmZmZmZmYiLz4KPHRleHQgeD0iMTQiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIiBmb250LXNpemU9IjE1Ij5Mb29raW5nIGZvciB0aGUgOS4gVGhlIGNhcmRzIGFyZSBtaXhlZCB1cC48L3RleHQ+CjxnPjxyZWN0IHg9IjE0IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48dGV4dCB4PSIzNC4wIiB5PSI3NS4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZGMyNjI2Ij43PC90ZXh0Pjx0ZXh0IHg9IjM0LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjZGMyNjI2Ij7imaU8L3RleHQ+PC9nPgo8dGV4dCB4PSIzNC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMzQuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj4xLjwvdGV4dD4KPGc+PHJlY3QgeD0iNjIiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjgyLjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjM8L3RleHQ+PHRleHQgeD0iODIuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiMxYzFjMWUiPuKZoDwvdGV4dD48L2c+Cjx0ZXh0IHg9IjgyLjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSI4Mi4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjIuPC90ZXh0Pgo8Zz48cmVjdCB4PSIxMTAiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjEzMC4wIiB5PSI3NS4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZGMyNjI2Ij4xMDwvdGV4dD48dGV4dCB4PSIxMzAuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNkYzI2MjYiPuKZpjwvdGV4dD48L2c+Cjx0ZXh0IHg9IjEzMC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMTMwLjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+My48L3RleHQ+CjxnPjxyZWN0IHg9IjE1OCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iMTc4LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjU8L3RleHQ+PHRleHQgeD0iMTc4LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxYzFlIj7imaM8L3RleHQ+PC9nPgo8dGV4dCB4PSIxNzguMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZGMyNjI2Ij7inJc8L3RleHQ+Cjx0ZXh0IHg9IjE3OC4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjQuPC90ZXh0Pgo8Zz48cmVjdCB4PSIyMDYiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiMxNTgwM2QiIHN0cm9rZS13aWR0aD0iMyIvPjx0ZXh0IHg9IjIyNi4wIiB5PSI3NS4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjMWMxYzFlIj45PC90ZXh0Pjx0ZXh0IHg9IjIyNi4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+4pmgPC90ZXh0PjwvZz4KPHRleHQgeD0iMjI2LjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iIzE1ODAzZCI+4pyTPC90ZXh0Pgo8dGV4dCB4PSIyMjYuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj41LjwvdGV4dD4KPGc+PHJlY3QgeD0iMjU0IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iIzFkNGVkOCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSIyNTgiIHk9IjU0IiB3aWR0aD0iMzIiIGhlaWdodD0iNDgiIHJ4PSIzIiBmaWxsPSJub25lIiBzdHJva2U9IiM5M2M1ZmQiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtZGFzaGFycmF5PSIzIDIiLz48L2c+CjxnPjxyZWN0IHg9IjMwMiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiMxZDRlZDgiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHJlY3QgeD0iMzA2IiB5PSI1NCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjQ4IiByeD0iMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTNjNWZkIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWRhc2hhcnJheT0iMyAyIi8+PC9nPgo8Zz48cmVjdCB4PSIzNTAiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjMWQ0ZWQ4IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjxyZWN0IHg9IjM1NCIgeT0iNTQiIHdpZHRoPSIzMiIgaGVpZ2h0PSI0OCIgcng9IjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzkzYzVmZCIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMiIvPjwvZz4KPHRleHQgeD0iMTQiIHk9IjE2OCIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzZlNmU3MyI+VHVybiB0aGVtIG92ZXIgZnJvbSBsZWZ0IHRvIHJpZ2h0OjwvdGV4dD48dGV4dCB4PSIxNCIgeT0iMTg4IiBmb250LXNpemU9IjE1IiBmaWxsPSIjNmU2ZTczIj5BZnRlciA1IGNvbXBhcmlzb25zIHRoZSA5IGlzIGZvdW5kLjwvdGV4dD4KPC9zdmc+Cg==",KP=""+new URL("ss-vergleiche-UczNldcC.svg",import.meta.url).href,eD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjAgNDUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KPGRlZnM+PG1hcmtlciBpZD0iayIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDEwIDUgTDAgMTAgWiIgZmlsbD0iIzFjMWMxZSIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImIiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjYiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNMCAwIEwxMCA1IEwwIDEwIFoiIGZpbGw9IiMxZDRlZDgiLz48L21hcmtlcj48bWFya2VyIGlkPSJvIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjYjQ1MzA5Ii8+PC9tYXJrZXI+PC9kZWZzPgo8cmVjdCB3aWR0aD0iNDIwIiBoZWlnaHQ9IjQ1MCIgZmlsbD0iI2ZmZmZmZiIvPgo8dGV4dCB4PSIxMCIgeT0iMjIiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI3MDAiPkNhbGwgYnkgdmFsdWU6IGEgY29weTwvdGV4dD4KPHJlY3QgeD0iMTAiIHk9IjM4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9Ijg2IiByeD0iOCIgZmlsbD0iI2VmZjZmZiIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8dGV4dCB4PSIyMCIgeT0iNTgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPk1haW4gcHJvZ3JhbTwvdGV4dD4KPHRleHQgeD0iMTYiIHk9Ijk4IiBmb250LXNpemU9IjEyIj5udW1iZXI8L3RleHQ+CjxyZWN0IHg9IjcwIiB5PSI3OCIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9Ijk4IiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+NTwvdGV4dD4KPHJlY3QgeD0iMjUwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNmZmY3ZWQiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjYwIiB5PSI1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+ZG91YmxlSXQ8L3RleHQ+Cjx0ZXh0IHg9IjI2MCIgeT0iOTgiPng8L3RleHQ+CjxyZWN0IHg9IjI4MCIgeT0iNzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMCIgcng9IjQiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8dGV4dCB4PSIzMjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dHNwYW4gZmlsbD0iIzZlNmU3MyIgdGV4dC1kZWNvcmF0aW9uPSJsaW5lLXRocm91Z2giPjU8L3RzcGFuPiA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCI+MTA8L3RzcGFuPjwvdGV4dD4KPGxpbmUgeDE9IjEyOCIgeTE9IjkzIiB4Mj0iMjQ4IiB5Mj0iOTMiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNCIgbWFya2VyLWVuZD0idXJsKCNrKSIvPgo8dGV4dCB4PSIyMTAiIHk9Ijg0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5jb3B5PC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iMTUwIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj54IGJlY29tZXMgMTAsIGJ1dCBudW1iZXIgc3RheXMgNS48L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxNjgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPkxpa2UgYSBwaG90b2NvcHk6IHdyaXRpbmcgb24gdGhlIGNvcHk8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxODYiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPmRvZXMgbm90IGNoYW5nZSB0aGUgb3JpZ2luYWwuPC90ZXh0Pgo8bGluZSB4MT0iMTAiIHkxPSIyMDgiIHgyPSI0MTAiIHkyPSIyMDgiIHN0cm9rZT0iI2QxZDFkNiIvPgo8dGV4dCB4PSIxMCIgeT0iMjM2IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNzAwIj5DYWxsIGJ5IHJlZmVyZW5jZTogdGhlIHNhbWUgYXJyYXk8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZWZmNmZmIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjIwIiB5PSIyNzIiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPk1haW4gcHJvZ3JhbTwvdGV4dD4KPHRleHQgeD0iMjAiIHk9IjMwMCI+cm93PC90ZXh0Pgo8Y2lyY2xlIGN4PSIxNTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiMxZDRlZDgiLz4KPHJlY3QgeD0iMjUwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZmZmN2VkIiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjI2MCIgeT0iMjcyIiBmb250LXNpemU9IjEzIiBmaWxsPSIjYjQ1MzA5Ij5jbGVhcjwvdGV4dD4KPHRleHQgeD0iMjYwIiB5PSIzMDAiPnNlYXRzPC90ZXh0Pgo8Y2lyY2xlIGN4PSIzOTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiNiNDUzMDkiLz4KPHBhdGggZD0iTTE1MCAzMDAgTDE1MCAzNDAgTDE0MCAzNTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYikiLz4KPHBhdGggZD0iTTM5MCAzMDAgTDM5MCAzNDAgTDMyMiAzNTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjbykiLz4KPHJlY3QgeD0iOTAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHJlY3QgeD0iMTUwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+CjxyZWN0IHg9IjIxMCIgeT0iMzU4IiB3aWR0aD0iNjAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8cmVjdCB4PSIyNzAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHRleHQgeD0iMTIwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxODAiIHk9IjM3OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+ZmFsc2U8L3RleHQ+Cjx0ZXh0IHg9IjI0MCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMzAwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iNDE2IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj5UaGVyZSBpcyBvbmx5IG9uZSBhcnJheS4gV2hhdCBjbGVhciBjaGFuZ2VzIHRocm91Z2ggc2VhdHMsPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iNDM0IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj50aGUgbWFpbiBwcm9ncmFtIHNlZXMgdW5kZXIgcm93LjwvdGV4dD4KPC9zdmc+Cg==",tD=""+new URL("zk-zeichen-CgUEhNoK.svg",import.meta.url).href,nD=""+new URL("ike-nassi-D2w47gvX.jpg",import.meta.url).href,iD=""+new URL("kino-saal-CYMOok4_.svg",import.meta.url).href,aD=""+new URL("kino-schleifen-DrTQV7dq.svg",import.meta.url).href,sD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDkyIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iNDkyIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiPgogICAgPCEtLSBTdGFydCAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMTAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjgiIHJ4PSIxNCIgZmlsbD0iI2QxZjJkOSIvPgogICAgPGxpbmUgeDE9IjE1MCIgeTE9IjM4IiB4Mj0iMTUwIiB5Mj0iNTQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gQW53ZWlzdW5nIC0tPgogICAgPHJlY3QgeD0iNTAiIHk9IjU2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iODYiIHgyPSIxNTAiIHkyPSI5OCIgbWFya2VyLWVuZD0idXJsKCNhKSIvPgogICAgPCEtLSBSYXV0ZSAxIC0tPgogICAgPHBhdGggZD0iTTE1MCAxMDAgTDIzNSAxMjggTDE1MCAxNTYgTDY1IDEyOCBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMTU2IiB4Mj0iMTUwIiB5Mj0iMTcyIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8cmVjdCB4PSI1MCIgeT0iMTc0IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMjA0IiB4Mj0iMTUwIiB5Mj0iMjUwIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIG5laW4tV2VnIHVtIGRlbiBLYXN0ZW4gaGVydW0gLS0+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIyMzUsMTI4IDI4NSwxMjggMjg1LDIyMiAxNTAsMjIyIiBmaWxsPSJub25lIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIFJhdXRlIDIgLS0+CiAgICA8cGF0aCBkPSJNMTUwIDI1MiBMMjM1IDI4MCBMMTUwIDMwOCBMNjUgMjgwIFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxsaW5lIHgxPSIyMzUiIHkxPSIyODAiIHgyPSIyNjgiIHkyPSIyODAiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjI3MCIgeT0iMjY1IiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8IS0tIHp1csO8Y2sgenVyIFByw7xmdW5nIC0tPgogICAgPHBvbHlsaW5lIHBvaW50cz0iMzI3LDI2NSAzMjcsMjM4IDE1MCwyMzgiIGZpbGw9Im5vbmUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzMDgiIHgyPSIxNTAiIHkyPSIzMjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjUwIiB5PSIzMjgiIHdpZHRoPSIyMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNlNWYwZmYiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzNTgiIHgyPSIxNTAiIHkyPSIzNzQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gRW5kZSAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjI4IiByeD0iMTQiIGZpbGw9IiNkMWYyZDkiLz4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSI+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI5Ij5TdGFydDwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iNzYiPlRhc3NlIGF1ZiBkZW4gVGlzY2ggc3RlbGxlbjwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTMzIj5adWNrZXIgZ2V3w7xuc2NodD88L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjE5NCI+WnVja2VyIGhpbmVpbmdlYmVuPC90ZXh0PgogICAgPHRleHQgeD0iMTUwIiB5PSIyODUiPlRlZSBub2NoIHp1IGhlacOfPzwvdGV4dD4KICAgIDx0ZXh0IHg9IjMyNy41IiB5PSIyODUiPjEgTWludXRlIHdhcnRlbjwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzQ4Ij5UZWUgdHJpbmtlbjwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzk1Ij5FbmRlPC90ZXh0PgogIDwvZz4KICA8ZyBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNjAwIj4KICAgIDx0ZXh0IHg9IjE1NiIgeT0iMTY4IiBmaWxsPSIjMjQ4YTNkIj5qYTwvdGV4dD4KICAgIDx0ZXh0IHg9IjI0MiIgeT0iMTIyIiBmaWxsPSIjZDcwMDE1Ij5uZWluPC90ZXh0PgogICAgPHRleHQgeD0iMjQwIiB5PSIyNzQiIGZpbGw9IiMyNDhhM2QiPmphPC90ZXh0PgogICAgPHRleHQgeD0iMTU2IiB5PSIzMjAiIGZpbGw9IiNkNzAwMTUiPm5laW48L3RleHQ+CiAgPC9nPgogIDwhLS0gTGVnZW5kZSAtLT4KICA8bGluZSB4MT0iMTAiIHkxPSI0MTgiIHgyPSIzOTAiIHkyPSI0MTgiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxnIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjUiPgogICAgPHJlY3QgeD0iNDAiIHk9IjQzMCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjE4IiByeD0iOSIgZmlsbD0iI2QxZjJkOSIvPgogICAgPHJlY3QgeD0iMjIwIiB5PSI0MzAiIHdpZHRoPSIzNiIgaGVpZ2h0PSIxOCIgZmlsbD0iI2U1ZjBmZiIvPgogICAgPHBhdGggZD0iTTU4IDQ1OCBMNzYgNDY5IEw1OCA0ODAgTDQwIDQ2OSBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8cGF0aCBkPSJNMjI2IDQ2MCBMMjU2IDQ2MCBMMjUwIDQ3OCBMMjIwIDQ3OCBaIiBmaWxsPSIjZjJlNmZmIi8+CiAgPC9nPgogIDxnIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiMzYTNhM2MiPgogICAgPHRleHQgeD0iODYiIHk9IjQ0MyI+U3RhcnQgb2RlciBFbmRlPC90ZXh0PgogICAgPHRleHQgeD0iMjY2IiB5PSI0NDMiPkFud2Vpc3VuZzwvdGV4dD4KICAgIDx0ZXh0IHg9Ijg2IiB5PSI0NzMiPlZlcnp3ZWlndW5nPC90ZXh0PgogICAgPHRleHQgeD0iMjY2IiB5PSI0NzMiPkVpbi0gb2RlciBBdXNnYWJlPC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",rD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE5MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwIiB5PSIyNCIgZm9udC13ZWlnaHQ9IjYwMCI+V29oaW4gbGFuZGV0IGRhcyBFbGVtZW50PzwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iNDAiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkYmVhZmUiLz4KICA8cmVjdCB4PSIyMCIgeT0iNzUiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkY2ZjZTciLz4KICA8bGluZSB4MT0iMjAiIHkxPSI3NSIgeDI9IjIxMCIgeTI9Ijc1IiBzdHJva2U9IiM2ZTZlNzMiIHN0cm9rZS1kYXNoYXJyYXk9IjQgMyIvPgogIDxyZWN0IHg9IjIwIiB5PSI0MCIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjYyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMWQ0ZWQ4Ij5vYmVyZSBIw6RsZnRlPC90ZXh0PgogIDx0ZXh0IHg9IjExNSIgeT0iOTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPnVudGVyZSBIw6RsZnRlPC90ZXh0PgogIDx0ZXh0IHg9IjIyNCIgeT0iNjIiPuKGkiBrb21tdCA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+ZGF2b3I8L3RzcGFuPjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9Ijk3Ij7ihpIga29tbXQgPHRzcGFuIGZvbnQtd2VpZ2h0PSI2MDAiPmRhaGludGVyPC90c3Bhbj48L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjEzMiIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI0MCIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjE1NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiI+w7g8L3RleHQ+CiAgPHRleHQgeD0iMjI0IiB5PSIxNTciPuKGkiA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+ZXJzZXR6dDwvdHNwYW4+IGRlbiBQbGF0emhhbHRlcjwvdGV4dD4KPC9zdmc+Cg==",oD=""+new URL("l03-lochkarte-beschriftet-7hmU_7ct.svg",import.meta.url).href,lD=""+new URL("l03-lochkarte-gzfFEatc.svg",import.meta.url).href,uD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgMjcwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CjxyZWN0IHdpZHRoPSI0NjAiIGhlaWdodD0iMjcwIiBmaWxsPSIjZmZmZmZmIi8+Cjx0ZXh0IHg9IjYyIiB5PSI0NCIgZm9udC1zaXplPSI0MCIgZmlsbD0iIzZlNmU3MyIgdGV4dExlbmd0aD0iMzM2IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmdBbmRHbHlwaHMiPnByZWlzPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPk08L3RzcGFuPml0PHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPlM8L3RzcGFuPnRldWVyPC90ZXh0Pgo8bGluZSB4MT0iMTk0IiB5MT0iNTQiIHgyPSIxOTQiIHkyPSI4NCIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSA0Ii8+CjxsaW5lIHgxPSIyNjYiIHkxPSI1NCIgeDI9IjI2NiIgeTI9Ijg0IiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtZGFzaGFycmF5PSI1IDQiLz4KPHBhdGggZD0iTTE0NiAxODUgTDE0MiAyMTQgTDE0NiAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2M5OTk1YiIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xNjYgMTg1IEwxNzAgMjE0IEwxNjYgMjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMjk1IDE4NSBMMjkxIDIxNCBMMjk1IDI0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzk5OTViIiBzdHJva2Utd2lkdGg9IjEwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTMxNSAxODUgTDMxOSAyMTQgTDMxNSAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xMjYgMTUwIEMxMTAgMTYwIDExMCAxODUgMTE4IDE5OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTM0IDE5MiBDMTE4IDE3OCAxMTggMTQ2IDE0MCAxNDAgQzE1OCAxMzggMTY0IDg2IDE5NCA4NiBDMjI0IDg2IDIyNCAxMzYgMjMwIDEzNCBDMjM2IDEzNiAyMzYgODYgMjY2IDg2IEMyOTYgODYgMjk0IDEzNiAzMTEgMTQwIEMzMzEgMTQyIDMzOSAxMTggMzQ1IDEwMCBDMzQ5IDg2IDM1OSA4MCAzNzMgODAgQzM4NyA4MCAzOTUgODYgMzk3IDk0IEMzOTkgMTAyIDM4NyAxMDYgMzcxIDEwNiBDMzYzIDEzMCAzNTMgMTY4IDMyOSAxODYgQzI2MCAyMDYgMjAwIDIwNiAxMzQgMTkyIFoiIGZpbGw9IiNjOTk5NWIiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyLjUiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTM2MSA4NCBMMzU3IDcyIEwzNjggODEgWiIgZmlsbD0iI2M5OTk1YiIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPGNpcmNsZSBjeD0iMzc5IiBjeT0iOTAiIHI9IjMuMiIgZmlsbD0iIzFjMWMxZSIvPgo8cGF0aCBkPSJNMzg5IDEwMCBRMzkzIDEwMiAzOTYgOTkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTMwIDI0MiBINDMwIiBzdHJva2U9IiNkMWQxZDYiIHN0cm9rZS13aWR0aD0iMyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=",cD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjYwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CiAgPHJlY3Qgd2lkdGg9IjQwMCIgaGVpZ2h0PSIyNjAiIGZpbGw9IiNmZmZmZmYiLz4KICA8IS0tIERhbXBmIC0tPgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2I4YjhjMCIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2UtbGluZWNhcD0icm91bmQiPgogICAgPHBhdGggZD0iTTE2MCA5MiBDMTQ1IDcyIDE3NSA2MiAxNjAgNDIgQzE1MCAyOCAxNjIgMTggMTY4IDEyIi8+CiAgICA8cGF0aCBkPSJNMTk1IDkwIEMxODAgNjggMjEyIDU4IDE5NiAzNiBDMTg2IDIyIDE5OCAxMiAyMDQgNiIvPgogICAgPHBhdGggZD0iTTIzMCA5MiBDMjE1IDcyIDI0NSA2MiAyMzAgNDIgQzIyMCAyOCAyMzIgMTggMjM4IDEyIi8+CiAgPC9nPgogIDwhLS0gVW50ZXJ0YXNzZSAtLT4KICA8ZWxsaXBzZSBjeD0iMTk1IiBjeT0iMjI2IiByeD0iMTM1IiByeT0iMTgiIGZpbGw9IiNlNWU1ZWEiIHN0cm9rZT0iI2FlYWViMiIgc3Ryb2tlLXdpZHRoPSIyLjUiLz4KICA8IS0tIEhlbmtlbCAtLT4KICA8cGF0aCBkPSJNMjYyIDEzMiBDMzA1IDEyOCAzMTIgMTkwIDI1OCAxOTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2E2NTMyYiIgc3Ryb2tlLXdpZHRoPSIxNiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CiAgPCEtLSBUYXNzZSAtLT4KICA8cGF0aCBkPSJNMTIwIDEwOCBIMjcwIFYxNzggQzI3MCAyMDUgMjQ4IDIyMiAyMjAgMjIyIEgxNzAgQzE0MiAyMjIgMTIwIDIwNSAxMjAgMTc4IFoiIGZpbGw9IiNjODY3M2EiIHN0cm9rZT0iI2E2NTMyYiIgc3Ryb2tlLXdpZHRoPSIzIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CiAgPGVsbGlwc2UgY3g9IjE5NSIgY3k9IjEwOCIgcng9Ijc1IiByeT0iMTMiIGZpbGw9IiM1YjNhMjQiIHN0cm9rZT0iI2E2NTMyYiIgc3Ryb2tlLXdpZHRoPSIzIi8+CiAgPGVsbGlwc2UgY3g9IjE4MCIgY3k9IjEwNiIgcng9IjIyIiByeT0iNCIgZmlsbD0iIzdhNTIzNiIvPgogIDwhLS0gQ29kZSBhdWYgZGVyIFRhc3NlIC0tPgogIDx0ZXh0IHg9IjE5NSIgeT0iMTc4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjQwIiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZmZmZmZmIj57IH08L3RleHQ+Cjwvc3ZnPgo=",mD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjEwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIxMCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjE2Ij5pbnQgYWx0ZXIgPSAxNDwvdGV4dD4KICA8cGF0aCBkPSJNMTMwIDcwIEwxNzAgNTAgTDMwMCA1MCBMMjYwIDcwIFoiIGZpbGw9IiNjOThhM2MiIHN0cm9rZT0iIzhhNWExZiIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHJlY3QgeD0iMTgwIiB5PSIzNCIgd2lkdGg9IjQ0IiBoZWlnaHQ9IjUwIiByeD0iMyIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjEuNSIvPgogIDx0ZXh0IHg9IjIwMiIgeT0iNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI3MDAiPjE0PC90ZXh0PgogIDxyZWN0IHg9IjEzMCIgeT0iNzAiIHdpZHRoPSIxMzAiIGhlaWdodD0iMTAwIiBmaWxsPSIjZTliODcyIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxwYXRoIGQ9Ik0yNjAgNzAgTDMwMCA1MCBMMzAwIDE1MCBMMjYwIDE3MCBaIiBmaWxsPSIjZDQ5YTRjIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjE1MCIgeT0iMTAwIiB3aWR0aD0iOTAiIGhlaWdodD0iMzAiIHJ4PSI0IiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiM4YTVhMWYiLz4KICA8dGV4dCB4PSIxOTUiIHk9IjEyMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+YWx0ZXI8L3RleHQ+CiAgPHJlY3QgeD0iMTM4IiB5PSIxNDIiIHdpZHRoPSIzNCIgaGVpZ2h0PSIyMCIgcng9IjEwIiBmaWxsPSIjMDA3YWZmIi8+CiAgPHRleHQgeD0iMTU1IiB5PSIxNTYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiNmZmZmZmYiIGZvbnQtd2VpZ2h0PSI2MDAiPmludDwvdGV4dD4KICA8ZyBzdHJva2U9IiM2ZTZlNzMiPgogICAgPGxpbmUgeDE9IjMxMCIgeTE9IjQ4IiB4Mj0iMjI2IiB5Mj0iNTIiLz4KICAgIDxsaW5lIHgxPSIzMTAiIHkxPSIxMTUiIHgyPSIyNDIiIHkyPSIxMTUiLz4KICAgIDxsaW5lIHgxPSI4MCIgeTE9IjE1MiIgeDI9IjEzNCIgeTI9IjE1MiIvPgogIDwvZz4KICA8dGV4dCB4PSIzMTYiIHk9IjUyIj5XZXJ0PC90ZXh0PgogIDx0ZXh0IHg9IjMxNiIgeT0iMTE5Ij5OYW1lPC90ZXh0PgogIDx0ZXh0IHg9IjgiIHk9IjE1NiI+RGF0ZW50eXA8L3RleHQ+CiAgPHRleHQgeD0iMjAwIiB5PSIxOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPsOcYmVyIGRlbiBOYW1lbiBrb21tc3QgZHUgYW4gZGVuIFdlcnQuPC90ZXh0Pgo8L3N2Zz4K",dD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiPgogICAgPHRleHQgeD0iNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+cHVua3RlPC90ZXh0PgogICAgPHRleHQgeD0iMTI1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPj08L3RleHQ+CiAgICA8dGV4dCB4PSIyNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cHVua3RlICsgNTwvdGV4dD4KICA8L2c+CiAgPHJlY3QgeD0iMTgwIiB5PSI4NiIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjYwIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPuKRoCByZWNodHMgYXVzcmVjaG5lbjogMTAgKyA1ID0gMTU8L3RleHQ+CiAgPHBhdGggZD0iTTI1MCA4MiBDMjMwIDMwLCA5MCAzMCwgNjQgODQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwN2FmZiIgc3Ryb2tlLXdpZHRoPSIyLjUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICA8dGV4dCB4PSIxNjAiIHk9IjM2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIj7ikaEgRXJnZWJuaXMgbGlua3Mgc3BlaWNoZXJuPC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSIxNjQiIHdpZHRoPSIzNjAiIGhlaWdodD0iMjYiIHJ4PSI2IiBmaWxsPSIjZjJmMmY3Ii8+CiAgPHRleHQgeD0iMjAwIiB5PSIxODIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPnB1bmt0ZSB2b3JoZXI6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xMDwvdHNwYW4+ICAg4oaSICAgcHVua3RlIG5hY2hoZXI6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xNTwvdHNwYW4+PC90ZXh0Pgo8L3N2Zz4K",hD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjYwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjYwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiPgogICAgPHBhdGggZD0iTTQwIDExMCBMNDggMTgwIEwxMDIgMTgwIEwxMTAgMTEwIi8+CiAgICA8cGF0aCBkPSJNMTY1IDExMCBMMTczIDE4MCBMMjI3IDE4MCBMMjM1IDExMCIvPgogICAgPHBhdGggZD0iTTI5MCAxMTAgTDI5OCAxODAgTDM1MiAxODAgTDM2MCAxMTAiLz4KICA8L2c+CiAgPHBhdGggZD0iTTQ0IDEzNSBMNDggMTgwIEwxMDIgMTgwIEwxMDYgMTM1IFoiIGZpbGw9IiNmZGJhNzQiLz4KICA8cGF0aCBkPSJNMjk0IDEzNSBMMjk4IDE4MCBMMzUyIDE4MCBMMzU2IDEzNSBaIiBmaWxsPSIjOTNjNWZkIi8+CiAgPHRleHQgeD0iNzUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+bGlua3M8L3RleHQ+CiAgPHRleHQgeD0iNzUiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+U2FmdDwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+aGlsZjwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+bGVlcjwvdGV4dD4KICA8dGV4dCB4PSIzMjUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+cmVjaHRzPC90ZXh0PgogIDx0ZXh0IHg9IjMyNSIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5XYXNzZXI8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8cGF0aCBkPSJNODggMTA0IEMxMTAgNzAsIDE2MCA3MCwgMTg2IDEwNCIvPgogICAgPHBhdGggZD0iTTMxOCAxMDQgQzI3MCAxNSwgMTMwIDE1LCA4MiAxMDQiLz4KICAgIDxwYXRoIGQ9Ik0yMTQgMTA0IEMyNDAgNzAsIDI5MCA3MCwgMzEyIDEwNCIvPgogIDwvZz4KICA8ZyBmb250LXdlaWdodD0iNzAwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4KICAgIDxjaXJjbGUgY3g9IjEzNyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMTM3IiB5PSI4NSI+MTwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjIwMCIgY3k9IjM4IiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjAwIiB5PSI0MyI+MjwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjI2MyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjYzIiB5PSI4NSI+MzwvdGV4dD4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTIiPgogICAgPHRleHQgeD0iNzAiIHk9IjI0NyI+MTogaGlsZiA9IGxpbmtzPC90ZXh0PgogICAgPHRleHQgeD0iMjAwIiB5PSIyNDciPjI6IGxpbmtzID0gcmVjaHRzPC90ZXh0PgogICAgPHRleHQgeD0iMzMwIiB5PSIyNDciPjM6IHJlY2h0cyA9IGhpbGY8L3RleHQ+CiAgPC9nPgo8L3N2Zz4K",gD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDxyZWN0IHg9IjIwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+PHJlY3QgeD0iMzEwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+CiAgPHJlY3QgeD0iOTAiIHk9IjUwIiB3aWR0aD0iMjIwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZGNmY2U3Ii8+CiAgPGxpbmUgeDE9IjIwIiB5MT0iNzQiIHgyPSIzODAiIHkyPSI3NCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8bGluZSB4MT0iNDYiIHkxPSI2OCIgeDI9IjQ2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iNDYiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4wPC90ZXh0PgogIDxsaW5lIHgxPSI5MCIgeTE9IjY4IiB4Mj0iOTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjE8L3RleHQ+CiAgPGxpbmUgeDE9IjEzNCIgeTE9IjY4IiB4Mj0iMTM0IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTM0IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MjwvdGV4dD4KICA8bGluZSB4MT0iMTc4IiB5MT0iNjgiIHgyPSIxNzgiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIxNzgiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4zPC90ZXh0PgogIDxsaW5lIHgxPSIyMjIiIHkxPSI2OCIgeDI9IjIyMiIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjIyMiIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjQ8L3RleHQ+CiAgPGxpbmUgeDE9IjI2NiIgeTE9IjY4IiB4Mj0iMjY2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjY2IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NTwvdGV4dD4KICA8bGluZSB4MT0iMzEwIiB5MT0iNjgiIHgyPSIzMTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIzMTAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj42PC90ZXh0PgogIDxsaW5lIHgxPSIzNTQiIHkxPSI2OCIgeDI9IjM1NCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjM1NCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjc8L3RleHQ+CiAgPGNpcmNsZSBjeD0iOTAiIGN5PSI3NCIgcj0iNiIgZmlsbD0iIzE1ODAzZCIvPjxjaXJjbGUgY3g9IjMxMCIgY3k9Ijc0IiByPSI2IiBmaWxsPSIjMTU4MDNkIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+Z8O8bHRpZzwvdGV4dD4KICA8dGV4dCB4PSI0MCIgeT0iNDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPnVuZ8O8bHRpZzwvdGV4dD48dGV4dCB4PSIzNjAiIHk9IjQwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj51bmfDvGx0aWc8L3RleHQ+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPHRleHQgeD0iMjAwIiB5PSIxMjQiIGZpbGw9IiMxNTgwM2QiPm5vdGUgJmd0Oz0gMSAmYW1wOyZhbXA7IG5vdGUgJmx0Oz0gNjwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMTQyIiBmaWxsPSIjYjkxYzFjIj5ub3RlICZsdDsgMSB8fCBub3RlICZndDsgNjwvdGV4dD4KICA8L2c+Cjwvc3ZnPgo=",pD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDAgMTkwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+CiAgPHJlY3Qgd2lkdGg9IjQ0MCIgaGVpZ2h0PSIxOTAiIGZpbGw9IiNmZmZmZmYiLz4KICA8cmVjdCB4PSIyMCIgeT0iMTQiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iNjAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPmE8L3RleHQ+CiAgPHJlY3QgeD0iMTAwIiB5PSIxNCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIxNDAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPmI8L3RleHQ+CiAgPHJlY3QgeD0iMTgwIiB5PSIxNCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIyMjAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPmEgJmFtcDsmYW1wOyBiPC90ZXh0PgogIDxyZWN0IHg9IjI2MCIgeT0iMTQiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzAwLjAiIHk9IjM1IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iNzAwIj5hIHx8IGI8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSIxNCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIzODAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPiFhPC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSI0NiIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSI2MC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIxMDAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjE0MC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIxODAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjIyMC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIyNjAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjMwMC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIzNDAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjM4MC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9Ijc4IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjYwLjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMTU4MDNkIj50cnVlPC90ZXh0PgogIDxyZWN0IHg9IjEwMCIgeT0iNzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMTQwLjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIj5mYWxzZTwvdGV4dD4KICA8cmVjdCB4PSIxODAiIHk9Ijc4IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjIyMC4wIiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMjYwIiB5PSI3OCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIzMDAuMCIgeT0iOTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPnRydWU8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSI3OCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmVlMmUyIiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIzODAuMCIgeT0iOTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiPmZhbHNlPC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSIxMTAiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iNjAuMCIgeT0iMTMxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIj5mYWxzZTwvdGV4dD4KICA8cmVjdCB4PSIxMDAiIHk9IjExMCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIxNDAuMCIgeT0iMTMxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMTU4MDNkIj50cnVlPC90ZXh0PgogIDxyZWN0IHg9IjE4MCIgeT0iMTEwIiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjIyMC4wIiB5PSIxMzEiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiPmZhbHNlPC90ZXh0PgogIDxyZWN0IHg9IjI2MCIgeT0iMTEwIiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjMwMC4wIiB5PSIxMzEiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPnRydWU8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSIxMTAiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2RjZmNlNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzgwLjAiIHk9IjEzMSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iMTQyIiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjYwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMTAwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMTQwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMTgwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMjIwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMjYwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzAwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2RjZmNlNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzgwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8bGluZSB4MT0iMTgwIiB5MT0iMTQiIHgyPSIxODAiIHkyPSIxNzQiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIzIi8+Cjwvc3ZnPgo=",fD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIj5BYmxhdWYgZGVyIFdoaWxlLVNjaGxlaWZlPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iNDQiIHdpZHRoPSIxNjAiIGhlaWdodD0iNDAiIHJ4PSIyMCIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjYjQ1MzA5IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjY5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaAgQmVkaW5ndW5nIHByw7xmZW48L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSIxMjgiIHdpZHRoPSIxNjAiIGhlaWdodD0iNDAiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTUzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgSW5oYWx0IGF1c2bDvGhyZW48L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iODQiIHgyPSIyMDAiIHkyPSIxMjYiLz4KICAgIDxwYXRoIGQ9Ik0xMjAgMTQ4IEM4MCAxNDgsIDgwIDY0LCAxMTggNjQiLz4KICAgIDxwYXRoIGQ9Ik0yODAgNjQgTDM0MCA2NCBMMzQwIDIwMCBMMjgyIDIwMCIvPgogIDwvZz4KICA8dGV4dCB4PSIyMDgiIHk9IjExMCIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dHJ1ZTwvdGV4dD4KICA8dGV4dCB4PSIzOCIgeT0iMTEwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj53aWVkZXI8L3RleHQ+CiAgPHRleHQgeD0iMzgiIHk9IjEyNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+bmFjaCBvYmVuPC90ZXh0PgogIDx0ZXh0IHg9IjM0OCIgeT0iMTM0IiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5mYWxzZTwvdGV4dD4KICA8dGV4dCB4PSIyNzYiIHk9IjIwNSIgdGV4dC1hbmNob3I9ImVuZCI+d2VpdGVyIHVudGVyIGRlciBTY2hsZWlmZTwvdGV4dD4KPC9zdmc+Cg==",bD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+a29wZmdlc3RldWVydCAoV2hpbGUpPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPmZ1w59nZXN0ZXVlcnQgKERvLXdoaWxlKTwvdGV4dD4KICA8bGluZSB4MT0iMjAwIiB5MT0iMTAiIHgyPSIyMDAiIHkyPSIyMjAiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxyZWN0IHg9IjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iNjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCBCZWRpbmd1bmc8L3RleHQ+CiAgPHJlY3QgeD0iMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIxNDciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoSBJbmhhbHQ8L3RleHQ+CiAgPHJlY3QgeD0iMjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIEluaGFsdDwvdGV4dD4KICA8cmVjdCB4PSIyMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjMwMCIgeT0iMTQ3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgQmVkaW5ndW5nPC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiPgogICAgPGxpbmUgeDE9IjEwMCIgeTE9IjgwIiB4Mj0iMTAwIiB5Mj0iMTIyIi8+CiAgICA8cGF0aCBkPSJNMzUgMTQyIEM4IDE0MiwgOCA2MiwgMzMgNjIiLz4KICAgIDxsaW5lIHgxPSIzMDAiIHkxPSI4MCIgeDI9IjMwMCIgeTI9IjEyMiIvPgogICAgPHBhdGggZD0iTTM2NSAxNDIgQzM5MiAxNDIsIDM5MiA2MiwgMzY3IDYyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjEwNiIgeT0iMTA2IiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTA2IiB0ZXh0LWFuY2hvcj0iZW5kIiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5Jc3QgZGllIEJlZGluZ3VuZyBnbGVpY2ggZmFsc2UsPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5sw6R1ZnQgZGVyIEluaGFsdCA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+bmllPC90c3Bhbj4uPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5EZXIgSW5oYWx0IGzDpHVmdCBpbW1lcjwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9IjIwNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+PHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPm1pbmRlc3RlbnMgZWlubWFsPC90c3Bhbj4uPC90ZXh0Pgo8L3N2Zz4K",xD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjUwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHJlY3QgeD0iMTIwIiB5PSIxNCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIFN0YXJ0IDx0c3BhbiBmaWxsPSIjNmU2ZTczIj4obnVyIGVpbm1hbCk8L3RzcGFuPjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9Ijc2IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iMTciIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGhIEJlZGluZ3VuZyBwcsO8ZmVuPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iMTM4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iNiIgZmlsbD0iI2RiZWFmZSIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGiIEluaGFsdCBhdXNmw7xocmVuPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iMjAwIiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iNiIgZmlsbD0iI2RjZmNlNyIgc3Ryb2tlPSIjMTU4MDNkIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGjIFNjaHJpdHQsIHouIEIuIGkrKzwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjIwMCIgeTI9Ijc0Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTEwIiB4Mj0iMjAwIiB5Mj0iMTM2Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTcyIiB4Mj0iMjAwIiB5Mj0iMTk4Ii8+CiAgICA8cGF0aCBkPSJNMTIwIDIxNyBDNjAgMjE3LCA2MCA5MywgMTE4IDkzIi8+CiAgICA8cGF0aCBkPSJNMjgwIDkzIEwzMzAgOTMiLz4KICA8L2c+CiAgPHRleHQgeD0iMjA4IiB5PSIxMjkiIGZpbGw9IiMxNTgwM2QiIGZvbnQtd2VpZ2h0PSI2MDAiPnRydWU8L3RleHQ+CiAgPHRleHQgeD0iNDgiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+enVyw7xjazwvdGV4dD4KICA8dGV4dCB4PSI0OCIgeT0iMTc2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj56dSDikaE8L3RleHQ+CiAgPHRleHQgeD0iMzAwIiB5PSI4NCIgZmlsbD0iI2I5MWMxYyIgZm9udC13ZWlnaHQ9IjYwMCI+ZmFsc2U8L3RleHQ+CiAgPHRleHQgeD0iMzM2IiB5PSI5OCI+ZmVydGlnPC90ZXh0Pgo8L3N2Zz4K",vD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMTkwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCI+aW50W10gemFobGVuID0gezIsIDQsIDYsIDgsIDEwfTwvdGV4dD4KICA8dGV4dCB4PSIyMCIgeT0iNTQiIGZpbGw9IiM2ZTZlNzMiIGZvbnQtc2l6ZT0iMTIiPkluZGV4PC90ZXh0PgogIDx0ZXh0IHg9IjkwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MDwvdGV4dD48cmVjdCB4PSI2MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjI8L3RleHQ+CiAgPHRleHQgeD0iMTUwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MTwvdGV4dD48cmVjdCB4PSIxMjAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTUwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+NDwvdGV4dD4KICA8dGV4dCB4PSIyMTAiIHk9IjU0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj4yPC90ZXh0PjxyZWN0IHg9IjE4MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyMTAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj42PC90ZXh0PgogIDx0ZXh0IHg9IjI3MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjM8L3RleHQ+PHJlY3QgeD0iMjQwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjI3MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjg8L3RleHQ+CiAgPHRleHQgeD0iMzMwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+NDwvdGV4dD48cmVjdCB4PSIzMDAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzMwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+MTA8L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjkwIiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj5XZXJ0PC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwN2FmZiIgc3Ryb2tlLXdpZHRoPSIxLjgiIG1hcmtlci1lbmQ9InVybCgjYSkiPjxsaW5lIHgxPSI5MCIgeTE9IjE0MCIgeDI9IjkwIiB5Mj0iMTEyIi8+PGxpbmUgeDE9IjMzMCIgeTE9IjE0MCIgeDI9IjMzMCIgeTI9IjExMiIvPjwvZz4KICA8ZyBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxMyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+PHRleHQgeD0iOTAiIHk9IjE1NiI+emFobGVuWzBdIGlzdCAyPC90ZXh0Pjx0ZXh0IHg9IjMzMCIgeT0iMTU2Ij56YWhsZW5bNF0gaXN0IDEwPC90ZXh0PjwvZz4KICA8dGV4dCB4PSIyMDAiIHk9IjE4MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+NSBGw6RjaGVyLCBnZXrDpGhsdCB3aXJkIGFiIDA6IGRlciBsZXR6dGUgSW5kZXggaXN0IDQuPC90ZXh0Pgo8L3N2Zz4K",yD=""+new URL("mvc-klick-KmFKqxH-.svg",import.meta.url).href,wD=""+new URL("aufgabe-mehrwertsteuer-KUkerRBd.svg",import.meta.url).href,zD=""+new URL("kino-saal-BOvcmdzb.svg",import.meta.url).href,ID=""+new URL("kino-schleifen-Ci9yPnbo.svg",import.meta.url).href,kD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDkyIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iNDkyIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiPgogICAgPCEtLSBTdGFydCAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMTAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjgiIHJ4PSIxNCIgZmlsbD0iI2QxZjJkOSIvPgogICAgPGxpbmUgeDE9IjE1MCIgeTE9IjM4IiB4Mj0iMTUwIiB5Mj0iNTQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gQW53ZWlzdW5nIC0tPgogICAgPHJlY3QgeD0iNTAiIHk9IjU2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iODYiIHgyPSIxNTAiIHkyPSI5OCIgbWFya2VyLWVuZD0idXJsKCNhKSIvPgogICAgPCEtLSBSYXV0ZSAxIC0tPgogICAgPHBhdGggZD0iTTE1MCAxMDAgTDIzNSAxMjggTDE1MCAxNTYgTDY1IDEyOCBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMTU2IiB4Mj0iMTUwIiB5Mj0iMTcyIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8cmVjdCB4PSI1MCIgeT0iMTc0IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMjA0IiB4Mj0iMTUwIiB5Mj0iMjUwIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIG5laW4tV2VnIHVtIGRlbiBLYXN0ZW4gaGVydW0gLS0+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIyMzUsMTI4IDI4NSwxMjggMjg1LDIyMiAxNTAsMjIyIiBmaWxsPSJub25lIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIFJhdXRlIDIgLS0+CiAgICA8cGF0aCBkPSJNMTUwIDI1MiBMMjM1IDI4MCBMMTUwIDMwOCBMNjUgMjgwIFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxsaW5lIHgxPSIyMzUiIHkxPSIyODAiIHgyPSIyNjgiIHkyPSIyODAiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjI3MCIgeT0iMjY1IiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8IS0tIHp1csO8Y2sgenVyIFByw7xmdW5nIC0tPgogICAgPHBvbHlsaW5lIHBvaW50cz0iMzI3LDI2NSAzMjcsMjM4IDE1MCwyMzgiIGZpbGw9Im5vbmUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzMDgiIHgyPSIxNTAiIHkyPSIzMjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjUwIiB5PSIzMjgiIHdpZHRoPSIyMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNlNWYwZmYiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzNTgiIHgyPSIxNTAiIHkyPSIzNzQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gRW5kZSAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjI4IiByeD0iMTQiIGZpbGw9IiNkMWYyZDkiLz4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSI+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI5Ij5JbsOtY2lvPC90ZXh0PgogICAgPHRleHQgeD0iMTUwIiB5PSI3NiI+UMO0ciB1bWEgY2jDoXZlbmEgbmEgbWVzYTwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTMzIj5RdWVyIGHDp8O6Y2FyPzwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTk0Ij5KdW50YXIgYcOnw7pjYXI8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI4NSI+Q2jDoSBtdWl0byBxdWVudGU/PC90ZXh0PgogICAgPHRleHQgeD0iMzI3LjUiIHk9IjI4NSI+RXNwZXJhciAxIG1pbnV0bzwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzQ4Ij5CZWJlciBvIGNow6E8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjM5NSI+RmltPC90ZXh0PgogIDwvZz4KICA8ZyBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNjAwIj4KICAgIDx0ZXh0IHg9IjE1NiIgeT0iMTY4IiBmaWxsPSIjMjQ4YTNkIj5zaW08L3RleHQ+CiAgICA8dGV4dCB4PSIyNDIiIHk9IjEyMiIgZmlsbD0iI2Q3MDAxNSI+bsOjbzwvdGV4dD4KICAgIDx0ZXh0IHg9IjI0MCIgeT0iMjc0IiBmaWxsPSIjMjQ4YTNkIj5zaW08L3RleHQ+CiAgICA8dGV4dCB4PSIxNTYiIHk9IjMyMCIgZmlsbD0iI2Q3MDAxNSI+bsOjbzwvdGV4dD4KICA8L2c+CiAgPCEtLSBMZWdlbmRlIC0tPgogIDxsaW5lIHgxPSIxMCIgeTE9IjQxOCIgeDI9IjM5MCIgeTI9IjQxOCIgc3Ryb2tlPSIjZDFkMWQ2Ii8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuNSI+CiAgICA8cmVjdCB4PSI0MCIgeT0iNDMwIiB3aWR0aD0iMzYiIGhlaWdodD0iMTgiIHJ4PSI5IiBmaWxsPSIjZDFmMmQ5Ii8+CiAgICA8cmVjdCB4PSIyMjAiIHk9IjQzMCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjE4IiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8cGF0aCBkPSJNNTggNDU4IEw3NiA0NjkgTDU4IDQ4MCBMNDAgNDY5IFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxwYXRoIGQ9Ik0yMjYgNDYwIEwyNTYgNDYwIEwyNTAgNDc4IEwyMjAgNDc4IFoiIGZpbGw9IiNmMmU2ZmYiLz4KICA8L2c+CiAgPGcgZm9udC1zaXplPSIxMiIgZmlsbD0iIzNhM2EzYyI+CiAgICA8dGV4dCB4PSI4NiIgeT0iNDQzIj5JbsOtY2lvIG91IGZpbTwvdGV4dD4KICAgIDx0ZXh0IHg9IjI2NiIgeT0iNDQzIj5JbnN0cnXDp8OjbzwvdGV4dD4KICAgIDx0ZXh0IHg9Ijg2IiB5PSI0NzMiPkRlY2lzw6NvPC90ZXh0PgogICAgPHRleHQgeD0iMjY2IiB5PSI0NzMiPkVudHJhZGEgb3Ugc2HDrWRhPC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",SD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE5MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwIiB5PSIyNCIgZm9udC13ZWlnaHQ9IjYwMCI+T25kZSBmaWNhIG8gZWxlbWVudG8/PC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSI0MCIgd2lkdGg9IjE5MCIgaGVpZ2h0PSIzNSIgZmlsbD0iI2RiZWFmZSIvPgogIDxyZWN0IHg9IjIwIiB5PSI3NSIgd2lkdGg9IjE5MCIgaGVpZ2h0PSIzNSIgZmlsbD0iI2RjZmNlNyIvPgogIDxsaW5lIHgxPSIyMCIgeTE9Ijc1IiB4Mj0iMjEwIiB5Mj0iNzUiIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLWRhc2hhcnJheT0iNCAzIi8+CiAgPHJlY3QgeD0iMjAiIHk9IjQwIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjcwIiBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjExNSIgeT0iNjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxZDRlZDgiPm1ldGFkZSBkZSBjaW1hPC90ZXh0PgogIDx0ZXh0IHg9IjExNSIgeT0iOTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPm1ldGFkZSBkZSBiYWl4bzwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9IjYyIj7ihpIgZmljYSA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+YW50ZXM8L3RzcGFuPjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9Ijk3Ij7ihpIgZmljYSA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+ZGVwb2lzPC90c3Bhbj48L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjEzMiIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI0MCIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjE1NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiI+w7g8L3RleHQ+CiAgPHRleHQgeD0iMjI0IiB5PSIxNTciPuKGkiA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+c3Vic3RpdHVpLW88L3RzcGFuPjwvdGV4dD4KPC9zdmc+Cg==",TD=""+new URL("l03-lochkarte-beschriftet-D1QjqGFo.svg",import.meta.url).href,_D=""+new URL("l03-lochkarte-BSn6oWaS.svg",import.meta.url).href,OD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgMjcwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CjxyZWN0IHdpZHRoPSI0NjAiIGhlaWdodD0iMjcwIiBmaWxsPSIjZmZmZmZmIi8+Cjx0ZXh0IHg9IjYyIiB5PSI0NCIgZm9udC1zaXplPSI0MCIgZmlsbD0iIzZlNmU3MyIgdGV4dExlbmd0aD0iMjY0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmdBbmRHbHlwaHMiPnByZWNvPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPkM8L3RzcGFuPm9tPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPkk8L3RzcGFuPnZhPC90ZXh0Pgo8bGluZSB4MT0iMTk0IiB5MT0iNTQiIHgyPSIxOTQiIHkyPSI4NCIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSA0Ii8+CjxsaW5lIHgxPSIyNjYiIHkxPSI1NCIgeDI9IjI2NiIgeTI9Ijg0IiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtZGFzaGFycmF5PSI1IDQiLz4KPHBhdGggZD0iTTE0NiAxODUgTDE0MiAyMTQgTDE0NiAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2M5OTk1YiIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xNjYgMTg1IEwxNzAgMjE0IEwxNjYgMjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiM4YTYyMzMiIHN0cm9rZS13aWR0aD0iMTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMjk1IDE4NSBMMjkxIDIxNCBMMjk1IDI0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYzk5OTViIiBzdHJva2Utd2lkdGg9IjEwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTMxNSAxODUgTDMxOSAyMTQgTDMxNSAyNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIxMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xMjYgMTUwIEMxMTAgMTYwIDExMCAxODUgMTE4IDE5OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTM0IDE5MiBDMTE4IDE3OCAxMTggMTQ2IDE0MCAxNDAgQzE1OCAxMzggMTY0IDg2IDE5NCA4NiBDMjI0IDg2IDIyNCAxMzYgMjMwIDEzNCBDMjM2IDEzNiAyMzYgODYgMjY2IDg2IEMyOTYgODYgMjk0IDEzNiAzMTEgMTQwIEMzMzEgMTQyIDMzOSAxMTggMzQ1IDEwMCBDMzQ5IDg2IDM1OSA4MCAzNzMgODAgQzM4NyA4MCAzOTUgODYgMzk3IDk0IEMzOTkgMTAyIDM4NyAxMDYgMzcxIDEwNiBDMzYzIDEzMCAzNTMgMTY4IDMyOSAxODYgQzI2MCAyMDYgMjAwIDIwNiAxMzQgMTkyIFoiIGZpbGw9IiNjOTk5NWIiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyLjUiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTM2MSA4NCBMMzU3IDcyIEwzNjggODEgWiIgZmlsbD0iI2M5OTk1YiIgc3Ryb2tlPSIjOGE2MjMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPGNpcmNsZSBjeD0iMzc5IiBjeT0iOTAiIHI9IjMuMiIgZmlsbD0iIzFjMWMxZSIvPgo8cGF0aCBkPSJNMzg5IDEwMCBRMzkzIDEwMiAzOTYgOTkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhhNjIzMyIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTMwIDI0MiBINDMwIiBzdHJva2U9IiNkMWQxZDYiIHN0cm9rZS13aWR0aD0iMyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=",AD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjEwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIxMCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjE2Ij5pbnQgaWRhZGUgPSAxNDwvdGV4dD4KICA8cGF0aCBkPSJNMTMwIDcwIEwxNzAgNTAgTDMwMCA1MCBMMjYwIDcwIFoiIGZpbGw9IiNjOThhM2MiIHN0cm9rZT0iIzhhNWExZiIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHJlY3QgeD0iMTgwIiB5PSIzNCIgd2lkdGg9IjQ0IiBoZWlnaHQ9IjUwIiByeD0iMyIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjEuNSIvPgogIDx0ZXh0IHg9IjIwMiIgeT0iNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI3MDAiPjE0PC90ZXh0PgogIDxyZWN0IHg9IjEzMCIgeT0iNzAiIHdpZHRoPSIxMzAiIGhlaWdodD0iMTAwIiBmaWxsPSIjZTliODcyIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxwYXRoIGQ9Ik0yNjAgNzAgTDMwMCA1MCBMMzAwIDE1MCBMMjYwIDE3MCBaIiBmaWxsPSIjZDQ5YTRjIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjE1MCIgeT0iMTAwIiB3aWR0aD0iOTAiIGhlaWdodD0iMzAiIHJ4PSI0IiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiM4YTVhMWYiLz4KICA8dGV4dCB4PSIxOTUiIHk9IjEyMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+aWRhZGU8L3RleHQ+CiAgPHJlY3QgeD0iMTM4IiB5PSIxNDIiIHdpZHRoPSIzNCIgaGVpZ2h0PSIyMCIgcng9IjEwIiBmaWxsPSIjMDA3YWZmIi8+CiAgPHRleHQgeD0iMTU1IiB5PSIxNTYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiNmZmZmZmYiIGZvbnQtd2VpZ2h0PSI2MDAiPmludDwvdGV4dD4KICA8ZyBzdHJva2U9IiM2ZTZlNzMiPgogICAgPGxpbmUgeDE9IjMxMCIgeTE9IjQ4IiB4Mj0iMjI2IiB5Mj0iNTIiLz4KICAgIDxsaW5lIHgxPSIzMTAiIHkxPSIxMTUiIHgyPSIyNDIiIHkyPSIxMTUiLz4KICAgIDxsaW5lIHgxPSI4MCIgeTE9IjE1MiIgeDI9IjEzNCIgeTI9IjE1MiIvPgogIDwvZz4KICA8dGV4dCB4PSIzMTYiIHk9IjUyIj5WYWxvcjwvdGV4dD4KICA8dGV4dCB4PSIzMTYiIHk9IjExOSI+Tm9tZTwvdGV4dD4KICA8dGV4dCB4PSI4IiB5PSIxNTYiPlRpcG8gZGUgZGFkb3M8L3RleHQ+CiAgPHRleHQgeD0iMjAwIiB5PSIxOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPlBlbG8gbm9tZSBjaGVnYXMgYW8gdmFsb3IuPC90ZXh0Pgo8L3N2Zz4K",CD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiPgogICAgPHRleHQgeD0iNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+cG9udG9zPC90ZXh0PgogICAgPHRleHQgeD0iMTI1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPj08L3RleHQ+CiAgICA8dGV4dCB4PSIyNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9udG9zICsgNTwvdGV4dD4KICA8L2c+CiAgPHJlY3QgeD0iMTgwIiB5PSI4NiIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjYwIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPuKRoCBjYWxjdWxhciBhIGRpcmVpdGE6IDEwICsgNSA9IDE1PC90ZXh0PgogIDxwYXRoIGQ9Ik0yNTAgODIgQzIzMCAzMCwgOTAgMzAsIDY0IDg0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgPHRleHQgeD0iMTYwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiI+4pGhIGd1YXJkYXIgbyByZXN1bHRhZG8gw6AgZXNxdWVyZGE8L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjE2NCIgd2lkdGg9IjM2MCIgaGVpZ2h0PSIyNiIgcng9IjYiIGZpbGw9IiNmMmYyZjciLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE4MiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9udG9zIGFudGVzOiA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCI+MTA8L3RzcGFuPiAgIOKGkiAgIHBvbnRvcyBkZXBvaXM6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xNTwvdHNwYW4+PC90ZXh0Pgo8L3N2Zz4K",jD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMzAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMzAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiPgogICAgPHBhdGggZD0iTTQwIDExMCBMNDggMTgwIEwxMDIgMTgwIEwxMTAgMTEwIi8+CiAgICA8cGF0aCBkPSJNMTY1IDExMCBMMTczIDE4MCBMMjI3IDE4MCBMMjM1IDExMCIvPgogICAgPHBhdGggZD0iTTI5MCAxMTAgTDI5OCAxODAgTDM1MiAxODAgTDM2MCAxMTAiLz4KICA8L2c+CiAgPHBhdGggZD0iTTQ0IDEzNSBMNDggMTgwIEwxMDIgMTgwIEwxMDYgMTM1IFoiIGZpbGw9IiNmZGJhNzQiLz4KICA8cGF0aCBkPSJNMjk0IDEzNSBMMjk4IDE4MCBMMzUyIDE4MCBMMzU2IDEzNSBaIiBmaWxsPSIjOTNjNWZkIi8+CiAgPHRleHQgeD0iNzUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+ZXNxdWVyZGE8L3RleHQ+CiAgPHRleHQgeD0iNzUiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+c3VtbzwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+YXV4PC90ZXh0PgogIDx0ZXh0IHg9IjIwMCIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj52YXppbzwvdGV4dD4KICA8dGV4dCB4PSIzMjUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+ZGlyZWl0YTwvdGV4dD4KICA8dGV4dCB4PSIzMjUiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+w6FndWE8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8cGF0aCBkPSJNODggMTA0IEMxMTAgNzAsIDE2MCA3MCwgMTg2IDEwNCIvPgogICAgPHBhdGggZD0iTTMxOCAxMDQgQzI3MCAxNSwgMTMwIDE1LCA4MiAxMDQiLz4KICAgIDxwYXRoIGQ9Ik0yMTQgMTA0IEMyNDAgNzAsIDI5MCA3MCwgMzEyIDEwNCIvPgogIDwvZz4KICA8ZyBmb250LXdlaWdodD0iNzAwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4KICAgIDxjaXJjbGUgY3g9IjEzNyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMTM3IiB5PSI4NSI+MTwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjIwMCIgY3k9IjM4IiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjAwIiB5PSI0MyI+MjwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjI2MyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjYzIiB5PSI4NSI+MzwvdGV4dD4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTIiPgogICAgPHRleHQgeD0iMjAwIiB5PSIyNTAiPjE6IGF1eCA9IGVzcXVlcmRhPC90ZXh0PgogICAgPHRleHQgeD0iMjAwIiB5PSIyNjgiPjI6IGVzcXVlcmRhID0gZGlyZWl0YTwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMjg2Ij4zOiBkaXJlaXRhID0gYXV4PC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",PD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDxyZWN0IHg9IjIwIiB5PSI1MCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+PHJlY3QgeD0iMzAwIiB5PSI1MCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+CiAgPHJlY3QgeD0iMTAwIiB5PSI1MCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyNCIgZmlsbD0iI2RjZmNlNyIvPgogIDxsaW5lIHgxPSIyMCIgeTE9Ijc0IiB4Mj0iMzgwIiB5Mj0iNzQiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPGxpbmUgeDE9IjUwIiB5MT0iNjgiIHgyPSI1MCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjUwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MDwvdGV4dD4KICA8bGluZSB4MT0iMTAwIiB5MT0iNjgiIHgyPSIxMDAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIxMDAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4xPC90ZXh0PgogIDxsaW5lIHgxPSIxNTAiIHkxPSI2OCIgeDI9IjE1MCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjE1MCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjI8L3RleHQ+CiAgPGxpbmUgeDE9IjIwMCIgeTE9IjY4IiB4Mj0iMjAwIiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MzwvdGV4dD4KICA8bGluZSB4MT0iMjUwIiB5MT0iNjgiIHgyPSIyNTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyNTAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj40PC90ZXh0PgogIDxsaW5lIHgxPSIzMDAiIHkxPSI2OCIgeDI9IjMwMCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjMwMCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjU8L3RleHQ+CiAgPGxpbmUgeDE9IjM1MCIgeTE9IjY4IiB4Mj0iMzUwIiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzUwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NjwvdGV4dD4KICA8Y2lyY2xlIGN4PSIxMDAiIGN5PSI3NCIgcj0iNiIgZmlsbD0iIzE1ODAzZCIvPjxjaXJjbGUgY3g9IjMwMCIgY3k9Ijc0IiByPSI2IiBmaWxsPSIjMTU4MDNkIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dsOhbGlkYTwvdGV4dD4KICA8dGV4dCB4PSI1MCIgeT0iNDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPmludsOhbGlkYTwvdGV4dD48dGV4dCB4PSIzNTAiIHk9IjQwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5pbnbDoWxpZGE8L3RleHQ+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPHRleHQgeD0iMjAwIiB5PSIxMjQiIGZpbGw9IiMxNTgwM2QiPm5vdGEgJmd0Oz0gMSAmYW1wOyZhbXA7IG5vdGEgJmx0Oz0gNTwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMTQyIiBmaWxsPSIjYjkxYzFjIj5ub3RhICZsdDsgMSB8fCBub3RhICZndDsgNTwvdGV4dD4KICA8L2c+Cjwvc3ZnPgo=",DD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIj5Db21vIGZ1bmNpb25hIG8gY2ljbG8gd2hpbGU8L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSI0NCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI0MCIgcng9IjIwIiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iNjkiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCB2ZXJpZmljYXIgYSBjb25kacOnw6NvPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iMTI4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjQwIiByeD0iNiIgZmlsbD0iI2RiZWFmZSIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE1MyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGhIGV4ZWN1dGFyIG8gaW50ZXJpb3I8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iODQiIHgyPSIyMDAiIHkyPSIxMjYiLz4KICAgIDxwYXRoIGQ9Ik0xMjAgMTQ4IEM4MCAxNDgsIDgwIDY0LCAxMTggNjQiLz4KICAgIDxwYXRoIGQ9Ik0yODAgNjQgTDM0MCA2NCBMMzQwIDIwMCBMMjgyIDIwMCIvPgogIDwvZz4KICA8dGV4dCB4PSIyMDgiIHk9IjExMCIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dHJ1ZTwvdGV4dD4KICA8dGV4dCB4PSIzOCIgeT0iMTEwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj52b2x0YXI8L3RleHQ+CiAgPHRleHQgeD0iMzgiIHk9IjEyNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+cGFyYSBjaW1hPC90ZXh0PgogIDx0ZXh0IHg9IjM0OCIgeT0iMTM0IiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5mYWxzZTwvdGV4dD4KICA8dGV4dCB4PSIyNzYiIHk9IjIwNSIgdGV4dC1hbmNob3I9ImVuZCI+Y29udGludWFyIHBvciBiYWl4byBkbyBjaWNsbzwvdGV4dD4KPC9zdmc+Cg==",BD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+cHLDqS10ZXN0ZSAod2hpbGUpPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPnDDs3MtdGVzdGUgKGRvLXdoaWxlKTwvdGV4dD4KICA8bGluZSB4MT0iMjAwIiB5MT0iMTAiIHgyPSIyMDAiIHkyPSIyMjAiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxyZWN0IHg9IjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iNjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCBjb25kacOnw6NvPC90ZXh0PgogIDxyZWN0IHg9IjM1IiB5PSIxMjQiIHdpZHRoPSIxMzAiIGhlaWdodD0iMzYiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iMTQ3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgaW50ZXJpb3I8L3RleHQ+CiAgPHJlY3QgeD0iMjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIGludGVyaW9yPC90ZXh0PgogIDxyZWN0IHg9IjIzNSIgeT0iMTI0IiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjM2IiByeD0iMTgiIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSIxNDciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoSBjb25kacOnw6NvPC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiPgogICAgPGxpbmUgeDE9IjEwMCIgeTE9IjgwIiB4Mj0iMTAwIiB5Mj0iMTIyIi8+CiAgICA8cGF0aCBkPSJNMzUgMTQyIEM4IDE0MiwgOCA2MiwgMzMgNjIiLz4KICAgIDxsaW5lIHgxPSIzMDAiIHkxPSI4MCIgeDI9IjMwMCIgeTI9IjEyMiIvPgogICAgPHBhdGggZD0iTTM2NSAxNDIgQzM5MiAxNDIsIDM5MiA2MiwgMzY3IDYyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjEwNiIgeT0iMTA2IiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTA2IiB0ZXh0LWFuY2hvcj0iZW5kIiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5TZSBhIGNvbmRpw6fDo28gZm9yIGxvZ28gZmFsc2EsPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5vIGludGVyaW9yIDx0c3BhbiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjMWMxYzFlIj5udW5jYTwvdHNwYW4+IMOpIGV4ZWN1dGFkby48L3RleHQ+CiAgPHRleHQgeD0iMzAwIiB5PSIxOTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPk8gaW50ZXJpb3Igw6kgc2VtcHJlIGV4ZWN1dGFkbzwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9IjIwNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+PHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPnBlbG8gbWVub3MgdW1hIHZlejwvdHNwYW4+LjwvdGV4dD4KPC9zdmc+Cg==",ZD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjUwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHJlY3QgeD0iMTIwIiB5PSIxNCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIEluw61jaW8gPHRzcGFuIGZpbGw9IiM2ZTZlNzMiPihzw7MgdW1hIHZleik8L3RzcGFuPjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9Ijc2IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iMTciIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGhIHZlcmlmaWNhciBhIGNvbmRpw6fDo288L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSIxMzgiIHdpZHRoPSIxNjAiIGhlaWdodD0iMzQiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTYwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaIgZXhlY3V0YXIgbyBpbnRlcmlvcjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjIwMCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIyMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoyBwYXNzbywgcC4gZXguIGkrKzwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjIwMCIgeTI9Ijc0Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTEwIiB4Mj0iMjAwIiB5Mj0iMTM2Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTcyIiB4Mj0iMjAwIiB5Mj0iMTk4Ii8+CiAgICA8cGF0aCBkPSJNMTIwIDIxNyBDNjAgMjE3LCA2MCA5MywgMTE4IDkzIi8+CiAgICA8cGF0aCBkPSJNMjgwIDkzIEwzMzAgOTMiLz4KICA8L2c+CiAgPHRleHQgeD0iMjA4IiB5PSIxMjkiIGZpbGw9IiMxNTgwM2QiIGZvbnQtd2VpZ2h0PSI2MDAiPnRydWU8L3RleHQ+CiAgPHRleHQgeD0iNDgiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+dm9sdGFyPC90ZXh0PgogIDx0ZXh0IHg9IjQ4IiB5PSIxNzYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPmFvIOKRoTwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9Ijg0IiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5mYWxzZTwvdGV4dD4KICA8dGV4dCB4PSIzMzYiIHk9Ijk4Ij5maW08L3RleHQ+Cjwvc3ZnPgo=",MD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMTkwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCI+aW50W10gbnVtZXJvcyA9IHsyLCA0LCA2LCA4LCAxMH08L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjU0IiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj7DjW5kaWNlPC90ZXh0PgogIDx0ZXh0IHg9IjkwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MDwvdGV4dD48cmVjdCB4PSI2MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjI8L3RleHQ+CiAgPHRleHQgeD0iMTUwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MTwvdGV4dD48cmVjdCB4PSIxMjAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTUwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+NDwvdGV4dD4KICA8dGV4dCB4PSIyMTAiIHk9IjU0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj4yPC90ZXh0PjxyZWN0IHg9IjE4MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyMTAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj42PC90ZXh0PgogIDx0ZXh0IHg9IjI3MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjM8L3RleHQ+PHJlY3QgeD0iMjQwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjI3MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjg8L3RleHQ+CiAgPHRleHQgeD0iMzMwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+NDwvdGV4dD48cmVjdCB4PSIzMDAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzMwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+MTA8L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjkwIiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj5WYWxvcjwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj48bGluZSB4MT0iOTAiIHkxPSIxNDAiIHgyPSI5MCIgeTI9IjExMiIvPjxsaW5lIHgxPSIzMzAiIHkxPSIxNDAiIHgyPSIzMzAiIHkyPSIxMTIiLz48L2c+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjx0ZXh0IHg9IjkwIiB5PSIxNTYiPm51bWVyb3NbMF0gw6kgMjwvdGV4dD48dGV4dCB4PSIzMzAiIHk9IjE1NiI+bnVtZXJvc1s0XSDDqSAxMDwvdGV4dD48L2c+CiAgPHRleHQgeD0iMjAwIiB5PSIxODIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPjUgcG9zacOnw7VlcywgY29udGEtc2UgYSBwYXJ0aXIgZGUgMDogbyDDumx0aW1vIMOtbmRpY2Ugw6kgNC48L3RleHQ+Cjwvc3ZnPgo=",LD=""+new URL("mvc-klick-DKonBpbs.svg",import.meta.url).href,ED=""+new URL("schiffe-versenken-iEBDHIxD.svg",import.meta.url).href,WD=""+new URL("ss-binaere-suche-DVVS2SNc.svg",import.meta.url).href,ND=""+new URL("ss-bubblesort-AFDcFDah.svg",import.meta.url).href,FD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDQgMTk2IiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KPHJlY3Qgd2lkdGg9IjQwNCIgaGVpZ2h0PSIxOTYiIGZpbGw9IiNmZmZmZmYiLz4KPHRleHQgeD0iMTQiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIiBmb250LXNpemU9IjE1Ij5Qcm9jdXJhLXNlIG8gOS4gQXMgY2FydGFzIGVzdMOjbyBiYXJhbGhhZGFzLjwvdGV4dD4KPGc+PHJlY3QgeD0iMTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjM0LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjc8L3RleHQ+PHRleHQgeD0iMzQuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNkYzI2MjYiPuKZpTwvdGV4dD48L2c+Cjx0ZXh0IHg9IjM0LjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIzNC4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjEuPC90ZXh0Pgo8Zz48cmVjdCB4PSI2MiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iODIuMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+MzwvdGV4dD48dGV4dCB4PSI4Mi4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+4pmgPC90ZXh0PjwvZz4KPHRleHQgeD0iODIuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZGMyNjI2Ij7inJc8L3RleHQ+Cjx0ZXh0IHg9IjgyLjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+Mi48L3RleHQ+CjxnPjxyZWN0IHg9IjExMCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iMTMwLjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjEwPC90ZXh0Pjx0ZXh0IHg9IjEzMC4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iI2RjMjYyNiI+4pmmPC90ZXh0PjwvZz4KPHRleHQgeD0iMTMwLjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIxMzAuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj4zLjwvdGV4dD4KPGc+PHJlY3QgeD0iMTU4IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48dGV4dCB4PSIxNzguMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+NTwvdGV4dD48dGV4dCB4PSIxNzguMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiMxYzFjMWUiPuKZozwvdGV4dD48L2c+Cjx0ZXh0IHg9IjE3OC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMTc4LjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+NC48L3RleHQ+CjxnPjxyZWN0IHg9IjIwNiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIzIi8+PHRleHQgeD0iMjI2LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjk8L3RleHQ+PHRleHQgeD0iMjI2LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxYzFlIj7imaA8L3RleHQ+PC9nPgo8dGV4dCB4PSIyMjYuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjMTU4MDNkIj7inJM8L3RleHQ+Cjx0ZXh0IHg9IjIyNi4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjUuPC90ZXh0Pgo8Zz48cmVjdCB4PSIyNTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjMWQ0ZWQ4IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjxyZWN0IHg9IjI1OCIgeT0iNTQiIHdpZHRoPSIzMiIgaGVpZ2h0PSI0OCIgcng9IjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzkzYzVmZCIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMiIvPjwvZz4KPGc+PHJlY3QgeD0iMzAyIiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iIzFkNGVkOCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSIzMDYiIHk9IjU0IiB3aWR0aD0iMzIiIGhlaWdodD0iNDgiIHJ4PSIzIiBmaWxsPSJub25lIiBzdHJva2U9IiM5M2M1ZmQiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtZGFzaGFycmF5PSIzIDIiLz48L2c+CjxnPjxyZWN0IHg9IjM1MCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiMxZDRlZDgiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHJlY3QgeD0iMzU0IiB5PSI1NCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjQ4IiByeD0iMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTNjNWZkIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWRhc2hhcnJheT0iMyAyIi8+PC9nPgo8dGV4dCB4PSIxNCIgeT0iMTY4IiBmb250LXNpemU9IjE1IiBmaWxsPSIjNmU2ZTczIj5WaXJhciBkYSBlc3F1ZXJkYSBwYXJhIGEgZGlyZWl0YTo8L3RleHQ+PHRleHQgeD0iMTQiIHk9IjE4OCIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzZlNmU3MyI+QXDDs3MgNSBjb21wYXJhw6fDtWVzLCBvIDkgw6kgZW5jb250cmFkby48L3RleHQ+Cjwvc3ZnPgo=",JD=""+new URL("ss-vergleiche-DWgkIvLr.svg",import.meta.url).href,RD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjAgNDUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KPGRlZnM+PG1hcmtlciBpZD0iayIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDEwIDUgTDAgMTAgWiIgZmlsbD0iIzFjMWMxZSIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImIiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjYiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNMCAwIEwxMCA1IEwwIDEwIFoiIGZpbGw9IiMxZDRlZDgiLz48L21hcmtlcj48bWFya2VyIGlkPSJvIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjYjQ1MzA5Ii8+PC9tYXJrZXI+PC9kZWZzPgo8cmVjdCB3aWR0aD0iNDIwIiBoZWlnaHQ9IjQ1MCIgZmlsbD0iI2ZmZmZmZiIvPgo8dGV4dCB4PSIxMCIgeT0iMjIiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI3MDAiPlBhc3NhZ2VtIHBvciB2YWxvcjogdW1hIGPDs3BpYTwvdGV4dD4KPHJlY3QgeD0iMTAiIHk9IjM4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9Ijg2IiByeD0iOCIgZmlsbD0iI2VmZjZmZiIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8dGV4dCB4PSIyMCIgeT0iNTgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPlByb2dyYW1hIHByaW5jaXBhbDwvdGV4dD4KPHRleHQgeD0iMTYiIHk9Ijk4IiBmb250LXNpemU9IjEyIj5udW1lcm88L3RleHQ+CjxyZWN0IHg9IjcwIiB5PSI3OCIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9Ijk4IiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+NTwvdGV4dD4KPHJlY3QgeD0iMjUwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNmZmY3ZWQiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjYwIiB5PSI1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+ZHVwbGljYXI8L3RleHQ+Cjx0ZXh0IHg9IjI2MCIgeT0iOTgiPng8L3RleHQ+CjxyZWN0IHg9IjI4MCIgeT0iNzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMCIgcng9IjQiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8dGV4dCB4PSIzMjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dHNwYW4gZmlsbD0iIzZlNmU3MyIgdGV4dC1kZWNvcmF0aW9uPSJsaW5lLXRocm91Z2giPjU8L3RzcGFuPiA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCI+MTA8L3RzcGFuPjwvdGV4dD4KPGxpbmUgeDE9IjEyOCIgeTE9IjkzIiB4Mj0iMjQ4IiB5Mj0iOTMiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNCIgbWFya2VyLWVuZD0idXJsKCNrKSIvPgo8dGV4dCB4PSIyMTAiIHk9Ijg0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5jw7NwaWE8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxNTAiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPnggcGFzc2EgYSAxMCwgbWFzIG51bWVybyBmaWNhIDUuPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iMTY4IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj5Db21vIHVtYSBmb3RvY8OzcGlhOiBlc2NyZXZlciBuYSBjw7NwaWE8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxODYiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPm7Do28gYWx0ZXJhIG8gb3JpZ2luYWwuPC90ZXh0Pgo8bGluZSB4MT0iMTAiIHkxPSIyMDgiIHgyPSI0MTAiIHkyPSIyMDgiIHN0cm9rZT0iI2QxZDFkNiIvPgo8dGV4dCB4PSIxMCIgeT0iMjM2IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNzAwIj5QYXNzYWdlbSBwb3IgcmVmZXLDqm5jaWE6IG8gbWVzbW8gYXJyYXk8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZWZmNmZmIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjIwIiB5PSIyNzIiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPlByb2dyYW1hIHByaW5jaXBhbDwvdGV4dD4KPHRleHQgeD0iMjAiIHk9IjMwMCI+ZmlsYTwvdGV4dD4KPGNpcmNsZSBjeD0iMTUwIiBjeT0iMjk1IiByPSI1IiBmaWxsPSIjMWQ0ZWQ4Ii8+CjxyZWN0IHg9IjI1MCIgeT0iMjUyIiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjYyIiByeD0iOCIgZmlsbD0iI2ZmZjdlZCIgc3Ryb2tlPSIjYjQ1MzA5IiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8dGV4dCB4PSIyNjAiIHk9IjI3MiIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+bGltcGFyPC90ZXh0Pgo8dGV4dCB4PSIyNjAiIHk9IjMwMCI+bHVnYXJlczwvdGV4dD4KPGNpcmNsZSBjeD0iMzkwIiBjeT0iMjk1IiByPSI1IiBmaWxsPSIjYjQ1MzA5Ii8+CjxwYXRoIGQ9Ik0xNTAgMzAwIEwxNTAgMzQwIEwxNDAgMzUyIiBmaWxsPSJub25lIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41IiBtYXJrZXItZW5kPSJ1cmwoI2IpIi8+CjxwYXRoIGQ9Ik0zOTAgMzAwIEwzOTAgMzQwIEwzMjIgMzU0IiBmaWxsPSJub25lIiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMS41IiBtYXJrZXItZW5kPSJ1cmwoI28pIi8+CjxyZWN0IHg9IjkwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+CjxyZWN0IHg9IjE1MCIgeT0iMzU4IiB3aWR0aD0iNjAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8cmVjdCB4PSIyMTAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHJlY3QgeD0iMjcwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9IjEyMCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMTgwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIyNDAiIHk9IjM3OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+ZmFsc2U8L3RleHQ+Cjx0ZXh0IHg9IjMwMCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjQxNiIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+U8OzIGjDoSB1bSBhcnJheS4gTyBxdWUgbGltcGFyIGFsdGVyYSBhdHJhdsOpcyBkZSBsdWdhcmVzLDwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjQzNCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+byBwcm9ncmFtYSBwcmluY2lwYWwgdsOqIGVtIGZpbGEuPC90ZXh0Pgo8L3N2Zz4K",GD=""+new URL("zk-zeichen-8efNmpGx.svg",import.meta.url).href,HD=""+new URL("schiffe-versenken-CXt1SF0S.svg",import.meta.url).href,VD=""+new URL("ss-binaere-suche-CPsLGldq.svg",import.meta.url).href,qD=""+new URL("ss-bubblesort-Dic2ZfaT.svg",import.meta.url).href,QD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDQgMTk2IiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KPHJlY3Qgd2lkdGg9IjQwNCIgaGVpZ2h0PSIxOTYiIGZpbGw9IiNmZmZmZmYiLz4KPHRleHQgeD0iMTQiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIiBmb250LXNpemU9IjE1Ij5HZXN1Y2h0OiBkaWUgOS4gRGllIEthcnRlbiBzaW5kIGdlbWlzY2h0LjwvdGV4dD4KPGc+PHJlY3QgeD0iMTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjM0LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjc8L3RleHQ+PHRleHQgeD0iMzQuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNkYzI2MjYiPuKZpTwvdGV4dD48L2c+Cjx0ZXh0IHg9IjM0LjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIzNC4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjEuPC90ZXh0Pgo8Zz48cmVjdCB4PSI2MiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iODIuMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+MzwvdGV4dD48dGV4dCB4PSI4Mi4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+4pmgPC90ZXh0PjwvZz4KPHRleHQgeD0iODIuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZGMyNjI2Ij7inJc8L3RleHQ+Cjx0ZXh0IHg9IjgyLjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+Mi48L3RleHQ+CjxnPjxyZWN0IHg9IjExMCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iMTMwLjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjEwPC90ZXh0Pjx0ZXh0IHg9IjEzMC4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iI2RjMjYyNiI+4pmmPC90ZXh0PjwvZz4KPHRleHQgeD0iMTMwLjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIxMzAuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj4zLjwvdGV4dD4KPGc+PHJlY3QgeD0iMTU4IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48dGV4dCB4PSIxNzguMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+NTwvdGV4dD48dGV4dCB4PSIxNzguMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiMxYzFjMWUiPuKZozwvdGV4dD48L2c+Cjx0ZXh0IHg9IjE3OC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMTc4LjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+NC48L3RleHQ+CjxnPjxyZWN0IHg9IjIwNiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIzIi8+PHRleHQgeD0iMjI2LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjk8L3RleHQ+PHRleHQgeD0iMjI2LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxYzFlIj7imaA8L3RleHQ+PC9nPgo8dGV4dCB4PSIyMjYuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjMTU4MDNkIj7inJM8L3RleHQ+Cjx0ZXh0IHg9IjIyNi4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjUuPC90ZXh0Pgo8Zz48cmVjdCB4PSIyNTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjMWQ0ZWQ4IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjxyZWN0IHg9IjI1OCIgeT0iNTQiIHdpZHRoPSIzMiIgaGVpZ2h0PSI0OCIgcng9IjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzkzYzVmZCIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMiIvPjwvZz4KPGc+PHJlY3QgeD0iMzAyIiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iIzFkNGVkOCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSIzMDYiIHk9IjU0IiB3aWR0aD0iMzIiIGhlaWdodD0iNDgiIHJ4PSIzIiBmaWxsPSJub25lIiBzdHJva2U9IiM5M2M1ZmQiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtZGFzaGFycmF5PSIzIDIiLz48L2c+CjxnPjxyZWN0IHg9IjM1MCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiMxZDRlZDgiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHJlY3QgeD0iMzU0IiB5PSI1NCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjQ4IiByeD0iMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTNjNWZkIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWRhc2hhcnJheT0iMyAyIi8+PC9nPgo8dGV4dCB4PSIxNCIgeT0iMTY4IiBmb250LXNpemU9IjE1IiBmaWxsPSIjNmU2ZTczIj5Wb24gbGlua3MgbmFjaCByZWNodHMgdW1kcmVoZW46PC90ZXh0Pjx0ZXh0IHg9IjE0IiB5PSIxODgiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiM2ZTZlNzMiPk5hY2ggNSBWZXJnbGVpY2hlbiBpc3QgZGllIDkgZ2VmdW5kZW4uPC90ZXh0Pgo8L3N2Zz4K",UD=""+new URL("ss-vergleiche-DRqzU2TZ.svg",import.meta.url).href,$D="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjAgNDUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KPGRlZnM+PG1hcmtlciBpZD0iayIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDEwIDUgTDAgMTAgWiIgZmlsbD0iIzFjMWMxZSIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImIiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjYiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNMCAwIEwxMCA1IEwwIDEwIFoiIGZpbGw9IiMxZDRlZDgiLz48L21hcmtlcj48bWFya2VyIGlkPSJvIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjYjQ1MzA5Ii8+PC9tYXJrZXI+PC9kZWZzPgo8cmVjdCB3aWR0aD0iNDIwIiBoZWlnaHQ9IjQ1MCIgZmlsbD0iI2ZmZmZmZiIvPgo8dGV4dCB4PSIxMCIgeT0iMjIiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI3MDAiPldlcnTDvGJlcmdhYmU6IGVpbmUgS29waWU8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNlZmY2ZmYiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjAiIHk9IjU4IiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWQ0ZWQ4Ij5IYXVwdHByb2dyYW1tPC90ZXh0Pgo8dGV4dCB4PSIyMCIgeT0iOTgiPnphaGw8L3RleHQ+CjxyZWN0IHg9IjcwIiB5PSI3OCIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9Ijk4IiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+NTwvdGV4dD4KPHJlY3QgeD0iMjUwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNmZmY3ZWQiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjYwIiB5PSI1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+dmVyZG9wcGxlPC90ZXh0Pgo8dGV4dCB4PSIyNjAiIHk9Ijk4Ij54PC90ZXh0Pgo8cmVjdCB4PSIyODAiIHk9Ijc4IiB3aWR0aD0iODAiIGhlaWdodD0iMzAiIHJ4PSI0IiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHRleHQgeD0iMzIwIiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+PHRzcGFuIGZpbGw9IiM2ZTZlNzMiIHRleHQtZGVjb3JhdGlvbj0ibGluZS10aHJvdWdoIj41PC90c3Bhbj4gPHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiPjEwPC90c3Bhbj48L3RleHQ+CjxsaW5lIHgxPSIxMjgiIHkxPSI5MyIgeDI9IjI0OCIgeTI9IjkzIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSI1IDQiIG1hcmtlci1lbmQ9InVybCgjaykiLz4KPHRleHQgeD0iMjEwIiB5PSI4NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+S29waWU8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxNTAiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPnggd2lyZCAxMCwgYWJlciB6YWhsIGJsZWlidCA1LjwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjE2OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+V2llIGJlaSBlaW5lciBGb3Rva29waWU6IFdlciBhdWYgZGVyIEtvcGllIHNjaHJlaWJ0LDwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjE4NiIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+w6RuZGVydCBkYXMgT3JpZ2luYWwgbmljaHQuPC90ZXh0Pgo8bGluZSB4MT0iMTAiIHkxPSIyMDgiIHgyPSI0MTAiIHkyPSIyMDgiIHN0cm9rZT0iI2QxZDFkNiIvPgo8dGV4dCB4PSIxMCIgeT0iMjM2IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNzAwIj5SZWZlcmVuesO8YmVyZ2FiZTogZGFzc2VsYmUgQXJyYXk8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZWZmNmZmIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjIwIiB5PSIyNzIiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPkhhdXB0cHJvZ3JhbW08L3RleHQ+Cjx0ZXh0IHg9IjIwIiB5PSIzMDAiPnJlaWhlPC90ZXh0Pgo8Y2lyY2xlIGN4PSIxNTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiMxZDRlZDgiLz4KPHJlY3QgeD0iMjUwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZmZmN2VkIiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjI2MCIgeT0iMjcyIiBmb250LXNpemU9IjEzIiBmaWxsPSIjYjQ1MzA5Ij5sZWVyZW48L3RleHQ+Cjx0ZXh0IHg9IjI2MCIgeT0iMzAwIj5wbGFldHplPC90ZXh0Pgo8Y2lyY2xlIGN4PSIzOTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiNiNDUzMDkiLz4KPHBhdGggZD0iTTE1MCAzMDAgTDE1MCAzNDAgTDE0MCAzNTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYikiLz4KPHBhdGggZD0iTTM5MCAzMDAgTDM5MCAzNDAgTDMyMiAzNTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjbykiLz4KPHJlY3QgeD0iOTAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHJlY3QgeD0iMTUwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+CjxyZWN0IHg9IjIxMCIgeT0iMzU4IiB3aWR0aD0iNjAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8cmVjdCB4PSIyNzAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHRleHQgeD0iMTIwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxODAiIHk9IjM3OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+ZmFsc2U8L3RleHQ+Cjx0ZXh0IHg9IjI0MCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMzAwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iNDE2IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj5FcyBnaWJ0IG51ciBlaW4gQXJyYXkuIFdhcyBsZWVyZW4gw7xiZXIgcGxhZXR6ZSDDpG5kZXJ0LDwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjQzNCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+c2llaHQgZGFzIEhhdXB0cHJvZ3JhbW0gdW50ZXIgcmVpaGUuPC90ZXh0Pgo8L3N2Zz4K",YD=""+new URL("zk-zeichen-vYvc3iJg.svg",import.meta.url).href;function XD(i){const e=[];for(const t of i.replace(/\r\n/g,` `).split(` -`)){const n=/^###\s+(.+)$/.exec(t),a=e.at(-1);if(n){const s=n[1].trim();e.push({term:s,forms:[s],text:""})}else a&&/^(auch|also):/i.test(t)?a.forms.push(...t.replace(/^(auch|also):/i,"").split(",").map(s=>s.trim()).filter(Boolean)):a&&t.trim()!==""&&(a.text=(a.text+" "+t.trim()).trim())}return e.filter(t=>t.text!=="")}const XD=i=>i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function Lu(i){const e=i.flatMap(t=>t.forms).sort((t,n)=>n.length-t.length);if(e.length!==0)return new RegExp(`(?t.forms.includes(e))}class jo extends Error{}function KD(i){return i==="zuhoerer"||i==="vertrag"||i==="layout"||i==="bombe"||i==="frage"||i==="reihenfolge"}function eB(i,e,t){const n=h=>{throw new jo(`${t}: ${h}`)};let a="",s="",r="",o=[],l,u;const c=[];let m,d=!1;for(const h of e){const g=h.trim();if(m&&d&&(/^ {4}|^\t/.test(h)||g==="")){m.code+=(m.code?` +`)){const n=/^###\s+(.+)$/.exec(t),a=e.at(-1);if(n){const s=n[1].trim();e.push({term:s,forms:[s],text:""})}else a&&/^(auch|also):/i.test(t)?a.forms.push(...t.replace(/^(auch|also):/i,"").split(",").map(s=>s.trim()).filter(Boolean)):a&&t.trim()!==""&&(a.text=(a.text+" "+t.trim()).trim())}return e.filter(t=>t.text!=="")}const KD=i=>i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function Lu(i){const e=i.flatMap(t=>t.forms).sort((t,n)=>n.length-t.length);if(e.length!==0)return new RegExp(`(?t.forms.includes(e))}class Po extends Error{}function eB(i){return i==="zuhoerer"||i==="vertrag"||i==="layout"||i==="bombe"||i==="frage"||i==="reihenfolge"}function tB(i,e,t){const n=h=>{throw new Po(`${t}: ${h}`)};let a="",s="",r="",o=[],l,u;const c=[];let m,d=!1;for(const h of e){const g=h.trim();if(m&&d&&(/^ {4}|^\t/.test(h)||g==="")){m.code+=(m.code?` `:"")+h.replace(/^( {4}|\t)/,"");continue}if(d=!1,!g)continue;const f=/^(titel|intro|antworten|frage|runde|klicks|richtig|zeit|fehler|besser|daten):\s*(.*)$/.exec(g);if(f){const[,v,w]=f;v==="runde"?(m={code:"",question:r,options:[],explanation:"",clicks:[]},c.push(m),d=!0):m?v==="frage"?m.question=w:v==="fehler"?m.wrongLine=Number(w):v==="besser"?m.fix=w:v==="klicks"?m.clicks=w.split(",").map(I=>I.trim()).filter(Boolean):v==="richtig"?m.rightText=w:n(`„${v}:“ gehört vor die erste Runde.`):v==="titel"?a=w:v==="intro"?s=w:v==="antworten"?o=w.split("|").map(I=>I.trim()):v==="frage"?r=w:v==="zeit"?l=Number(w):v==="daten"?u=w==="csv"?w:n("„daten:“ kennt nur „csv“."):n(`„${v}:“ gehört in eine Runde.`);continue}m||n(`Unbekannte Zeile vor der ersten Runde: „${g}“`);const b=m,x=/^-\s+(\[x\]\s+)?(.+)$/.exec(g);x?b.options.push({text:x[2].trim().replaceAll("\\n",` `),right:!!x[1]}):g.startsWith(">")?b.explanation+=(b.explanation?" ":"")+g.slice(1).trim():n(`Unbekannte Zeile im Spiel: „${g}“`)}return a||n("Das Spiel braucht eine Zeile „titel:“."),c.length||n("Das Spiel braucht mindestens eine „runde:“."),c.forEach((h,g)=>{if(h.code=h.code.replace(/\n+$/,""),i==="bombe"){const f=h.code.split(` -`),b=h.wrongLine;(!b||!Number.isInteger(b)||b<1||b>f.length||!f[b-1].trim())&&n(`Runde ${g+1}: „fehler:“ muss eine Zeile des Codes sein.`),h.fix||n(`Runde ${g+1}: „besser:“ fehlt.`),h.options.length&&n(`Runde ${g+1}: Bei „bombe“ gibt es keine Antworten, man tippt auf die Zeile.`),h.question||n(`Runde ${g+1}: keine Frage.`);return}if(i==="reihenfolge"){h.options.length<3&&n(`Runde ${g+1}: „reihenfolge“ braucht mindestens drei Schritte.`),h.options.some(f=>f.right)&&n(`Runde ${g+1}: Bei „reihenfolge“ gibt es kein [x], die Schritte stehen der Reihe nach da.`),new Set(h.options.map(f=>f.text)).size!==h.options.length&&n(`Runde ${g+1}: zwei Schritte sind gleich.`),h.question||n(`Runde ${g+1}: keine Frage.`);return}if(h.options.length||(o.length||n(`Runde ${g+1}: keine Antworten.`),(!h.rightText||!o.includes(h.rightText))&&n(`Runde ${g+1}: „richtig:“ muss eine der Antworten sein.`),h.options=o.map(f=>({text:f,right:f===h.rightText}))),h.options.filter(f=>f.right).length!==1&&n(`Runde ${g+1}: genau eine Antwort muss richtig sein.`),h.question||n(`Runde ${g+1}: keine Frage.`),i==="layout"&&h.options.forEach(f=>Rh(f.text,`Runde ${g+1}`,n)),i==="zuhoerer")try{const f=Gh(h.code);for(const b of h.clicks)f.buttons.some(x=>x.caption===b)||n(`Runde ${g+1}: Knopf „${b}“ gibt es nicht.`);tB(f,h.clicks)}catch(f){if(f instanceof jo)throw f;n(`Runde ${g+1}: ${f.message}`)}delete h.rightText}),i==="bombe"&&!(l&&l>0)&&n("„bombe“ braucht „zeit:“ mit den Sekunden je Runde."),{kind:i,title:a,intro:s,...i==="bombe"?{seconds:l,...u?{data:u}:{}}:{},rounds:c}}function Rh(i,e="",t=n=>{throw new jo(n)}){const n=/^(grid|flow|border):\s*(.+)$/.exec(i);if(!n)return t(`${e}: Antwort „${i}“ ist kein Fensterbild (grid:, flow: oder border:).`);if(n[1]==="border"){const s={};for(const r of n[2].split(/\s+/)){const o=/^([NSWEC])=(.+)$/.exec(r);o||t(`${e}: „${r}“ im BorderLayout-Bild verstehe ich nicht (z. B. N=A).`),s[o[1]]=o[2]}return{kind:"border",areas:s}}const a=n[2].split("/").map(s=>s.trim().split(/\s+/).filter(Boolean));return{kind:n[1],rows:a}}const Ea='"((?:[^"\\\\]|\\\\.)*)"';function Gh(i){const e=i.split(` -`),t={title:"",buttons:[],labels:[],ints:{},listeners:[]},n=new Map,a=(r,o,l)=>{if(o.startsWith("{")){let c=r+1;const m=[];for(;c=e.length)throw new Error(`Dem Zuhörer fehlt „${l}“.`);return{from:r,to:c,statements:Do(m.join(" "))}}const u=l==="});"?o.replace(/\)\s*;\s*$/,""):o.replace(/;\s*$/,"");return{from:r,to:r,statements:Do(u)}},s=r=>{if(!t.buttons.some(o=>o.name===r))throw new Error(`Knopf ${r} ist nicht angelegt.`);return r};for(let r=0;r\s*(.*)$/.exec(o)){const u=a(r,l[2],"};");n.set(l[1],u),r=u.to}else if(l=/^(\w+)\.addActionListener\(\s*(\w+)\s*\)\s*;$/.exec(o)){const u=n.get(l[2]);if(!u)throw new Error(`Zuhörer ${l[2]} ist nicht angelegt.`);t.listeners.push({button:s(l[1]),...u})}else if(l=/^(\w+)\.addActionListener\(\s*\w+\s*->\s*(.*)$/.exec(o)){const u=a(r,l[2],"});");t.listeners.push({button:s(l[1]),...u}),r=u.to}}return t}function Do(i){const e=[];let t=0;const n=()=>{for(;t{let u=0,c=!1;const m=t+1;for(;t{let o=0,l=!1;const u=t;for(;t{if(n(),i[t]==="{")return Do(a("{","}"));if(/^if\s*\(/.test(i.slice(t))){t=i.indexOf("(",t);const l=a("(",")").trim(),u=r();n();let c=[];return/^else\b/.test(i.slice(t))&&(t+=4,c=r()),[{condition:l,then:u,otherwise:c}]}const o=s();return o?[o]:[]};for(n();ta.caption===t)??i.buttons.find(a=>e.texts[a.name]===t);if(!n)throw new Error(`Knopf „${t}“ gibt es nicht.`);return qh(i,e,n.name)}function qh(i,e,t){const n=i.listeners.find(r=>r.button===t),a=[],s={source:t,command:e.texts[t]};for(const r of(n==null?void 0:n.statements)??[])Qh(r,e,a,s);return{button:t,listener:n,texts:{...e.texts},console:a}}function tB(i,e){const t=Hh(i);return e.map(n=>Vh(i,t,n))}function Qh(i,e,t,n){if(typeof i!="string"){for(const s of nB(i.condition,e,n)?i.then:i.otherwise)Qh(s,e,t,n);return}let a;if(a=/^(\w+)\.setText\((.*)\)$/.exec(i)){if(!(a[1]in e.texts))throw new Error(`${a[1]} ist keine Beschriftung und kein Knopf.`);e.texts[a[1]]=String(Un(a[2],e,n))}else if(a=/^System\.out\.println\((.*)\)$/.exec(i))t.push(String(Un(a[1],e,n)));else if(a=/^(\w+)\s*(\+\+|--)$/.exec(i))e.ints[Wu(a[1],e)]+=a[2]==="++"?1:-1;else if(a=/^(\w+)\s*([+-]?=)\s*(.+)$/.exec(i)){const s=Wu(a[1],e),r=Number(Un(a[3],e,n));e.ints[s]=a[2]==="="?r:a[2]==="+="?e.ints[s]+r:e.ints[s]-r}else throw new Error(`Diese Anweisung kann das Spiel nicht nachspielen: „${i}“`)}function nB(i,e,t){let n;if(n=/^e\.getSource\(\)\s*(==|!=)\s*(\w+)$/.exec(i)){if(!(n[2]in e.texts))throw new Error(`${n[2]} ist kein Knopf.`);return t.source===n[2]==(n[1]==="==")}if(n=/^(!?)(.+)\.equals\((.+)\)$/.exec(i))return String(Un(n[2],e,t))===String(Un(n[3],e,t))!=(n[1]==="!");if(n=/^(.+?)\s*(==|!=|<=|>=|<|>)\s*(.+)$/.exec(i)){const a=Number(Un(n[1],e,t)),s=Number(Un(n[3],e,t));return{"==":a===s,"!=":a!==s,"<=":a<=s,">=":a>=s,"<":a":a>s}[n[2]]}throw new Error(`Diese Bedingung kann das Spiel nicht nachspielen: „${i}“`)}function Wu(i,e){if(!(i in e.ints))throw new Error(`Variable ${i} ist nicht angelegt.`);return i}function Un(i,e,t){const n=i.match(new RegExp(`${Ea}|\\d+|e\\.getActionCommand\\(\\)|\\w+(?:\\.getText\\(\\))?|[-+*/()]`,"g"))??[];let a=0;const s=()=>{const l=n[a++];if(l===void 0)throw new Error(`Unvollständiger Ausdruck „${i}“`);if(l==="("){const u=o();return a++,u}if(l.startsWith('"'))return JSON.parse(l);if(/^\d+$/.test(l))return Number(l);if(l==="e.getActionCommand()"){if(!t)throw new Error("e.getActionCommand() gibt es nur im Zuhörer.");return t.command}if(l.endsWith(".getText()"))return e.texts[l.slice(0,-10)]??"";if(l in e.ints)return e.ints[l];throw new Error(`Unbekannt: „${l}“`)},r=()=>{let l=s();for(;n[a]==="*"||n[a]==="/";){const u=n[a++],c=Number(s());l=u==="*"?Number(l)*c:Math.trunc(Number(l)/c)}return l},o=()=>{let l=r();for(;n[a]==="+"||n[a]==="-";){const u=n[a++],c=r();u==="+"?l=typeof l=="string"||typeof c=="string"?`${l}${c}`:l+c:l=Number(l)-Number(c)}return l};return o()}class iB extends Error{}const gs="___";function aB(i){const e=Array.from({length:i.rows},()=>Array(i.cols).fill(""));for(const t of i.words)[...t.word].forEach((n,a)=>e[t.row+(t.across?0:a)][t.col+(t.across?a:0)]=n);return e}function sB(i,e){const t=O=>{throw new iB(`${e}: ${O}`)},n=(O,D)=>{const j=/^(\d+)\s+(\d+)$/.exec(O.trim());return!j||Number(j[1])<1||Number(j[2])<1?t(`${D}: „${O}“ ist kein Feld (Zeile Spalte, ab 1).`):{row:Number(j[1])-1,col:Number(j[2])-1}};let a="",s="",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",o="",l="",u="",c="";const m=[],d=[];let h=[],g,f="start";for(const O of i){const D=O.trim();if(g&&(/^( {4}|\t)/.test(O)||D==="")){const P=O.replace(/^( {4}|\t)/,"");if(g==="station"){const A=m[m.length-1];A.code+=(A.code?` -`:"")+P}else u+=(u?` -`:"")+P;continue}if(g=void 0,!D)continue;const j=/^(titel|intro|alphabet|station|frage|zahl|feld|tipp|kreuzwort|lösung|loesung|tor|ende):\s*(.*)$/.exec(D);if(j){const[,P,A]=j;if(P==="station")m.push({name:A,code:"",question:"",hint:"",explanation:""}),f="station",g="station";else if(P==="kreuzwort")o=A,f="crossword";else if(P==="tor")l=A,f="gate",g="gate";else if(P==="titel")a=A;else if(P==="intro")s=A;else if(P==="alphabet")r=A;else if(P==="ende")c=A;else if(P==="lösung"||P==="loesung")f!=="crossword"&&t("„lösung:“ gehört zum Kreuzworträtsel."),h=A.split(",").map(M=>n(M,"lösung"));else{f!=="station"&&t(`„${P}:“ gehört in eine Station.`);const M=m[m.length-1];P==="frage"?M.question=A:P==="tipp"?M.hint=A:P==="zahl"?M.answer=/^-?\d+$/.test(A)?Number(A):t(`Station „${M.name}“: „zahl:“ muss eine ganze Zahl sein.`):Object.assign(M,n(A,`Station „${M.name}“`))}continue}if(f==="crossword"){const P=/^-\s+([→↓])\s+(\d+)\s+(\d+)\s+([A-ZÄÖÜ]+):\s*(.+)$/u.exec(D);P||t(`Kreuzworträtsel: „${D}“ verstehe ich nicht (z. B. „- → 1 3 STRING: Hinweis“).`),d.push({across:P[1]==="→",row:Number(P[2])-1,col:Number(P[3])-1,word:P[4],clue:P[5]});continue}if(f==="station"&&D.startsWith(">")){const P=m[m.length-1];P.explanation+=(P.explanation?" ":"")+D.slice(1).trim();continue}t(`Unbekannte Zeile im Spiel: „${D}“`)}a||t("Das Spiel braucht eine Zeile „titel:“."),m.length||t("Das Spiel braucht mindestens eine „station:“."),d.length||t("Das Spiel braucht ein „kreuzwort:“ mit Wörtern."),h.length||t("Das Kreuzworträtsel braucht eine Zeile „lösung:“."),u.includes(gs)||t(`Der Code bei „tor:“ braucht ${gs} für das Eingabefeld.`),new Set(r).size!==r.length&&t("Im Alphabet kommt ein Zeichen doppelt vor.");const b=Math.max(...d.map(O=>O.row+(O.across?1:O.word.length))),x=Math.max(...d.map(O=>O.col+(O.across?O.word.length:1))),v=Array.from({length:b},()=>Array(x).fill(""));for(const O of d)[...O.word].forEach((D,j)=>{const P=O.row+(O.across?0:j),A=O.col+(O.across?j:0);v[P][A]&&v[P][A]!==D&&t(`Kreuzworträtsel: ${O.word} passt in Zeile ${P+1}, Spalte ${A+1} nicht (dort steht ${v[P][A]}).`),v[P][A]=D});const w=[...new Set(d.map(O=>O.row*x+O.col))].sort((O,D)=>O-D),I=d.map(O=>({...O,number:w.indexOf(O.row*x+O.col)+1})),z=(O,D)=>{var j;return((j=v[O])==null?void 0:j[D])??""},k=h.map(({row:O,col:D})=>z(O,D)||t(`lösung: In Zeile ${O+1}, Spalte ${D+1} ist kein Feld.`)).join(""),T=m.map(O=>{O.code||t(`Station „${O.name}“: Code fehlt.`),O.question||t(`Station „${O.name}“: „frage:“ fehlt.`),O.answer===void 0&&t(`Station „${O.name}“: „zahl:“ fehlt.`),O.row===void 0&&t(`Station „${O.name}“: „feld:“ fehlt.`);const D=r.charAt(O.answer);D||t(`Station „${O.name}“: alphabet.charAt(${O.answer}) gibt es nicht.`);const j=z(O.row,O.col);return j!==D&&t(`Station „${O.name}“: alphabet.charAt(${O.answer}) ist ${D}, im Feld ${O.row+1} ${O.col+1} steht aber „${j}“.`),O.code=O.code.replace(/\n+$/,""),O});return{title:a,intro:s,alphabet:r,stations:T,crosswordText:o,rows:b,cols:x,words:I,solution:h,keyword:k,gateText:l,gateCode:u.replace(/\n+$/,""),end:c}}const rB=/\[\[(.+?)\]\]/g;function oB(i,e){const t={title:"",task:"",blocks:[]},n=[];let a=!1;for(const s of i){if(/^\s*```/.test(s)){a||n.push([]),a=!a;continue}if(a){n[n.length-1].push(s.replace(/\s+$/,""));continue}const r=s.trim();if(!r)continue;const o=/^([a-zäöü]+):\s*(.*)$/i.exec(r);if(!o)throw new Error(`${e}: Unbekannte Zeile im Lückentext: „${r}“.`);const l=o[2].trim();switch(o[1].toLowerCase()){case"titel":t.title=l;break;case"auftrag":t.task=l;break;case"erklärung":case"erklaerung":t.explanation=l;break;default:throw new Error(`${e}: Unbekannter Schlüssel „${o[1]}“ im Lückentext.`)}}if(a)throw new Error(`${e}: Der Codeblock im Lückentext wird nicht mit \`\`\` geschlossen.`);if(!t.title)throw new Error(`${e}: Ein Lückentext braucht einen Titel.`);if(!n.some(s=>s.some(r=>r.trim())))throw new Error(`${e}: Lückentext „${t.title}“ braucht einen Codeblock.`);if(t.blocks=n.map(s=>{const r=Math.min(...s.filter(o=>o.trim()).map(o=>/^ */.exec(o)[0].length));return s.map(o=>lB(o.slice(r),e,t.title))}),!uB(t).length)throw new Error(`${e}: Lückentext „${t.title}“ braucht mindestens eine Lücke [[…]].`);return t}function lB(i,e,t){const n=[];let a=0;for(const s of i.matchAll(rB)){s.index>a&&n.push(i.slice(a,s.index));const r=s[1].split(/\s+\|\s+/).map(o=>o.trim()).filter(Boolean);if(!r.length)throw new Error(`${e}: Leere Lücke im Lückentext „${t}“.`);n.push({answers:r}),a=s.index+s[0].length}if(atypeof s=="string"&&(s.includes("[[")||s.includes("]]"))))throw new Error(`${e}: Unvollständige Lücke im Lückentext „${t}“: „${i}“.`);return n}function uB(i){return i.blocks.flat().flatMap(e=>e.flatMap(t=>typeof t=="string"?[]:[t.answers]))}function cB(i,e){const t=n=>n.replace(/\s+/g,"");return t(e)!==""&&i.some(n=>t(n)===t(e))}const Nu={start:"oval",ende:"oval",anweisung:"rechteck",eingabe:"parallelogramm",ausgabe:"parallelogramm",frage:"raute"};function mB(i,e){const t={title:"",task:"",nodes:[]},n=[];for(const a of i){const s=a.trim();if(!s)continue;const r=/^([a-zäöü]+):\s*(.*)$/i.exec(s);if(!r)throw new Error(`${e}: Unbekannte Zeile im PAP: „${s}“.`);const o=r[1].toLowerCase(),l=r[2].trim();if(o==="titel")t.title=l;else if(o==="auftrag")t.task=l;else if(o==="erklärung"||o==="erklaerung")t.explanation=l;else if(o==="legende")t.legend=/^(ja|yes|true|sim)$/i.test(l);else if(o in Nu){const[u,c]=l.split(/\s+\|\s+/);if(!u)throw new Error(`${e}: Leeres Element im PAP: „${s}“.`);const m={shape:Nu[o],text:u.trim()};if(t.nodes.push(m),o!=="frage"){if(c)throw new Error(`${e}: Nur eine Frage hat einen zweiten Ausgang: „${s}“.`);continue}const d=/^(ja|nein)\s*(->|:)\s*(.+)$/i.exec(c??"");if(!d)throw new Error(`${e}: Eine Frage braucht „| nein -> Text“ oder „| nein: Text“: „${s}“.`);m.sideExit=d[1].toLowerCase(),d[2]===":"?(m.side=t.nodes.length,t.nodes.push({shape:"rechteck",text:d[3].trim(),isSide:!0})):n.push({node:t.nodes.length-1,target:d[3].trim(),line:s})}else throw new Error(`${e}: Unbekannter Schlüssel „${r[1]}“ im PAP.`)}for(const a of n){const s=t.nodes.findIndex((r,o)=>o{if(n.isSide)return;const s=bB(n.shape);(i.nodes.some(r=>r.backTo===a)||n.side!==void 0)&&(t+=12),e[a]={x:hB,y:t+s/2,w:n.shape==="raute"?170:n.shape==="oval"?110:gB,h:s},n.side!==void 0&&(e[n.side]={x:pB,y:t+s/2,w:fB,h:40}),t+=s+Fu}),{boxes:e,height:t-Fu+10}}function Uh(i,e){if((r=>r.length*6.6<=e)(i))return[i];const n=i.split(" ");let a=[i],s=1/0;for(let r=1;ru.length));lf.length||!f[b-1].trim())&&n(`Runde ${g+1}: „fehler:“ muss eine Zeile des Codes sein.`),h.fix||n(`Runde ${g+1}: „besser:“ fehlt.`),h.options.length&&n(`Runde ${g+1}: Bei „bombe“ gibt es keine Antworten, man tippt auf die Zeile.`),h.question||n(`Runde ${g+1}: keine Frage.`);return}if(i==="reihenfolge"){h.options.length<3&&n(`Runde ${g+1}: „reihenfolge“ braucht mindestens drei Schritte.`),h.options.some(f=>f.right)&&n(`Runde ${g+1}: Bei „reihenfolge“ gibt es kein [x], die Schritte stehen der Reihe nach da.`),new Set(h.options.map(f=>f.text)).size!==h.options.length&&n(`Runde ${g+1}: zwei Schritte sind gleich.`),h.question||n(`Runde ${g+1}: keine Frage.`);return}if(h.options.length||(o.length||n(`Runde ${g+1}: keine Antworten.`),(!h.rightText||!o.includes(h.rightText))&&n(`Runde ${g+1}: „richtig:“ muss eine der Antworten sein.`),h.options=o.map(f=>({text:f,right:f===h.rightText}))),h.options.filter(f=>f.right).length!==1&&n(`Runde ${g+1}: genau eine Antwort muss richtig sein.`),h.question||n(`Runde ${g+1}: keine Frage.`),i==="layout"&&h.options.forEach(f=>Rh(f.text,`Runde ${g+1}`,n)),i==="zuhoerer")try{const f=Gh(h.code);for(const b of h.clicks)f.buttons.some(x=>x.caption===b)||n(`Runde ${g+1}: Knopf „${b}“ gibt es nicht.`);nB(f,h.clicks)}catch(f){if(f instanceof Po)throw f;n(`Runde ${g+1}: ${f.message}`)}delete h.rightText}),i==="bombe"&&!(l&&l>0)&&n("„bombe“ braucht „zeit:“ mit den Sekunden je Runde."),{kind:i,title:a,intro:s,...i==="bombe"?{seconds:l,...u?{data:u}:{}}:{},rounds:c}}function Rh(i,e="",t=n=>{throw new Po(n)}){const n=/^(grid|flow|border):\s*(.+)$/.exec(i);if(!n)return t(`${e}: Antwort „${i}“ ist kein Fensterbild (grid:, flow: oder border:).`);if(n[1]==="border"){const s={};for(const r of n[2].split(/\s+/)){const o=/^([NSWEC])=(.+)$/.exec(r);o||t(`${e}: „${r}“ im BorderLayout-Bild verstehe ich nicht (z. B. N=A).`),s[o[1]]=o[2]}return{kind:"border",areas:s}}const a=n[2].split("/").map(s=>s.trim().split(/\s+/).filter(Boolean));return{kind:n[1],rows:a}}const Ea='"((?:[^"\\\\]|\\\\.)*)"';function Gh(i){const e=i.split(` +`),t={title:"",buttons:[],labels:[],ints:{},listeners:[]},n=new Map,a=(r,o,l)=>{if(o.startsWith("{")){let c=r+1;const m=[];for(;c=e.length)throw new Error(`Dem Zuhörer fehlt „${l}“.`);return{from:r,to:c,statements:Do(m.join(" "))}}const u=l==="});"?o.replace(/\)\s*;\s*$/,""):o.replace(/;\s*$/,"");return{from:r,to:r,statements:Do(u)}},s=r=>{if(!t.buttons.some(o=>o.name===r))throw new Error(`Knopf ${r} ist nicht angelegt.`);return r};for(let r=0;r\s*(.*)$/.exec(o)){const u=a(r,l[2],"};");n.set(l[1],u),r=u.to}else if(l=/^(\w+)\.addActionListener\(\s*(\w+)\s*\)\s*;$/.exec(o)){const u=n.get(l[2]);if(!u)throw new Error(`Zuhörer ${l[2]} ist nicht angelegt.`);t.listeners.push({button:s(l[1]),...u})}else if(l=/^(\w+)\.addActionListener\(\s*\w+\s*->\s*(.*)$/.exec(o)){const u=a(r,l[2],"});");t.listeners.push({button:s(l[1]),...u}),r=u.to}}return t}function Do(i){const e=[];let t=0;const n=()=>{for(;t{let u=0,c=!1;const m=t+1;for(;t{let o=0,l=!1;const u=t;for(;t{if(n(),i[t]==="{")return Do(a("{","}"));if(/^if\s*\(/.test(i.slice(t))){t=i.indexOf("(",t);const l=a("(",")").trim(),u=r();n();let c=[];return/^else\b/.test(i.slice(t))&&(t+=4,c=r()),[{condition:l,then:u,otherwise:c}]}const o=s();return o?[o]:[]};for(n();ta.caption===t)??i.buttons.find(a=>e.texts[a.name]===t);if(!n)throw new Error(`Knopf „${t}“ gibt es nicht.`);return qh(i,e,n.name)}function qh(i,e,t){const n=i.listeners.find(r=>r.button===t),a=[],s={source:t,command:e.texts[t]};for(const r of(n==null?void 0:n.statements)??[])Qh(r,e,a,s);return{button:t,listener:n,texts:{...e.texts},console:a}}function nB(i,e){const t=Hh(i);return e.map(n=>Vh(i,t,n))}function Qh(i,e,t,n){if(typeof i!="string"){for(const s of iB(i.condition,e,n)?i.then:i.otherwise)Qh(s,e,t,n);return}let a;if(a=/^(\w+)\.setText\((.*)\)$/.exec(i)){if(!(a[1]in e.texts))throw new Error(`${a[1]} ist keine Beschriftung und kein Knopf.`);e.texts[a[1]]=String(Un(a[2],e,n))}else if(a=/^System\.out\.println\((.*)\)$/.exec(i))t.push(String(Un(a[1],e,n)));else if(a=/^(\w+)\s*(\+\+|--)$/.exec(i))e.ints[Wu(a[1],e)]+=a[2]==="++"?1:-1;else if(a=/^(\w+)\s*([+-]?=)\s*(.+)$/.exec(i)){const s=Wu(a[1],e),r=Number(Un(a[3],e,n));e.ints[s]=a[2]==="="?r:a[2]==="+="?e.ints[s]+r:e.ints[s]-r}else throw new Error(`Diese Anweisung kann das Spiel nicht nachspielen: „${i}“`)}function iB(i,e,t){let n;if(n=/^e\.getSource\(\)\s*(==|!=)\s*(\w+)$/.exec(i)){if(!(n[2]in e.texts))throw new Error(`${n[2]} ist kein Knopf.`);return t.source===n[2]==(n[1]==="==")}if(n=/^(!?)(.+)\.equals\((.+)\)$/.exec(i))return String(Un(n[2],e,t))===String(Un(n[3],e,t))!=(n[1]==="!");if(n=/^(.+?)\s*(==|!=|<=|>=|<|>)\s*(.+)$/.exec(i)){const a=Number(Un(n[1],e,t)),s=Number(Un(n[3],e,t));return{"==":a===s,"!=":a!==s,"<=":a<=s,">=":a>=s,"<":a":a>s}[n[2]]}throw new Error(`Diese Bedingung kann das Spiel nicht nachspielen: „${i}“`)}function Wu(i,e){if(!(i in e.ints))throw new Error(`Variable ${i} ist nicht angelegt.`);return i}function Un(i,e,t){const n=i.match(new RegExp(`${Ea}|\\d+|e\\.getActionCommand\\(\\)|\\w+(?:\\.getText\\(\\))?|[-+*/()]`,"g"))??[];let a=0;const s=()=>{const l=n[a++];if(l===void 0)throw new Error(`Unvollständiger Ausdruck „${i}“`);if(l==="("){const u=o();return a++,u}if(l.startsWith('"'))return JSON.parse(l);if(/^\d+$/.test(l))return Number(l);if(l==="e.getActionCommand()"){if(!t)throw new Error("e.getActionCommand() gibt es nur im Zuhörer.");return t.command}if(l.endsWith(".getText()"))return e.texts[l.slice(0,-10)]??"";if(l in e.ints)return e.ints[l];throw new Error(`Unbekannt: „${l}“`)},r=()=>{let l=s();for(;n[a]==="*"||n[a]==="/";){const u=n[a++],c=Number(s());l=u==="*"?Number(l)*c:Math.trunc(Number(l)/c)}return l},o=()=>{let l=r();for(;n[a]==="+"||n[a]==="-";){const u=n[a++],c=r();u==="+"?l=typeof l=="string"||typeof c=="string"?`${l}${c}`:l+c:l=Number(l)-Number(c)}return l};return o()}class aB extends Error{}const gs="___";function sB(i){const e=Array.from({length:i.rows},()=>Array(i.cols).fill(""));for(const t of i.words)[...t.word].forEach((n,a)=>e[t.row+(t.across?0:a)][t.col+(t.across?a:0)]=n);return e}function rB(i,e){const t=O=>{throw new aB(`${e}: ${O}`)},n=(O,D)=>{const P=/^(\d+)\s+(\d+)$/.exec(O.trim());return!P||Number(P[1])<1||Number(P[2])<1?t(`${D}: „${O}“ ist kein Feld (Zeile Spalte, ab 1).`):{row:Number(P[1])-1,col:Number(P[2])-1}};let a="",s="",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",o="",l="",u="",c="";const m=[],d=[];let h=[],g,f="start";for(const O of i){const D=O.trim();if(g&&(/^( {4}|\t)/.test(O)||D==="")){const j=O.replace(/^( {4}|\t)/,"");if(g==="station"){const A=m[m.length-1];A.code+=(A.code?` +`:"")+j}else u+=(u?` +`:"")+j;continue}if(g=void 0,!D)continue;const P=/^(titel|intro|alphabet|station|frage|zahl|feld|tipp|kreuzwort|lösung|loesung|tor|ende):\s*(.*)$/.exec(D);if(P){const[,j,A]=P;if(j==="station")m.push({name:A,code:"",question:"",hint:"",explanation:""}),f="station",g="station";else if(j==="kreuzwort")o=A,f="crossword";else if(j==="tor")l=A,f="gate",g="gate";else if(j==="titel")a=A;else if(j==="intro")s=A;else if(j==="alphabet")r=A;else if(j==="ende")c=A;else if(j==="lösung"||j==="loesung")f!=="crossword"&&t("„lösung:“ gehört zum Kreuzworträtsel."),h=A.split(",").map(M=>n(M,"lösung"));else{f!=="station"&&t(`„${j}:“ gehört in eine Station.`);const M=m[m.length-1];j==="frage"?M.question=A:j==="tipp"?M.hint=A:j==="zahl"?M.answer=/^-?\d+$/.test(A)?Number(A):t(`Station „${M.name}“: „zahl:“ muss eine ganze Zahl sein.`):Object.assign(M,n(A,`Station „${M.name}“`))}continue}if(f==="crossword"){const j=/^-\s+([→↓])\s+(\d+)\s+(\d+)\s+([A-ZÄÖÜ]+):\s*(.+)$/u.exec(D);j||t(`Kreuzworträtsel: „${D}“ verstehe ich nicht (z. B. „- → 1 3 STRING: Hinweis“).`),d.push({across:j[1]==="→",row:Number(j[2])-1,col:Number(j[3])-1,word:j[4],clue:j[5]});continue}if(f==="station"&&D.startsWith(">")){const j=m[m.length-1];j.explanation+=(j.explanation?" ":"")+D.slice(1).trim();continue}t(`Unbekannte Zeile im Spiel: „${D}“`)}a||t("Das Spiel braucht eine Zeile „titel:“."),m.length||t("Das Spiel braucht mindestens eine „station:“."),d.length||t("Das Spiel braucht ein „kreuzwort:“ mit Wörtern."),h.length||t("Das Kreuzworträtsel braucht eine Zeile „lösung:“."),u.includes(gs)||t(`Der Code bei „tor:“ braucht ${gs} für das Eingabefeld.`),new Set(r).size!==r.length&&t("Im Alphabet kommt ein Zeichen doppelt vor.");const b=Math.max(...d.map(O=>O.row+(O.across?1:O.word.length))),x=Math.max(...d.map(O=>O.col+(O.across?O.word.length:1))),v=Array.from({length:b},()=>Array(x).fill(""));for(const O of d)[...O.word].forEach((D,P)=>{const j=O.row+(O.across?0:P),A=O.col+(O.across?P:0);v[j][A]&&v[j][A]!==D&&t(`Kreuzworträtsel: ${O.word} passt in Zeile ${j+1}, Spalte ${A+1} nicht (dort steht ${v[j][A]}).`),v[j][A]=D});const w=[...new Set(d.map(O=>O.row*x+O.col))].sort((O,D)=>O-D),I=d.map(O=>({...O,number:w.indexOf(O.row*x+O.col)+1})),z=(O,D)=>{var P;return((P=v[O])==null?void 0:P[D])??""},k=h.map(({row:O,col:D})=>z(O,D)||t(`lösung: In Zeile ${O+1}, Spalte ${D+1} ist kein Feld.`)).join(""),T=m.map(O=>{O.code||t(`Station „${O.name}“: Code fehlt.`),O.question||t(`Station „${O.name}“: „frage:“ fehlt.`),O.answer===void 0&&t(`Station „${O.name}“: „zahl:“ fehlt.`),O.row===void 0&&t(`Station „${O.name}“: „feld:“ fehlt.`);const D=r.charAt(O.answer);D||t(`Station „${O.name}“: alphabet.charAt(${O.answer}) gibt es nicht.`);const P=z(O.row,O.col);return P!==D&&t(`Station „${O.name}“: alphabet.charAt(${O.answer}) ist ${D}, im Feld ${O.row+1} ${O.col+1} steht aber „${P}“.`),O.code=O.code.replace(/\n+$/,""),O});return{title:a,intro:s,alphabet:r,stations:T,crosswordText:o,rows:b,cols:x,words:I,solution:h,keyword:k,gateText:l,gateCode:u.replace(/\n+$/,""),end:c}}const oB=/\[\[(.+?)\]\]/g;function lB(i,e){const t={title:"",task:"",blocks:[]},n=[];let a=!1;for(const s of i){if(/^\s*```/.test(s)){a||n.push([]),a=!a;continue}if(a){n[n.length-1].push(s.replace(/\s+$/,""));continue}const r=s.trim();if(!r)continue;const o=/^([a-zäöü]+):\s*(.*)$/i.exec(r);if(!o)throw new Error(`${e}: Unbekannte Zeile im Lückentext: „${r}“.`);const l=o[2].trim();switch(o[1].toLowerCase()){case"titel":t.title=l;break;case"auftrag":t.task=l;break;case"erklärung":case"erklaerung":t.explanation=l;break;default:throw new Error(`${e}: Unbekannter Schlüssel „${o[1]}“ im Lückentext.`)}}if(a)throw new Error(`${e}: Der Codeblock im Lückentext wird nicht mit \`\`\` geschlossen.`);if(!t.title)throw new Error(`${e}: Ein Lückentext braucht einen Titel.`);if(!n.some(s=>s.some(r=>r.trim())))throw new Error(`${e}: Lückentext „${t.title}“ braucht einen Codeblock.`);if(t.blocks=n.map(s=>{const r=Math.min(...s.filter(o=>o.trim()).map(o=>/^ */.exec(o)[0].length));return s.map(o=>uB(o.slice(r),e,t.title))}),!cB(t).length)throw new Error(`${e}: Lückentext „${t.title}“ braucht mindestens eine Lücke [[…]].`);return t}function uB(i,e,t){const n=[];let a=0;for(const s of i.matchAll(oB)){s.index>a&&n.push(i.slice(a,s.index));const r=s[1].split(/\s+\|\s+/).map(o=>o.trim()).filter(Boolean);if(!r.length)throw new Error(`${e}: Leere Lücke im Lückentext „${t}“.`);n.push({answers:r}),a=s.index+s[0].length}if(atypeof s=="string"&&(s.includes("[[")||s.includes("]]"))))throw new Error(`${e}: Unvollständige Lücke im Lückentext „${t}“: „${i}“.`);return n}function cB(i){return i.blocks.flat().flatMap(e=>e.flatMap(t=>typeof t=="string"?[]:[t.answers]))}function mB(i,e){const t=n=>n.replace(/\s+/g,"");return t(e)!==""&&i.some(n=>t(n)===t(e))}const Nu={start:"oval",ende:"oval",anweisung:"rechteck",eingabe:"parallelogramm",ausgabe:"parallelogramm",frage:"raute"};function dB(i,e){const t={title:"",task:"",nodes:[]},n=[];for(const a of i){const s=a.trim();if(!s)continue;const r=/^([a-zäöü]+):\s*(.*)$/i.exec(s);if(!r)throw new Error(`${e}: Unbekannte Zeile im PAP: „${s}“.`);const o=r[1].toLowerCase(),l=r[2].trim();if(o==="titel")t.title=l;else if(o==="auftrag")t.task=l;else if(o==="erklärung"||o==="erklaerung")t.explanation=l;else if(o==="legende")t.legend=/^(ja|yes|true|sim)$/i.test(l);else if(o in Nu){const[u,c]=l.split(/\s+\|\s+/);if(!u)throw new Error(`${e}: Leeres Element im PAP: „${s}“.`);const m={shape:Nu[o],text:u.trim()};if(t.nodes.push(m),o!=="frage"){if(c)throw new Error(`${e}: Nur eine Frage hat einen zweiten Ausgang: „${s}“.`);continue}const d=/^(ja|nein)\s*(->|:)\s*(.+)$/i.exec(c??"");if(!d)throw new Error(`${e}: Eine Frage braucht „| nein -> Text“ oder „| nein: Text“: „${s}“.`);m.sideExit=d[1].toLowerCase(),d[2]===":"?(m.side=t.nodes.length,t.nodes.push({shape:"rechteck",text:d[3].trim(),isSide:!0})):n.push({node:t.nodes.length-1,target:d[3].trim(),line:s})}else throw new Error(`${e}: Unbekannter Schlüssel „${r[1]}“ im PAP.`)}for(const a of n){const s=t.nodes.findIndex((r,o)=>o{if(n.isSide)return;const s=xB(n.shape);(i.nodes.some(r=>r.backTo===a)||n.side!==void 0)&&(t+=12),e[a]={x:gB,y:t+s/2,w:n.shape==="raute"?170:n.shape==="oval"?110:pB,h:s},n.side!==void 0&&(e[n.side]={x:fB,y:t+s/2,w:bB,h:40}),t+=s+Fu}),{boxes:e,height:t-Fu+10}}function Uh(i,e){if((r=>r.length*6.6<=e)(i))return[i];const n=i.split(" ");let a=[i],s=1/0;for(let r=1;ru.length));l|→)\s*/);if(t.length!==2)throw new ne(`${e}: Test „${i}“ braucht genau ein „->“.`);const n=(a,s)=>a.trim()===""||a.trim()==="-"?[]:a.split(s).map(r=>r.trim());return{inputs:n(t[0],/\s*,\s*/),expected:n(t[1],/\s*\|\s*/)}}function yB(i){const e=/^(.*?)\s*(?:->|→)\s*(.*)$/.exec(i.trim());if(!e)throw new Error(`„messwerte: ${i}“ braucht ein „->“.`);const t={};for(const n of e[1].split(/\s*,\s*/).filter(Boolean)){const a=/^(\w+)\s*=\s*(.+)$/.exec(n);if(!a||!(a[1]in Ot))throw new Error(`Unbekannter Sensor in „${n}“.`);t[a[1]]=a[2].split("/").map(s=>{const r=s.trim();if(r==="true"||r==="false")return r==="true";if(/^-?\d+(\.\d+)?$/.test(r))return Number(r);if(typeof Ot[a[1]].simulated=="string")return r;throw new Error(`Messwert „${r}“ ist keine Zahl und nicht true/false.`)})}return Yh({inputs:[],expected:[],sensors:t},e[2])}function Yh(i,e){const t=[];e=e.replace(/\bscreen\s+("(?:[^"\\]|\\.)*")/u,(n,a)=>(i.screen=JSON.parse(a),""));for(const n of e.split(/\s*,\s*/).filter(Boolean))n==="ledOn"||n==="ledOff"?i.led=n==="ledOn":n==="tone"||n==="noTone"?i.tone=n==="tone":n==="none"?i.drive=[]:n==="drives"?i.drives=!0:t.push(n);return t.length&&(i.drive=is(dh(t.join(", ")))),i}function wB(i,e,t){const n={id:i,title:"",task:"",tests:[],requires:[],hints:[],subprograms:[]};let a;for(const s of e){const r=/^(titel|auftrag|start|test|datei|fahrt|befehle|welt|messwerte|schleifentiefe|braucht|tipp|lösung|loesung|unterprogramm|code):\s*(.*)$/i.exec(s.trim());if(r){const[,o,l]=r;switch(a=void 0,o.toLowerCase()){case"titel":n.title=l;break;case"auftrag":n.task=l,a="task";break;case"start":n.start=l;break;case"test":n.tests.push(vB(l,t));break;case"datei":{const u=/^([\w.-]+)\s*(?:->|→)\s*(.*)$/.exec(l.trim());if(!u||!n.tests.length)throw new ne(`${t}: Übung „${i}“: „datei:“ braucht vorher einen Test und die Form „name.txt -> Zeile | Zeile“.`);const c=n.tests[n.tests.length-1];c.files=[...c.files??[],{name:u[1],lines:u[2].trim()===""?[]:u[2].split(/\s*\|\s*/).map(m=>m.trim())}];break}case"fahrt":try{n.tests.push({inputs:[],expected:[],drive:is(dh(l))})}catch(u){throw new ne(`${t}: Übung „${i}“: ${u.message}`)}break;case"welt":{const u=/^([\w-]+)\s*(?:->|→)\s*(.+)$/.exec(l.trim());if(u){try{n.tests.push(Yh({inputs:[],expected:[],world:u[1]},u[2]))}catch(c){throw new ne(`${t}: Übung „${i}“: ${c.message}`)}break}for(const c of l.split(/\s*,\s*/).filter(Boolean)){if(!/^[\w-]+$/.test(c))throw new ne(`${t}: Übung „${i}“: Weltname „${c}“ (nur Buchstaben, Ziffern, -).`);n.tests.push({inputs:[],expected:[],world:c})}break}case"befehle":try{n.tests.push({inputs:[],expected:[],actions:x3(l)})}catch(u){throw new ne(`${t}: Übung „${i}“: ${u.message}`)}break;case"messwerte":try{n.tests.push(yB(l))}catch(u){throw new ne(`${t}: Übung „${i}“: ${u.message}`)}break;case"schleifentiefe":if(n.loopDepth=Number(l),!Number.isInteger(n.loopDepth)||n.loopDepth<1)throw new ne(`${t}: Übung „${i}“: „schleifentiefe:“ braucht eine Zahl ab 1.`);break;case"braucht":n.requires.push(...l.split(/\s*,\s*/).filter(Boolean));break;case"tipp":n.hints.push(l),a="hint";break;case"lösung":case"loesung":n.solution=l;break;case"unterprogramm":n.subprograms.push(...l.split(/\s*,\s*/).filter(Boolean));break;case"code":if(l.trim().toLowerCase()!=="java")throw new ne(`${t}: Übung „${i}“: „code:“ kennt nur „java“.`);n.code="java";break}}else a&&s.trim()!==""?a==="task"?n.task+=` +`).slice(t[0].length)}}function yB(i,e){const t=i.split(/\s*(?:->|→)\s*/);if(t.length!==2)throw new ne(`${e}: Test „${i}“ braucht genau ein „->“.`);const n=(a,s)=>a.trim()===""||a.trim()==="-"?[]:a.split(s).map(r=>r.trim());return{inputs:n(t[0],/\s*,\s*/),expected:n(t[1],/\s*\|\s*/)}}function wB(i){const e=/^(.*?)\s*(?:->|→)\s*(.*)$/.exec(i.trim());if(!e)throw new Error(`„messwerte: ${i}“ braucht ein „->“.`);const t={};for(const n of e[1].split(/\s*,\s*/).filter(Boolean)){const a=/^(\w+)\s*=\s*(.+)$/.exec(n);if(!a||!(a[1]in Ot))throw new Error(`Unbekannter Sensor in „${n}“.`);t[a[1]]=a[2].split("/").map(s=>{const r=s.trim();if(r==="true"||r==="false")return r==="true";if(/^-?\d+(\.\d+)?$/.test(r))return Number(r);if(typeof Ot[a[1]].simulated=="string")return r;throw new Error(`Messwert „${r}“ ist keine Zahl und nicht true/false.`)})}return Xh({inputs:[],expected:[],sensors:t},e[2])}function Xh(i,e){const t=[];e=e.replace(/\bscreen\s+("(?:[^"\\]|\\.)*")/u,(n,a)=>(i.screen=JSON.parse(a),""));for(const n of e.split(/\s*,\s*/).filter(Boolean))n==="ledOn"||n==="ledOff"?i.led=n==="ledOn":n==="tone"||n==="noTone"?i.tone=n==="tone":n==="none"?i.drive=[]:n==="drives"?i.drives=!0:t.push(n);return t.length&&(i.drive=is(dh(t.join(", ")))),i}function zB(i,e,t){const n={id:i,title:"",task:"",tests:[],requires:[],hints:[],subprograms:[]};let a;for(const s of e){const r=/^(titel|auftrag|start|test|datei|fahrt|befehle|welt|messwerte|schleifentiefe|braucht|tipp|lösung|loesung|unterprogramm|code|bereich):\s*(.*)$/i.exec(s.trim());if(r){const[,o,l]=r;switch(a=void 0,o.toLowerCase()){case"titel":n.title=l;break;case"auftrag":n.task=l,a="task";break;case"start":n.start=l;break;case"test":n.tests.push(yB(l,t));break;case"datei":{const u=/^([\w.-]+)\s*(?:->|→)\s*(.*)$/.exec(l.trim());if(!u||!n.tests.length)throw new ne(`${t}: Übung „${i}“: „datei:“ braucht vorher einen Test und die Form „name.txt -> Zeile | Zeile“.`);const c=n.tests[n.tests.length-1];c.files=[...c.files??[],{name:u[1],lines:u[2].trim()===""?[]:u[2].split(/\s*\|\s*/).map(m=>m.trim())}];break}case"fahrt":try{n.tests.push({inputs:[],expected:[],drive:is(dh(l))})}catch(u){throw new ne(`${t}: Übung „${i}“: ${u.message}`)}break;case"welt":{const u=/^([\w-]+)\s*(?:->|→)\s*(.+)$/.exec(l.trim());if(u){try{n.tests.push(Xh({inputs:[],expected:[],world:u[1]},u[2]))}catch(c){throw new ne(`${t}: Übung „${i}“: ${c.message}`)}break}for(const c of l.split(/\s*,\s*/).filter(Boolean)){if(!/^[\w-]+$/.test(c))throw new ne(`${t}: Übung „${i}“: Weltname „${c}“ (nur Buchstaben, Ziffern, -).`);n.tests.push({inputs:[],expected:[],world:c})}break}case"befehle":try{n.tests.push({inputs:[],expected:[],actions:v3(l)})}catch(u){throw new ne(`${t}: Übung „${i}“: ${u.message}`)}break;case"messwerte":try{n.tests.push(wB(l))}catch(u){throw new ne(`${t}: Übung „${i}“: ${u.message}`)}break;case"schleifentiefe":if(n.loopDepth=Number(l),!Number.isInteger(n.loopDepth)||n.loopDepth<1)throw new ne(`${t}: Übung „${i}“: „schleifentiefe:“ braucht eine Zahl ab 1.`);break;case"braucht":n.requires.push(...l.split(/\s*,\s*/).filter(Boolean));break;case"tipp":n.hints.push(l),a="hint";break;case"lösung":case"loesung":n.solution=l;break;case"unterprogramm":n.subprograms.push(...l.split(/\s*,\s*/).filter(Boolean));break;case"code":if(l.trim().toLowerCase()!=="java")throw new ne(`${t}: Übung „${i}“: „code:“ kennt nur „java“.`);n.code="java";break;case"bereich":{const u=l.trim().toLowerCase();if(u!=="struktogramm"&&u!=="code"&&u!=="beide")throw new ne(`${t}: Übung „${i}“: „bereich:“ kennt nur „struktogramm“, „code“ oder „beide“.`);n.area=u;break}}}else a&&s.trim()!==""?a==="task"?n.task+=` `+s.trim():n.hints[n.hints.length-1]+=` `+s.trim():s.trim()===""&&a==="task"&&(n.task+=` -`)}if(!n.title)throw new ne(`${t}: Übung „${i}“ hat keinen Titel.`);if(!n.task.trim())throw new ne(`${t}: Übung „${i}“ hat keinen Auftrag.`);return n.task=n.task.trim(),n}function zB(i,e){const t=[];for(const n of i){const a=n.trim();if(a.startsWith("?"))t.push({question:a.slice(1).trim(),options:[]});else if(/^- \[[ xX]\]/.test(a)){const s=t.at(-1);if(!s)throw new ne(`${e}: Antwort ohne Frage im Quiz.`);s.options.push({text:a.slice(5).trim(),correct:a[3].toLowerCase()==="x"})}else if(a.startsWith("= ")){const s=t.at(-1),r=/^=\s+(.+?)\s+->\s+(.+)$/.exec(a);if(!s||!r)throw new ne(`${e}: Zuordnung „${a}“ braucht die Form „= links -> rechts“ nach einer Frage.`);(s.pairs??(s.pairs=[])).push({left:r[1].trim(),right:r[2].trim()})}else if(a.startsWith("→")){const s=t.at(-1);if(!s)throw new ne(`${e}: „→ Schritt“ ohne Frage im Quiz.`);s.ref=a.slice(1).trim()}else if(a.startsWith(">")){const s=t.at(-1);s&&(s.explanation=((s.explanation?s.explanation+" ":"")+a.slice(1).trim()).trim())}}for(const n of t){if(n.pairs){const a=new Set(n.pairs.map(s=>s.right));if(n.options.length>0||n.pairs.length<2||a.size!==n.pairs.length)throw new ne(`${e}: Zuordnung „${n.question}“ braucht mindestens zwei Paare mit verschiedenen rechten Seiten und keine Antworten.`);continue}if(n.options.length<2||!n.options.some(a=>a.correct))throw new ne(`${e}: Quizfrage „${n.question}“ braucht mindestens zwei Antworten, davon eine richtige.`)}return t}function Xh(i,e){const t=[],n=i.split(` +`)}if(!n.title)throw new ne(`${t}: Übung „${i}“ hat keinen Titel.`);if(!n.task.trim())throw new ne(`${t}: Übung „${i}“ hat keinen Auftrag.`);return n.task=n.task.trim(),n}function IB(i,e){const t=[];for(const n of i){const a=n.trim();if(a.startsWith("?"))t.push({question:a.slice(1).trim(),options:[]});else if(/^- \[[ xX]\]/.test(a)){const s=t.at(-1);if(!s)throw new ne(`${e}: Antwort ohne Frage im Quiz.`);s.options.push({text:a.slice(5).trim(),correct:a[3].toLowerCase()==="x"})}else if(a.startsWith("= ")){const s=t.at(-1),r=/^=\s+(.+?)\s+->\s+(.+)$/.exec(a);if(!s||!r)throw new ne(`${e}: Zuordnung „${a}“ braucht die Form „= links -> rechts“ nach einer Frage.`);(s.pairs??(s.pairs=[])).push({left:r[1].trim(),right:r[2].trim()})}else if(a.startsWith("→")){const s=t.at(-1);if(!s)throw new ne(`${e}: „→ Schritt“ ohne Frage im Quiz.`);s.ref=a.slice(1).trim()}else if(a.startsWith(">")){const s=t.at(-1);s&&(s.explanation=((s.explanation?s.explanation+" ":"")+a.slice(1).trim()).trim())}}for(const n of t){if(n.pairs){const a=new Set(n.pairs.map(s=>s.right));if(n.options.length>0||n.pairs.length<2||a.size!==n.pairs.length)throw new ne(`${e}: Zuordnung „${n.question}“ braucht mindestens zwei Paare mit verschiedenen rechten Seiten und keine Antworten.`);continue}if(n.options.length<2||!n.options.some(a=>a.correct))throw new ne(`${e}: Quizfrage „${n.question}“ braucht mindestens zwei Antworten, davon eine richtige.`)}return t}function Kh(i,e){const t=[],n=i.split(` `);let a=[];const s=()=>{const r=a.join(` -`).trim();r&&t.push({kind:"markdown",text:r}),a=[]};for(let r=0;r=n.length)throw new ne(`${e}: Block „::: ${o[1]}“ wird nicht mit „:::“ geschlossen.`);const c=o[1].toLowerCase(),m=o[2].trim();switch(c){case"diagramm":if(!m)throw new ne(`${e}: „::: diagramm“ braucht einen Dateinamen.`);t.push({kind:"diagram",file:m,caption:l.join(" ").trim()});break;case"übung":case"uebung":if(!m)throw new ne(`${e}: „::: übung“ braucht eine Kennung.`);t.push({kind:"exercise",exercise:wB(m,l,e)});break;case"checkliste":t.push({kind:"checklist",items:l.map(d=>d.trim()).filter(d=>d.startsWith("- ")).map(d=>IB(d.slice(2).trim()))});break;case"kompetenzen":t.push({kind:"competences",items:l.map(d=>d.trim()).filter(d=>d.startsWith("- ")).map(d=>d.slice(2).trim())});break;case"quiz":t.push({kind:"quiz",questions:zB(l,e)});break;case"bild":if(!m)throw new ne(`${e}: „::: bild“ braucht einen Dateinamen.`);t.push({kind:"images",files:m.split(/\s+/),caption:l.join(" ").trim()});break;case"grafik":if(!m)throw new ne(`${e}: „::: grafik“ braucht einen Dateinamen.`);{const[d,h]=m.split(/\s+/);t.push({kind:"graphic",file:d,...h?{labeled:h}:{},caption:l.join(" ").trim()})}break;case"angeberwissen":t.push({kind:"brag",text:l.join(` -`).trim()});break;case"spiel":try{if(KD(m))t.push({kind:"roundGame",game:eB(m,l,e)});else if(m==="prinzessin")t.push({kind:"rescueGame",game:sB(l,e)});else{if(m)throw new ne(`${e}: Unbekanntes Spiel „${m}“ (zuhoerer, vertrag, layout, bombe, frage, reihenfolge oder prinzessin).`);t.push({kind:"game",game:ax(l,e)})}}catch(d){throw new ne(d.message)}break;case"lückentext":case"lueckentext":try{t.push({kind:"cloze",cloze:oB(l,e)})}catch(d){throw new ne(d.message)}break;case"pap":try{t.push({kind:"pap",pap:mB(l,e)})}catch(d){throw new ne(d.message)}break;case"ludwig":t.push({kind:"brag",text:l.join(` +`).trim();r&&t.push({kind:"markdown",text:r}),a=[]};for(let r=0;r=n.length)throw new ne(`${e}: Block „::: ${o[1]}“ wird nicht mit „:::“ geschlossen.`);const c=o[1].toLowerCase(),m=o[2].trim();switch(c){case"diagramm":if(!m)throw new ne(`${e}: „::: diagramm“ braucht einen Dateinamen.`);t.push({kind:"diagram",file:m,caption:l.join(" ").trim()});break;case"übung":case"uebung":if(!m)throw new ne(`${e}: „::: übung“ braucht eine Kennung.`);t.push({kind:"exercise",exercise:zB(m,l,e)});break;case"checkliste":t.push({kind:"checklist",items:l.map(d=>d.trim()).filter(d=>d.startsWith("- ")).map(d=>kB(d.slice(2).trim()))});break;case"kompetenzen":t.push({kind:"competences",items:l.map(d=>d.trim()).filter(d=>d.startsWith("- ")).map(d=>d.slice(2).trim())});break;case"quiz":t.push({kind:"quiz",questions:IB(l,e)});break;case"bild":if(!m)throw new ne(`${e}: „::: bild“ braucht einen Dateinamen.`);t.push({kind:"images",files:m.split(/\s+/),caption:l.join(" ").trim()});break;case"grafik":if(!m)throw new ne(`${e}: „::: grafik“ braucht einen Dateinamen.`);{const[d,h]=m.split(/\s+/);t.push({kind:"graphic",file:d,...h?{labeled:h}:{},caption:l.join(" ").trim()})}break;case"angeberwissen":t.push({kind:"brag",text:l.join(` +`).trim()});break;case"spiel":try{if(eB(m))t.push({kind:"roundGame",game:tB(m,l,e)});else if(m==="prinzessin")t.push({kind:"rescueGame",game:rB(l,e)});else{if(m)throw new ne(`${e}: Unbekanntes Spiel „${m}“ (zuhoerer, vertrag, layout, bombe, frage, reihenfolge oder prinzessin).`);t.push({kind:"game",game:sx(l,e)})}}catch(d){throw new ne(d.message)}break;case"lückentext":case"lueckentext":try{t.push({kind:"cloze",cloze:lB(l,e)})}catch(d){throw new ne(d.message)}break;case"pap":try{t.push({kind:"pap",pap:dB(l,e)})}catch(d){throw new ne(d.message)}break;case"ludwig":t.push({kind:"brag",text:l.join(` `).trim(),tip:!0});break;case"caesar":{const d=m?Number(m):3;if(!Number.isInteger(d)||d<0||d>25)throw new ne(`${e}: „::: caesar“ braucht einen Schlüssel von 0 bis 25.`);t.push({kind:"caesar",key:d,text:l.join(" ").trim()});break}case"mbot2":{const d={kind:"robotModel",focus:[]};for(const h of l.filter(g=>g.trim())){const g=/^\s*(fokus|focus|ansicht|view|drehen|spin):\s*(.*)$/i.exec(h);if(!g)throw new ne(`${e}: „::: mbot2“ kennt nur Zeilen „fokus:“, „ansicht:“ und „drehen:“.`);const f=g[1].toLowerCase();f==="fokus"||f==="focus"?d.focus=Ju(g[2],e):f==="ansicht"||f==="view"?d.view=g[2].trim().toLowerCase():d.spin=/^(ja|yes|true|sim)$/i.test(g[2].trim())}t.push(d);break}case"mbot2quiz":{const d={kind:"robotQuiz",tasks:[]};for(const h of l.filter(g=>g.trim())){const g=/^\s*-\s*(\w+)\s*:\s*(.+)$/.exec(h),f=/^\s*(fertig|done):\s*(.+)$/i.exec(h);if(g)d.tasks.push({part:Ju(g[1],e)[0],question:g[2].trim()});else if(f)d.done=f[2].trim();else throw new ne(`${e}: „::: mbot2quiz“ braucht Zeilen „- teil: Frage“ und optional „fertig: Text“.`)}if(!d.tasks.length)throw new ne(`${e}: „::: mbot2quiz“ hat keine Fragen.`);t.push(d);break}case"datei":{if(!/^[\w.-]+\.(txt|csv|json)$/u.test(m))throw new ne(`${e}: „::: datei“ braucht einen Dateinamen wie brief.txt, liste.csv oder daten.json.`);for(;l.length&&l[0].trim()==="";)l.shift();for(;l.length&&l[l.length-1].trim()==="";)l.pop();t.push({kind:"textFile",name:m,content:l.join(` -`)});break}default:throw new ne(`${e}: Unbekannter Block „::: ${o[1]}“.`)}r=u}return s(),t}function IB(i){const e=/^(.*?)\s+→\s+(.+)$/.exec(i);return e?{text:e[1],ref:e[2].trim()}:{text:i}}function kB(i,e){const t=new Map(i.map((a,s)=>[a.title.toLowerCase(),s]));for(const a of i.flatMap(s=>s.blocks))if(a.kind==="checklist"){for(const s of a.items)if(s.ref!==void 0&&(s.step=t.get(s.ref.toLowerCase()),s.step===void 0))throw new ne(`${e}: Checkliste verweist auf unbekannten Schritt „${s.ref}“.`)}const n=new Set(i.flatMap(a=>a.blocks).flatMap(a=>a.kind==="checklist"?a.items.map(s=>s.step):[]));for(const a of i.flatMap(s=>s.blocks))if(a.kind==="quiz"){for(const s of a.questions)if(s.ref!==void 0){if(s.step=t.get(s.ref.toLowerCase()),s.step===void 0)throw new ne(`${e}: Quizfrage „${s.question}“ verweist auf unbekannten Schritt „${s.ref}“.`);if(!n.has(s.step))throw new ne(`${e}: Zu „${s.ref}“ (Quizfrage „${s.question}“) gibt es keinen Checklistenpunkt.`)}}}function SB(i,e){var m;const{meta:t,body:n}=$h(i,e),a=e.replace(/^.*\//,"").replace(/\.md$/,""),s=Number((m=/^(\d+)/.exec(a))==null?void 0:m[1]);if(!Number.isFinite(s))throw new ne(`${e}: Dateiname muss mit der Nummer beginnen (z. B. 01-…).`);const r=[];let o=[],l;const u=()=>{l&&r.push({title:l.title,blocks:Xh(l.lines.join(` +`)});break}default:throw new ne(`${e}: Unbekannter Block „::: ${o[1]}“.`)}r=u}return s(),t}function kB(i){const e=/^(.*?)\s+→\s+(.+)$/.exec(i);return e?{text:e[1],ref:e[2].trim()}:{text:i}}function SB(i,e){const t=new Map(i.map((a,s)=>[a.title.toLowerCase(),s]));for(const a of i.flatMap(s=>s.blocks))if(a.kind==="checklist"){for(const s of a.items)if(s.ref!==void 0&&(s.step=t.get(s.ref.toLowerCase()),s.step===void 0))throw new ne(`${e}: Checkliste verweist auf unbekannten Schritt „${s.ref}“.`)}const n=new Set(i.flatMap(a=>a.blocks).flatMap(a=>a.kind==="checklist"?a.items.map(s=>s.step):[]));for(const a of i.flatMap(s=>s.blocks))if(a.kind==="quiz"){for(const s of a.questions)if(s.ref!==void 0){if(s.step=t.get(s.ref.toLowerCase()),s.step===void 0)throw new ne(`${e}: Quizfrage „${s.question}“ verweist auf unbekannten Schritt „${s.ref}“.`);if(!n.has(s.step))throw new ne(`${e}: Zu „${s.ref}“ (Quizfrage „${s.question}“) gibt es keinen Checklistenpunkt.`)}}}function TB(i,e){var m;const{meta:t,body:n}=Yh(i,e),a=e.replace(/^.*\//,"").replace(/\.md$/,""),s=Number((m=/^(\d+)/.exec(a))==null?void 0:m[1]);if(!Number.isFinite(s))throw new ne(`${e}: Dateiname muss mit der Nummer beginnen (z. B. 01-…).`);const r=[];let o=[],l;const u=()=>{l&&r.push({title:l.title,blocks:Kh(l.lines.join(` `),e)})};for(const d of n.split(` -`)){const h=/^##\s+(.*)$/.exec(d);h?(u(),l={title:h[1].trim(),lines:[]}):l?l.lines.push(d):o.push(d)}if(u(),r.length===0)throw new ne(`${e}: Keine Schritte (## Überschrift) gefunden.`);kB(r,e);const c=t.get("titel");if(!c)throw new ne(`${e}: „titel:“ fehlt.`);return{id:a,number:s,title:c,section:t.get("bereich")??"",summary:t.get("kurz")??o.join(" ").trim(),steps:r}}function TB(i,e){const{meta:t,body:n}=$h(i,e),a=t.get("titel");if(!a)throw new ne(`${e}: „titel:“ fehlt.`);const s=t.get("nach");return{id:e.replace(/^.*\//,"").replace(/\.md$/,""),title:a,after:s?Number(s):void 0,level:Number(t.get("stufe")??"1")||1,blocks:Xh(n,e)}}function Ju(i,e){const t=i.split(/\s*,\s*/).map(n=>n.trim()).filter(Boolean);for(const n of t)if(!w3(n))throw new ne(`${e}: Unbekanntes Teil „${n}“. Bekannt: ${hh.join(", ")}.`);return t}const _B=Object.assign({"../../lessons/de/01-was-ist-ein-struktogramm.md":mx,"../../lessons/de/02-der-editor.md":dx,"../../lessons/de/03-speichern-oeffnen-exportieren.md":hx,"../../lessons/de/04-variablen-und-datentypen.md":gx,"../../lessons/de/05-sequenz.md":px,"../../lessons/de/06-eingabe-und-ausgabe.md":fx,"../../lessons/de/07-simulation-und-schreibtischtest.md":bx,"../../lessons/de/08-verzweigung.md":xx,"../../lessons/de/09-bedingungen-verknuepfen.md":vx,"../../lessons/de/10-fallauswahl.md":yx,"../../lessons/de/11-while-schleife.md":wx,"../../lessons/de/12-do-while-schleife.md":zx,"../../lessons/de/13-for-schleife.md":Ix,"../../lessons/de/14-verschachteln.md":kx,"../../lessons/de/15-arrays.md":Sx,"../../lessons/de/16-zweidimensionale-arrays.md":Tx,"../../lessons/de/17-zeichenketten.md":_x,"../../lessons/de/18-aufruf-und-aussprung.md":Ox,"../../lessons/de/19-suchen-und-sortieren.md":Ax,"../../lessons/de/20-java.md":Cx,"../../lessons/de/21-python-und-javascript.md":Px,"../../lessons/de/22-try-und-catch.md":jx,"../../lessons/de/23-text-einlesen-und-speichern.md":Dx,"../../lessons/de/24-zeile-fuer-zeile.md":Bx,"../../lessons/de/25-tabellen-als-csv.md":Zx,"../../lessons/de/26-json.md":Mx,"../../lessons/de/27-formate-im-vergleich.md":Lx,"../../lessons/de/28-erstes-fenster.md":Ex,"../../lessons/de/29-knopf-im-fenster.md":Wx,"../../lessons/de/30-der-knopf-reagiert.md":Nx,"../../lessons/de/31-zahl-verdoppeln.md":Fx,"../../lessons/de/32-klickzaehler.md":Jx,"../../lessons/de/33-ampel.md":Rx,"../../lessons/de/34-notenrechner.md":Gx,"../../lessons/de/35-taschenrechner.md":Hx,"../../lessons/de/36-zahlenraten.md":Vx,"../../lessons/de/37-viele-knoepfe-ein-zuhoerer.md":qx,"../../lessons/de/38-innere-klassen.md":Qx,"../../lessons/de/39-zwei-reiter.md":Ux,"../../lessons/de/40-model-view-controller.md":$x,"../../lessons/de/begriffe.md":Yx,"../../lessons/de/nachschlagen.md":Xx,"../../lessons/en/01-was-ist-ein-struktogramm.md":Kx,"../../lessons/en/02-der-editor.md":e4,"../../lessons/en/03-speichern-oeffnen-exportieren.md":t4,"../../lessons/en/04-variablen-und-datentypen.md":n4,"../../lessons/en/05-sequenz.md":i4,"../../lessons/en/06-eingabe-und-ausgabe.md":a4,"../../lessons/en/07-simulation-und-schreibtischtest.md":s4,"../../lessons/en/08-verzweigung.md":r4,"../../lessons/en/09-bedingungen-verknuepfen.md":o4,"../../lessons/en/10-fallauswahl.md":l4,"../../lessons/en/11-while-schleife.md":u4,"../../lessons/en/12-do-while-schleife.md":c4,"../../lessons/en/13-for-schleife.md":m4,"../../lessons/en/14-verschachteln.md":d4,"../../lessons/en/15-arrays.md":h4,"../../lessons/en/16-zweidimensionale-arrays.md":g4,"../../lessons/en/17-zeichenketten.md":p4,"../../lessons/en/18-aufruf-und-aussprung.md":f4,"../../lessons/en/19-suchen-und-sortieren.md":b4,"../../lessons/en/20-java.md":x4,"../../lessons/en/21-python-und-javascript.md":v4,"../../lessons/en/22-try-und-catch.md":y4,"../../lessons/en/23-text-einlesen-und-speichern.md":w4,"../../lessons/en/24-zeile-fuer-zeile.md":z4,"../../lessons/en/25-tabellen-als-csv.md":I4,"../../lessons/en/26-json.md":k4,"../../lessons/en/27-formate-im-vergleich.md":S4,"../../lessons/en/28-erstes-fenster.md":T4,"../../lessons/en/29-knopf-im-fenster.md":_4,"../../lessons/en/30-der-knopf-reagiert.md":O4,"../../lessons/en/31-zahl-verdoppeln.md":A4,"../../lessons/en/32-klickzaehler.md":C4,"../../lessons/en/33-ampel.md":P4,"../../lessons/en/34-notenrechner.md":j4,"../../lessons/en/35-taschenrechner.md":D4,"../../lessons/en/36-zahlenraten.md":B4,"../../lessons/en/37-viele-knoepfe-ein-zuhoerer.md":Z4,"../../lessons/en/38-innere-klassen.md":M4,"../../lessons/en/39-zwei-reiter.md":L4,"../../lessons/en/40-model-view-controller.md":E4,"../../lessons/en/begriffe.md":W4,"../../lessons/en/nachschlagen.md":N4,"../../lessons/pt/01-was-ist-ein-struktogramm.md":F4,"../../lessons/pt/02-der-editor.md":J4,"../../lessons/pt/03-speichern-oeffnen-exportieren.md":R4,"../../lessons/pt/04-variablen-und-datentypen.md":G4,"../../lessons/pt/05-sequenz.md":H4,"../../lessons/pt/06-eingabe-und-ausgabe.md":V4,"../../lessons/pt/07-simulation-und-schreibtischtest.md":q4,"../../lessons/pt/08-verzweigung.md":Q4,"../../lessons/pt/09-bedingungen-verknuepfen.md":U4,"../../lessons/pt/10-fallauswahl.md":$4,"../../lessons/pt/11-while-schleife.md":Y4,"../../lessons/pt/12-do-while-schleife.md":X4,"../../lessons/pt/13-for-schleife.md":K4,"../../lessons/pt/14-verschachteln.md":ev,"../../lessons/pt/15-arrays.md":tv,"../../lessons/pt/16-zweidimensionale-arrays.md":nv,"../../lessons/pt/17-zeichenketten.md":iv,"../../lessons/pt/18-aufruf-und-aussprung.md":av,"../../lessons/pt/19-suchen-und-sortieren.md":sv,"../../lessons/pt/20-java.md":rv,"../../lessons/pt/21-python-und-javascript.md":ov,"../../lessons/pt/22-try-und-catch.md":lv,"../../lessons/pt/23-text-einlesen-und-speichern.md":uv,"../../lessons/pt/24-zeile-fuer-zeile.md":cv,"../../lessons/pt/25-tabellen-als-csv.md":mv,"../../lessons/pt/26-json.md":dv,"../../lessons/pt/27-formate-im-vergleich.md":hv,"../../lessons/pt/28-erstes-fenster.md":gv,"../../lessons/pt/29-knopf-im-fenster.md":pv,"../../lessons/pt/30-der-knopf-reagiert.md":fv,"../../lessons/pt/31-zahl-verdoppeln.md":bv,"../../lessons/pt/32-klickzaehler.md":xv,"../../lessons/pt/33-ampel.md":vv,"../../lessons/pt/34-notenrechner.md":yv,"../../lessons/pt/35-taschenrechner.md":wv,"../../lessons/pt/36-zahlenraten.md":zv,"../../lessons/pt/37-viele-knoepfe-ein-zuhoerer.md":Iv,"../../lessons/pt/38-innere-klassen.md":kv,"../../lessons/pt/39-zwei-reiter.md":Sv,"../../lessons/pt/40-model-view-controller.md":Tv,"../../lessons/pt/begriffe.md":_v,"../../lessons/pt/nachschlagen.md":Ov}),OB=Object.assign({"../../lessons/de/aufgaben/alter-unterprogramm.md":Av,"../../lessons/de/aufgaben/ballwurf.md":Cv,"../../lessons/de/aufgaben/bestenliste.md":Pv,"../../lessons/de/aufgaben/binaerzahl.md":jv,"../../lessons/de/aufgaben/caesar.md":Dv,"../../lessons/de/aufgaben/collatz.md":Bv,"../../lessons/de/aufgaben/einheitenrechner.md":Zv,"../../lessons/de/aufgaben/fibonacci.md":Mv,"../../lessons/de/aufgaben/gerade-ungerade.md":Lv,"../../lessons/de/aufgaben/mehrwertsteuer.md":Ev,"../../lessons/de/aufgaben/notendurchschnitt.md":Wv,"../../lessons/de/aufgaben/pin-pruefen.md":Nv,"../../lessons/de/aufgaben/schiffe-versenken.md":Fv,"../../lessons/de/aufgaben/speisekarte.md":Jv,"../../lessons/de/aufgaben/summe-bilden.md":Rv,"../../lessons/de/aufgaben/tafeldienst.md":Gv,"../../lessons/de/aufgaben/taschenrechner.md":Hv,"../../lessons/de/aufgaben/verleih-menue.md":Vv,"../../lessons/de/aufgaben/vokabeltrainer.md":qv,"../../lessons/de/aufgaben/volljaehrig.md":Qv,"../../lessons/de/aufgaben/wuerfel-mvc.md":Uv,"../../lessons/de/aufgaben/zahl-verdoppeln.md":$v,"../../lessons/en/aufgaben/alter-unterprogramm.md":Yv,"../../lessons/en/aufgaben/ballwurf.md":Xv,"../../lessons/en/aufgaben/bestenliste.md":Kv,"../../lessons/en/aufgaben/binaerzahl.md":ey,"../../lessons/en/aufgaben/caesar.md":ty,"../../lessons/en/aufgaben/collatz.md":ny,"../../lessons/en/aufgaben/einheitenrechner.md":iy,"../../lessons/en/aufgaben/fibonacci.md":ay,"../../lessons/en/aufgaben/gerade-ungerade.md":sy,"../../lessons/en/aufgaben/mehrwertsteuer.md":ry,"../../lessons/en/aufgaben/notendurchschnitt.md":oy,"../../lessons/en/aufgaben/pin-pruefen.md":ly,"../../lessons/en/aufgaben/schiffe-versenken.md":uy,"../../lessons/en/aufgaben/speisekarte.md":cy,"../../lessons/en/aufgaben/summe-bilden.md":my,"../../lessons/en/aufgaben/tafeldienst.md":dy,"../../lessons/en/aufgaben/taschenrechner.md":hy,"../../lessons/en/aufgaben/verleih-menue.md":gy,"../../lessons/en/aufgaben/vokabeltrainer.md":py,"../../lessons/en/aufgaben/volljaehrig.md":fy,"../../lessons/en/aufgaben/wuerfel-mvc.md":by,"../../lessons/en/aufgaben/zahl-verdoppeln.md":xy,"../../lessons/pt/aufgaben/alter-unterprogramm.md":vy,"../../lessons/pt/aufgaben/ballwurf.md":yy,"../../lessons/pt/aufgaben/bestenliste.md":wy,"../../lessons/pt/aufgaben/binaerzahl.md":zy,"../../lessons/pt/aufgaben/caesar.md":Iy,"../../lessons/pt/aufgaben/collatz.md":ky,"../../lessons/pt/aufgaben/einheitenrechner.md":Sy,"../../lessons/pt/aufgaben/fibonacci.md":Ty,"../../lessons/pt/aufgaben/gerade-ungerade.md":_y,"../../lessons/pt/aufgaben/mehrwertsteuer.md":Oy,"../../lessons/pt/aufgaben/notendurchschnitt.md":Ay,"../../lessons/pt/aufgaben/pin-pruefen.md":Cy,"../../lessons/pt/aufgaben/schiffe-versenken.md":Py,"../../lessons/pt/aufgaben/speisekarte.md":jy,"../../lessons/pt/aufgaben/summe-bilden.md":Dy,"../../lessons/pt/aufgaben/tafeldienst.md":By,"../../lessons/pt/aufgaben/taschenrechner.md":Zy,"../../lessons/pt/aufgaben/verleih-menue.md":My,"../../lessons/pt/aufgaben/vokabeltrainer.md":Ly,"../../lessons/pt/aufgaben/volljaehrig.md":Ey,"../../lessons/pt/aufgaben/wuerfel-mvc.md":Wy,"../../lessons/pt/aufgaben/zahl-verdoppeln.md":Ny}),Ru=Object.assign({"../../lessons/de/visubot/01-der-mbot2.md":Fy,"../../lessons/de/visubot/02-das-quadrat.md":Jy,"../../lessons/de/visubot/03-variablen-und-ausgabe.md":Ry,"../../lessons/de/visubot/04-sensoren.md":Gy,"../../lessons/de/visubot/05-bis-zur-wand.md":Hy,"../../lessons/de/visubot/06-abstand.md":Vy,"../../lessons/de/visubot/07-linie.md":qy,"../../lessons/de/visubot/08-farben.md":Qy,"../../lessons/de/visubot/09-fallauswahl.md":Uy,"../../lessons/de/visubot/10-tasten-joystick.md":$y,"../../lessons/de/visubot/11-licht.md":Yy,"../../lessons/de/visubot/12-lautstaerke.md":Xy,"../../lessons/de/visubot/13-neigung.md":Ky,"../../lessons/de/visubot/14-leds.md":ew,"../../lessons/de/visubot/15-einzelne-leds.md":tw,"../../lessons/de/visubot/16-lautsprecher.md":nw,"../../lessons/de/visubot/17-arrays-melodie.md":iw,"../../lessons/de/visubot/18-bildschirm.md":aw,"../../lessons/de/visubot/19-zeichenketten.md":sw,"../../lessons/de/visubot/20-motoren.md":rw,"../../lessons/de/visubot/21-stoppuhr-akku.md":ow,"../../lessons/de/visubot/22-eigene-methoden.md":lw,"../../lessons/de/visubot/nachschlagen.md":uw,"../../lessons/en/visubot/01-der-mbot2.md":cw,"../../lessons/en/visubot/02-das-quadrat.md":mw,"../../lessons/en/visubot/03-variablen-und-ausgabe.md":dw,"../../lessons/en/visubot/04-sensoren.md":hw,"../../lessons/en/visubot/05-bis-zur-wand.md":gw,"../../lessons/en/visubot/06-abstand.md":pw,"../../lessons/en/visubot/07-linie.md":fw,"../../lessons/en/visubot/08-farben.md":bw,"../../lessons/en/visubot/09-fallauswahl.md":xw,"../../lessons/en/visubot/10-tasten-joystick.md":vw,"../../lessons/en/visubot/11-licht.md":yw,"../../lessons/en/visubot/12-lautstaerke.md":ww,"../../lessons/en/visubot/13-neigung.md":zw,"../../lessons/en/visubot/14-leds.md":Iw,"../../lessons/en/visubot/15-einzelne-leds.md":kw,"../../lessons/en/visubot/16-lautsprecher.md":Sw,"../../lessons/en/visubot/17-arrays-melodie.md":Tw,"../../lessons/en/visubot/18-bildschirm.md":_w,"../../lessons/en/visubot/19-zeichenketten.md":Ow,"../../lessons/en/visubot/20-motoren.md":Aw,"../../lessons/en/visubot/21-stoppuhr-akku.md":Cw,"../../lessons/en/visubot/22-eigene-methoden.md":Pw,"../../lessons/en/visubot/nachschlagen.md":jw}),AB=Object.assign({"../../lessons/de/visubot/aufgaben/alarmanlage.md":Dw,"../../lessons/de/visubot/aufgaben/ausgang.md":Bw,"../../lessons/de/visubot/aufgaben/binaer-zaehlen.md":Zw,"../../lessons/de/visubot/aufgaben/dreieck.md":Mw,"../../lessons/de/visubot/aufgaben/einparken.md":Lw,"../../lessons/de/visubot/aufgaben/hindernis.md":Ew,"../../lessons/de/visubot/aufgaben/knight-rider.md":Ww,"../../lessons/de/visubot/aufgaben/labyrinth.md":Nw,"../../lessons/de/visubot/aufgaben/linienfolger-stopp.md":Fw,"../../lessons/de/visubot/aufgaben/morsen.md":Jw,"../../lessons/de/visubot/aufgaben/nachtwaechter.md":Rw,"../../lessons/de/visubot/aufgaben/slalom.md":Gw,"../../lessons/de/visubot/aufgaben/spirale.md":Hw,"../../lessons/de/visubot/aufgaben/treppe.md":Vw,"../../lessons/de/visubot/aufgaben/tunnel.md":qw,"../../lessons/de/visubot/aufgaben/wald.md":Qw,"../../lessons/en/visubot/aufgaben/alarmanlage.md":Uw,"../../lessons/en/visubot/aufgaben/ausgang.md":$w,"../../lessons/en/visubot/aufgaben/binaer-zaehlen.md":Yw,"../../lessons/en/visubot/aufgaben/dreieck.md":Xw,"../../lessons/en/visubot/aufgaben/einparken.md":Kw,"../../lessons/en/visubot/aufgaben/hindernis.md":e9,"../../lessons/en/visubot/aufgaben/knight-rider.md":t9,"../../lessons/en/visubot/aufgaben/labyrinth.md":n9,"../../lessons/en/visubot/aufgaben/linienfolger-stopp.md":i9,"../../lessons/en/visubot/aufgaben/morsen.md":a9,"../../lessons/en/visubot/aufgaben/nachtwaechter.md":s9,"../../lessons/en/visubot/aufgaben/slalom.md":r9,"../../lessons/en/visubot/aufgaben/spirale.md":o9,"../../lessons/en/visubot/aufgaben/treppe.md":l9,"../../lessons/en/visubot/aufgaben/tunnel.md":u9,"../../lessons/en/visubot/aufgaben/wald.md":c9}),CB=Object.assign({"../../lessons/diagramme/aufgabe-alter-haupt-loesung.visustruct":m9,"../../lessons/diagramme/aufgabe-alter-unterprogramm-loesung.visustruct":d9,"../../lessons/diagramme/aufgabe-ballwurf-loesung.visustruct":h9,"../../lessons/diagramme/aufgabe-ballwurf-start.visustruct":g9,"../../lessons/diagramme/aufgabe-bestenliste-loesung.visustruct":p9,"../../lessons/diagramme/aufgabe-binaer-loesung.visustruct":f9,"../../lessons/diagramme/aufgabe-caesar-array-loesung.visustruct":b9,"../../lessons/diagramme/aufgabe-caesar-array-start.visustruct":x9,"../../lessons/diagramme/aufgabe-caesar-ascii-loesung.visustruct":v9,"../../lessons/diagramme/aufgabe-caesar-entschluesseln-loesung.visustruct":y9,"../../lessons/diagramme/aufgabe-collatz-loesung.visustruct":w9,"../../lessons/diagramme/aufgabe-durchschnitt-loesung.visustruct":z9,"../../lessons/diagramme/aufgabe-fibonacci-loesung.visustruct":I9,"../../lessons/diagramme/aufgabe-gerade-loesung.visustruct":k9,"../../lessons/diagramme/aufgabe-mehrwertsteuer-loesung.visustruct":S9,"../../lessons/diagramme/aufgabe-pin-java-loesung.visustruct":T9,"../../lessons/diagramme/aufgabe-pin-loesung.visustruct":_9,"../../lessons/diagramme/aufgabe-rechner-loesung.visustruct":O9,"../../lessons/diagramme/aufgabe-schiffe-loesung.visustruct":A9,"../../lessons/diagramme/aufgabe-schiffe-start.visustruct":C9,"../../lessons/diagramme/aufgabe-speisekarte-loesung.visustruct":P9,"../../lessons/diagramme/aufgabe-summe-loesung.visustruct":j9,"../../lessons/diagramme/aufgabe-tafeldienst-loesung.visustruct":D9,"../../lessons/diagramme/aufgabe-verdoppeln-loesung.visustruct":B9,"../../lessons/diagramme/aufgabe-verleih-java-loesung.visustruct":Z9,"../../lessons/diagramme/aufgabe-verleih-loesung.visustruct":M9,"../../lessons/diagramme/aufgabe-vokabeln-loesung.visustruct":L9,"../../lessons/diagramme/aufgabe-vokabeln-start.visustruct":E9,"../../lessons/diagramme/aufgabe-volljaehrig-loesung.visustruct":W9,"../../lessons/diagramme/dt-buffered.visustruct":N9,"../../lessons/diagramme/dt-csv.visustruct":F9,"../../lessons/diagramme/dt-json.visustruct":J9,"../../lessons/diagramme/dt-lesen.visustruct":R9,"../../lessons/diagramme/en/aufgabe-alter-haupt-loesung.visustruct":G9,"../../lessons/diagramme/en/aufgabe-alter-unterprogramm-loesung.visustruct":H9,"../../lessons/diagramme/en/aufgabe-ballwurf-loesung.visustruct":V9,"../../lessons/diagramme/en/aufgabe-ballwurf-start.visustruct":q9,"../../lessons/diagramme/en/aufgabe-bestenliste-loesung.visustruct":Q9,"../../lessons/diagramme/en/aufgabe-binaer-loesung.visustruct":U9,"../../lessons/diagramme/en/aufgabe-caesar-array-loesung.visustruct":$9,"../../lessons/diagramme/en/aufgabe-caesar-array-start.visustruct":Y9,"../../lessons/diagramme/en/aufgabe-caesar-ascii-loesung.visustruct":X9,"../../lessons/diagramme/en/aufgabe-caesar-entschluesseln-loesung.visustruct":K9,"../../lessons/diagramme/en/aufgabe-collatz-loesung.visustruct":e5,"../../lessons/diagramme/en/aufgabe-durchschnitt-loesung.visustruct":t5,"../../lessons/diagramme/en/aufgabe-fibonacci-loesung.visustruct":n5,"../../lessons/diagramme/en/aufgabe-gerade-loesung.visustruct":i5,"../../lessons/diagramme/en/aufgabe-mehrwertsteuer-loesung.visustruct":a5,"../../lessons/diagramme/en/aufgabe-pin-java-loesung.visustruct":s5,"../../lessons/diagramme/en/aufgabe-pin-loesung.visustruct":r5,"../../lessons/diagramme/en/aufgabe-rechner-loesung.visustruct":o5,"../../lessons/diagramme/en/aufgabe-schiffe-loesung.visustruct":l5,"../../lessons/diagramme/en/aufgabe-schiffe-start.visustruct":u5,"../../lessons/diagramme/en/aufgabe-speisekarte-loesung.visustruct":c5,"../../lessons/diagramme/en/aufgabe-summe-loesung.visustruct":m5,"../../lessons/diagramme/en/aufgabe-tafeldienst-loesung.visustruct":d5,"../../lessons/diagramme/en/aufgabe-verdoppeln-loesung.visustruct":h5,"../../lessons/diagramme/en/aufgabe-verleih-java-loesung.visustruct":g5,"../../lessons/diagramme/en/aufgabe-verleih-loesung.visustruct":p5,"../../lessons/diagramme/en/aufgabe-vokabeln-loesung.visustruct":f5,"../../lessons/diagramme/en/aufgabe-vokabeln-start.visustruct":b5,"../../lessons/diagramme/en/aufgabe-volljaehrig-loesung.visustruct":x5,"../../lessons/diagramme/en/dt-buffered.visustruct":v5,"../../lessons/diagramme/en/dt-csv.visustruct":y5,"../../lessons/diagramme/en/dt-json.visustruct":w5,"../../lessons/diagramme/en/dt-lesen.visustruct":z5,"../../lessons/diagramme/en/kino-einmaleins-loesung.visustruct":I5,"../../lessons/diagramme/en/kino-frei-loesung.visustruct":k5,"../../lessons/diagramme/en/kino-frei-start.visustruct":S5,"../../lessons/diagramme/en/kino-karte-loesung.visustruct":T5,"../../lessons/diagramme/en/kino-karte-start.visustruct":_5,"../../lessons/diagramme/en/kino-saalplan.visustruct":O5,"../../lessons/diagramme/en/kino-verkaufen.visustruct":A5,"../../lessons/diagramme/en/l04-java-fehler-loesung.visustruct":C5,"../../lessons/diagramme/en/l04-java-fehler-start.visustruct":P5,"../../lessons/diagramme/en/l04-java-steckbrief-loesung.visustruct":j5,"../../lessons/diagramme/en/l04-rechnen.visustruct":D5,"../../lessons/diagramme/en/l04-reihenfolge-loesung.visustruct":B5,"../../lessons/diagramme/en/l04-reihenfolge-start.visustruct":Z5,"../../lessons/diagramme/en/l04-tauschen-loesung.visustruct":M5,"../../lessons/diagramme/en/l04-tauschen-start.visustruct":L5,"../../lessons/diagramme/en/l04-tauschen.visustruct":E5,"../../lessons/diagramme/en/l05-datentypen.visustruct":W5,"../../lessons/diagramme/en/l05-division.visustruct":N5,"../../lessons/diagramme/en/l05-einkauf-loesung.visustruct":F5,"../../lessons/diagramme/en/l05-java-fehler-loesung.visustruct":J5,"../../lessons/diagramme/en/l05-java-fehler-start.visustruct":R5,"../../lessons/diagramme/en/l05-java-kino-loesung.visustruct":G5,"../../lessons/diagramme/en/l05-rechteck-loesung.visustruct":H5,"../../lessons/diagramme/en/l05-sekunden-loesung.visustruct":V5,"../../lessons/diagramme/en/l05-sekunden-start.visustruct":q5,"../../lessons/diagramme/en/l05-sequenz.visustruct":Q5,"../../lessons/diagramme/en/l06-begruessung-loesung.visustruct":U5,"../../lessons/diagramme/en/l06-eva.visustruct":$5,"../../lessons/diagramme/en/l06-java-fehler-loesung.visustruct":Y5,"../../lessons/diagramme/en/l06-java-fehler-start.visustruct":X5,"../../lessons/diagramme/en/l06-java-tage-loesung.visustruct":K5,"../../lessons/diagramme/en/l06-mittelwert-loesung.visustruct":ez,"../../lessons/diagramme/en/l06-rechner-loesung.visustruct":tz,"../../lessons/diagramme/en/l07-alter-pruefen.visustruct":nz,"../../lessons/diagramme/en/l07-betrag-loesung.visustruct":iz,"../../lessons/diagramme/en/l07-gerade-loesung.visustruct":az,"../../lessons/diagramme/en/l07-java-fehler-loesung.visustruct":sz,"../../lessons/diagramme/en/l07-java-fehler-start.visustruct":rz,"../../lessons/diagramme/en/l07-java-pizza-loesung.visustruct":oz,"../../lessons/diagramme/en/l07-java-pizza-start.visustruct":lz,"../../lessons/diagramme/en/l07-maximum-loesung.visustruct":uz,"../../lessons/diagramme/en/l07-rabatt.visustruct":cz,"../../lessons/diagramme/en/l08-gueltig-loesung.visustruct":mz,"../../lessons/diagramme/en/l08-java-bestanden-loesung.visustruct":dz,"../../lessons/diagramme/en/l08-java-fehler-loesung.visustruct":hz,"../../lessons/diagramme/en/l08-java-fehler-start.visustruct":gz,"../../lessons/diagramme/en/l08-jugendticket.visustruct":pz,"../../lessons/diagramme/en/l08-note.visustruct":fz,"../../lessons/diagramme/en/l08-schaltjahr-loesung.visustruct":bz,"../../lessons/diagramme/en/l08-wochenende-loesung.visustruct":xz,"../../lessons/diagramme/en/l09-ampel.visustruct":vz,"../../lessons/diagramme/en/l09-automat.visustruct":yz,"../../lessons/diagramme/en/l09-java-fehler-loesung.visustruct":wz,"../../lessons/diagramme/en/l09-java-fehler-start.visustruct":zz,"../../lessons/diagramme/en/l09-java-schule-loesung.visustruct":Iz,"../../lessons/diagramme/en/l09-note-loesung.visustruct":kz,"../../lessons/diagramme/en/l09-rechner-loesung.visustruct":Sz,"../../lessons/diagramme/en/l09-verschachtelt.visustruct":Tz,"../../lessons/diagramme/en/l1-grundbausteine.visustruct":_z,"../../lessons/diagramme/en/l1-sequenz.visustruct":Oz,"../../lessons/diagramme/en/l1-tee.visustruct":Az,"../../lessons/diagramme/en/l1-verzweigung.visustruct":Cz,"../../lessons/diagramme/en/l1-wiederholung.visustruct":Pz,"../../lessons/diagramme/en/l10-bis-n-loesung.visustruct":jz,"../../lessons/diagramme/en/l10-countdown.visustruct":Dz,"../../lessons/diagramme/en/l10-endlos.visustruct":Bz,"../../lessons/diagramme/en/l10-fakultaet.visustruct":Zz,"../../lessons/diagramme/en/l10-java-fehler-loesung.visustruct":Mz,"../../lessons/diagramme/en/l10-java-fehler-start.visustruct":Lz,"../../lessons/diagramme/en/l10-java-wuerfel-loesung.visustruct":Ez,"../../lessons/diagramme/en/l10-verdoppeln-loesung.visustruct":Wz,"../../lessons/diagramme/en/l11-eingabe-pruefen.visustruct":Nz,"../../lessons/diagramme/en/l11-einmal.visustruct":Fz,"../../lessons/diagramme/en/l11-java-fehler-loesung.visustruct":Jz,"../../lessons/diagramme/en/l11-java-fehler-start.visustruct":Rz,"../../lessons/diagramme/en/l11-java-gerade-loesung.visustruct":Gz,"../../lessons/diagramme/en/l11-note-loesung.visustruct":Hz,"../../lessons/diagramme/en/l11-summe-loesung.visustruct":Vz,"../../lessons/diagramme/en/l12-countdown-loesung.visustruct":qz,"../../lessons/diagramme/en/l12-einmaleins-loesung.visustruct":Qz,"../../lessons/diagramme/en/l12-eins-bis-fuenf.visustruct":Uz,"../../lessons/diagramme/en/l12-java-fehler-loesung.visustruct":$z,"../../lessons/diagramme/en/l12-java-fehler-start.visustruct":Yz,"../../lessons/diagramme/en/l12-java-verdoppeln-loesung.visustruct":Xz,"../../lessons/diagramme/en/l12-summe.visustruct":Kz,"../../lessons/diagramme/en/l13-dreieck.visustruct":e6,"../../lessons/diagramme/en/l13-gerade-eingaben-loesung.visustruct":t6,"../../lessons/diagramme/en/l13-gerade-zaehlen.visustruct":n6,"../../lessons/diagramme/en/l13-java-fehler-loesung.visustruct":i6,"../../lessons/diagramme/en/l13-java-fehler-start.visustruct":a6,"../../lessons/diagramme/en/l13-java-quadrate-loesung.visustruct":s6,"../../lessons/diagramme/en/l13-rechteck-loesung.visustruct":r6,"../../lessons/diagramme/en/l14-array-durchlaufen.visustruct":o6,"../../lessons/diagramme/en/l14-erster-letzter-loesung.visustruct":l6,"../../lessons/diagramme/en/l14-java-fehler-loesung.visustruct":u6,"../../lessons/diagramme/en/l14-java-fehler-start.visustruct":c6,"../../lessons/diagramme/en/l14-java-treppe-loesung.visustruct":m6,"../../lessons/diagramme/en/l14-namen-eingeben.visustruct":d6,"../../lessons/diagramme/en/l14-rueckwaerts-loesung.visustruct":h6,"../../lessons/diagramme/en/l14-summe-max-loesung.visustruct":g6,"../../lessons/diagramme/en/l14-summe-maximum.visustruct":p6,"../../lessons/diagramme/en/l15-bis-null-loesung.visustruct":f6,"../../lessons/diagramme/en/l15-endlos-aussprung.visustruct":b6,"../../lessons/diagramme/en/l15-flaeche-loesung.visustruct":x6,"../../lessons/diagramme/en/l15-flaeche-unterprogramm-loesung.visustruct":v6,"../../lessons/diagramme/en/l15-hauptprogramm.visustruct":y6,"../../lessons/diagramme/en/l15-java-fehler-loesung.visustruct":w6,"../../lessons/diagramme/en/l15-java-fehler-start.visustruct":z6,"../../lessons/diagramme/en/l15-java-noten-loesung.visustruct":I6,"../../lessons/diagramme/en/l15-quadrat-haupt.visustruct":k6,"../../lessons/diagramme/en/l15-quadrat.visustruct":S6,"../../lessons/diagramme/en/l15-titel-loesung.visustruct":T6,"../../lessons/diagramme/en/l15-unterprogramm.visustruct":_6,"../../lessons/diagramme/en/l15-zeige-summe-haupt.visustruct":O6,"../../lessons/diagramme/en/l15-zeige-summe.visustruct":A6,"../../lessons/diagramme/en/l16-countdown-loesung.visustruct":C6,"../../lessons/diagramme/en/l16-countdown-start.visustruct":P6,"../../lessons/diagramme/en/l16-java-fehler-loesung.visustruct":j6,"../../lessons/diagramme/en/l16-java-fehler-start.visustruct":D6,"../../lessons/diagramme/en/l16-java-punkte-loesung.visustruct":B6,"../../lessons/diagramme/en/l16-schreibtisch.visustruct":Z6,"../../lessons/diagramme/en/l16-summe-loesung.visustruct":M6,"../../lessons/diagramme/en/l16-summe-start.visustruct":L6,"../../lessons/diagramme/en/l17-beispiel.visustruct":E6,"../../lessons/diagramme/en/l17-fakultaet-loesung.visustruct":W6,"../../lessons/diagramme/en/l17-java-brief-loesung.visustruct":N6,"../../lessons/diagramme/en/l17-java-brief-start.visustruct":F6,"../../lessons/diagramme/en/l17-java-fehler-loesung.visustruct":J6,"../../lessons/diagramme/en/l17-java-fehler-start.visustruct":R6,"../../lessons/diagramme/en/l17-java-passwort-loesung.visustruct":G6,"../../lessons/diagramme/en/l17-ticket-loesung.visustruct":H6,"../../lessons/diagramme/en/l18-beispiel.visustruct":V6,"../../lessons/diagramme/en/l18-java-fehler-loesung.visustruct":q6,"../../lessons/diagramme/en/l18-java-fehler-start.visustruct":Q6,"../../lessons/diagramme/en/l18-java-kasse-loesung.visustruct":U6,"../../lessons/diagramme/en/l18-js-loesung.visustruct":$6,"../../lessons/diagramme/en/l18-python-loesung.visustruct":Y6,"../../lessons/diagramme/en/l19-java-fehler-loesung.visustruct":X6,"../../lessons/diagramme/en/l19-java-fehler-start.visustruct":K6,"../../lessons/diagramme/en/l19-java-zaehlen-loesung.visustruct":e7,"../../lessons/diagramme/en/l2-ausgabe.visustruct":t7,"../../lessons/diagramme/en/l2-hallo-loesung.visustruct":n7,"../../lessons/diagramme/en/l2-zwei-zeilen-loesung.visustruct":i7,"../../lessons/diagramme/en/l23-java-ergaenzen-loesung.visustruct":a7,"../../lessons/diagramme/en/l23-java-ergaenzen-start.visustruct":s7,"../../lessons/diagramme/en/l23-java-nummern-loesung.visustruct":r7,"../../lessons/diagramme/en/l23-java-nummern-start.visustruct":o7,"../../lessons/diagramme/en/l24-java-fuchs-loesung.visustruct":l7,"../../lessons/diagramme/en/l24-java-fuchs-start.visustruct":u7,"../../lessons/diagramme/en/l24-java-laengster-loesung.visustruct":c7,"../../lessons/diagramme/en/l24-java-laengster-start.visustruct":m7,"../../lessons/diagramme/en/l25-java-beste-loesung.visustruct":d7,"../../lessons/diagramme/en/l25-java-beste-start.visustruct":h7,"../../lessons/diagramme/en/l25-java-schnitt-loesung.visustruct":g7,"../../lessons/diagramme/en/l25-java-schnitt-start.visustruct":p7,"../../lessons/diagramme/en/l26-java-namen-loesung.visustruct":f7,"../../lessons/diagramme/en/l26-java-namen-start.visustruct":b7,"../../lessons/diagramme/en/l26-java-schreiben-loesung.visustruct":x7,"../../lessons/diagramme/en/l26-java-schreiben-start.visustruct":v7,"../../lessons/diagramme/en/l27-java-json-loesung.visustruct":y7,"../../lessons/diagramme/en/l27-java-json-start.visustruct":w7,"../../lessons/diagramme/en/l27-java-saetze-loesung.visustruct":z7,"../../lessons/diagramme/en/l27-java-saetze-start.visustruct":I7,"../../lessons/diagramme/en/sim-kino-loesung.visustruct":k7,"../../lessons/diagramme/en/sim-kino-start.visustruct":S7,"../../lessons/diagramme/en/sim-tausch-loesung.visustruct":T7,"../../lessons/diagramme/en/sim-tausch-start.visustruct":_7,"../../lessons/diagramme/en/sim-tausch.visustruct":O7,"../../lessons/diagramme/en/ss-absteigend-loesung.visustruct":A7,"../../lessons/diagramme/en/ss-absteigend-start.visustruct":C7,"../../lessons/diagramme/en/ss-binaere-suche.visustruct":P7,"../../lessons/diagramme/en/ss-bubblesort.visustruct":j7,"../../lessons/diagramme/en/ss-karte-suchen-loesung.visustruct":D7,"../../lessons/diagramme/en/ss-lineare-suche.visustruct":B7,"../../lessons/diagramme/en/uebergabe-bonus-loesung.visustruct":Z7,"../../lessons/diagramme/en/uebergabe-bonus-start.visustruct":M7,"../../lessons/diagramme/en/uebergabe-bonus-unterprogramm-loesung.visustruct":L7,"../../lessons/diagramme/en/uebergabe-haupt.visustruct":E7,"../../lessons/diagramme/en/uebergabe-leeren.visustruct":W7,"../../lessons/diagramme/en/uebergabe-verdopple.visustruct":N7,"../../lessons/diagramme/en/vb-abstand-anzeigen-loesung.visustruct":F7,"../../lessons/diagramme/en/vb-abstand-halten-loesung.visustruct":J7,"../../lessons/diagramme/en/vb-alarmanlage-loesung.visustruct":R7,"../../lessons/diagramme/en/vb-ampel-loesung.visustruct":G7,"../../lessons/diagramme/en/vb-ausgang-loesung.visustruct":H7,"../../lessons/diagramme/en/vb-begruessung-loesung.visustruct":V7,"../../lessons/diagramme/en/vb-binaer-zaehlen-loesung.visustruct":q7,"../../lessons/diagramme/en/vb-bis-rot-loesung.visustruct":Q7,"../../lessons/diagramme/en/vb-bis-wand-loesung.visustruct":U7,"../../lessons/diagramme/en/vb-bis-ziel-loesung.visustruct":$7,"../../lessons/diagramme/en/vb-buchstaben-loesung.visustruct":Y7,"../../lessons/diagramme/en/vb-drei-lichter-loesung.visustruct":X7,"../../lessons/diagramme/en/vb-dreieck-loesung.visustruct":K7,"../../lessons/diagramme/en/vb-einparken-loesung.visustruct":eI,"../../lessons/diagramme/en/vb-farben-loesung.visustruct":tI,"../../lessons/diagramme/en/vb-farbweiche-loesung.visustruct":nI,"../../lessons/diagramme/en/vb-gas-bis-wand-loesung.visustruct":iI,"../../lessons/diagramme/en/vb-gerade-loesung.visustruct":aI,"../../lessons/diagramme/en/vb-hindernis-loesung.visustruct":sI,"../../lessons/diagramme/en/vb-java-akku-loesung.visustruct":rI,"../../lessons/diagramme/en/vb-java-blau-gruen-loesung.visustruct":oI,"../../lessons/diagramme/en/vb-java-blinken-loesung.visustruct":lI,"../../lessons/diagramme/en/vb-java-countdown-loesung.visustruct":uI,"../../lessons/diagramme/en/vb-java-hoeher-loesung.visustruct":cI,"../../lessons/diagramme/en/vb-java-joystick-loesung.visustruct":mI,"../../lessons/diagramme/en/vb-java-laermampel-loesung.visustruct":dI,"../../lessons/diagramme/en/vb-java-lauflicht-loesung.visustruct":hI,"../../lessons/diagramme/en/vb-java-linienfolger-loesung.visustruct":gI,"../../lessons/diagramme/en/vb-java-nachtlicht-ton-loesung.visustruct":pI,"../../lessons/diagramme/en/vb-java-rand-loesung.visustruct":fI,"../../lessons/diagramme/en/vb-java-rechteck-loesung.visustruct":bI,"../../lessons/diagramme/en/vb-java-textlaenge-loesung.visustruct":xI,"../../lessons/diagramme/en/vb-java-wand-piep-loesung.visustruct":vI,"../../lessons/diagramme/en/vb-java-wasserwaage-loesung.visustruct":yI,"../../lessons/diagramme/en/vb-klatschen-loesung.visustruct":wI,"../../lessons/diagramme/en/vb-knight-rider-loesung.visustruct":zI,"../../lessons/diagramme/en/vb-labyrinth-loesung.visustruct":II,"../../lessons/diagramme/en/vb-linienfolger-stopp-loesung.visustruct":kI,"../../lessons/diagramme/en/vb-linienmuster-loesung.visustruct":SI,"../../lessons/diagramme/en/vb-melodie-loesung.visustruct":TI,"../../lessons/diagramme/en/vb-morsen-loesung.visustruct":_I,"../../lessons/diagramme/en/vb-nachtlicht-loesung.visustruct":OI,"../../lessons/diagramme/en/vb-nachtwaechter-loesung.visustruct":AI,"../../lessons/diagramme/en/vb-ohne-noten-loesung.visustruct":CI,"../../lessons/diagramme/en/vb-ohne-quadratzahl-loesung.visustruct":PI,"../../lessons/diagramme/en/vb-ohne-quadratzahl-unterprogramm-loesung.visustruct":jI,"../../lessons/diagramme/en/vb-ohne-rueckwaerts-loesung.visustruct":DI,"../../lessons/diagramme/en/vb-ohne-strecke-loesung.visustruct":BI,"../../lessons/diagramme/en/vb-ohne-summe-loesung.visustruct":ZI,"../../lessons/diagramme/en/vb-quadrat-loesung.visustruct":MI,"../../lessons/diagramme/en/vb-quadrat-methode-loesung.visustruct":LI,"../../lessons/diagramme/en/vb-quadrat-schleife-loesung.visustruct":EI,"../../lessons/diagramme/en/vb-quadrat-unterprogramm-loesung.visustruct":WI,"../../lessons/diagramme/en/vb-quadrat-verschachtelt-loesung.visustruct":NI,"../../lessons/diagramme/en/vb-rand-loesung.visustruct":FI,"../../lessons/diagramme/en/vb-schraeglage-loesung.visustruct":JI,"../../lessons/diagramme/en/vb-slalom-loesung.visustruct":RI,"../../lessons/diagramme/en/vb-spirale-loesung.visustruct":GI,"../../lessons/diagramme/en/vb-start-a-loesung.visustruct":HI,"../../lessons/diagramme/en/vb-tonleiter-loesung.visustruct":VI,"../../lessons/diagramme/en/vb-treppe-loesung.visustruct":qI,"../../lessons/diagramme/en/vb-tunnel-loesung.visustruct":QI,"../../lessons/diagramme/en/vb-variable-seite-loesung.visustruct":UI,"../../lessons/diagramme/en/vb-vier-quadrate-loesung.visustruct":$I,"../../lessons/diagramme/en/vb-wald-loesung.visustruct":YI,"../../lessons/diagramme/en/vb-wand-vorn-loesung.visustruct":XI,"../../lessons/diagramme/en/vb-zwei-sekunden-loesung.visustruct":KI,"../../lessons/diagramme/en/zk-initialen-loesung.visustruct":ek,"../../lessons/diagramme/en/zk-mehr.visustruct":tk,"../../lessons/diagramme/en/zk-rueckwaerts-loesung.visustruct":nk,"../../lessons/diagramme/en/zk-split.visustruct":ik,"../../lessons/diagramme/en/zk-woerter-loesung.visustruct":ak,"../../lessons/diagramme/en/zk-zaehlen.visustruct":sk,"../../lessons/diagramme/en/zk-zeichen.visustruct":rk,"../../lessons/diagramme/kino-einmaleins-loesung.visustruct":ok,"../../lessons/diagramme/kino-frei-loesung.visustruct":lk,"../../lessons/diagramme/kino-frei-start.visustruct":uk,"../../lessons/diagramme/kino-karte-loesung.visustruct":ck,"../../lessons/diagramme/kino-karte-start.visustruct":mk,"../../lessons/diagramme/kino-saalplan.visustruct":dk,"../../lessons/diagramme/kino-verkaufen.visustruct":hk,"../../lessons/diagramme/l04-java-fehler-loesung.visustruct":gk,"../../lessons/diagramme/l04-java-fehler-start.visustruct":pk,"../../lessons/diagramme/l04-java-steckbrief-loesung.visustruct":fk,"../../lessons/diagramme/l04-rechnen.visustruct":bk,"../../lessons/diagramme/l04-reihenfolge-loesung.visustruct":xk,"../../lessons/diagramme/l04-reihenfolge-start.visustruct":vk,"../../lessons/diagramme/l04-tauschen-loesung.visustruct":yk,"../../lessons/diagramme/l04-tauschen-start.visustruct":wk,"../../lessons/diagramme/l04-tauschen.visustruct":zk,"../../lessons/diagramme/l05-datentypen.visustruct":Ik,"../../lessons/diagramme/l05-division.visustruct":kk,"../../lessons/diagramme/l05-einkauf-loesung.visustruct":Sk,"../../lessons/diagramme/l05-java-fehler-loesung.visustruct":Tk,"../../lessons/diagramme/l05-java-fehler-start.visustruct":_k,"../../lessons/diagramme/l05-java-kino-loesung.visustruct":Ok,"../../lessons/diagramme/l05-rechteck-loesung.visustruct":Ak,"../../lessons/diagramme/l05-sekunden-loesung.visustruct":Ck,"../../lessons/diagramme/l05-sekunden-start.visustruct":Pk,"../../lessons/diagramme/l05-sequenz.visustruct":jk,"../../lessons/diagramme/l06-begruessung-loesung.visustruct":Dk,"../../lessons/diagramme/l06-eva.visustruct":Bk,"../../lessons/diagramme/l06-java-fehler-loesung.visustruct":Zk,"../../lessons/diagramme/l06-java-fehler-start.visustruct":Mk,"../../lessons/diagramme/l06-java-tage-loesung.visustruct":Lk,"../../lessons/diagramme/l06-mittelwert-loesung.visustruct":Ek,"../../lessons/diagramme/l06-rechner-loesung.visustruct":Wk,"../../lessons/diagramme/l07-alter-pruefen.visustruct":Nk,"../../lessons/diagramme/l07-betrag-loesung.visustruct":Fk,"../../lessons/diagramme/l07-gerade-loesung.visustruct":Jk,"../../lessons/diagramme/l07-java-fehler-loesung.visustruct":Rk,"../../lessons/diagramme/l07-java-fehler-start.visustruct":Gk,"../../lessons/diagramme/l07-java-pizza-loesung.visustruct":Hk,"../../lessons/diagramme/l07-java-pizza-start.visustruct":Vk,"../../lessons/diagramme/l07-maximum-loesung.visustruct":qk,"../../lessons/diagramme/l07-rabatt.visustruct":Qk,"../../lessons/diagramme/l08-gueltig-loesung.visustruct":Uk,"../../lessons/diagramme/l08-java-bestanden-loesung.visustruct":$k,"../../lessons/diagramme/l08-java-fehler-loesung.visustruct":Yk,"../../lessons/diagramme/l08-java-fehler-start.visustruct":Xk,"../../lessons/diagramme/l08-jugendticket.visustruct":Kk,"../../lessons/diagramme/l08-note.visustruct":e8,"../../lessons/diagramme/l08-schaltjahr-loesung.visustruct":t8,"../../lessons/diagramme/l08-wochenende-loesung.visustruct":n8,"../../lessons/diagramme/l09-ampel.visustruct":i8,"../../lessons/diagramme/l09-automat.visustruct":a8,"../../lessons/diagramme/l09-java-fehler-loesung.visustruct":s8,"../../lessons/diagramme/l09-java-fehler-start.visustruct":r8,"../../lessons/diagramme/l09-java-schule-loesung.visustruct":o8,"../../lessons/diagramme/l09-note-loesung.visustruct":l8,"../../lessons/diagramme/l09-rechner-loesung.visustruct":u8,"../../lessons/diagramme/l09-verschachtelt.visustruct":c8,"../../lessons/diagramme/l1-grundbausteine.visustruct":m8,"../../lessons/diagramme/l1-sequenz.visustruct":d8,"../../lessons/diagramme/l1-tee.visustruct":h8,"../../lessons/diagramme/l1-verzweigung.visustruct":g8,"../../lessons/diagramme/l1-wiederholung.visustruct":p8,"../../lessons/diagramme/l10-bis-n-loesung.visustruct":f8,"../../lessons/diagramme/l10-countdown.visustruct":b8,"../../lessons/diagramme/l10-endlos.visustruct":x8,"../../lessons/diagramme/l10-fakultaet.visustruct":v8,"../../lessons/diagramme/l10-java-fehler-loesung.visustruct":y8,"../../lessons/diagramme/l10-java-fehler-start.visustruct":w8,"../../lessons/diagramme/l10-java-wuerfel-loesung.visustruct":z8,"../../lessons/diagramme/l10-verdoppeln-loesung.visustruct":I8,"../../lessons/diagramme/l11-eingabe-pruefen.visustruct":k8,"../../lessons/diagramme/l11-einmal.visustruct":S8,"../../lessons/diagramme/l11-java-fehler-loesung.visustruct":T8,"../../lessons/diagramme/l11-java-fehler-start.visustruct":_8,"../../lessons/diagramme/l11-java-gerade-loesung.visustruct":O8,"../../lessons/diagramme/l11-note-loesung.visustruct":A8,"../../lessons/diagramme/l11-summe-loesung.visustruct":C8,"../../lessons/diagramme/l12-countdown-loesung.visustruct":P8,"../../lessons/diagramme/l12-einmaleins-loesung.visustruct":j8,"../../lessons/diagramme/l12-eins-bis-fuenf.visustruct":D8,"../../lessons/diagramme/l12-java-fehler-loesung.visustruct":B8,"../../lessons/diagramme/l12-java-fehler-start.visustruct":Z8,"../../lessons/diagramme/l12-java-verdoppeln-loesung.visustruct":M8,"../../lessons/diagramme/l12-summe.visustruct":L8,"../../lessons/diagramme/l13-dreieck.visustruct":E8,"../../lessons/diagramme/l13-gerade-eingaben-loesung.visustruct":W8,"../../lessons/diagramme/l13-gerade-zaehlen.visustruct":N8,"../../lessons/diagramme/l13-java-fehler-loesung.visustruct":F8,"../../lessons/diagramme/l13-java-fehler-start.visustruct":J8,"../../lessons/diagramme/l13-java-quadrate-loesung.visustruct":R8,"../../lessons/diagramme/l13-rechteck-loesung.visustruct":G8,"../../lessons/diagramme/l14-array-durchlaufen.visustruct":H8,"../../lessons/diagramme/l14-erster-letzter-loesung.visustruct":V8,"../../lessons/diagramme/l14-java-fehler-loesung.visustruct":q8,"../../lessons/diagramme/l14-java-fehler-start.visustruct":Q8,"../../lessons/diagramme/l14-java-treppe-loesung.visustruct":U8,"../../lessons/diagramme/l14-namen-eingeben.visustruct":$8,"../../lessons/diagramme/l14-rueckwaerts-loesung.visustruct":Y8,"../../lessons/diagramme/l14-summe-max-loesung.visustruct":X8,"../../lessons/diagramme/l14-summe-maximum.visustruct":K8,"../../lessons/diagramme/l15-bis-null-loesung.visustruct":eS,"../../lessons/diagramme/l15-endlos-aussprung.visustruct":tS,"../../lessons/diagramme/l15-flaeche-loesung.visustruct":nS,"../../lessons/diagramme/l15-flaeche-unterprogramm-loesung.visustruct":iS,"../../lessons/diagramme/l15-hauptprogramm.visustruct":aS,"../../lessons/diagramme/l15-java-fehler-loesung.visustruct":sS,"../../lessons/diagramme/l15-java-fehler-start.visustruct":rS,"../../lessons/diagramme/l15-java-noten-loesung.visustruct":oS,"../../lessons/diagramme/l15-quadrat-haupt.visustruct":lS,"../../lessons/diagramme/l15-quadrat.visustruct":uS,"../../lessons/diagramme/l15-titel-loesung.visustruct":cS,"../../lessons/diagramme/l15-unterprogramm.visustruct":mS,"../../lessons/diagramme/l15-zeige-summe-haupt.visustruct":dS,"../../lessons/diagramme/l15-zeige-summe.visustruct":hS,"../../lessons/diagramme/l16-countdown-loesung.visustruct":gS,"../../lessons/diagramme/l16-countdown-start.visustruct":pS,"../../lessons/diagramme/l16-java-fehler-loesung.visustruct":fS,"../../lessons/diagramme/l16-java-fehler-start.visustruct":bS,"../../lessons/diagramme/l16-java-punkte-loesung.visustruct":xS,"../../lessons/diagramme/l16-schreibtisch.visustruct":vS,"../../lessons/diagramme/l16-summe-loesung.visustruct":yS,"../../lessons/diagramme/l16-summe-start.visustruct":wS,"../../lessons/diagramme/l17-beispiel.visustruct":zS,"../../lessons/diagramme/l17-fakultaet-loesung.visustruct":IS,"../../lessons/diagramme/l17-java-brief-loesung.visustruct":kS,"../../lessons/diagramme/l17-java-brief-start.visustruct":SS,"../../lessons/diagramme/l17-java-fehler-loesung.visustruct":TS,"../../lessons/diagramme/l17-java-fehler-start.visustruct":_S,"../../lessons/diagramme/l17-java-passwort-loesung.visustruct":OS,"../../lessons/diagramme/l17-ticket-loesung.visustruct":AS,"../../lessons/diagramme/l18-beispiel.visustruct":CS,"../../lessons/diagramme/l18-java-fehler-loesung.visustruct":PS,"../../lessons/diagramme/l18-java-fehler-start.visustruct":jS,"../../lessons/diagramme/l18-java-kasse-loesung.visustruct":DS,"../../lessons/diagramme/l18-js-loesung.visustruct":BS,"../../lessons/diagramme/l18-python-loesung.visustruct":ZS,"../../lessons/diagramme/l19-java-fehler-loesung.visustruct":MS,"../../lessons/diagramme/l19-java-fehler-start.visustruct":LS,"../../lessons/diagramme/l19-java-zaehlen-loesung.visustruct":ES,"../../lessons/diagramme/l2-ausgabe.visustruct":WS,"../../lessons/diagramme/l2-hallo-loesung.visustruct":NS,"../../lessons/diagramme/l2-zwei-zeilen-loesung.visustruct":FS,"../../lessons/diagramme/l20-countdown-loesung.visustruct":JS,"../../lessons/diagramme/l23-java-ergaenzen-loesung.visustruct":RS,"../../lessons/diagramme/l23-java-ergaenzen-start.visustruct":GS,"../../lessons/diagramme/l23-java-nummern-loesung.visustruct":HS,"../../lessons/diagramme/l23-java-nummern-start.visustruct":VS,"../../lessons/diagramme/l24-java-fuchs-loesung.visustruct":qS,"../../lessons/diagramme/l24-java-fuchs-start.visustruct":QS,"../../lessons/diagramme/l24-java-laengster-loesung.visustruct":US,"../../lessons/diagramme/l24-java-laengster-start.visustruct":$S,"../../lessons/diagramme/l25-java-beste-loesung.visustruct":YS,"../../lessons/diagramme/l25-java-beste-start.visustruct":XS,"../../lessons/diagramme/l25-java-schnitt-loesung.visustruct":KS,"../../lessons/diagramme/l25-java-schnitt-start.visustruct":eT,"../../lessons/diagramme/l26-java-namen-loesung.visustruct":tT,"../../lessons/diagramme/l26-java-namen-start.visustruct":nT,"../../lessons/diagramme/l26-java-schreiben-loesung.visustruct":iT,"../../lessons/diagramme/l26-java-schreiben-start.visustruct":aT,"../../lessons/diagramme/l27-java-json-loesung.visustruct":sT,"../../lessons/diagramme/l27-java-json-start.visustruct":rT,"../../lessons/diagramme/l27-java-saetze-loesung.visustruct":oT,"../../lessons/diagramme/l27-java-saetze-start.visustruct":lT,"../../lessons/diagramme/pt/aufgabe-alter-haupt-loesung.visustruct":uT,"../../lessons/diagramme/pt/aufgabe-alter-unterprogramm-loesung.visustruct":cT,"../../lessons/diagramme/pt/aufgabe-ballwurf-loesung.visustruct":mT,"../../lessons/diagramme/pt/aufgabe-ballwurf-start.visustruct":dT,"../../lessons/diagramme/pt/aufgabe-bestenliste-loesung.visustruct":hT,"../../lessons/diagramme/pt/aufgabe-binaer-loesung.visustruct":gT,"../../lessons/diagramme/pt/aufgabe-caesar-array-loesung.visustruct":pT,"../../lessons/diagramme/pt/aufgabe-caesar-array-start.visustruct":fT,"../../lessons/diagramme/pt/aufgabe-caesar-ascii-loesung.visustruct":bT,"../../lessons/diagramme/pt/aufgabe-caesar-entschluesseln-loesung.visustruct":xT,"../../lessons/diagramme/pt/aufgabe-collatz-loesung.visustruct":vT,"../../lessons/diagramme/pt/aufgabe-durchschnitt-loesung.visustruct":yT,"../../lessons/diagramme/pt/aufgabe-fibonacci-loesung.visustruct":wT,"../../lessons/diagramme/pt/aufgabe-gerade-loesung.visustruct":zT,"../../lessons/diagramme/pt/aufgabe-mehrwertsteuer-loesung.visustruct":IT,"../../lessons/diagramme/pt/aufgabe-pin-java-loesung.visustruct":kT,"../../lessons/diagramme/pt/aufgabe-pin-loesung.visustruct":ST,"../../lessons/diagramme/pt/aufgabe-rechner-loesung.visustruct":TT,"../../lessons/diagramme/pt/aufgabe-schiffe-loesung.visustruct":_T,"../../lessons/diagramme/pt/aufgabe-schiffe-start.visustruct":OT,"../../lessons/diagramme/pt/aufgabe-speisekarte-loesung.visustruct":AT,"../../lessons/diagramme/pt/aufgabe-summe-loesung.visustruct":CT,"../../lessons/diagramme/pt/aufgabe-tafeldienst-loesung.visustruct":PT,"../../lessons/diagramme/pt/aufgabe-verdoppeln-loesung.visustruct":jT,"../../lessons/diagramme/pt/aufgabe-verleih-java-loesung.visustruct":DT,"../../lessons/diagramme/pt/aufgabe-verleih-loesung.visustruct":BT,"../../lessons/diagramme/pt/aufgabe-vokabeln-loesung.visustruct":ZT,"../../lessons/diagramme/pt/aufgabe-vokabeln-start.visustruct":MT,"../../lessons/diagramme/pt/aufgabe-volljaehrig-loesung.visustruct":LT,"../../lessons/diagramme/pt/dt-buffered.visustruct":ET,"../../lessons/diagramme/pt/dt-csv.visustruct":WT,"../../lessons/diagramme/pt/dt-json.visustruct":NT,"../../lessons/diagramme/pt/dt-lesen.visustruct":FT,"../../lessons/diagramme/pt/kino-einmaleins-loesung.visustruct":JT,"../../lessons/diagramme/pt/kino-frei-loesung.visustruct":RT,"../../lessons/diagramme/pt/kino-frei-start.visustruct":GT,"../../lessons/diagramme/pt/kino-karte-loesung.visustruct":HT,"../../lessons/diagramme/pt/kino-karte-start.visustruct":VT,"../../lessons/diagramme/pt/kino-saalplan.visustruct":qT,"../../lessons/diagramme/pt/kino-verkaufen.visustruct":QT,"../../lessons/diagramme/pt/l04-java-fehler-loesung.visustruct":UT,"../../lessons/diagramme/pt/l04-java-fehler-start.visustruct":$T,"../../lessons/diagramme/pt/l04-java-steckbrief-loesung.visustruct":YT,"../../lessons/diagramme/pt/l04-rechnen.visustruct":XT,"../../lessons/diagramme/pt/l04-reihenfolge-loesung.visustruct":KT,"../../lessons/diagramme/pt/l04-reihenfolge-start.visustruct":e_,"../../lessons/diagramme/pt/l04-tauschen-loesung.visustruct":t_,"../../lessons/diagramme/pt/l04-tauschen-start.visustruct":n_,"../../lessons/diagramme/pt/l04-tauschen.visustruct":i_,"../../lessons/diagramme/pt/l05-datentypen.visustruct":a_,"../../lessons/diagramme/pt/l05-division.visustruct":s_,"../../lessons/diagramme/pt/l05-einkauf-loesung.visustruct":r_,"../../lessons/diagramme/pt/l05-java-fehler-loesung.visustruct":o_,"../../lessons/diagramme/pt/l05-java-fehler-start.visustruct":l_,"../../lessons/diagramme/pt/l05-java-kino-loesung.visustruct":u_,"../../lessons/diagramme/pt/l05-rechteck-loesung.visustruct":c_,"../../lessons/diagramme/pt/l05-sekunden-loesung.visustruct":m_,"../../lessons/diagramme/pt/l05-sekunden-start.visustruct":d_,"../../lessons/diagramme/pt/l05-sequenz.visustruct":h_,"../../lessons/diagramme/pt/l06-begruessung-loesung.visustruct":g_,"../../lessons/diagramme/pt/l06-eva.visustruct":p_,"../../lessons/diagramme/pt/l06-java-fehler-loesung.visustruct":f_,"../../lessons/diagramme/pt/l06-java-fehler-start.visustruct":b_,"../../lessons/diagramme/pt/l06-java-tage-loesung.visustruct":x_,"../../lessons/diagramme/pt/l06-mittelwert-loesung.visustruct":v_,"../../lessons/diagramme/pt/l06-rechner-loesung.visustruct":y_,"../../lessons/diagramme/pt/l07-alter-pruefen.visustruct":w_,"../../lessons/diagramme/pt/l07-betrag-loesung.visustruct":z_,"../../lessons/diagramme/pt/l07-gerade-loesung.visustruct":I_,"../../lessons/diagramme/pt/l07-java-fehler-loesung.visustruct":k_,"../../lessons/diagramme/pt/l07-java-fehler-start.visustruct":S_,"../../lessons/diagramme/pt/l07-java-pizza-loesung.visustruct":T_,"../../lessons/diagramme/pt/l07-java-pizza-start.visustruct":__,"../../lessons/diagramme/pt/l07-maximum-loesung.visustruct":O_,"../../lessons/diagramme/pt/l07-rabatt.visustruct":A_,"../../lessons/diagramme/pt/l08-gueltig-loesung.visustruct":C_,"../../lessons/diagramme/pt/l08-java-bestanden-loesung.visustruct":P_,"../../lessons/diagramme/pt/l08-java-fehler-loesung.visustruct":j_,"../../lessons/diagramme/pt/l08-java-fehler-start.visustruct":D_,"../../lessons/diagramme/pt/l08-jugendticket.visustruct":B_,"../../lessons/diagramme/pt/l08-note.visustruct":Z_,"../../lessons/diagramme/pt/l08-schaltjahr-loesung.visustruct":M_,"../../lessons/diagramme/pt/l08-wochenende-loesung.visustruct":L_,"../../lessons/diagramme/pt/l09-ampel.visustruct":E_,"../../lessons/diagramme/pt/l09-automat.visustruct":W_,"../../lessons/diagramme/pt/l09-java-fehler-loesung.visustruct":N_,"../../lessons/diagramme/pt/l09-java-fehler-start.visustruct":F_,"../../lessons/diagramme/pt/l09-java-schule-loesung.visustruct":J_,"../../lessons/diagramme/pt/l09-note-loesung.visustruct":R_,"../../lessons/diagramme/pt/l09-rechner-loesung.visustruct":G_,"../../lessons/diagramme/pt/l09-verschachtelt.visustruct":H_,"../../lessons/diagramme/pt/l1-grundbausteine.visustruct":V_,"../../lessons/diagramme/pt/l1-sequenz.visustruct":q_,"../../lessons/diagramme/pt/l1-tee.visustruct":Q_,"../../lessons/diagramme/pt/l1-verzweigung.visustruct":U_,"../../lessons/diagramme/pt/l1-wiederholung.visustruct":$_,"../../lessons/diagramme/pt/l10-bis-n-loesung.visustruct":Y_,"../../lessons/diagramme/pt/l10-countdown.visustruct":X_,"../../lessons/diagramme/pt/l10-endlos.visustruct":K_,"../../lessons/diagramme/pt/l10-fakultaet.visustruct":eO,"../../lessons/diagramme/pt/l10-java-fehler-loesung.visustruct":tO,"../../lessons/diagramme/pt/l10-java-fehler-start.visustruct":nO,"../../lessons/diagramme/pt/l10-java-wuerfel-loesung.visustruct":iO,"../../lessons/diagramme/pt/l10-verdoppeln-loesung.visustruct":aO,"../../lessons/diagramme/pt/l11-eingabe-pruefen.visustruct":sO,"../../lessons/diagramme/pt/l11-einmal.visustruct":rO,"../../lessons/diagramme/pt/l11-java-fehler-loesung.visustruct":oO,"../../lessons/diagramme/pt/l11-java-fehler-start.visustruct":lO,"../../lessons/diagramme/pt/l11-java-gerade-loesung.visustruct":uO,"../../lessons/diagramme/pt/l11-note-loesung.visustruct":cO,"../../lessons/diagramme/pt/l11-summe-loesung.visustruct":mO,"../../lessons/diagramme/pt/l12-countdown-loesung.visustruct":dO,"../../lessons/diagramme/pt/l12-einmaleins-loesung.visustruct":hO,"../../lessons/diagramme/pt/l12-eins-bis-fuenf.visustruct":gO,"../../lessons/diagramme/pt/l12-java-fehler-loesung.visustruct":pO,"../../lessons/diagramme/pt/l12-java-fehler-start.visustruct":fO,"../../lessons/diagramme/pt/l12-java-verdoppeln-loesung.visustruct":bO,"../../lessons/diagramme/pt/l12-summe.visustruct":xO,"../../lessons/diagramme/pt/l13-dreieck.visustruct":vO,"../../lessons/diagramme/pt/l13-gerade-eingaben-loesung.visustruct":yO,"../../lessons/diagramme/pt/l13-gerade-zaehlen.visustruct":wO,"../../lessons/diagramme/pt/l13-java-fehler-loesung.visustruct":zO,"../../lessons/diagramme/pt/l13-java-fehler-start.visustruct":IO,"../../lessons/diagramme/pt/l13-java-quadrate-loesung.visustruct":kO,"../../lessons/diagramme/pt/l13-rechteck-loesung.visustruct":SO,"../../lessons/diagramme/pt/l14-array-durchlaufen.visustruct":TO,"../../lessons/diagramme/pt/l14-erster-letzter-loesung.visustruct":_O,"../../lessons/diagramme/pt/l14-java-fehler-loesung.visustruct":OO,"../../lessons/diagramme/pt/l14-java-fehler-start.visustruct":AO,"../../lessons/diagramme/pt/l14-java-treppe-loesung.visustruct":CO,"../../lessons/diagramme/pt/l14-namen-eingeben.visustruct":PO,"../../lessons/diagramme/pt/l14-rueckwaerts-loesung.visustruct":jO,"../../lessons/diagramme/pt/l14-summe-max-loesung.visustruct":DO,"../../lessons/diagramme/pt/l14-summe-maximum.visustruct":BO,"../../lessons/diagramme/pt/l15-bis-null-loesung.visustruct":ZO,"../../lessons/diagramme/pt/l15-endlos-aussprung.visustruct":MO,"../../lessons/diagramme/pt/l15-flaeche-loesung.visustruct":LO,"../../lessons/diagramme/pt/l15-hauptprogramm.visustruct":EO,"../../lessons/diagramme/pt/l15-java-fehler-loesung.visustruct":WO,"../../lessons/diagramme/pt/l15-java-fehler-start.visustruct":NO,"../../lessons/diagramme/pt/l15-java-noten-loesung.visustruct":FO,"../../lessons/diagramme/pt/l15-quadrat-haupt.visustruct":JO,"../../lessons/diagramme/pt/l15-quadrat.visustruct":RO,"../../lessons/diagramme/pt/l15-titel-loesung.visustruct":GO,"../../lessons/diagramme/pt/l15-unterprogramm.visustruct":HO,"../../lessons/diagramme/pt/l15-zeige-summe-haupt.visustruct":VO,"../../lessons/diagramme/pt/l15-zeige-summe.visustruct":qO,"../../lessons/diagramme/pt/l16-countdown-loesung.visustruct":QO,"../../lessons/diagramme/pt/l16-countdown-start.visustruct":UO,"../../lessons/diagramme/pt/l16-java-fehler-loesung.visustruct":$O,"../../lessons/diagramme/pt/l16-java-fehler-start.visustruct":YO,"../../lessons/diagramme/pt/l16-java-punkte-loesung.visustruct":XO,"../../lessons/diagramme/pt/l16-schreibtisch.visustruct":KO,"../../lessons/diagramme/pt/l16-summe-loesung.visustruct":eA,"../../lessons/diagramme/pt/l16-summe-start.visustruct":tA,"../../lessons/diagramme/pt/l17-beispiel.visustruct":nA,"../../lessons/diagramme/pt/l17-fakultaet-loesung.visustruct":iA,"../../lessons/diagramme/pt/l17-java-brief-loesung.visustruct":aA,"../../lessons/diagramme/pt/l17-java-brief-start.visustruct":sA,"../../lessons/diagramme/pt/l17-java-fehler-loesung.visustruct":rA,"../../lessons/diagramme/pt/l17-java-fehler-start.visustruct":oA,"../../lessons/diagramme/pt/l17-java-passwort-loesung.visustruct":lA,"../../lessons/diagramme/pt/l17-ticket-loesung.visustruct":uA,"../../lessons/diagramme/pt/l18-beispiel.visustruct":cA,"../../lessons/diagramme/pt/l18-java-fehler-loesung.visustruct":mA,"../../lessons/diagramme/pt/l18-java-fehler-start.visustruct":dA,"../../lessons/diagramme/pt/l18-java-kasse-loesung.visustruct":hA,"../../lessons/diagramme/pt/l18-js-loesung.visustruct":gA,"../../lessons/diagramme/pt/l18-python-loesung.visustruct":pA,"../../lessons/diagramme/pt/l19-java-fehler-loesung.visustruct":fA,"../../lessons/diagramme/pt/l19-java-fehler-start.visustruct":bA,"../../lessons/diagramme/pt/l19-java-zaehlen-loesung.visustruct":xA,"../../lessons/diagramme/pt/l2-ausgabe.visustruct":vA,"../../lessons/diagramme/pt/l2-hallo-loesung.visustruct":yA,"../../lessons/diagramme/pt/l2-zwei-zeilen-loesung.visustruct":wA,"../../lessons/diagramme/pt/l23-java-ergaenzen-loesung.visustruct":zA,"../../lessons/diagramme/pt/l23-java-ergaenzen-start.visustruct":IA,"../../lessons/diagramme/pt/l23-java-nummern-loesung.visustruct":kA,"../../lessons/diagramme/pt/l23-java-nummern-start.visustruct":SA,"../../lessons/diagramme/pt/l24-java-fuchs-loesung.visustruct":TA,"../../lessons/diagramme/pt/l24-java-fuchs-start.visustruct":_A,"../../lessons/diagramme/pt/l24-java-laengster-loesung.visustruct":OA,"../../lessons/diagramme/pt/l24-java-laengster-start.visustruct":AA,"../../lessons/diagramme/pt/l25-java-beste-loesung.visustruct":CA,"../../lessons/diagramme/pt/l25-java-beste-start.visustruct":PA,"../../lessons/diagramme/pt/l25-java-schnitt-loesung.visustruct":jA,"../../lessons/diagramme/pt/l25-java-schnitt-start.visustruct":DA,"../../lessons/diagramme/pt/l26-java-namen-loesung.visustruct":BA,"../../lessons/diagramme/pt/l26-java-namen-start.visustruct":ZA,"../../lessons/diagramme/pt/l26-java-schreiben-loesung.visustruct":MA,"../../lessons/diagramme/pt/l26-java-schreiben-start.visustruct":LA,"../../lessons/diagramme/pt/l27-java-json-loesung.visustruct":EA,"../../lessons/diagramme/pt/l27-java-json-start.visustruct":WA,"../../lessons/diagramme/pt/l27-java-saetze-loesung.visustruct":NA,"../../lessons/diagramme/pt/l27-java-saetze-start.visustruct":FA,"../../lessons/diagramme/pt/sim-kino-loesung.visustruct":JA,"../../lessons/diagramme/pt/sim-kino-start.visustruct":RA,"../../lessons/diagramme/pt/sim-tausch-loesung.visustruct":GA,"../../lessons/diagramme/pt/sim-tausch-start.visustruct":HA,"../../lessons/diagramme/pt/sim-tausch.visustruct":VA,"../../lessons/diagramme/pt/ss-absteigend-loesung.visustruct":qA,"../../lessons/diagramme/pt/ss-absteigend-start.visustruct":QA,"../../lessons/diagramme/pt/ss-binaere-suche.visustruct":UA,"../../lessons/diagramme/pt/ss-bubblesort.visustruct":$A,"../../lessons/diagramme/pt/ss-karte-suchen-loesung.visustruct":YA,"../../lessons/diagramme/pt/ss-lineare-suche.visustruct":XA,"../../lessons/diagramme/pt/uebergabe-bonus-loesung.visustruct":KA,"../../lessons/diagramme/pt/uebergabe-bonus-start.visustruct":eC,"../../lessons/diagramme/pt/uebergabe-bonus-unterprogramm-loesung.visustruct":tC,"../../lessons/diagramme/pt/uebergabe-haupt.visustruct":nC,"../../lessons/diagramme/pt/uebergabe-leeren.visustruct":iC,"../../lessons/diagramme/pt/uebergabe-verdopple.visustruct":aC,"../../lessons/diagramme/pt/zk-initialen-loesung.visustruct":sC,"../../lessons/diagramme/pt/zk-mehr.visustruct":rC,"../../lessons/diagramme/pt/zk-rueckwaerts-loesung.visustruct":oC,"../../lessons/diagramme/pt/zk-split.visustruct":lC,"../../lessons/diagramme/pt/zk-woerter-loesung.visustruct":uC,"../../lessons/diagramme/pt/zk-zaehlen.visustruct":cC,"../../lessons/diagramme/pt/zk-zeichen.visustruct":mC,"../../lessons/diagramme/sim-kino-loesung.visustruct":dC,"../../lessons/diagramme/sim-kino-start.visustruct":hC,"../../lessons/diagramme/sim-tausch-loesung.visustruct":gC,"../../lessons/diagramme/sim-tausch-start.visustruct":pC,"../../lessons/diagramme/sim-tausch.visustruct":fC,"../../lessons/diagramme/ss-absteigend-loesung.visustruct":bC,"../../lessons/diagramme/ss-absteigend-start.visustruct":xC,"../../lessons/diagramme/ss-binaere-suche.visustruct":vC,"../../lessons/diagramme/ss-bubblesort.visustruct":yC,"../../lessons/diagramme/ss-karte-suchen-loesung.visustruct":wC,"../../lessons/diagramme/ss-lineare-suche.visustruct":zC,"../../lessons/diagramme/uebergabe-bonus-loesung.visustruct":IC,"../../lessons/diagramme/uebergabe-bonus-start.visustruct":kC,"../../lessons/diagramme/uebergabe-bonus-unterprogramm-loesung.visustruct":SC,"../../lessons/diagramme/uebergabe-haupt.visustruct":TC,"../../lessons/diagramme/uebergabe-leeren.visustruct":_C,"../../lessons/diagramme/uebergabe-verdopple.visustruct":OC,"../../lessons/diagramme/vb-abstand-anzeigen-loesung.visustruct":AC,"../../lessons/diagramme/vb-abstand-halten-loesung.visustruct":CC,"../../lessons/diagramme/vb-alarmanlage-loesung.visustruct":PC,"../../lessons/diagramme/vb-ampel-loesung.visustruct":jC,"../../lessons/diagramme/vb-ausgang-loesung.visustruct":DC,"../../lessons/diagramme/vb-begruessung-loesung.visustruct":BC,"../../lessons/diagramme/vb-binaer-zaehlen-loesung.visustruct":ZC,"../../lessons/diagramme/vb-bis-rot-loesung.visustruct":MC,"../../lessons/diagramme/vb-bis-wand-loesung.visustruct":LC,"../../lessons/diagramme/vb-bis-ziel-loesung.visustruct":EC,"../../lessons/diagramme/vb-buchstaben-loesung.visustruct":WC,"../../lessons/diagramme/vb-drei-lichter-loesung.visustruct":NC,"../../lessons/diagramme/vb-dreieck-loesung.visustruct":FC,"../../lessons/diagramme/vb-einparken-loesung.visustruct":JC,"../../lessons/diagramme/vb-farben-loesung.visustruct":RC,"../../lessons/diagramme/vb-farbweiche-loesung.visustruct":GC,"../../lessons/diagramme/vb-gas-bis-wand-loesung.visustruct":HC,"../../lessons/diagramme/vb-gerade-loesung.visustruct":VC,"../../lessons/diagramme/vb-hindernis-loesung.visustruct":qC,"../../lessons/diagramme/vb-java-akku-loesung.visustruct":QC,"../../lessons/diagramme/vb-java-blau-gruen-loesung.visustruct":UC,"../../lessons/diagramme/vb-java-blinken-loesung.visustruct":$C,"../../lessons/diagramme/vb-java-countdown-loesung.visustruct":YC,"../../lessons/diagramme/vb-java-hoeher-loesung.visustruct":XC,"../../lessons/diagramme/vb-java-joystick-loesung.visustruct":KC,"../../lessons/diagramme/vb-java-laermampel-loesung.visustruct":eP,"../../lessons/diagramme/vb-java-lauflicht-loesung.visustruct":tP,"../../lessons/diagramme/vb-java-linienfolger-loesung.visustruct":nP,"../../lessons/diagramme/vb-java-nachtlicht-ton-loesung.visustruct":iP,"../../lessons/diagramme/vb-java-rand-loesung.visustruct":aP,"../../lessons/diagramme/vb-java-rechteck-loesung.visustruct":sP,"../../lessons/diagramme/vb-java-textlaenge-loesung.visustruct":rP,"../../lessons/diagramme/vb-java-wand-piep-loesung.visustruct":oP,"../../lessons/diagramme/vb-java-wasserwaage-loesung.visustruct":lP,"../../lessons/diagramme/vb-klatschen-loesung.visustruct":uP,"../../lessons/diagramme/vb-knight-rider-loesung.visustruct":cP,"../../lessons/diagramme/vb-labyrinth-loesung.visustruct":mP,"../../lessons/diagramme/vb-linienfolger-stopp-loesung.visustruct":dP,"../../lessons/diagramme/vb-linienmuster-loesung.visustruct":hP,"../../lessons/diagramme/vb-melodie-loesung.visustruct":gP,"../../lessons/diagramme/vb-morsen-loesung.visustruct":pP,"../../lessons/diagramme/vb-nachtlicht-loesung.visustruct":fP,"../../lessons/diagramme/vb-nachtwaechter-loesung.visustruct":bP,"../../lessons/diagramme/vb-ohne-noten-loesung.visustruct":xP,"../../lessons/diagramme/vb-ohne-quadratzahl-loesung.visustruct":vP,"../../lessons/diagramme/vb-ohne-quadratzahl-unterprogramm-loesung.visustruct":yP,"../../lessons/diagramme/vb-ohne-rueckwaerts-loesung.visustruct":wP,"../../lessons/diagramme/vb-ohne-strecke-loesung.visustruct":zP,"../../lessons/diagramme/vb-ohne-summe-loesung.visustruct":IP,"../../lessons/diagramme/vb-quadrat-loesung.visustruct":kP,"../../lessons/diagramme/vb-quadrat-methode-loesung.visustruct":SP,"../../lessons/diagramme/vb-quadrat-schleife-loesung.visustruct":TP,"../../lessons/diagramme/vb-quadrat-unterprogramm-loesung.visustruct":_P,"../../lessons/diagramme/vb-quadrat-verschachtelt-loesung.visustruct":OP,"../../lessons/diagramme/vb-rand-loesung.visustruct":AP,"../../lessons/diagramme/vb-schraeglage-loesung.visustruct":CP,"../../lessons/diagramme/vb-slalom-loesung.visustruct":PP,"../../lessons/diagramme/vb-spirale-loesung.visustruct":jP,"../../lessons/diagramme/vb-start-a-loesung.visustruct":DP,"../../lessons/diagramme/vb-tonleiter-loesung.visustruct":BP,"../../lessons/diagramme/vb-treppe-loesung.visustruct":ZP,"../../lessons/diagramme/vb-tunnel-loesung.visustruct":MP,"../../lessons/diagramme/vb-variable-seite-loesung.visustruct":LP,"../../lessons/diagramme/vb-vier-quadrate-loesung.visustruct":EP,"../../lessons/diagramme/vb-wald-loesung.visustruct":WP,"../../lessons/diagramme/vb-wand-vorn-loesung.visustruct":NP,"../../lessons/diagramme/vb-zwei-sekunden-loesung.visustruct":FP,"../../lessons/diagramme/zk-initialen-loesung.visustruct":JP,"../../lessons/diagramme/zk-mehr.visustruct":RP,"../../lessons/diagramme/zk-rueckwaerts-loesung.visustruct":GP,"../../lessons/diagramme/zk-split.visustruct":HP,"../../lessons/diagramme/zk-woerter-loesung.visustruct":VP,"../../lessons/diagramme/zk-zaehlen.visustruct":qP,"../../lessons/diagramme/zk-zeichen.visustruct":QP}),PB=Object.assign({"../../lessons/welten/ausgang-1.txt":UP,"../../lessons/welten/ausgang-2.txt":$P,"../../lessons/welten/ecke.txt":YP,"../../lessons/welten/farbe-1.txt":XP,"../../lessons/welten/farbe-2.txt":KP,"../../lessons/welten/farbe-3.txt":ej,"../../lessons/welten/farbe-4.txt":tj,"../../lessons/welten/hindernis-1.txt":nj,"../../lessons/welten/hindernis-2.txt":ij,"../../lessons/welten/labyrinth-1.txt":aj,"../../lessons/welten/labyrinth-2.txt":sj,"../../lessons/welten/linie-1.txt":rj,"../../lessons/welten/linie-2.txt":oj,"../../lessons/welten/linie-rot-1.txt":lj,"../../lessons/welten/linie-rot-2.txt":uj,"../../lessons/welten/parken-1.txt":cj,"../../lessons/welten/parken-2.txt":mj,"../../lessons/welten/rand-1.txt":dj,"../../lessons/welten/rand-2.txt":hj,"../../lessons/welten/slalom.txt":gj,"../../lessons/welten/tunnel-1.txt":pj,"../../lessons/welten/tunnel-2.txt":fj,"../../lessons/welten/wald-1.txt":bj,"../../lessons/welten/wald-2.txt":xj,"../../lessons/welten/wand-frei.txt":vj,"../../lessons/welten/wand-kurz.txt":yj,"../../lessons/welten/wand-lang.txt":wj,"../../lessons/welten/wand-mittel.txt":zj,"../../lessons/welten/wand-nah.txt":Ij,"../../lessons/welten/zeit-1.txt":kj,"../../lessons/welten/ziel-kurz.txt":Sj,"../../lessons/welten/ziel-lang.txt":Tj}),jB=Object.assign({"../../lessons/bilder/aufgabe-mehrwertsteuer.svg":_j,"../../lessons/bilder/ben-shneiderman.jpg":Oj,"../../lessons/bilder/caesar-ascii.svg":Aj,"../../lessons/bilder/caesar-scheibe.svg":Cj,"../../lessons/bilder/caesar-verschiebung.svg":Pj,"../../lessons/bilder/en/aufgabe-mehrwertsteuer.svg":jj,"../../lessons/bilder/en/kino-saal.svg":Dj,"../../lessons/bilder/en/kino-schleifen.svg":Bj,"../../lessons/bilder/en/l01-pap.svg":Zj,"../../lessons/bilder/en/l02-einfuegen.svg":Mj,"../../lessons/bilder/en/l03-lochkarte-beschriftet.svg":Lj,"../../lessons/bilder/en/l03-lochkarte.svg":Ej,"../../lessons/bilder/en/l04-camelcase.svg":Wj,"../../lessons/bilder/en/l04-variable.svg":Nj,"../../lessons/bilder/en/l04-zuweisung.svg":Fj,"../../lessons/bilder/en/l05-tauschen.svg":Jj,"../../lessons/bilder/en/l08-zahlenstrahl.svg":Rj,"../../lessons/bilder/en/l10-kopfgesteuert.svg":Gj,"../../lessons/bilder/en/l11-vergleich.svg":Hj,"../../lessons/bilder/en/l12-for-ablauf.svg":Vj,"../../lessons/bilder/en/l14-array.svg":qj,"../../lessons/bilder/en/mvc-klick.svg":Qj,"../../lessons/bilder/en/ss-binaere-suche.svg":Uj,"../../lessons/bilder/en/ss-bubblesort.svg":$j,"../../lessons/bilder/en/ss-lineare-suche.svg":Yj,"../../lessons/bilder/en/ss-vergleiche.svg":Xj,"../../lessons/bilder/en/uebergabe.svg":Kj,"../../lessons/bilder/en/zk-zeichen.svg":eD,"../../lessons/bilder/ike-nassi.jpg":tD,"../../lessons/bilder/kino-saal.svg":nD,"../../lessons/bilder/kino-schleifen.svg":iD,"../../lessons/bilder/l01-pap.svg":aD,"../../lessons/bilder/l02-einfuegen.svg":sD,"../../lessons/bilder/l03-lochkarte-beschriftet.svg":rD,"../../lessons/bilder/l03-lochkarte.svg":oD,"../../lessons/bilder/l04-camelcase.svg":lD,"../../lessons/bilder/l04-kaffee.svg":uD,"../../lessons/bilder/l04-variable.svg":cD,"../../lessons/bilder/l04-zuweisung.svg":mD,"../../lessons/bilder/l05-tauschen.svg":dD,"../../lessons/bilder/l08-zahlenstrahl.svg":hD,"../../lessons/bilder/l09-wahrheitstabelle.svg":gD,"../../lessons/bilder/l10-kopfgesteuert.svg":pD,"../../lessons/bilder/l11-vergleich.svg":fD,"../../lessons/bilder/l12-for-ablauf.svg":bD,"../../lessons/bilder/l14-array.svg":xD,"../../lessons/bilder/mvc-klick.svg":vD,"../../lessons/bilder/pt/aufgabe-mehrwertsteuer.svg":yD,"../../lessons/bilder/pt/kino-saal.svg":wD,"../../lessons/bilder/pt/kino-schleifen.svg":zD,"../../lessons/bilder/pt/l01-pap.svg":ID,"../../lessons/bilder/pt/l02-einfuegen.svg":kD,"../../lessons/bilder/pt/l03-lochkarte-beschriftet.svg":SD,"../../lessons/bilder/pt/l03-lochkarte.svg":TD,"../../lessons/bilder/pt/l04-camelcase.svg":_D,"../../lessons/bilder/pt/l04-variable.svg":OD,"../../lessons/bilder/pt/l04-zuweisung.svg":AD,"../../lessons/bilder/pt/l05-tauschen.svg":CD,"../../lessons/bilder/pt/l08-zahlenstrahl.svg":PD,"../../lessons/bilder/pt/l10-kopfgesteuert.svg":jD,"../../lessons/bilder/pt/l11-vergleich.svg":DD,"../../lessons/bilder/pt/l12-for-ablauf.svg":BD,"../../lessons/bilder/pt/l14-array.svg":ZD,"../../lessons/bilder/pt/mvc-klick.svg":MD,"../../lessons/bilder/pt/schiffe-versenken.svg":LD,"../../lessons/bilder/pt/ss-binaere-suche.svg":ED,"../../lessons/bilder/pt/ss-bubblesort.svg":WD,"../../lessons/bilder/pt/ss-lineare-suche.svg":ND,"../../lessons/bilder/pt/ss-vergleiche.svg":FD,"../../lessons/bilder/pt/uebergabe.svg":JD,"../../lessons/bilder/pt/zk-zeichen.svg":RD,"../../lessons/bilder/schiffe-versenken.svg":GD,"../../lessons/bilder/ss-binaere-suche.svg":HD,"../../lessons/bilder/ss-bubblesort.svg":VD,"../../lessons/bilder/ss-lineare-suche.svg":qD,"../../lessons/bilder/ss-vergleiche.svg":QD,"../../lessons/bilder/uebergabe.svg":UD,"../../lessons/bilder/zk-zeichen.svg":$D}),Kh=i=>i.replace(/^.*\//,"");function G1(i,e,t){const n=s=>new Map(Object.entries(i).filter(([r])=>{var o;return((o=e.exec(r))==null?void 0:o[1])===s}).map(([r,o])=>[Kh(r),o]));return[...new Map([...n("en"),...t==="en"?[]:n(t)])]}function Gu(i){return i==="de"?"de":i==="pt-PT"?"pt":"en"}let I1="en",Pt=[],An=[],Wa="",Na=[],ps="off";function Hu(i){i!==ps&&(ps=i,Pt=[],fs(I1))}function fs(i){var s,r,o;if(g3(i),i===I1&&Pt.length>0)return;I1=i;const e=G1(_B,/\/lessons\/([^/]+)\/[^/]+\.md$/,i),t=(l,u)=>l.filter(([c])=>/^\d+/.test(c)).map(([c,m])=>SB(Qu(m,u),`${i}/${c}`)).sort((c,m)=>c.number-m.number),n=(l,u,c)=>l.map(([m,d])=>{const h=TB(Qu(d,c),`${i}/${u}${m}`);return c&&h.after!==void 0?{...h,after:c.get(h.after)??h.after}:h}),a=G1(OB,/\/lessons\/([^/]+)\/aufgaben\/[^/]+\.md$/,i);if(ps==="on"){const l=G1(Ru,/\/lessons\/([^/]+)\/visubot\/[^/]+\.md$/,i),u=DB(qu(e),qu(l)),c=t(e,u.normal),m=h=>{var g;return((g=[...c].reverse().find(f=>u.normal.get(f.number)({...h,number:u.normal.get(h.number)})),...t(l,u.robot).map(h=>{const g=u.robot.get(h.number);return{...h,number:g,section:m(g),robot:!0}})].sort((h,g)=>h.number-g.number);const d=G1(AB,/\/lessons\/([^/]+)\/visubot\/aufgaben\/[^/]+\.md$/,i);An=[...n(a,"aufgaben/",u.normal),...n(d,"visubot/aufgaben/",u.robot).map(h=>({...h,robot:!0}))]}else Pt=t(e),An=n(a,"aufgaben/");An.sort((l,u)=>(l.after??0)-(u.after??0)||l.level-u.level||l.title.localeCompare(u.title,i));for(const l of[...Pt.flatMap(u=>u.steps.flatMap(c=>c.blocks)),...An.flatMap(u=>u.blocks)])l.kind==="textFile"&&k3(l.name,l.content);if(Wa=((s=e.find(([l])=>l==="nachschlagen.md"))==null?void 0:s[1])??"",ps!=="off"){const l=(r=G1(Ru,/\/lessons\/([^/]+)\/visubot\/[^/]+\.md$/,i).find(([u])=>u==="nachschlagen.md"))==null?void 0:r[1];l&&(Wa=`${Wa.trimEnd()} +`)){const h=/^##\s+(.*)$/.exec(d);h?(u(),l={title:h[1].trim(),lines:[]}):l?l.lines.push(d):o.push(d)}if(u(),r.length===0)throw new ne(`${e}: Keine Schritte (## Überschrift) gefunden.`);SB(r,e);const c=t.get("titel");if(!c)throw new ne(`${e}: „titel:“ fehlt.`);return{id:a,number:s,title:c,section:t.get("bereich")??"",summary:t.get("kurz")??o.join(" ").trim(),steps:r}}function _B(i,e){const{meta:t,body:n}=Yh(i,e),a=t.get("titel");if(!a)throw new ne(`${e}: „titel:“ fehlt.`);const s=t.get("nach");return{id:e.replace(/^.*\//,"").replace(/\.md$/,""),title:a,after:s?Number(s):void 0,level:Number(t.get("stufe")??"1")||1,blocks:Kh(n,e)}}function Ju(i,e){const t=i.split(/\s*,\s*/).map(n=>n.trim()).filter(Boolean);for(const n of t)if(!z3(n))throw new ne(`${e}: Unbekanntes Teil „${n}“. Bekannt: ${hh.join(", ")}.`);return t}const OB=Object.assign({"../../lessons/de/01-was-ist-ein-struktogramm.md":dx,"../../lessons/de/02-der-editor.md":hx,"../../lessons/de/03-speichern-oeffnen-exportieren.md":gx,"../../lessons/de/04-variablen-und-datentypen.md":px,"../../lessons/de/05-sequenz.md":fx,"../../lessons/de/06-eingabe-und-ausgabe.md":bx,"../../lessons/de/07-simulation-und-schreibtischtest.md":xx,"../../lessons/de/08-verzweigung.md":vx,"../../lessons/de/09-bedingungen-verknuepfen.md":yx,"../../lessons/de/10-fallauswahl.md":wx,"../../lessons/de/11-while-schleife.md":zx,"../../lessons/de/12-do-while-schleife.md":Ix,"../../lessons/de/13-for-schleife.md":kx,"../../lessons/de/14-verschachteln.md":Sx,"../../lessons/de/15-arrays.md":Tx,"../../lessons/de/16-zweidimensionale-arrays.md":_x,"../../lessons/de/17-zeichenketten.md":Ox,"../../lessons/de/18-aufruf-und-aussprung.md":Ax,"../../lessons/de/19-suchen-und-sortieren.md":Cx,"../../lessons/de/20-java.md":jx,"../../lessons/de/21-python-und-javascript.md":Px,"../../lessons/de/22-try-und-catch.md":Dx,"../../lessons/de/23-text-einlesen-und-speichern.md":Bx,"../../lessons/de/24-zeile-fuer-zeile.md":Zx,"../../lessons/de/25-tabellen-als-csv.md":Mx,"../../lessons/de/26-json.md":Lx,"../../lessons/de/27-formate-im-vergleich.md":Ex,"../../lessons/de/28-erstes-fenster.md":Wx,"../../lessons/de/29-knopf-im-fenster.md":Nx,"../../lessons/de/30-der-knopf-reagiert.md":Fx,"../../lessons/de/31-zahl-verdoppeln.md":Jx,"../../lessons/de/32-klickzaehler.md":Rx,"../../lessons/de/33-ampel.md":Gx,"../../lessons/de/34-notenrechner.md":Hx,"../../lessons/de/35-taschenrechner.md":Vx,"../../lessons/de/36-zahlenraten.md":qx,"../../lessons/de/37-viele-knoepfe-ein-zuhoerer.md":Qx,"../../lessons/de/38-innere-klassen.md":Ux,"../../lessons/de/39-zwei-reiter.md":$x,"../../lessons/de/40-model-view-controller.md":Yx,"../../lessons/de/begriffe.md":Xx,"../../lessons/de/nachschlagen.md":Kx,"../../lessons/en/01-was-ist-ein-struktogramm.md":e4,"../../lessons/en/02-der-editor.md":t4,"../../lessons/en/03-speichern-oeffnen-exportieren.md":n4,"../../lessons/en/04-variablen-und-datentypen.md":i4,"../../lessons/en/05-sequenz.md":a4,"../../lessons/en/06-eingabe-und-ausgabe.md":s4,"../../lessons/en/07-simulation-und-schreibtischtest.md":r4,"../../lessons/en/08-verzweigung.md":o4,"../../lessons/en/09-bedingungen-verknuepfen.md":l4,"../../lessons/en/10-fallauswahl.md":u4,"../../lessons/en/11-while-schleife.md":c4,"../../lessons/en/12-do-while-schleife.md":m4,"../../lessons/en/13-for-schleife.md":d4,"../../lessons/en/14-verschachteln.md":h4,"../../lessons/en/15-arrays.md":g4,"../../lessons/en/16-zweidimensionale-arrays.md":p4,"../../lessons/en/17-zeichenketten.md":f4,"../../lessons/en/18-aufruf-und-aussprung.md":b4,"../../lessons/en/19-suchen-und-sortieren.md":x4,"../../lessons/en/20-java.md":v4,"../../lessons/en/21-python-und-javascript.md":y4,"../../lessons/en/22-try-und-catch.md":w4,"../../lessons/en/23-text-einlesen-und-speichern.md":z4,"../../lessons/en/24-zeile-fuer-zeile.md":I4,"../../lessons/en/25-tabellen-als-csv.md":k4,"../../lessons/en/26-json.md":S4,"../../lessons/en/27-formate-im-vergleich.md":T4,"../../lessons/en/28-erstes-fenster.md":_4,"../../lessons/en/29-knopf-im-fenster.md":O4,"../../lessons/en/30-der-knopf-reagiert.md":A4,"../../lessons/en/31-zahl-verdoppeln.md":C4,"../../lessons/en/32-klickzaehler.md":j4,"../../lessons/en/33-ampel.md":P4,"../../lessons/en/34-notenrechner.md":D4,"../../lessons/en/35-taschenrechner.md":B4,"../../lessons/en/36-zahlenraten.md":Z4,"../../lessons/en/37-viele-knoepfe-ein-zuhoerer.md":M4,"../../lessons/en/38-innere-klassen.md":L4,"../../lessons/en/39-zwei-reiter.md":E4,"../../lessons/en/40-model-view-controller.md":W4,"../../lessons/en/begriffe.md":N4,"../../lessons/en/nachschlagen.md":F4,"../../lessons/pt/01-was-ist-ein-struktogramm.md":J4,"../../lessons/pt/02-der-editor.md":R4,"../../lessons/pt/03-speichern-oeffnen-exportieren.md":G4,"../../lessons/pt/04-variablen-und-datentypen.md":H4,"../../lessons/pt/05-sequenz.md":V4,"../../lessons/pt/06-eingabe-und-ausgabe.md":q4,"../../lessons/pt/07-simulation-und-schreibtischtest.md":Q4,"../../lessons/pt/08-verzweigung.md":U4,"../../lessons/pt/09-bedingungen-verknuepfen.md":$4,"../../lessons/pt/10-fallauswahl.md":Y4,"../../lessons/pt/11-while-schleife.md":X4,"../../lessons/pt/12-do-while-schleife.md":K4,"../../lessons/pt/13-for-schleife.md":ev,"../../lessons/pt/14-verschachteln.md":tv,"../../lessons/pt/15-arrays.md":nv,"../../lessons/pt/16-zweidimensionale-arrays.md":iv,"../../lessons/pt/17-zeichenketten.md":av,"../../lessons/pt/18-aufruf-und-aussprung.md":sv,"../../lessons/pt/19-suchen-und-sortieren.md":rv,"../../lessons/pt/20-java.md":ov,"../../lessons/pt/21-python-und-javascript.md":lv,"../../lessons/pt/22-try-und-catch.md":uv,"../../lessons/pt/23-text-einlesen-und-speichern.md":cv,"../../lessons/pt/24-zeile-fuer-zeile.md":mv,"../../lessons/pt/25-tabellen-als-csv.md":dv,"../../lessons/pt/26-json.md":hv,"../../lessons/pt/27-formate-im-vergleich.md":gv,"../../lessons/pt/28-erstes-fenster.md":pv,"../../lessons/pt/29-knopf-im-fenster.md":fv,"../../lessons/pt/30-der-knopf-reagiert.md":bv,"../../lessons/pt/31-zahl-verdoppeln.md":xv,"../../lessons/pt/32-klickzaehler.md":vv,"../../lessons/pt/33-ampel.md":yv,"../../lessons/pt/34-notenrechner.md":wv,"../../lessons/pt/35-taschenrechner.md":zv,"../../lessons/pt/36-zahlenraten.md":Iv,"../../lessons/pt/37-viele-knoepfe-ein-zuhoerer.md":kv,"../../lessons/pt/38-innere-klassen.md":Sv,"../../lessons/pt/39-zwei-reiter.md":Tv,"../../lessons/pt/40-model-view-controller.md":_v,"../../lessons/pt/begriffe.md":Ov,"../../lessons/pt/nachschlagen.md":Av}),AB=Object.assign({"../../lessons/de/aufgaben/alter-unterprogramm.md":Cv,"../../lessons/de/aufgaben/ballwurf.md":jv,"../../lessons/de/aufgaben/bestenliste.md":Pv,"../../lessons/de/aufgaben/binaerzahl.md":Dv,"../../lessons/de/aufgaben/caesar.md":Bv,"../../lessons/de/aufgaben/collatz.md":Zv,"../../lessons/de/aufgaben/einheitenrechner.md":Mv,"../../lessons/de/aufgaben/fibonacci.md":Lv,"../../lessons/de/aufgaben/gerade-ungerade.md":Ev,"../../lessons/de/aufgaben/mehrwertsteuer.md":Wv,"../../lessons/de/aufgaben/notendurchschnitt.md":Nv,"../../lessons/de/aufgaben/pin-pruefen.md":Fv,"../../lessons/de/aufgaben/schiffe-versenken.md":Jv,"../../lessons/de/aufgaben/speisekarte.md":Rv,"../../lessons/de/aufgaben/summe-bilden.md":Gv,"../../lessons/de/aufgaben/tafeldienst.md":Hv,"../../lessons/de/aufgaben/taschenrechner.md":Vv,"../../lessons/de/aufgaben/verleih-menue.md":qv,"../../lessons/de/aufgaben/vokabeltrainer.md":Qv,"../../lessons/de/aufgaben/volljaehrig.md":Uv,"../../lessons/de/aufgaben/wuerfel-mvc.md":$v,"../../lessons/de/aufgaben/zahl-verdoppeln.md":Yv,"../../lessons/en/aufgaben/alter-unterprogramm.md":Xv,"../../lessons/en/aufgaben/ballwurf.md":Kv,"../../lessons/en/aufgaben/bestenliste.md":ey,"../../lessons/en/aufgaben/binaerzahl.md":ty,"../../lessons/en/aufgaben/caesar.md":ny,"../../lessons/en/aufgaben/collatz.md":iy,"../../lessons/en/aufgaben/einheitenrechner.md":ay,"../../lessons/en/aufgaben/fibonacci.md":sy,"../../lessons/en/aufgaben/gerade-ungerade.md":ry,"../../lessons/en/aufgaben/mehrwertsteuer.md":oy,"../../lessons/en/aufgaben/notendurchschnitt.md":ly,"../../lessons/en/aufgaben/pin-pruefen.md":uy,"../../lessons/en/aufgaben/schiffe-versenken.md":cy,"../../lessons/en/aufgaben/speisekarte.md":my,"../../lessons/en/aufgaben/summe-bilden.md":dy,"../../lessons/en/aufgaben/tafeldienst.md":hy,"../../lessons/en/aufgaben/taschenrechner.md":gy,"../../lessons/en/aufgaben/verleih-menue.md":py,"../../lessons/en/aufgaben/vokabeltrainer.md":fy,"../../lessons/en/aufgaben/volljaehrig.md":by,"../../lessons/en/aufgaben/wuerfel-mvc.md":xy,"../../lessons/en/aufgaben/zahl-verdoppeln.md":vy,"../../lessons/pt/aufgaben/alter-unterprogramm.md":yy,"../../lessons/pt/aufgaben/ballwurf.md":wy,"../../lessons/pt/aufgaben/bestenliste.md":zy,"../../lessons/pt/aufgaben/binaerzahl.md":Iy,"../../lessons/pt/aufgaben/caesar.md":ky,"../../lessons/pt/aufgaben/collatz.md":Sy,"../../lessons/pt/aufgaben/einheitenrechner.md":Ty,"../../lessons/pt/aufgaben/fibonacci.md":_y,"../../lessons/pt/aufgaben/gerade-ungerade.md":Oy,"../../lessons/pt/aufgaben/mehrwertsteuer.md":Ay,"../../lessons/pt/aufgaben/notendurchschnitt.md":Cy,"../../lessons/pt/aufgaben/pin-pruefen.md":jy,"../../lessons/pt/aufgaben/schiffe-versenken.md":Py,"../../lessons/pt/aufgaben/speisekarte.md":Dy,"../../lessons/pt/aufgaben/summe-bilden.md":By,"../../lessons/pt/aufgaben/tafeldienst.md":Zy,"../../lessons/pt/aufgaben/taschenrechner.md":My,"../../lessons/pt/aufgaben/verleih-menue.md":Ly,"../../lessons/pt/aufgaben/vokabeltrainer.md":Ey,"../../lessons/pt/aufgaben/volljaehrig.md":Wy,"../../lessons/pt/aufgaben/wuerfel-mvc.md":Ny,"../../lessons/pt/aufgaben/zahl-verdoppeln.md":Fy}),Ru=Object.assign({"../../lessons/de/visubot/01-der-mbot2.md":Jy,"../../lessons/de/visubot/02-das-quadrat.md":Ry,"../../lessons/de/visubot/03-variablen-und-ausgabe.md":Gy,"../../lessons/de/visubot/04-sensoren.md":Hy,"../../lessons/de/visubot/05-bis-zur-wand.md":Vy,"../../lessons/de/visubot/06-abstand.md":qy,"../../lessons/de/visubot/07-linie.md":Qy,"../../lessons/de/visubot/08-farben.md":Uy,"../../lessons/de/visubot/09-fallauswahl.md":$y,"../../lessons/de/visubot/10-tasten-joystick.md":Yy,"../../lessons/de/visubot/11-licht.md":Xy,"../../lessons/de/visubot/12-lautstaerke.md":Ky,"../../lessons/de/visubot/13-neigung.md":ew,"../../lessons/de/visubot/14-leds.md":tw,"../../lessons/de/visubot/15-einzelne-leds.md":nw,"../../lessons/de/visubot/16-lautsprecher.md":iw,"../../lessons/de/visubot/17-arrays-melodie.md":aw,"../../lessons/de/visubot/18-bildschirm.md":sw,"../../lessons/de/visubot/19-zeichenketten.md":rw,"../../lessons/de/visubot/20-motoren.md":ow,"../../lessons/de/visubot/21-stoppuhr-akku.md":lw,"../../lessons/de/visubot/22-eigene-methoden.md":uw,"../../lessons/de/visubot/nachschlagen.md":cw,"../../lessons/en/visubot/01-der-mbot2.md":mw,"../../lessons/en/visubot/02-das-quadrat.md":dw,"../../lessons/en/visubot/03-variablen-und-ausgabe.md":hw,"../../lessons/en/visubot/04-sensoren.md":gw,"../../lessons/en/visubot/05-bis-zur-wand.md":pw,"../../lessons/en/visubot/06-abstand.md":fw,"../../lessons/en/visubot/07-linie.md":bw,"../../lessons/en/visubot/08-farben.md":xw,"../../lessons/en/visubot/09-fallauswahl.md":vw,"../../lessons/en/visubot/10-tasten-joystick.md":yw,"../../lessons/en/visubot/11-licht.md":ww,"../../lessons/en/visubot/12-lautstaerke.md":zw,"../../lessons/en/visubot/13-neigung.md":Iw,"../../lessons/en/visubot/14-leds.md":kw,"../../lessons/en/visubot/15-einzelne-leds.md":Sw,"../../lessons/en/visubot/16-lautsprecher.md":Tw,"../../lessons/en/visubot/17-arrays-melodie.md":_w,"../../lessons/en/visubot/18-bildschirm.md":Ow,"../../lessons/en/visubot/19-zeichenketten.md":Aw,"../../lessons/en/visubot/20-motoren.md":Cw,"../../lessons/en/visubot/21-stoppuhr-akku.md":jw,"../../lessons/en/visubot/22-eigene-methoden.md":Pw,"../../lessons/en/visubot/nachschlagen.md":Dw}),CB=Object.assign({"../../lessons/de/visubot/aufgaben/alarmanlage.md":Bw,"../../lessons/de/visubot/aufgaben/ausgang.md":Zw,"../../lessons/de/visubot/aufgaben/binaer-zaehlen.md":Mw,"../../lessons/de/visubot/aufgaben/dreieck.md":Lw,"../../lessons/de/visubot/aufgaben/einparken.md":Ew,"../../lessons/de/visubot/aufgaben/hindernis.md":Ww,"../../lessons/de/visubot/aufgaben/knight-rider.md":Nw,"../../lessons/de/visubot/aufgaben/labyrinth.md":Fw,"../../lessons/de/visubot/aufgaben/linienfolger-stopp.md":Jw,"../../lessons/de/visubot/aufgaben/morsen.md":Rw,"../../lessons/de/visubot/aufgaben/nachtwaechter.md":Gw,"../../lessons/de/visubot/aufgaben/slalom.md":Hw,"../../lessons/de/visubot/aufgaben/spirale.md":Vw,"../../lessons/de/visubot/aufgaben/treppe.md":qw,"../../lessons/de/visubot/aufgaben/tunnel.md":Qw,"../../lessons/de/visubot/aufgaben/wald.md":Uw,"../../lessons/en/visubot/aufgaben/alarmanlage.md":$w,"../../lessons/en/visubot/aufgaben/ausgang.md":Yw,"../../lessons/en/visubot/aufgaben/binaer-zaehlen.md":Xw,"../../lessons/en/visubot/aufgaben/dreieck.md":Kw,"../../lessons/en/visubot/aufgaben/einparken.md":e9,"../../lessons/en/visubot/aufgaben/hindernis.md":t9,"../../lessons/en/visubot/aufgaben/knight-rider.md":n9,"../../lessons/en/visubot/aufgaben/labyrinth.md":i9,"../../lessons/en/visubot/aufgaben/linienfolger-stopp.md":a9,"../../lessons/en/visubot/aufgaben/morsen.md":s9,"../../lessons/en/visubot/aufgaben/nachtwaechter.md":r9,"../../lessons/en/visubot/aufgaben/slalom.md":o9,"../../lessons/en/visubot/aufgaben/spirale.md":l9,"../../lessons/en/visubot/aufgaben/treppe.md":u9,"../../lessons/en/visubot/aufgaben/tunnel.md":c9,"../../lessons/en/visubot/aufgaben/wald.md":m9}),jB=Object.assign({"../../lessons/diagramme/aufgabe-alter-haupt-loesung.visustruct":d9,"../../lessons/diagramme/aufgabe-alter-unterprogramm-loesung.visustruct":h9,"../../lessons/diagramme/aufgabe-ballwurf-loesung.visustruct":g9,"../../lessons/diagramme/aufgabe-ballwurf-start.visustruct":p9,"../../lessons/diagramme/aufgabe-bestenliste-loesung.visustruct":f9,"../../lessons/diagramme/aufgabe-binaer-loesung.visustruct":b9,"../../lessons/diagramme/aufgabe-caesar-array-loesung.visustruct":x9,"../../lessons/diagramme/aufgabe-caesar-array-start.visustruct":v9,"../../lessons/diagramme/aufgabe-caesar-ascii-loesung.visustruct":y9,"../../lessons/diagramme/aufgabe-caesar-entschluesseln-loesung.visustruct":w9,"../../lessons/diagramme/aufgabe-collatz-loesung.visustruct":z9,"../../lessons/diagramme/aufgabe-durchschnitt-loesung.visustruct":I9,"../../lessons/diagramme/aufgabe-fibonacci-loesung.visustruct":k9,"../../lessons/diagramme/aufgabe-gerade-loesung.visustruct":S9,"../../lessons/diagramme/aufgabe-mehrwertsteuer-loesung.visustruct":T9,"../../lessons/diagramme/aufgabe-pin-java-loesung.visustruct":_9,"../../lessons/diagramme/aufgabe-pin-loesung.visustruct":O9,"../../lessons/diagramme/aufgabe-rechner-loesung.visustruct":A9,"../../lessons/diagramme/aufgabe-schiffe-loesung.visustruct":C9,"../../lessons/diagramme/aufgabe-schiffe-start.visustruct":j9,"../../lessons/diagramme/aufgabe-speisekarte-loesung.visustruct":P9,"../../lessons/diagramme/aufgabe-summe-loesung.visustruct":D9,"../../lessons/diagramme/aufgabe-tafeldienst-loesung.visustruct":B9,"../../lessons/diagramme/aufgabe-verdoppeln-loesung.visustruct":Z9,"../../lessons/diagramme/aufgabe-verleih-java-loesung.visustruct":M9,"../../lessons/diagramme/aufgabe-verleih-loesung.visustruct":L9,"../../lessons/diagramme/aufgabe-vokabeln-loesung.visustruct":E9,"../../lessons/diagramme/aufgabe-vokabeln-start.visustruct":W9,"../../lessons/diagramme/aufgabe-volljaehrig-loesung.visustruct":N9,"../../lessons/diagramme/dt-buffered.visustruct":F9,"../../lessons/diagramme/dt-csv.visustruct":J9,"../../lessons/diagramme/dt-json.visustruct":R9,"../../lessons/diagramme/dt-lesen.visustruct":G9,"../../lessons/diagramme/en/aufgabe-alter-haupt-loesung.visustruct":H9,"../../lessons/diagramme/en/aufgabe-alter-unterprogramm-loesung.visustruct":V9,"../../lessons/diagramme/en/aufgabe-ballwurf-loesung.visustruct":q9,"../../lessons/diagramme/en/aufgabe-ballwurf-start.visustruct":Q9,"../../lessons/diagramme/en/aufgabe-bestenliste-loesung.visustruct":U9,"../../lessons/diagramme/en/aufgabe-binaer-loesung.visustruct":$9,"../../lessons/diagramme/en/aufgabe-caesar-array-loesung.visustruct":Y9,"../../lessons/diagramme/en/aufgabe-caesar-array-start.visustruct":X9,"../../lessons/diagramme/en/aufgabe-caesar-ascii-loesung.visustruct":K9,"../../lessons/diagramme/en/aufgabe-caesar-entschluesseln-loesung.visustruct":e5,"../../lessons/diagramme/en/aufgabe-collatz-loesung.visustruct":t5,"../../lessons/diagramme/en/aufgabe-durchschnitt-loesung.visustruct":n5,"../../lessons/diagramme/en/aufgabe-fibonacci-loesung.visustruct":i5,"../../lessons/diagramme/en/aufgabe-gerade-loesung.visustruct":a5,"../../lessons/diagramme/en/aufgabe-mehrwertsteuer-loesung.visustruct":s5,"../../lessons/diagramme/en/aufgabe-pin-java-loesung.visustruct":r5,"../../lessons/diagramme/en/aufgabe-pin-loesung.visustruct":o5,"../../lessons/diagramme/en/aufgabe-rechner-loesung.visustruct":l5,"../../lessons/diagramme/en/aufgabe-schiffe-loesung.visustruct":u5,"../../lessons/diagramme/en/aufgabe-schiffe-start.visustruct":c5,"../../lessons/diagramme/en/aufgabe-speisekarte-loesung.visustruct":m5,"../../lessons/diagramme/en/aufgabe-summe-loesung.visustruct":d5,"../../lessons/diagramme/en/aufgabe-tafeldienst-loesung.visustruct":h5,"../../lessons/diagramme/en/aufgabe-verdoppeln-loesung.visustruct":g5,"../../lessons/diagramme/en/aufgabe-verleih-java-loesung.visustruct":p5,"../../lessons/diagramme/en/aufgabe-verleih-loesung.visustruct":f5,"../../lessons/diagramme/en/aufgabe-vokabeln-loesung.visustruct":b5,"../../lessons/diagramme/en/aufgabe-vokabeln-start.visustruct":x5,"../../lessons/diagramme/en/aufgabe-volljaehrig-loesung.visustruct":v5,"../../lessons/diagramme/en/dt-buffered.visustruct":y5,"../../lessons/diagramme/en/dt-csv.visustruct":w5,"../../lessons/diagramme/en/dt-json.visustruct":z5,"../../lessons/diagramme/en/dt-lesen.visustruct":I5,"../../lessons/diagramme/en/kino-einmaleins-loesung.visustruct":k5,"../../lessons/diagramme/en/kino-frei-loesung.visustruct":S5,"../../lessons/diagramme/en/kino-frei-start.visustruct":T5,"../../lessons/diagramme/en/kino-karte-loesung.visustruct":_5,"../../lessons/diagramme/en/kino-karte-start.visustruct":O5,"../../lessons/diagramme/en/kino-saalplan.visustruct":A5,"../../lessons/diagramme/en/kino-verkaufen.visustruct":C5,"../../lessons/diagramme/en/l04-java-fehler-loesung.visustruct":j5,"../../lessons/diagramme/en/l04-java-fehler-start.visustruct":P5,"../../lessons/diagramme/en/l04-java-steckbrief-loesung.visustruct":D5,"../../lessons/diagramme/en/l04-rechnen.visustruct":B5,"../../lessons/diagramme/en/l04-reihenfolge-loesung.visustruct":Z5,"../../lessons/diagramme/en/l04-reihenfolge-start.visustruct":M5,"../../lessons/diagramme/en/l04-tauschen-loesung.visustruct":L5,"../../lessons/diagramme/en/l04-tauschen-start.visustruct":E5,"../../lessons/diagramme/en/l04-tauschen.visustruct":W5,"../../lessons/diagramme/en/l05-datentypen.visustruct":N5,"../../lessons/diagramme/en/l05-division.visustruct":F5,"../../lessons/diagramme/en/l05-einkauf-loesung.visustruct":J5,"../../lessons/diagramme/en/l05-java-fehler-loesung.visustruct":R5,"../../lessons/diagramme/en/l05-java-fehler-start.visustruct":G5,"../../lessons/diagramme/en/l05-java-kino-loesung.visustruct":H5,"../../lessons/diagramme/en/l05-rechteck-loesung.visustruct":V5,"../../lessons/diagramme/en/l05-sekunden-loesung.visustruct":q5,"../../lessons/diagramme/en/l05-sekunden-start.visustruct":Q5,"../../lessons/diagramme/en/l05-sequenz.visustruct":U5,"../../lessons/diagramme/en/l06-begruessung-loesung.visustruct":$5,"../../lessons/diagramme/en/l06-eva.visustruct":Y5,"../../lessons/diagramme/en/l06-java-fehler-loesung.visustruct":X5,"../../lessons/diagramme/en/l06-java-fehler-start.visustruct":K5,"../../lessons/diagramme/en/l06-java-tage-loesung.visustruct":ez,"../../lessons/diagramme/en/l06-mittelwert-loesung.visustruct":tz,"../../lessons/diagramme/en/l06-rechner-loesung.visustruct":nz,"../../lessons/diagramme/en/l07-alter-pruefen.visustruct":iz,"../../lessons/diagramme/en/l07-betrag-loesung.visustruct":az,"../../lessons/diagramme/en/l07-gerade-loesung.visustruct":sz,"../../lessons/diagramme/en/l07-java-fehler-loesung.visustruct":rz,"../../lessons/diagramme/en/l07-java-fehler-start.visustruct":oz,"../../lessons/diagramme/en/l07-java-pizza-loesung.visustruct":lz,"../../lessons/diagramme/en/l07-java-pizza-start.visustruct":uz,"../../lessons/diagramme/en/l07-maximum-loesung.visustruct":cz,"../../lessons/diagramme/en/l07-rabatt.visustruct":mz,"../../lessons/diagramme/en/l08-gueltig-loesung.visustruct":dz,"../../lessons/diagramme/en/l08-java-bestanden-loesung.visustruct":hz,"../../lessons/diagramme/en/l08-java-fehler-loesung.visustruct":gz,"../../lessons/diagramme/en/l08-java-fehler-start.visustruct":pz,"../../lessons/diagramme/en/l08-jugendticket.visustruct":fz,"../../lessons/diagramme/en/l08-note.visustruct":bz,"../../lessons/diagramme/en/l08-schaltjahr-loesung.visustruct":xz,"../../lessons/diagramme/en/l08-wochenende-loesung.visustruct":vz,"../../lessons/diagramme/en/l09-ampel.visustruct":yz,"../../lessons/diagramme/en/l09-automat.visustruct":wz,"../../lessons/diagramme/en/l09-java-fehler-loesung.visustruct":zz,"../../lessons/diagramme/en/l09-java-fehler-start.visustruct":Iz,"../../lessons/diagramme/en/l09-java-schule-loesung.visustruct":kz,"../../lessons/diagramme/en/l09-note-loesung.visustruct":Sz,"../../lessons/diagramme/en/l09-rechner-loesung.visustruct":Tz,"../../lessons/diagramme/en/l09-verschachtelt.visustruct":_z,"../../lessons/diagramme/en/l1-grundbausteine.visustruct":Oz,"../../lessons/diagramme/en/l1-sequenz.visustruct":Az,"../../lessons/diagramme/en/l1-tee.visustruct":Cz,"../../lessons/diagramme/en/l1-verzweigung.visustruct":jz,"../../lessons/diagramme/en/l1-wiederholung.visustruct":Pz,"../../lessons/diagramme/en/l10-bis-n-loesung.visustruct":Dz,"../../lessons/diagramme/en/l10-countdown.visustruct":Bz,"../../lessons/diagramme/en/l10-endlos.visustruct":Zz,"../../lessons/diagramme/en/l10-fakultaet.visustruct":Mz,"../../lessons/diagramme/en/l10-java-fehler-loesung.visustruct":Lz,"../../lessons/diagramme/en/l10-java-fehler-start.visustruct":Ez,"../../lessons/diagramme/en/l10-java-wuerfel-loesung.visustruct":Wz,"../../lessons/diagramme/en/l10-verdoppeln-loesung.visustruct":Nz,"../../lessons/diagramme/en/l11-eingabe-pruefen.visustruct":Fz,"../../lessons/diagramme/en/l11-einmal.visustruct":Jz,"../../lessons/diagramme/en/l11-java-fehler-loesung.visustruct":Rz,"../../lessons/diagramme/en/l11-java-fehler-start.visustruct":Gz,"../../lessons/diagramme/en/l11-java-gerade-loesung.visustruct":Hz,"../../lessons/diagramme/en/l11-note-loesung.visustruct":Vz,"../../lessons/diagramme/en/l11-summe-loesung.visustruct":qz,"../../lessons/diagramme/en/l12-countdown-loesung.visustruct":Qz,"../../lessons/diagramme/en/l12-einmaleins-loesung.visustruct":Uz,"../../lessons/diagramme/en/l12-eins-bis-fuenf.visustruct":$z,"../../lessons/diagramme/en/l12-java-fehler-loesung.visustruct":Yz,"../../lessons/diagramme/en/l12-java-fehler-start.visustruct":Xz,"../../lessons/diagramme/en/l12-java-verdoppeln-loesung.visustruct":Kz,"../../lessons/diagramme/en/l12-summe.visustruct":e6,"../../lessons/diagramme/en/l13-dreieck.visustruct":t6,"../../lessons/diagramme/en/l13-gerade-eingaben-loesung.visustruct":n6,"../../lessons/diagramme/en/l13-gerade-zaehlen.visustruct":i6,"../../lessons/diagramme/en/l13-java-fehler-loesung.visustruct":a6,"../../lessons/diagramme/en/l13-java-fehler-start.visustruct":s6,"../../lessons/diagramme/en/l13-java-quadrate-loesung.visustruct":r6,"../../lessons/diagramme/en/l13-rechteck-loesung.visustruct":o6,"../../lessons/diagramme/en/l14-array-durchlaufen.visustruct":l6,"../../lessons/diagramme/en/l14-erster-letzter-loesung.visustruct":u6,"../../lessons/diagramme/en/l14-java-fehler-loesung.visustruct":c6,"../../lessons/diagramme/en/l14-java-fehler-start.visustruct":m6,"../../lessons/diagramme/en/l14-java-treppe-loesung.visustruct":d6,"../../lessons/diagramme/en/l14-namen-eingeben.visustruct":h6,"../../lessons/diagramme/en/l14-rueckwaerts-loesung.visustruct":g6,"../../lessons/diagramme/en/l14-summe-max-loesung.visustruct":p6,"../../lessons/diagramme/en/l14-summe-maximum.visustruct":f6,"../../lessons/diagramme/en/l15-bis-null-loesung.visustruct":b6,"../../lessons/diagramme/en/l15-endlos-aussprung.visustruct":x6,"../../lessons/diagramme/en/l15-flaeche-loesung.visustruct":v6,"../../lessons/diagramme/en/l15-flaeche-unterprogramm-loesung.visustruct":y6,"../../lessons/diagramme/en/l15-hauptprogramm.visustruct":w6,"../../lessons/diagramme/en/l15-java-fehler-loesung.visustruct":z6,"../../lessons/diagramme/en/l15-java-fehler-start.visustruct":I6,"../../lessons/diagramme/en/l15-java-noten-loesung.visustruct":k6,"../../lessons/diagramme/en/l15-quadrat-haupt.visustruct":S6,"../../lessons/diagramme/en/l15-quadrat.visustruct":T6,"../../lessons/diagramme/en/l15-titel-loesung.visustruct":_6,"../../lessons/diagramme/en/l15-unterprogramm.visustruct":O6,"../../lessons/diagramme/en/l15-zeige-summe-haupt.visustruct":A6,"../../lessons/diagramme/en/l15-zeige-summe.visustruct":C6,"../../lessons/diagramme/en/l16-countdown-loesung.visustruct":j6,"../../lessons/diagramme/en/l16-countdown-start.visustruct":P6,"../../lessons/diagramme/en/l16-java-fehler-loesung.visustruct":D6,"../../lessons/diagramme/en/l16-java-fehler-start.visustruct":B6,"../../lessons/diagramme/en/l16-java-punkte-loesung.visustruct":Z6,"../../lessons/diagramme/en/l16-schreibtisch.visustruct":M6,"../../lessons/diagramme/en/l16-summe-loesung.visustruct":L6,"../../lessons/diagramme/en/l16-summe-start.visustruct":E6,"../../lessons/diagramme/en/l17-beispiel.visustruct":W6,"../../lessons/diagramme/en/l17-fakultaet-loesung.visustruct":N6,"../../lessons/diagramme/en/l17-java-brief-loesung.visustruct":F6,"../../lessons/diagramme/en/l17-java-brief-start.visustruct":J6,"../../lessons/diagramme/en/l17-java-fehler-loesung.visustruct":R6,"../../lessons/diagramme/en/l17-java-fehler-start.visustruct":G6,"../../lessons/diagramme/en/l17-java-passwort-loesung.visustruct":H6,"../../lessons/diagramme/en/l17-ticket-loesung.visustruct":V6,"../../lessons/diagramme/en/l18-beispiel.visustruct":q6,"../../lessons/diagramme/en/l18-java-fehler-loesung.visustruct":Q6,"../../lessons/diagramme/en/l18-java-fehler-start.visustruct":U6,"../../lessons/diagramme/en/l18-java-kasse-loesung.visustruct":$6,"../../lessons/diagramme/en/l18-js-loesung.visustruct":Y6,"../../lessons/diagramme/en/l18-python-loesung.visustruct":X6,"../../lessons/diagramme/en/l19-java-fehler-loesung.visustruct":K6,"../../lessons/diagramme/en/l19-java-fehler-start.visustruct":e7,"../../lessons/diagramme/en/l19-java-zaehlen-loesung.visustruct":t7,"../../lessons/diagramme/en/l2-ausgabe.visustruct":n7,"../../lessons/diagramme/en/l2-hallo-loesung.visustruct":i7,"../../lessons/diagramme/en/l2-zwei-zeilen-loesung.visustruct":a7,"../../lessons/diagramme/en/l23-java-ergaenzen-loesung.visustruct":s7,"../../lessons/diagramme/en/l23-java-ergaenzen-start.visustruct":r7,"../../lessons/diagramme/en/l23-java-nummern-loesung.visustruct":o7,"../../lessons/diagramme/en/l23-java-nummern-start.visustruct":l7,"../../lessons/diagramme/en/l24-java-fuchs-loesung.visustruct":u7,"../../lessons/diagramme/en/l24-java-fuchs-start.visustruct":c7,"../../lessons/diagramme/en/l24-java-laengster-loesung.visustruct":m7,"../../lessons/diagramme/en/l24-java-laengster-start.visustruct":d7,"../../lessons/diagramme/en/l25-java-beste-loesung.visustruct":h7,"../../lessons/diagramme/en/l25-java-beste-start.visustruct":g7,"../../lessons/diagramme/en/l25-java-schnitt-loesung.visustruct":p7,"../../lessons/diagramme/en/l25-java-schnitt-start.visustruct":f7,"../../lessons/diagramme/en/l26-java-namen-loesung.visustruct":b7,"../../lessons/diagramme/en/l26-java-namen-start.visustruct":x7,"../../lessons/diagramme/en/l26-java-schreiben-loesung.visustruct":v7,"../../lessons/diagramme/en/l26-java-schreiben-start.visustruct":y7,"../../lessons/diagramme/en/l27-java-json-loesung.visustruct":w7,"../../lessons/diagramme/en/l27-java-json-start.visustruct":z7,"../../lessons/diagramme/en/l27-java-saetze-loesung.visustruct":I7,"../../lessons/diagramme/en/l27-java-saetze-start.visustruct":k7,"../../lessons/diagramme/en/sim-kino-loesung.visustruct":S7,"../../lessons/diagramme/en/sim-kino-start.visustruct":T7,"../../lessons/diagramme/en/sim-tausch-loesung.visustruct":_7,"../../lessons/diagramme/en/sim-tausch-start.visustruct":O7,"../../lessons/diagramme/en/sim-tausch.visustruct":A7,"../../lessons/diagramme/en/ss-absteigend-loesung.visustruct":C7,"../../lessons/diagramme/en/ss-absteigend-start.visustruct":j7,"../../lessons/diagramme/en/ss-binaere-suche.visustruct":P7,"../../lessons/diagramme/en/ss-bubblesort.visustruct":D7,"../../lessons/diagramme/en/ss-karte-suchen-loesung.visustruct":B7,"../../lessons/diagramme/en/ss-lineare-suche.visustruct":Z7,"../../lessons/diagramme/en/uebergabe-bonus-loesung.visustruct":M7,"../../lessons/diagramme/en/uebergabe-bonus-start.visustruct":L7,"../../lessons/diagramme/en/uebergabe-bonus-unterprogramm-loesung.visustruct":E7,"../../lessons/diagramme/en/uebergabe-haupt.visustruct":W7,"../../lessons/diagramme/en/uebergabe-leeren.visustruct":N7,"../../lessons/diagramme/en/uebergabe-verdopple.visustruct":F7,"../../lessons/diagramme/en/vb-abstand-anzeigen-loesung.visustruct":J7,"../../lessons/diagramme/en/vb-abstand-halten-loesung.visustruct":R7,"../../lessons/diagramme/en/vb-alarmanlage-loesung.visustruct":G7,"../../lessons/diagramme/en/vb-ampel-loesung.visustruct":H7,"../../lessons/diagramme/en/vb-ausgang-loesung.visustruct":V7,"../../lessons/diagramme/en/vb-begruessung-loesung.visustruct":q7,"../../lessons/diagramme/en/vb-binaer-zaehlen-loesung.visustruct":Q7,"../../lessons/diagramme/en/vb-bis-rot-loesung.visustruct":U7,"../../lessons/diagramme/en/vb-bis-wand-loesung.visustruct":$7,"../../lessons/diagramme/en/vb-bis-ziel-loesung.visustruct":Y7,"../../lessons/diagramme/en/vb-buchstaben-loesung.visustruct":X7,"../../lessons/diagramme/en/vb-drei-lichter-loesung.visustruct":K7,"../../lessons/diagramme/en/vb-dreieck-loesung.visustruct":eI,"../../lessons/diagramme/en/vb-einparken-loesung.visustruct":tI,"../../lessons/diagramme/en/vb-farben-loesung.visustruct":nI,"../../lessons/diagramme/en/vb-farbweiche-loesung.visustruct":iI,"../../lessons/diagramme/en/vb-gas-bis-wand-loesung.visustruct":aI,"../../lessons/diagramme/en/vb-gerade-loesung.visustruct":sI,"../../lessons/diagramme/en/vb-hindernis-loesung.visustruct":rI,"../../lessons/diagramme/en/vb-java-akku-loesung.visustruct":oI,"../../lessons/diagramme/en/vb-java-blau-gruen-loesung.visustruct":lI,"../../lessons/diagramme/en/vb-java-blinken-loesung.visustruct":uI,"../../lessons/diagramme/en/vb-java-countdown-loesung.visustruct":cI,"../../lessons/diagramme/en/vb-java-hoeher-loesung.visustruct":mI,"../../lessons/diagramme/en/vb-java-joystick-loesung.visustruct":dI,"../../lessons/diagramme/en/vb-java-laermampel-loesung.visustruct":hI,"../../lessons/diagramme/en/vb-java-lauflicht-loesung.visustruct":gI,"../../lessons/diagramme/en/vb-java-linienfolger-loesung.visustruct":pI,"../../lessons/diagramme/en/vb-java-nachtlicht-ton-loesung.visustruct":fI,"../../lessons/diagramme/en/vb-java-rand-loesung.visustruct":bI,"../../lessons/diagramme/en/vb-java-rechteck-loesung.visustruct":xI,"../../lessons/diagramme/en/vb-java-textlaenge-loesung.visustruct":vI,"../../lessons/diagramme/en/vb-java-wand-piep-loesung.visustruct":yI,"../../lessons/diagramme/en/vb-java-wasserwaage-loesung.visustruct":wI,"../../lessons/diagramme/en/vb-klatschen-loesung.visustruct":zI,"../../lessons/diagramme/en/vb-knight-rider-loesung.visustruct":II,"../../lessons/diagramme/en/vb-labyrinth-loesung.visustruct":kI,"../../lessons/diagramme/en/vb-linienfolger-stopp-loesung.visustruct":SI,"../../lessons/diagramme/en/vb-linienmuster-loesung.visustruct":TI,"../../lessons/diagramme/en/vb-melodie-loesung.visustruct":_I,"../../lessons/diagramme/en/vb-morsen-loesung.visustruct":OI,"../../lessons/diagramme/en/vb-nachtlicht-loesung.visustruct":AI,"../../lessons/diagramme/en/vb-nachtwaechter-loesung.visustruct":CI,"../../lessons/diagramme/en/vb-ohne-noten-loesung.visustruct":jI,"../../lessons/diagramme/en/vb-ohne-quadratzahl-loesung.visustruct":PI,"../../lessons/diagramme/en/vb-ohne-quadratzahl-unterprogramm-loesung.visustruct":DI,"../../lessons/diagramme/en/vb-ohne-rueckwaerts-loesung.visustruct":BI,"../../lessons/diagramme/en/vb-ohne-strecke-loesung.visustruct":ZI,"../../lessons/diagramme/en/vb-ohne-summe-loesung.visustruct":MI,"../../lessons/diagramme/en/vb-quadrat-loesung.visustruct":LI,"../../lessons/diagramme/en/vb-quadrat-methode-loesung.visustruct":EI,"../../lessons/diagramme/en/vb-quadrat-schleife-loesung.visustruct":WI,"../../lessons/diagramme/en/vb-quadrat-unterprogramm-loesung.visustruct":NI,"../../lessons/diagramme/en/vb-quadrat-verschachtelt-loesung.visustruct":FI,"../../lessons/diagramme/en/vb-rand-loesung.visustruct":JI,"../../lessons/diagramme/en/vb-schraeglage-loesung.visustruct":RI,"../../lessons/diagramme/en/vb-slalom-loesung.visustruct":GI,"../../lessons/diagramme/en/vb-spirale-loesung.visustruct":HI,"../../lessons/diagramme/en/vb-start-a-loesung.visustruct":VI,"../../lessons/diagramme/en/vb-tonleiter-loesung.visustruct":qI,"../../lessons/diagramme/en/vb-treppe-loesung.visustruct":QI,"../../lessons/diagramme/en/vb-tunnel-loesung.visustruct":UI,"../../lessons/diagramme/en/vb-variable-seite-loesung.visustruct":$I,"../../lessons/diagramme/en/vb-vier-quadrate-loesung.visustruct":YI,"../../lessons/diagramme/en/vb-wald-loesung.visustruct":XI,"../../lessons/diagramme/en/vb-wand-vorn-loesung.visustruct":KI,"../../lessons/diagramme/en/vb-zwei-sekunden-loesung.visustruct":ek,"../../lessons/diagramme/en/zk-initialen-loesung.visustruct":tk,"../../lessons/diagramme/en/zk-mehr.visustruct":nk,"../../lessons/diagramme/en/zk-rueckwaerts-loesung.visustruct":ik,"../../lessons/diagramme/en/zk-split.visustruct":ak,"../../lessons/diagramme/en/zk-woerter-loesung.visustruct":sk,"../../lessons/diagramme/en/zk-zaehlen.visustruct":rk,"../../lessons/diagramme/en/zk-zeichen.visustruct":ok,"../../lessons/diagramme/kino-einmaleins-loesung.visustruct":lk,"../../lessons/diagramme/kino-frei-loesung.visustruct":uk,"../../lessons/diagramme/kino-frei-start.visustruct":ck,"../../lessons/diagramme/kino-karte-loesung.visustruct":mk,"../../lessons/diagramme/kino-karte-start.visustruct":dk,"../../lessons/diagramme/kino-saalplan.visustruct":hk,"../../lessons/diagramme/kino-verkaufen.visustruct":gk,"../../lessons/diagramme/l04-java-fehler-loesung.visustruct":pk,"../../lessons/diagramme/l04-java-fehler-start.visustruct":fk,"../../lessons/diagramme/l04-java-steckbrief-loesung.visustruct":bk,"../../lessons/diagramme/l04-rechnen.visustruct":xk,"../../lessons/diagramme/l04-reihenfolge-loesung.visustruct":vk,"../../lessons/diagramme/l04-reihenfolge-start.visustruct":yk,"../../lessons/diagramme/l04-tauschen-loesung.visustruct":wk,"../../lessons/diagramme/l04-tauschen-start.visustruct":zk,"../../lessons/diagramme/l04-tauschen.visustruct":Ik,"../../lessons/diagramme/l05-datentypen.visustruct":kk,"../../lessons/diagramme/l05-division.visustruct":Sk,"../../lessons/diagramme/l05-einkauf-loesung.visustruct":Tk,"../../lessons/diagramme/l05-java-fehler-loesung.visustruct":_k,"../../lessons/diagramme/l05-java-fehler-start.visustruct":Ok,"../../lessons/diagramme/l05-java-kino-loesung.visustruct":Ak,"../../lessons/diagramme/l05-rechteck-loesung.visustruct":Ck,"../../lessons/diagramme/l05-sekunden-loesung.visustruct":jk,"../../lessons/diagramme/l05-sekunden-start.visustruct":Pk,"../../lessons/diagramme/l05-sequenz.visustruct":Dk,"../../lessons/diagramme/l06-begruessung-loesung.visustruct":Bk,"../../lessons/diagramme/l06-eva.visustruct":Zk,"../../lessons/diagramme/l06-java-fehler-loesung.visustruct":Mk,"../../lessons/diagramme/l06-java-fehler-start.visustruct":Lk,"../../lessons/diagramme/l06-java-tage-loesung.visustruct":Ek,"../../lessons/diagramme/l06-mittelwert-loesung.visustruct":Wk,"../../lessons/diagramme/l06-rechner-loesung.visustruct":Nk,"../../lessons/diagramme/l07-alter-pruefen.visustruct":Fk,"../../lessons/diagramme/l07-betrag-loesung.visustruct":Jk,"../../lessons/diagramme/l07-gerade-loesung.visustruct":Rk,"../../lessons/diagramme/l07-java-fehler-loesung.visustruct":Gk,"../../lessons/diagramme/l07-java-fehler-start.visustruct":Hk,"../../lessons/diagramme/l07-java-pizza-loesung.visustruct":Vk,"../../lessons/diagramme/l07-java-pizza-start.visustruct":qk,"../../lessons/diagramme/l07-maximum-loesung.visustruct":Qk,"../../lessons/diagramme/l07-rabatt.visustruct":Uk,"../../lessons/diagramme/l08-gueltig-loesung.visustruct":$k,"../../lessons/diagramme/l08-java-bestanden-loesung.visustruct":Yk,"../../lessons/diagramme/l08-java-fehler-loesung.visustruct":Xk,"../../lessons/diagramme/l08-java-fehler-start.visustruct":Kk,"../../lessons/diagramme/l08-jugendticket.visustruct":e8,"../../lessons/diagramme/l08-note.visustruct":t8,"../../lessons/diagramme/l08-schaltjahr-loesung.visustruct":n8,"../../lessons/diagramme/l08-wochenende-loesung.visustruct":i8,"../../lessons/diagramme/l09-ampel.visustruct":a8,"../../lessons/diagramme/l09-automat.visustruct":s8,"../../lessons/diagramme/l09-java-fehler-loesung.visustruct":r8,"../../lessons/diagramme/l09-java-fehler-start.visustruct":o8,"../../lessons/diagramme/l09-java-schule-loesung.visustruct":l8,"../../lessons/diagramme/l09-note-loesung.visustruct":u8,"../../lessons/diagramme/l09-rechner-loesung.visustruct":c8,"../../lessons/diagramme/l09-verschachtelt.visustruct":m8,"../../lessons/diagramme/l1-grundbausteine.visustruct":d8,"../../lessons/diagramme/l1-sequenz.visustruct":h8,"../../lessons/diagramme/l1-tee.visustruct":g8,"../../lessons/diagramme/l1-verzweigung.visustruct":p8,"../../lessons/diagramme/l1-wiederholung.visustruct":f8,"../../lessons/diagramme/l10-bis-n-loesung.visustruct":b8,"../../lessons/diagramme/l10-countdown.visustruct":x8,"../../lessons/diagramme/l10-endlos.visustruct":v8,"../../lessons/diagramme/l10-fakultaet.visustruct":y8,"../../lessons/diagramme/l10-java-fehler-loesung.visustruct":w8,"../../lessons/diagramme/l10-java-fehler-start.visustruct":z8,"../../lessons/diagramme/l10-java-wuerfel-loesung.visustruct":I8,"../../lessons/diagramme/l10-verdoppeln-loesung.visustruct":k8,"../../lessons/diagramme/l11-eingabe-pruefen.visustruct":S8,"../../lessons/diagramme/l11-einmal.visustruct":T8,"../../lessons/diagramme/l11-java-fehler-loesung.visustruct":_8,"../../lessons/diagramme/l11-java-fehler-start.visustruct":O8,"../../lessons/diagramme/l11-java-gerade-loesung.visustruct":A8,"../../lessons/diagramme/l11-note-loesung.visustruct":C8,"../../lessons/diagramme/l11-summe-loesung.visustruct":j8,"../../lessons/diagramme/l12-countdown-loesung.visustruct":P8,"../../lessons/diagramme/l12-einmaleins-loesung.visustruct":D8,"../../lessons/diagramme/l12-eins-bis-fuenf.visustruct":B8,"../../lessons/diagramme/l12-java-fehler-loesung.visustruct":Z8,"../../lessons/diagramme/l12-java-fehler-start.visustruct":M8,"../../lessons/diagramme/l12-java-verdoppeln-loesung.visustruct":L8,"../../lessons/diagramme/l12-summe.visustruct":E8,"../../lessons/diagramme/l13-dreieck.visustruct":W8,"../../lessons/diagramme/l13-gerade-eingaben-loesung.visustruct":N8,"../../lessons/diagramme/l13-gerade-zaehlen.visustruct":F8,"../../lessons/diagramme/l13-java-fehler-loesung.visustruct":J8,"../../lessons/diagramme/l13-java-fehler-start.visustruct":R8,"../../lessons/diagramme/l13-java-quadrate-loesung.visustruct":G8,"../../lessons/diagramme/l13-rechteck-loesung.visustruct":H8,"../../lessons/diagramme/l14-array-durchlaufen.visustruct":V8,"../../lessons/diagramme/l14-erster-letzter-loesung.visustruct":q8,"../../lessons/diagramme/l14-java-fehler-loesung.visustruct":Q8,"../../lessons/diagramme/l14-java-fehler-start.visustruct":U8,"../../lessons/diagramme/l14-java-treppe-loesung.visustruct":$8,"../../lessons/diagramme/l14-namen-eingeben.visustruct":Y8,"../../lessons/diagramme/l14-rueckwaerts-loesung.visustruct":X8,"../../lessons/diagramme/l14-summe-max-loesung.visustruct":K8,"../../lessons/diagramme/l14-summe-maximum.visustruct":eS,"../../lessons/diagramme/l15-bis-null-loesung.visustruct":tS,"../../lessons/diagramme/l15-endlos-aussprung.visustruct":nS,"../../lessons/diagramme/l15-flaeche-loesung.visustruct":iS,"../../lessons/diagramme/l15-flaeche-unterprogramm-loesung.visustruct":aS,"../../lessons/diagramme/l15-hauptprogramm.visustruct":sS,"../../lessons/diagramme/l15-java-fehler-loesung.visustruct":rS,"../../lessons/diagramme/l15-java-fehler-start.visustruct":oS,"../../lessons/diagramme/l15-java-noten-loesung.visustruct":lS,"../../lessons/diagramme/l15-quadrat-haupt.visustruct":uS,"../../lessons/diagramme/l15-quadrat.visustruct":cS,"../../lessons/diagramme/l15-titel-loesung.visustruct":mS,"../../lessons/diagramme/l15-unterprogramm.visustruct":dS,"../../lessons/diagramme/l15-zeige-summe-haupt.visustruct":hS,"../../lessons/diagramme/l15-zeige-summe.visustruct":gS,"../../lessons/diagramme/l16-countdown-loesung.visustruct":pS,"../../lessons/diagramme/l16-countdown-start.visustruct":fS,"../../lessons/diagramme/l16-java-fehler-loesung.visustruct":bS,"../../lessons/diagramme/l16-java-fehler-start.visustruct":xS,"../../lessons/diagramme/l16-java-punkte-loesung.visustruct":vS,"../../lessons/diagramme/l16-schreibtisch.visustruct":yS,"../../lessons/diagramme/l16-summe-loesung.visustruct":wS,"../../lessons/diagramme/l16-summe-start.visustruct":zS,"../../lessons/diagramme/l17-beispiel.visustruct":IS,"../../lessons/diagramme/l17-fakultaet-loesung.visustruct":kS,"../../lessons/diagramme/l17-java-brief-loesung.visustruct":SS,"../../lessons/diagramme/l17-java-brief-start.visustruct":TS,"../../lessons/diagramme/l17-java-fehler-loesung.visustruct":_S,"../../lessons/diagramme/l17-java-fehler-start.visustruct":OS,"../../lessons/diagramme/l17-java-passwort-loesung.visustruct":AS,"../../lessons/diagramme/l17-ticket-loesung.visustruct":CS,"../../lessons/diagramme/l18-beispiel.visustruct":jS,"../../lessons/diagramme/l18-java-fehler-loesung.visustruct":PS,"../../lessons/diagramme/l18-java-fehler-start.visustruct":DS,"../../lessons/diagramme/l18-java-kasse-loesung.visustruct":BS,"../../lessons/diagramme/l18-js-loesung.visustruct":ZS,"../../lessons/diagramme/l18-python-loesung.visustruct":MS,"../../lessons/diagramme/l19-java-fehler-loesung.visustruct":LS,"../../lessons/diagramme/l19-java-fehler-start.visustruct":ES,"../../lessons/diagramme/l19-java-zaehlen-loesung.visustruct":WS,"../../lessons/diagramme/l2-ausgabe.visustruct":NS,"../../lessons/diagramme/l2-hallo-loesung.visustruct":FS,"../../lessons/diagramme/l2-zwei-zeilen-loesung.visustruct":JS,"../../lessons/diagramme/l20-countdown-loesung.visustruct":RS,"../../lessons/diagramme/l23-java-ergaenzen-loesung.visustruct":GS,"../../lessons/diagramme/l23-java-ergaenzen-start.visustruct":HS,"../../lessons/diagramme/l23-java-nummern-loesung.visustruct":VS,"../../lessons/diagramme/l23-java-nummern-start.visustruct":qS,"../../lessons/diagramme/l24-java-fuchs-loesung.visustruct":QS,"../../lessons/diagramme/l24-java-fuchs-start.visustruct":US,"../../lessons/diagramme/l24-java-laengster-loesung.visustruct":$S,"../../lessons/diagramme/l24-java-laengster-start.visustruct":YS,"../../lessons/diagramme/l25-java-beste-loesung.visustruct":XS,"../../lessons/diagramme/l25-java-beste-start.visustruct":KS,"../../lessons/diagramme/l25-java-schnitt-loesung.visustruct":eT,"../../lessons/diagramme/l25-java-schnitt-start.visustruct":tT,"../../lessons/diagramme/l26-java-namen-loesung.visustruct":nT,"../../lessons/diagramme/l26-java-namen-start.visustruct":iT,"../../lessons/diagramme/l26-java-schreiben-loesung.visustruct":aT,"../../lessons/diagramme/l26-java-schreiben-start.visustruct":sT,"../../lessons/diagramme/l27-java-json-loesung.visustruct":rT,"../../lessons/diagramme/l27-java-json-start.visustruct":oT,"../../lessons/diagramme/l27-java-saetze-loesung.visustruct":lT,"../../lessons/diagramme/l27-java-saetze-start.visustruct":uT,"../../lessons/diagramme/pt/aufgabe-alter-haupt-loesung.visustruct":cT,"../../lessons/diagramme/pt/aufgabe-alter-unterprogramm-loesung.visustruct":mT,"../../lessons/diagramme/pt/aufgabe-ballwurf-loesung.visustruct":dT,"../../lessons/diagramme/pt/aufgabe-ballwurf-start.visustruct":hT,"../../lessons/diagramme/pt/aufgabe-bestenliste-loesung.visustruct":gT,"../../lessons/diagramme/pt/aufgabe-binaer-loesung.visustruct":pT,"../../lessons/diagramme/pt/aufgabe-caesar-array-loesung.visustruct":fT,"../../lessons/diagramme/pt/aufgabe-caesar-array-start.visustruct":bT,"../../lessons/diagramme/pt/aufgabe-caesar-ascii-loesung.visustruct":xT,"../../lessons/diagramme/pt/aufgabe-caesar-entschluesseln-loesung.visustruct":vT,"../../lessons/diagramme/pt/aufgabe-collatz-loesung.visustruct":yT,"../../lessons/diagramme/pt/aufgabe-durchschnitt-loesung.visustruct":wT,"../../lessons/diagramme/pt/aufgabe-fibonacci-loesung.visustruct":zT,"../../lessons/diagramme/pt/aufgabe-gerade-loesung.visustruct":IT,"../../lessons/diagramme/pt/aufgabe-mehrwertsteuer-loesung.visustruct":kT,"../../lessons/diagramme/pt/aufgabe-pin-java-loesung.visustruct":ST,"../../lessons/diagramme/pt/aufgabe-pin-loesung.visustruct":TT,"../../lessons/diagramme/pt/aufgabe-rechner-loesung.visustruct":_T,"../../lessons/diagramme/pt/aufgabe-schiffe-loesung.visustruct":OT,"../../lessons/diagramme/pt/aufgabe-schiffe-start.visustruct":AT,"../../lessons/diagramme/pt/aufgabe-speisekarte-loesung.visustruct":CT,"../../lessons/diagramme/pt/aufgabe-summe-loesung.visustruct":jT,"../../lessons/diagramme/pt/aufgabe-tafeldienst-loesung.visustruct":PT,"../../lessons/diagramme/pt/aufgabe-verdoppeln-loesung.visustruct":DT,"../../lessons/diagramme/pt/aufgabe-verleih-java-loesung.visustruct":BT,"../../lessons/diagramme/pt/aufgabe-verleih-loesung.visustruct":ZT,"../../lessons/diagramme/pt/aufgabe-vokabeln-loesung.visustruct":MT,"../../lessons/diagramme/pt/aufgabe-vokabeln-start.visustruct":LT,"../../lessons/diagramme/pt/aufgabe-volljaehrig-loesung.visustruct":ET,"../../lessons/diagramme/pt/dt-buffered.visustruct":WT,"../../lessons/diagramme/pt/dt-csv.visustruct":NT,"../../lessons/diagramme/pt/dt-json.visustruct":FT,"../../lessons/diagramme/pt/dt-lesen.visustruct":JT,"../../lessons/diagramme/pt/kino-einmaleins-loesung.visustruct":RT,"../../lessons/diagramme/pt/kino-frei-loesung.visustruct":GT,"../../lessons/diagramme/pt/kino-frei-start.visustruct":HT,"../../lessons/diagramme/pt/kino-karte-loesung.visustruct":VT,"../../lessons/diagramme/pt/kino-karte-start.visustruct":qT,"../../lessons/diagramme/pt/kino-saalplan.visustruct":QT,"../../lessons/diagramme/pt/kino-verkaufen.visustruct":UT,"../../lessons/diagramme/pt/l04-java-fehler-loesung.visustruct":$T,"../../lessons/diagramme/pt/l04-java-fehler-start.visustruct":YT,"../../lessons/diagramme/pt/l04-java-steckbrief-loesung.visustruct":XT,"../../lessons/diagramme/pt/l04-rechnen.visustruct":KT,"../../lessons/diagramme/pt/l04-reihenfolge-loesung.visustruct":e_,"../../lessons/diagramme/pt/l04-reihenfolge-start.visustruct":t_,"../../lessons/diagramme/pt/l04-tauschen-loesung.visustruct":n_,"../../lessons/diagramme/pt/l04-tauschen-start.visustruct":i_,"../../lessons/diagramme/pt/l04-tauschen.visustruct":a_,"../../lessons/diagramme/pt/l05-datentypen.visustruct":s_,"../../lessons/diagramme/pt/l05-division.visustruct":r_,"../../lessons/diagramme/pt/l05-einkauf-loesung.visustruct":o_,"../../lessons/diagramme/pt/l05-java-fehler-loesung.visustruct":l_,"../../lessons/diagramme/pt/l05-java-fehler-start.visustruct":u_,"../../lessons/diagramme/pt/l05-java-kino-loesung.visustruct":c_,"../../lessons/diagramme/pt/l05-rechteck-loesung.visustruct":m_,"../../lessons/diagramme/pt/l05-sekunden-loesung.visustruct":d_,"../../lessons/diagramme/pt/l05-sekunden-start.visustruct":h_,"../../lessons/diagramme/pt/l05-sequenz.visustruct":g_,"../../lessons/diagramme/pt/l06-begruessung-loesung.visustruct":p_,"../../lessons/diagramme/pt/l06-eva.visustruct":f_,"../../lessons/diagramme/pt/l06-java-fehler-loesung.visustruct":b_,"../../lessons/diagramme/pt/l06-java-fehler-start.visustruct":x_,"../../lessons/diagramme/pt/l06-java-tage-loesung.visustruct":v_,"../../lessons/diagramme/pt/l06-mittelwert-loesung.visustruct":y_,"../../lessons/diagramme/pt/l06-rechner-loesung.visustruct":w_,"../../lessons/diagramme/pt/l07-alter-pruefen.visustruct":z_,"../../lessons/diagramme/pt/l07-betrag-loesung.visustruct":I_,"../../lessons/diagramme/pt/l07-gerade-loesung.visustruct":k_,"../../lessons/diagramme/pt/l07-java-fehler-loesung.visustruct":S_,"../../lessons/diagramme/pt/l07-java-fehler-start.visustruct":T_,"../../lessons/diagramme/pt/l07-java-pizza-loesung.visustruct":__,"../../lessons/diagramme/pt/l07-java-pizza-start.visustruct":O_,"../../lessons/diagramme/pt/l07-maximum-loesung.visustruct":A_,"../../lessons/diagramme/pt/l07-rabatt.visustruct":C_,"../../lessons/diagramme/pt/l08-gueltig-loesung.visustruct":j_,"../../lessons/diagramme/pt/l08-java-bestanden-loesung.visustruct":P_,"../../lessons/diagramme/pt/l08-java-fehler-loesung.visustruct":D_,"../../lessons/diagramme/pt/l08-java-fehler-start.visustruct":B_,"../../lessons/diagramme/pt/l08-jugendticket.visustruct":Z_,"../../lessons/diagramme/pt/l08-note.visustruct":M_,"../../lessons/diagramme/pt/l08-schaltjahr-loesung.visustruct":L_,"../../lessons/diagramme/pt/l08-wochenende-loesung.visustruct":E_,"../../lessons/diagramme/pt/l09-ampel.visustruct":W_,"../../lessons/diagramme/pt/l09-automat.visustruct":N_,"../../lessons/diagramme/pt/l09-java-fehler-loesung.visustruct":F_,"../../lessons/diagramme/pt/l09-java-fehler-start.visustruct":J_,"../../lessons/diagramme/pt/l09-java-schule-loesung.visustruct":R_,"../../lessons/diagramme/pt/l09-note-loesung.visustruct":G_,"../../lessons/diagramme/pt/l09-rechner-loesung.visustruct":H_,"../../lessons/diagramme/pt/l09-verschachtelt.visustruct":V_,"../../lessons/diagramme/pt/l1-grundbausteine.visustruct":q_,"../../lessons/diagramme/pt/l1-sequenz.visustruct":Q_,"../../lessons/diagramme/pt/l1-tee.visustruct":U_,"../../lessons/diagramme/pt/l1-verzweigung.visustruct":$_,"../../lessons/diagramme/pt/l1-wiederholung.visustruct":Y_,"../../lessons/diagramme/pt/l10-bis-n-loesung.visustruct":X_,"../../lessons/diagramme/pt/l10-countdown.visustruct":K_,"../../lessons/diagramme/pt/l10-endlos.visustruct":eO,"../../lessons/diagramme/pt/l10-fakultaet.visustruct":tO,"../../lessons/diagramme/pt/l10-java-fehler-loesung.visustruct":nO,"../../lessons/diagramme/pt/l10-java-fehler-start.visustruct":iO,"../../lessons/diagramme/pt/l10-java-wuerfel-loesung.visustruct":aO,"../../lessons/diagramme/pt/l10-verdoppeln-loesung.visustruct":sO,"../../lessons/diagramme/pt/l11-eingabe-pruefen.visustruct":rO,"../../lessons/diagramme/pt/l11-einmal.visustruct":oO,"../../lessons/diagramme/pt/l11-java-fehler-loesung.visustruct":lO,"../../lessons/diagramme/pt/l11-java-fehler-start.visustruct":uO,"../../lessons/diagramme/pt/l11-java-gerade-loesung.visustruct":cO,"../../lessons/diagramme/pt/l11-note-loesung.visustruct":mO,"../../lessons/diagramme/pt/l11-summe-loesung.visustruct":dO,"../../lessons/diagramme/pt/l12-countdown-loesung.visustruct":hO,"../../lessons/diagramme/pt/l12-einmaleins-loesung.visustruct":gO,"../../lessons/diagramme/pt/l12-eins-bis-fuenf.visustruct":pO,"../../lessons/diagramme/pt/l12-java-fehler-loesung.visustruct":fO,"../../lessons/diagramme/pt/l12-java-fehler-start.visustruct":bO,"../../lessons/diagramme/pt/l12-java-verdoppeln-loesung.visustruct":xO,"../../lessons/diagramme/pt/l12-summe.visustruct":vO,"../../lessons/diagramme/pt/l13-dreieck.visustruct":yO,"../../lessons/diagramme/pt/l13-gerade-eingaben-loesung.visustruct":wO,"../../lessons/diagramme/pt/l13-gerade-zaehlen.visustruct":zO,"../../lessons/diagramme/pt/l13-java-fehler-loesung.visustruct":IO,"../../lessons/diagramme/pt/l13-java-fehler-start.visustruct":kO,"../../lessons/diagramme/pt/l13-java-quadrate-loesung.visustruct":SO,"../../lessons/diagramme/pt/l13-rechteck-loesung.visustruct":TO,"../../lessons/diagramme/pt/l14-array-durchlaufen.visustruct":_O,"../../lessons/diagramme/pt/l14-erster-letzter-loesung.visustruct":OO,"../../lessons/diagramme/pt/l14-java-fehler-loesung.visustruct":AO,"../../lessons/diagramme/pt/l14-java-fehler-start.visustruct":CO,"../../lessons/diagramme/pt/l14-java-treppe-loesung.visustruct":jO,"../../lessons/diagramme/pt/l14-namen-eingeben.visustruct":PO,"../../lessons/diagramme/pt/l14-rueckwaerts-loesung.visustruct":DO,"../../lessons/diagramme/pt/l14-summe-max-loesung.visustruct":BO,"../../lessons/diagramme/pt/l14-summe-maximum.visustruct":ZO,"../../lessons/diagramme/pt/l15-bis-null-loesung.visustruct":MO,"../../lessons/diagramme/pt/l15-endlos-aussprung.visustruct":LO,"../../lessons/diagramme/pt/l15-flaeche-loesung.visustruct":EO,"../../lessons/diagramme/pt/l15-hauptprogramm.visustruct":WO,"../../lessons/diagramme/pt/l15-java-fehler-loesung.visustruct":NO,"../../lessons/diagramme/pt/l15-java-fehler-start.visustruct":FO,"../../lessons/diagramme/pt/l15-java-noten-loesung.visustruct":JO,"../../lessons/diagramme/pt/l15-quadrat-haupt.visustruct":RO,"../../lessons/diagramme/pt/l15-quadrat.visustruct":GO,"../../lessons/diagramme/pt/l15-titel-loesung.visustruct":HO,"../../lessons/diagramme/pt/l15-unterprogramm.visustruct":VO,"../../lessons/diagramme/pt/l15-zeige-summe-haupt.visustruct":qO,"../../lessons/diagramme/pt/l15-zeige-summe.visustruct":QO,"../../lessons/diagramme/pt/l16-countdown-loesung.visustruct":UO,"../../lessons/diagramme/pt/l16-countdown-start.visustruct":$O,"../../lessons/diagramme/pt/l16-java-fehler-loesung.visustruct":YO,"../../lessons/diagramme/pt/l16-java-fehler-start.visustruct":XO,"../../lessons/diagramme/pt/l16-java-punkte-loesung.visustruct":KO,"../../lessons/diagramme/pt/l16-schreibtisch.visustruct":eA,"../../lessons/diagramme/pt/l16-summe-loesung.visustruct":tA,"../../lessons/diagramme/pt/l16-summe-start.visustruct":nA,"../../lessons/diagramme/pt/l17-beispiel.visustruct":iA,"../../lessons/diagramme/pt/l17-fakultaet-loesung.visustruct":aA,"../../lessons/diagramme/pt/l17-java-brief-loesung.visustruct":sA,"../../lessons/diagramme/pt/l17-java-brief-start.visustruct":rA,"../../lessons/diagramme/pt/l17-java-fehler-loesung.visustruct":oA,"../../lessons/diagramme/pt/l17-java-fehler-start.visustruct":lA,"../../lessons/diagramme/pt/l17-java-passwort-loesung.visustruct":uA,"../../lessons/diagramme/pt/l17-ticket-loesung.visustruct":cA,"../../lessons/diagramme/pt/l18-beispiel.visustruct":mA,"../../lessons/diagramme/pt/l18-java-fehler-loesung.visustruct":dA,"../../lessons/diagramme/pt/l18-java-fehler-start.visustruct":hA,"../../lessons/diagramme/pt/l18-java-kasse-loesung.visustruct":gA,"../../lessons/diagramme/pt/l18-js-loesung.visustruct":pA,"../../lessons/diagramme/pt/l18-python-loesung.visustruct":fA,"../../lessons/diagramme/pt/l19-java-fehler-loesung.visustruct":bA,"../../lessons/diagramme/pt/l19-java-fehler-start.visustruct":xA,"../../lessons/diagramme/pt/l19-java-zaehlen-loesung.visustruct":vA,"../../lessons/diagramme/pt/l2-ausgabe.visustruct":yA,"../../lessons/diagramme/pt/l2-hallo-loesung.visustruct":wA,"../../lessons/diagramme/pt/l2-zwei-zeilen-loesung.visustruct":zA,"../../lessons/diagramme/pt/l23-java-ergaenzen-loesung.visustruct":IA,"../../lessons/diagramme/pt/l23-java-ergaenzen-start.visustruct":kA,"../../lessons/diagramme/pt/l23-java-nummern-loesung.visustruct":SA,"../../lessons/diagramme/pt/l23-java-nummern-start.visustruct":TA,"../../lessons/diagramme/pt/l24-java-fuchs-loesung.visustruct":_A,"../../lessons/diagramme/pt/l24-java-fuchs-start.visustruct":OA,"../../lessons/diagramme/pt/l24-java-laengster-loesung.visustruct":AA,"../../lessons/diagramme/pt/l24-java-laengster-start.visustruct":CA,"../../lessons/diagramme/pt/l25-java-beste-loesung.visustruct":jA,"../../lessons/diagramme/pt/l25-java-beste-start.visustruct":PA,"../../lessons/diagramme/pt/l25-java-schnitt-loesung.visustruct":DA,"../../lessons/diagramme/pt/l25-java-schnitt-start.visustruct":BA,"../../lessons/diagramme/pt/l26-java-namen-loesung.visustruct":ZA,"../../lessons/diagramme/pt/l26-java-namen-start.visustruct":MA,"../../lessons/diagramme/pt/l26-java-schreiben-loesung.visustruct":LA,"../../lessons/diagramme/pt/l26-java-schreiben-start.visustruct":EA,"../../lessons/diagramme/pt/l27-java-json-loesung.visustruct":WA,"../../lessons/diagramme/pt/l27-java-json-start.visustruct":NA,"../../lessons/diagramme/pt/l27-java-saetze-loesung.visustruct":FA,"../../lessons/diagramme/pt/l27-java-saetze-start.visustruct":JA,"../../lessons/diagramme/pt/sim-kino-loesung.visustruct":RA,"../../lessons/diagramme/pt/sim-kino-start.visustruct":GA,"../../lessons/diagramme/pt/sim-tausch-loesung.visustruct":HA,"../../lessons/diagramme/pt/sim-tausch-start.visustruct":VA,"../../lessons/diagramme/pt/sim-tausch.visustruct":qA,"../../lessons/diagramme/pt/ss-absteigend-loesung.visustruct":QA,"../../lessons/diagramme/pt/ss-absteigend-start.visustruct":UA,"../../lessons/diagramme/pt/ss-binaere-suche.visustruct":$A,"../../lessons/diagramme/pt/ss-bubblesort.visustruct":YA,"../../lessons/diagramme/pt/ss-karte-suchen-loesung.visustruct":XA,"../../lessons/diagramme/pt/ss-lineare-suche.visustruct":KA,"../../lessons/diagramme/pt/uebergabe-bonus-loesung.visustruct":eC,"../../lessons/diagramme/pt/uebergabe-bonus-start.visustruct":tC,"../../lessons/diagramme/pt/uebergabe-bonus-unterprogramm-loesung.visustruct":nC,"../../lessons/diagramme/pt/uebergabe-haupt.visustruct":iC,"../../lessons/diagramme/pt/uebergabe-leeren.visustruct":aC,"../../lessons/diagramme/pt/uebergabe-verdopple.visustruct":sC,"../../lessons/diagramme/pt/zk-initialen-loesung.visustruct":rC,"../../lessons/diagramme/pt/zk-mehr.visustruct":oC,"../../lessons/diagramme/pt/zk-rueckwaerts-loesung.visustruct":lC,"../../lessons/diagramme/pt/zk-split.visustruct":uC,"../../lessons/diagramme/pt/zk-woerter-loesung.visustruct":cC,"../../lessons/diagramme/pt/zk-zaehlen.visustruct":mC,"../../lessons/diagramme/pt/zk-zeichen.visustruct":dC,"../../lessons/diagramme/sim-kino-loesung.visustruct":hC,"../../lessons/diagramme/sim-kino-start.visustruct":gC,"../../lessons/diagramme/sim-tausch-loesung.visustruct":pC,"../../lessons/diagramme/sim-tausch-start.visustruct":fC,"../../lessons/diagramme/sim-tausch.visustruct":bC,"../../lessons/diagramme/ss-absteigend-loesung.visustruct":xC,"../../lessons/diagramme/ss-absteigend-start.visustruct":vC,"../../lessons/diagramme/ss-binaere-suche.visustruct":yC,"../../lessons/diagramme/ss-bubblesort.visustruct":wC,"../../lessons/diagramme/ss-karte-suchen-loesung.visustruct":zC,"../../lessons/diagramme/ss-lineare-suche.visustruct":IC,"../../lessons/diagramme/uebergabe-bonus-loesung.visustruct":kC,"../../lessons/diagramme/uebergabe-bonus-start.visustruct":SC,"../../lessons/diagramme/uebergabe-bonus-unterprogramm-loesung.visustruct":TC,"../../lessons/diagramme/uebergabe-haupt.visustruct":_C,"../../lessons/diagramme/uebergabe-leeren.visustruct":OC,"../../lessons/diagramme/uebergabe-verdopple.visustruct":AC,"../../lessons/diagramme/vb-abstand-anzeigen-loesung.visustruct":CC,"../../lessons/diagramme/vb-abstand-halten-loesung.visustruct":jC,"../../lessons/diagramme/vb-alarmanlage-loesung.visustruct":PC,"../../lessons/diagramme/vb-ampel-loesung.visustruct":DC,"../../lessons/diagramme/vb-ausgang-loesung.visustruct":BC,"../../lessons/diagramme/vb-begruessung-loesung.visustruct":ZC,"../../lessons/diagramme/vb-binaer-zaehlen-loesung.visustruct":MC,"../../lessons/diagramme/vb-bis-rot-loesung.visustruct":LC,"../../lessons/diagramme/vb-bis-wand-loesung.visustruct":EC,"../../lessons/diagramme/vb-bis-ziel-loesung.visustruct":WC,"../../lessons/diagramme/vb-buchstaben-loesung.visustruct":NC,"../../lessons/diagramme/vb-drei-lichter-loesung.visustruct":FC,"../../lessons/diagramme/vb-dreieck-loesung.visustruct":JC,"../../lessons/diagramme/vb-einparken-loesung.visustruct":RC,"../../lessons/diagramme/vb-farben-loesung.visustruct":GC,"../../lessons/diagramme/vb-farbweiche-loesung.visustruct":HC,"../../lessons/diagramme/vb-gas-bis-wand-loesung.visustruct":VC,"../../lessons/diagramme/vb-gerade-loesung.visustruct":qC,"../../lessons/diagramme/vb-hindernis-loesung.visustruct":QC,"../../lessons/diagramme/vb-java-akku-loesung.visustruct":UC,"../../lessons/diagramme/vb-java-blau-gruen-loesung.visustruct":$C,"../../lessons/diagramme/vb-java-blinken-loesung.visustruct":YC,"../../lessons/diagramme/vb-java-countdown-loesung.visustruct":XC,"../../lessons/diagramme/vb-java-hoeher-loesung.visustruct":KC,"../../lessons/diagramme/vb-java-joystick-loesung.visustruct":ej,"../../lessons/diagramme/vb-java-laermampel-loesung.visustruct":tj,"../../lessons/diagramme/vb-java-lauflicht-loesung.visustruct":nj,"../../lessons/diagramme/vb-java-linienfolger-loesung.visustruct":ij,"../../lessons/diagramme/vb-java-nachtlicht-ton-loesung.visustruct":aj,"../../lessons/diagramme/vb-java-rand-loesung.visustruct":sj,"../../lessons/diagramme/vb-java-rechteck-loesung.visustruct":rj,"../../lessons/diagramme/vb-java-textlaenge-loesung.visustruct":oj,"../../lessons/diagramme/vb-java-wand-piep-loesung.visustruct":lj,"../../lessons/diagramme/vb-java-wasserwaage-loesung.visustruct":uj,"../../lessons/diagramme/vb-klatschen-loesung.visustruct":cj,"../../lessons/diagramme/vb-knight-rider-loesung.visustruct":mj,"../../lessons/diagramme/vb-labyrinth-loesung.visustruct":dj,"../../lessons/diagramme/vb-linienfolger-stopp-loesung.visustruct":hj,"../../lessons/diagramme/vb-linienmuster-loesung.visustruct":gj,"../../lessons/diagramme/vb-melodie-loesung.visustruct":pj,"../../lessons/diagramme/vb-morsen-loesung.visustruct":fj,"../../lessons/diagramme/vb-nachtlicht-loesung.visustruct":bj,"../../lessons/diagramme/vb-nachtwaechter-loesung.visustruct":xj,"../../lessons/diagramme/vb-ohne-noten-loesung.visustruct":vj,"../../lessons/diagramme/vb-ohne-quadratzahl-loesung.visustruct":yj,"../../lessons/diagramme/vb-ohne-quadratzahl-unterprogramm-loesung.visustruct":wj,"../../lessons/diagramme/vb-ohne-rueckwaerts-loesung.visustruct":zj,"../../lessons/diagramme/vb-ohne-strecke-loesung.visustruct":Ij,"../../lessons/diagramme/vb-ohne-summe-loesung.visustruct":kj,"../../lessons/diagramme/vb-quadrat-loesung.visustruct":Sj,"../../lessons/diagramme/vb-quadrat-methode-loesung.visustruct":Tj,"../../lessons/diagramme/vb-quadrat-schleife-loesung.visustruct":_j,"../../lessons/diagramme/vb-quadrat-unterprogramm-loesung.visustruct":Oj,"../../lessons/diagramme/vb-quadrat-verschachtelt-loesung.visustruct":Aj,"../../lessons/diagramme/vb-rand-loesung.visustruct":Cj,"../../lessons/diagramme/vb-schraeglage-loesung.visustruct":jj,"../../lessons/diagramme/vb-slalom-loesung.visustruct":Pj,"../../lessons/diagramme/vb-spirale-loesung.visustruct":Dj,"../../lessons/diagramme/vb-start-a-loesung.visustruct":Bj,"../../lessons/diagramme/vb-tonleiter-loesung.visustruct":Zj,"../../lessons/diagramme/vb-treppe-loesung.visustruct":Mj,"../../lessons/diagramme/vb-tunnel-loesung.visustruct":Lj,"../../lessons/diagramme/vb-variable-seite-loesung.visustruct":Ej,"../../lessons/diagramme/vb-vier-quadrate-loesung.visustruct":Wj,"../../lessons/diagramme/vb-wald-loesung.visustruct":Nj,"../../lessons/diagramme/vb-wand-vorn-loesung.visustruct":Fj,"../../lessons/diagramme/vb-zwei-sekunden-loesung.visustruct":Jj,"../../lessons/diagramme/zk-initialen-loesung.visustruct":Rj,"../../lessons/diagramme/zk-mehr.visustruct":Gj,"../../lessons/diagramme/zk-rueckwaerts-loesung.visustruct":Hj,"../../lessons/diagramme/zk-split.visustruct":Vj,"../../lessons/diagramme/zk-woerter-loesung.visustruct":qj,"../../lessons/diagramme/zk-zaehlen.visustruct":Qj,"../../lessons/diagramme/zk-zeichen.visustruct":Uj}),PB=Object.assign({"../../lessons/welten/ausgang-1.txt":$j,"../../lessons/welten/ausgang-2.txt":Yj,"../../lessons/welten/ecke.txt":Xj,"../../lessons/welten/farbe-1.txt":Kj,"../../lessons/welten/farbe-2.txt":eP,"../../lessons/welten/farbe-3.txt":tP,"../../lessons/welten/farbe-4.txt":nP,"../../lessons/welten/hindernis-1.txt":iP,"../../lessons/welten/hindernis-2.txt":aP,"../../lessons/welten/labyrinth-1.txt":sP,"../../lessons/welten/labyrinth-2.txt":rP,"../../lessons/welten/linie-1.txt":oP,"../../lessons/welten/linie-2.txt":lP,"../../lessons/welten/linie-rot-1.txt":uP,"../../lessons/welten/linie-rot-2.txt":cP,"../../lessons/welten/parken-1.txt":mP,"../../lessons/welten/parken-2.txt":dP,"../../lessons/welten/rand-1.txt":hP,"../../lessons/welten/rand-2.txt":gP,"../../lessons/welten/slalom.txt":pP,"../../lessons/welten/tunnel-1.txt":fP,"../../lessons/welten/tunnel-2.txt":bP,"../../lessons/welten/wald-1.txt":xP,"../../lessons/welten/wald-2.txt":vP,"../../lessons/welten/wand-frei.txt":yP,"../../lessons/welten/wand-kurz.txt":wP,"../../lessons/welten/wand-lang.txt":zP,"../../lessons/welten/wand-mittel.txt":IP,"../../lessons/welten/wand-nah.txt":kP,"../../lessons/welten/zeit-1.txt":SP,"../../lessons/welten/ziel-kurz.txt":TP,"../../lessons/welten/ziel-lang.txt":_P}),DB=Object.assign({"../../lessons/bilder/aufgabe-mehrwertsteuer.svg":OP,"../../lessons/bilder/ben-shneiderman.jpg":AP,"../../lessons/bilder/caesar-ascii.svg":CP,"../../lessons/bilder/caesar-scheibe.svg":jP,"../../lessons/bilder/caesar-verschiebung.svg":PP,"../../lessons/bilder/en/aufgabe-mehrwertsteuer.svg":DP,"../../lessons/bilder/en/kino-saal.svg":BP,"../../lessons/bilder/en/kino-schleifen.svg":ZP,"../../lessons/bilder/en/l01-pap.svg":MP,"../../lessons/bilder/en/l02-einfuegen.svg":LP,"../../lessons/bilder/en/l03-lochkarte-beschriftet.svg":EP,"../../lessons/bilder/en/l03-lochkarte.svg":WP,"../../lessons/bilder/en/l04-camelcase.svg":NP,"../../lessons/bilder/en/l04-variable.svg":FP,"../../lessons/bilder/en/l04-zuweisung.svg":JP,"../../lessons/bilder/en/l05-tauschen.svg":RP,"../../lessons/bilder/en/l08-zahlenstrahl.svg":GP,"../../lessons/bilder/en/l10-kopfgesteuert.svg":HP,"../../lessons/bilder/en/l11-vergleich.svg":VP,"../../lessons/bilder/en/l12-for-ablauf.svg":qP,"../../lessons/bilder/en/l14-array.svg":QP,"../../lessons/bilder/en/mvc-klick.svg":UP,"../../lessons/bilder/en/ss-binaere-suche.svg":$P,"../../lessons/bilder/en/ss-bubblesort.svg":YP,"../../lessons/bilder/en/ss-lineare-suche.svg":XP,"../../lessons/bilder/en/ss-vergleiche.svg":KP,"../../lessons/bilder/en/uebergabe.svg":eD,"../../lessons/bilder/en/zk-zeichen.svg":tD,"../../lessons/bilder/ike-nassi.jpg":nD,"../../lessons/bilder/kino-saal.svg":iD,"../../lessons/bilder/kino-schleifen.svg":aD,"../../lessons/bilder/l01-pap.svg":sD,"../../lessons/bilder/l02-einfuegen.svg":rD,"../../lessons/bilder/l03-lochkarte-beschriftet.svg":oD,"../../lessons/bilder/l03-lochkarte.svg":lD,"../../lessons/bilder/l04-camelcase.svg":uD,"../../lessons/bilder/l04-kaffee.svg":cD,"../../lessons/bilder/l04-variable.svg":mD,"../../lessons/bilder/l04-zuweisung.svg":dD,"../../lessons/bilder/l05-tauschen.svg":hD,"../../lessons/bilder/l08-zahlenstrahl.svg":gD,"../../lessons/bilder/l09-wahrheitstabelle.svg":pD,"../../lessons/bilder/l10-kopfgesteuert.svg":fD,"../../lessons/bilder/l11-vergleich.svg":bD,"../../lessons/bilder/l12-for-ablauf.svg":xD,"../../lessons/bilder/l14-array.svg":vD,"../../lessons/bilder/mvc-klick.svg":yD,"../../lessons/bilder/pt/aufgabe-mehrwertsteuer.svg":wD,"../../lessons/bilder/pt/kino-saal.svg":zD,"../../lessons/bilder/pt/kino-schleifen.svg":ID,"../../lessons/bilder/pt/l01-pap.svg":kD,"../../lessons/bilder/pt/l02-einfuegen.svg":SD,"../../lessons/bilder/pt/l03-lochkarte-beschriftet.svg":TD,"../../lessons/bilder/pt/l03-lochkarte.svg":_D,"../../lessons/bilder/pt/l04-camelcase.svg":OD,"../../lessons/bilder/pt/l04-variable.svg":AD,"../../lessons/bilder/pt/l04-zuweisung.svg":CD,"../../lessons/bilder/pt/l05-tauschen.svg":jD,"../../lessons/bilder/pt/l08-zahlenstrahl.svg":PD,"../../lessons/bilder/pt/l10-kopfgesteuert.svg":DD,"../../lessons/bilder/pt/l11-vergleich.svg":BD,"../../lessons/bilder/pt/l12-for-ablauf.svg":ZD,"../../lessons/bilder/pt/l14-array.svg":MD,"../../lessons/bilder/pt/mvc-klick.svg":LD,"../../lessons/bilder/pt/schiffe-versenken.svg":ED,"../../lessons/bilder/pt/ss-binaere-suche.svg":WD,"../../lessons/bilder/pt/ss-bubblesort.svg":ND,"../../lessons/bilder/pt/ss-lineare-suche.svg":FD,"../../lessons/bilder/pt/ss-vergleiche.svg":JD,"../../lessons/bilder/pt/uebergabe.svg":RD,"../../lessons/bilder/pt/zk-zeichen.svg":GD,"../../lessons/bilder/schiffe-versenken.svg":HD,"../../lessons/bilder/ss-binaere-suche.svg":VD,"../../lessons/bilder/ss-bubblesort.svg":qD,"../../lessons/bilder/ss-lineare-suche.svg":QD,"../../lessons/bilder/ss-vergleiche.svg":UD,"../../lessons/bilder/uebergabe.svg":$D,"../../lessons/bilder/zk-zeichen.svg":YD}),eg=i=>i.replace(/^.*\//,"");function G1(i,e,t){const n=s=>new Map(Object.entries(i).filter(([r])=>{var o;return((o=e.exec(r))==null?void 0:o[1])===s}).map(([r,o])=>[eg(r),o]));return[...new Map([...n("en"),...t==="en"?[]:n(t)])]}function Gu(i){return i==="de"?"de":i==="pt-PT"?"pt":"en"}let I1="en",jt=[],An=[],Wa="",Na=[],ps="off";function Hu(i){i!==ps&&(ps=i,jt=[],fs(I1))}function fs(i){var s,r,o;if(p3(i),i===I1&&jt.length>0)return;I1=i;const e=G1(OB,/\/lessons\/([^/]+)\/[^/]+\.md$/,i),t=(l,u)=>l.filter(([c])=>/^\d+/.test(c)).map(([c,m])=>TB(Qu(m,u),`${i}/${c}`)).sort((c,m)=>c.number-m.number),n=(l,u,c)=>l.map(([m,d])=>{const h=_B(Qu(d,c),`${i}/${u}${m}`);return c&&h.after!==void 0?{...h,after:c.get(h.after)??h.after}:h}),a=G1(AB,/\/lessons\/([^/]+)\/aufgaben\/[^/]+\.md$/,i);if(ps==="on"){const l=G1(Ru,/\/lessons\/([^/]+)\/visubot\/[^/]+\.md$/,i),u=BB(qu(e),qu(l)),c=t(e,u.normal),m=h=>{var g;return((g=[...c].reverse().find(f=>u.normal.get(f.number)({...h,number:u.normal.get(h.number)})),...t(l,u.robot).map(h=>{const g=u.robot.get(h.number);return{...h,number:g,section:m(g),robot:!0}})].sort((h,g)=>h.number-g.number);const d=G1(CB,/\/lessons\/([^/]+)\/visubot\/aufgaben\/[^/]+\.md$/,i);An=[...n(a,"aufgaben/",u.normal),...n(d,"visubot/aufgaben/",u.robot).map(h=>({...h,robot:!0}))]}else jt=t(e),An=n(a,"aufgaben/");An.sort((l,u)=>(l.after??0)-(u.after??0)||l.level-u.level||l.title.localeCompare(u.title,i));for(const l of[...jt.flatMap(u=>u.steps.flatMap(c=>c.blocks)),...An.flatMap(u=>u.blocks)])l.kind==="textFile"&&S3(l.name,l.content);if(Wa=((s=e.find(([l])=>l==="nachschlagen.md"))==null?void 0:s[1])??"",ps!=="off"){const l=(r=G1(Ru,/\/lessons\/([^/]+)\/visubot\/[^/]+\.md$/,i).find(([u])=>u==="nachschlagen.md"))==null?void 0:r[1];l&&(Wa=`${Wa.trimEnd()} -${l}`)}Na=YD(((o=e.find(([l])=>l==="begriffe.md"))==null?void 0:o[1])??"")}const Vu={1:3,2:5,3:5,4:8,5:11,6:11,7:11,8:11,9:11,10:11,11:11,12:11,13:11,14:11,15:11,16:14,17:15,18:15,19:17,20:17,21:17,22:18},qu=i=>i.map(([e])=>{var t;return Number((t=/^(\d+)/.exec(e))==null?void 0:t[1])}).filter(Number.isFinite).sort((e,t)=>e-t);function DB(i,e){const t=[...i].reverse().find(o=>o<=19)??i.at(-1)??0,n=o=>i.includes(Vu[o])?Vu[o]:t,a=new Map,s=new Map;let r=1;for(const o of i){a.set(o,r++);for(const l of e.filter(u=>n(u)===o))s.set(l,r++)}return{normal:a,robot:s}}function Qu(i,e){return e?i.replace(/\b(Lektion(?:en)?|Lessons?|Li[cç](?:ão|ões))(\s+\d+(?:\s*(?:,|bis|und|and|to|a|e|–|-)\s*\d+)*)/gi,(t,n,a)=>n+a.replace(/\d+/g,s=>String(e.get(Number(s))??s))):i}fs("en");function eg(i,e){return I1==="de"?i.get(e)??i.get(`en/${e}`):(I1==="en"?void 0:i.get(`${I1}/${e}`))??i.get(`en/${e}`)??i.get(e)}const tg=(i,e)=>i.slice(i.indexOf(e)+e.length),BB=new Map(Object.entries(CB).map(([i,e])=>[tg(i,"/diagramme/"),e]));function ti(i){const e=eg(BB,i);return e===void 0?void 0:El(e)}const ZB=new Map(Object.entries(jB).map(([i,e])=>[tg(i,"/bilder/"),e]));function yr(i){return eg(ZB,i)}const MB=new Map(Object.entries(PB).map(([i,e])=>[Kh(i).replace(/\.txt$/,""),e])),Uu=new Map;function Fa(i){const e=MB.get(i);if(e===void 0)return;let t=Uu.get(i);return t||Uu.set(i,t=Jb(e)),t}const ng=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,""");function Pe(i){const e=[];let t=ng(i).replace(/`([^`]+)`/g,(n,a)=>(e.push(a),`\0${e.length-1}\0`));return t=t.replace(/\*\*(.+?)\*\*/g,"$1").replace(/(^|[^*])\*([^*\s][^*]*?)\*/g,"$1$2").replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(n,a,s)=>{const r=/^(https?:|mailto:|#|\.{0,2}\/)/.test(s)?s:"#",o=/^https?:/.test(r)?' target="_blank" rel="noopener noreferrer"':"";return`${a}`}).replace(/\[([^\]]+)\]\{\.(blau|orange|gruen|gelb|rosa)\}/g,'$1').replace(/\[([^\]]+)\]\{(?:teil|part)=([\w,]+)\}/g,'$1'),t.replace(/\u0000(\d+)\u0000/g,(n,a)=>`${e[Number(a)]}`)}function Tn(i){const e=[],t=i.replace(/\r\n/g,` +${l}`)}Na=XD(((o=e.find(([l])=>l==="begriffe.md"))==null?void 0:o[1])??"")}const Vu={1:3,2:5,3:5,4:8,5:11,6:11,7:11,8:11,9:11,10:11,11:11,12:11,13:11,14:11,15:11,16:14,17:15,18:15,19:17,20:17,21:17,22:18},qu=i=>i.map(([e])=>{var t;return Number((t=/^(\d+)/.exec(e))==null?void 0:t[1])}).filter(Number.isFinite).sort((e,t)=>e-t);function BB(i,e){const t=[...i].reverse().find(o=>o<=19)??i.at(-1)??0,n=o=>i.includes(Vu[o])?Vu[o]:t,a=new Map,s=new Map;let r=1;for(const o of i){a.set(o,r++);for(const l of e.filter(u=>n(u)===o))s.set(l,r++)}return{normal:a,robot:s}}function Qu(i,e){return e?i.replace(/\b(Lektion(?:en)?|Lessons?|Li[cç](?:ão|ões))(\s+\d+(?:\s*(?:,|bis|und|and|to|a|e|–|-)\s*\d+)*)/gi,(t,n,a)=>n+a.replace(/\d+/g,s=>String(e.get(Number(s))??s))):i}fs("en");function tg(i,e){return I1==="de"?i.get(e)??i.get(`en/${e}`):(I1==="en"?void 0:i.get(`${I1}/${e}`))??i.get(`en/${e}`)??i.get(e)}const ng=(i,e)=>i.slice(i.indexOf(e)+e.length),ZB=new Map(Object.entries(jB).map(([i,e])=>[ng(i,"/diagramme/"),e]));function ti(i){const e=tg(ZB,i);return e===void 0?void 0:El(e)}const MB=new Map(Object.entries(DB).map(([i,e])=>[ng(i,"/bilder/"),e]));function yr(i){return tg(MB,i)}const LB=new Map(Object.entries(PB).map(([i,e])=>[eg(i).replace(/\.txt$/,""),e])),Uu=new Map;function Fa(i){const e=LB.get(i);if(e===void 0)return;let t=Uu.get(i);return t||Uu.set(i,t=Rb(e)),t}const ig=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,""");function je(i){const e=[];let t=ig(i).replace(/`([^`]+)`/g,(n,a)=>(e.push(a),`\0${e.length-1}\0`));return t=t.replace(/\*\*(.+?)\*\*/g,"$1").replace(/(^|[^*])\*([^*\s][^*]*?)\*/g,"$1$2").replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(n,a,s)=>{const r=/^(https?:|mailto:|#|\.{0,2}\/)/.test(s)?s:"#",o=/^https?:/.test(r)?' target="_blank" rel="noopener noreferrer"':"";return`${a}`}).replace(/\[([^\]]+)\]\{\.(blau|orange|gruen|gelb|rosa)\}/g,'$1').replace(/\[([^\]]+)\]\{(?:teil|part)=([\w,]+)\}/g,'$1'),t.replace(/\u0000(\d+)\u0000/g,(n,a)=>`${e[Number(a)]}`)}function Tn(i){const e=[],t=i.replace(/\r\n/g,` `).split(` -`);let n=0;for(;n${ng(m.join(` -`))}`);continue}const s=/^(#{2,4})\s+(.*)$/.exec(a);if(s){const o=s[1].length;e.push(`${Pe(s[2])}`),n++;continue}if(/^\s*([-*]|\d+\.)\s+/.test(a)){const o=/^\s*\d+\./.test(a),l=[];for(;n${Pe(u)}`)}e.push(o?`
    ${l.join("")}
`:`
    ${l.join("")}
`);continue}if(a.startsWith("|")&&/^\|?[\s:|-]*-{3,}[\s:|-]*$/.test(t[n+1]??"")){const o=c=>c.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(m=>Pe(m.trim())),l=o(a);n+=2;const u=[];for(;n${l.map(c=>``).join("")}${u.map(c=>`${c.map(m=>``).join("")}`).join("")}
${c}
${m}
`);continue}if(a.startsWith(">")){const o=[];for(;n");)o.push(t[n++].replace(/^>\s?/,""));e.push(``);continue}const r=[];for(;n|\||\s*([-*]|\d+\.)\s+)/.test(t[n]);)r.push(t[n++].trim());e.push(`

${Pe(r.join(" "))}

`)}return e.join(` -`)}const ra=""+new URL("ludwig-Cus1i402.webp",import.meta.url).href,Bo="f4ecc8e489ae7865308288c7d0fa313333cf2be3ff529b23bc214bee010310e0",a0="visustruct.learn.teacher";let s0=!1;function $u(){if(s0)return!0;try{return localStorage.getItem(a0)===Bo}catch{return!1}}async function LB(i){const e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(i));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}async function EB(i){let e=!1;try{e=await LB(i.trim())===Bo}catch{return!1}if(e){s0=!0;try{localStorage.setItem(a0,Bo)}catch{}}return e}function WB(){s0=!1;try{localStorage.removeItem(a0)}catch{}}function ig(i,e,t=!1){const n=document.createElement("figure");n.className=t?"learn-file written":"learn-file";const a=document.createElement("figcaption"),s=document.createElement("span");s.className="learn-file-icon",s.setAttribute("aria-hidden","true"),s.textContent="📄",a.append(s,t?p("web_sim_written_file_fmt",i):i);const r=document.createElement("pre");return r.className="learn-file-text",r.dir="ltr",e.replace(/\n$/,"").split(` +`);let n=0;for(;n${ig(m.join(` +`))}`);continue}const s=/^(#{2,4})\s+(.*)$/.exec(a);if(s){const o=s[1].length;e.push(`${je(s[2])}`),n++;continue}if(/^\s*([-*]|\d+\.)\s+/.test(a)){const o=/^\s*\d+\./.test(a),l=[];for(;n${je(u)}`)}e.push(o?`
    ${l.join("")}
`:`
    ${l.join("")}
`);continue}if(a.startsWith("|")&&/^\|?[\s:|-]*-{3,}[\s:|-]*$/.test(t[n+1]??"")){const o=c=>c.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(m=>je(m.trim())),l=o(a);n+=2;const u=[];for(;n${l.map(c=>``).join("")}${u.map(c=>`${c.map(m=>``).join("")}`).join("")}
${c}
${m}
`);continue}if(a.startsWith(">")){const o=[];for(;n");)o.push(t[n++].replace(/^>\s?/,""));e.push(``);continue}const r=[];for(;n|\||\s*([-*]|\d+\.)\s+)/.test(t[n]);)r.push(t[n++].trim());e.push(`

${je(r.join(" "))}

`)}return e.join(` +`)}const ra=""+new URL("ludwig-Cus1i402.webp",import.meta.url).href,Bo="f4ecc8e489ae7865308288c7d0fa313333cf2be3ff529b23bc214bee010310e0",a0="visustruct.learn.teacher";let s0=!1;function $u(){if(s0)return!0;try{return localStorage.getItem(a0)===Bo}catch{return!1}}async function EB(i){const e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(i));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}async function WB(i){let e=!1;try{e=await EB(i.trim())===Bo}catch{return!1}if(e){s0=!0;try{localStorage.setItem(a0,Bo)}catch{}}return e}function NB(){s0=!1;try{localStorage.removeItem(a0)}catch{}}function ag(i,e,t=!1){const n=document.createElement("figure");n.className=t?"learn-file written":"learn-file";const a=document.createElement("figcaption"),s=document.createElement("span");s.className="learn-file-icon",s.setAttribute("aria-hidden","true"),s.textContent="📄",a.append(s,t?p("web_sim_written_file_fmt",i):i);const r=document.createElement("pre");return r.className="learn-file-text",r.dir="ltr",e.replace(/\n$/,"").split(` `).forEach((l,u)=>{const c=document.createElement("span");c.className="ln",c.textContent=String(u+1),r.append(c,l+` -`)}),n.append(a,r),n}function ag(i){return[...i].map(([e,t])=>ig(e,t,!0))}function t1(i){switch(i.kind){case"finished":return p("sim_notice_finished");case"infiniteLoopWithoutBody":return p("sim_notice_infinite_loop_empty");case"unsupportedStatement":return p("sim_notice_unsupported_statement_fmt",i.text);case"invalidExpression":return p("sim_notice_invalid_expression_fmt",i.text);case"unknownVariable":return p("sim_notice_unknown_variable_fmt",i.text);case"divisionByZero":return p("sim_notice_division_by_zero");case"wholeNumberExpected":return p("sim_notice_whole_number_expected");case"numberExpected":return p("sim_notice_number_expected");case"booleanExpected":return p("sim_notice_boolean_expected");case"subprogramNotFound":return p("sim_notice_subprogram_not_found_fmt",i.text);case"callTooDeep":return p("sim_notice_call_too_deep");case"callArguments":return p("web_sim_call_arguments_fmt",i.text);case"missingReturn":return p("web_sim_missing_return_fmt",i.text);case"fileNotFound":return p("web_sim_file_not_found_fmt",i.text);case"endOfFile":return p("web_sim_end_of_file_fmt",i.text);case"nullValue":return p("web_sim_null_value_fmt",i.text);case"other":return i.text}}const Be=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,"""),Yu=["0.2","0.5","1.0","1.5","2.0"],NB=i=>Number(i).toLocaleString(s1()==="java"?"en":s1(),{minimumFractionDigits:1}),wr="visustruct.simulation.stepDelay",Xu="visustruct.simulation.highlightMode";function zr(i){try{return localStorage.getItem(i)}catch{return null}}function Ku(i,e){try{localStorage.setItem(i,e)}catch{}}class FB{constructor(e,t,n=()=>{},a=()=>{},s=()=>{}){y(this,"element");y(this,"engine");y(this,"isPlaying",!1);y(this,"playTimer");y(this,"wasPlayingBeforeInput",!1);y(this,"delay",Yu.includes(zr(wr)??"")?zr(wr):"0.5");y(this,"highlightMode",zr(Xu)==="nextToExecute"?"nextToExecute":"lastExecuted");y(this,"buttons");y(this,"inputSection");y(this,"trace");y(this,"variables");y(this,"output");y(this,"transcript",[]);y(this,"printed",0);y(this,"notice");y(this,"editButton");y(this,"robot");y(this,"liveBusy",!1);this.currentDocument=e,this.onHighlight=t,this.findSubprogram=n,this.onEdit=a,this.onTranscript=s,this.engine=new wi(e(),n),this.element=document.createElement("aside"),this.element.className="simpanel",this.build()}setRobot(e){var t;this.robot!==e&&((t=this.robot)==null||t.element.remove(),this.robot=e,e&&(this.element.querySelector("section").after(e.element),e.onWorldChange=()=>this.restartEngine(),e.reset()))}showRobot(){var e;(e=this.robot)==null||e.show()}begin(){this.pause(),this.restartEngine(),this.showRobot()}end(){this.pause()}step(){var n,a,s;if((n=this.robot)!=null&&n.live){this.stepLive();return}if(!this.engine.canStep){this.pause();return}const e=this.isPlaying,t=this.engine.currentStepPath;(a=this.robot)==null||a.prepare(this.engine),this.engine.step(),(s=this.robot)==null||s.follow(this.engine.state.robotActions,e?Number(this.delay)*850:450),this.afterStep(e,t)}async stepLive(){if(this.liveBusy)return;if(!this.engine.canStep){this.pause();return}this.liveBusy=!0;const e=this.robot,t=this.isPlaying,n=this.engine.currentStepPath;try{await e.prepareLive(this.engine,f3(JSON.stringify(this.currentDocument()))),this.engine.step(),e.follow(this.engine.state.robotActions,450),await e.drive(this.engine.state.robotActions)}catch(a){e.liveFailed(a),this.isPlaying=!1}finally{this.liveBusy=!1}this.afterStep(t,n)}afterStep(e,t){this.collectOutput(),this.highlightMode==="nextToExecute"&&this.engine.canStep?this.onHighlight(this.engine.currentStepPath):this.onHighlight(t??this.engine.currentStepPath),this.engine.state.inputRequest&&e&&(this.wasPlayingBeforeInput=!0),this.engine.canStep||this.pause(),this.update()}reset(){this.pause(),this.restartEngine()}play(){if(this.isPlaying||!this.engine.canStep)return;this.isPlaying=!0;const e=async()=>{var t;this.playTimer=void 0,this.isPlaying&&((t=this.robot)!=null&&t.live?await this.stepLive():this.step(),this.isPlaying&&this.engine.canStep?this.playTimer=window.setTimeout(()=>void e(),Number(this.delay)*1e3):(this.isPlaying=!1,this.update()))};e()}pause(){this.playTimer!==void 0&&window.clearTimeout(this.playTimer),this.playTimer=void 0,this.isPlaying=!1,this.update()}submitInput(e){var s,r;const t=this.isPlaying||this.wasPlayingBeforeInput;this.pause();const n=((s=this.engine.state.inputRequest)==null?void 0:s.prompt)??"",a=(r=this.engine.state.inputRequest)==null?void 0:r.continuesLine;if(this.engine.provideInput(e.value),!this.engine.state.inputRequest){const o=this.transcript[this.transcript.length-1];a&&o&&o.typed===void 0?o.typed=e.value:this.transcript.push({text:n?`${n} `:"",typed:e.value}),e.value=""}this.onHighlight(this.engine.currentStepPath),t&&this.engine.canStep&&(this.wasPlayingBeforeInput=!1,this.play()),this.update()}restartEngine(){var e;this.engine=new wi(this.currentDocument(),this.findSubprogram),this.transcript=[],this.printed=0,this.wasPlayingBeforeInput=!1,(e=this.robot)==null||e.reset(),this.onHighlight(this.engine.currentStepPath),this.update()}build(){this.element.innerHTML=` +`)}),n.append(a,r),n}function sg(i){return[...i].map(([e,t])=>ag(e,t,!0))}function t1(i){switch(i.kind){case"finished":return p("sim_notice_finished");case"infiniteLoopWithoutBody":return p("sim_notice_infinite_loop_empty");case"unsupportedStatement":return p("sim_notice_unsupported_statement_fmt",i.text);case"invalidExpression":return p("sim_notice_invalid_expression_fmt",i.text);case"unknownVariable":return p("sim_notice_unknown_variable_fmt",i.text);case"divisionByZero":return p("sim_notice_division_by_zero");case"wholeNumberExpected":return p("sim_notice_whole_number_expected");case"numberExpected":return p("sim_notice_number_expected");case"booleanExpected":return p("sim_notice_boolean_expected");case"subprogramNotFound":return p("sim_notice_subprogram_not_found_fmt",i.text);case"callTooDeep":return p("sim_notice_call_too_deep");case"callArguments":return p("web_sim_call_arguments_fmt",i.text);case"missingReturn":return p("web_sim_missing_return_fmt",i.text);case"fileNotFound":return p("web_sim_file_not_found_fmt",i.text);case"endOfFile":return p("web_sim_end_of_file_fmt",i.text);case"nullValue":return p("web_sim_null_value_fmt",i.text);case"other":return i.text}}const Be=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,"""),Yu=["0.2","0.5","1.0","1.5","2.0"],FB=i=>Number(i).toLocaleString(s1()==="java"?"en":s1(),{minimumFractionDigits:1}),wr="visustruct.simulation.stepDelay",Xu="visustruct.simulation.highlightMode";function zr(i){try{return localStorage.getItem(i)}catch{return null}}function Ku(i,e){try{localStorage.setItem(i,e)}catch{}}class JB{constructor(e,t,n=()=>{},a=()=>{},s=()=>{}){y(this,"element");y(this,"engine");y(this,"isPlaying",!1);y(this,"playTimer");y(this,"wasPlayingBeforeInput",!1);y(this,"delay",Yu.includes(zr(wr)??"")?zr(wr):"0.5");y(this,"highlightMode",zr(Xu)==="nextToExecute"?"nextToExecute":"lastExecuted");y(this,"buttons");y(this,"inputSection");y(this,"trace");y(this,"variables");y(this,"output");y(this,"transcript",[]);y(this,"printed",0);y(this,"notice");y(this,"editButton");y(this,"robot");y(this,"liveBusy",!1);this.currentDocument=e,this.onHighlight=t,this.findSubprogram=n,this.onEdit=a,this.onTranscript=s,this.engine=new wi(e(),n),this.element=document.createElement("aside"),this.element.className="simpanel",this.build()}setRobot(e){var t;this.robot!==e&&((t=this.robot)==null||t.element.remove(),this.robot=e,e&&(this.element.querySelector("section").after(e.element),e.onWorldChange=()=>this.restartEngine(),e.reset()))}showRobot(){var e;(e=this.robot)==null||e.show()}begin(){this.pause(),this.restartEngine(),this.showRobot()}end(){this.pause()}step(){var n,a,s;if((n=this.robot)!=null&&n.live){this.stepLive();return}if(!this.engine.canStep){this.pause();return}const e=this.isPlaying,t=this.engine.currentStepPath;(a=this.robot)==null||a.prepare(this.engine),this.engine.step(),(s=this.robot)==null||s.follow(this.engine.state.robotActions,e?Number(this.delay)*850:450),this.afterStep(e,t)}async stepLive(){if(this.liveBusy)return;if(!this.engine.canStep){this.pause();return}this.liveBusy=!0;const e=this.robot,t=this.isPlaying,n=this.engine.currentStepPath;try{await e.prepareLive(this.engine,b3(JSON.stringify(this.currentDocument()))),this.engine.step(),e.follow(this.engine.state.robotActions,450),await e.drive(this.engine.state.robotActions)}catch(a){e.liveFailed(a),this.isPlaying=!1}finally{this.liveBusy=!1}this.afterStep(t,n)}afterStep(e,t){this.collectOutput(),this.highlightMode==="nextToExecute"&&this.engine.canStep?this.onHighlight(this.engine.currentStepPath):this.onHighlight(t??this.engine.currentStepPath),this.engine.state.inputRequest&&e&&(this.wasPlayingBeforeInput=!0),this.engine.canStep||this.pause(),this.update()}reset(){this.pause(),this.restartEngine()}play(){if(this.isPlaying||!this.engine.canStep)return;this.isPlaying=!0;const e=async()=>{var t;this.playTimer=void 0,this.isPlaying&&((t=this.robot)!=null&&t.live?await this.stepLive():this.step(),this.isPlaying&&this.engine.canStep?this.playTimer=window.setTimeout(()=>void e(),Number(this.delay)*1e3):(this.isPlaying=!1,this.update()))};e()}pause(){this.playTimer!==void 0&&window.clearTimeout(this.playTimer),this.playTimer=void 0,this.isPlaying=!1,this.update()}submitInput(e){var s,r;const t=this.isPlaying||this.wasPlayingBeforeInput;this.pause();const n=((s=this.engine.state.inputRequest)==null?void 0:s.prompt)??"",a=(r=this.engine.state.inputRequest)==null?void 0:r.continuesLine;if(this.engine.provideInput(e.value),!this.engine.state.inputRequest){const o=this.transcript[this.transcript.length-1];a&&o&&o.typed===void 0?o.typed=e.value:this.transcript.push({text:n?`${n} `:"",typed:e.value}),e.value=""}this.onHighlight(this.engine.currentStepPath),t&&this.engine.canStep&&(this.wasPlayingBeforeInput=!1,this.play()),this.update()}restartEngine(){var e;this.engine=new wi(this.currentDocument(),this.findSubprogram),this.transcript=[],this.printed=0,this.wasPlayingBeforeInput=!1,(e=this.robot)==null||e.reset(),this.onHighlight(this.engine.currentStepPath),this.update()}build(){this.element.innerHTML=`

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

@@ -63576,7 +63582,7 @@ ${l}`)}Na=YD(((o=e.find(([l])=>l==="begriffe.md"))==null?void 0:o[1])??"")}const

@@ -63585,22 +63591,22 @@ ${l}`)}Na=YD(((o=e.find(([l])=>l==="begriffe.md"))==null?void 0:o[1])??"")}const

${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,Ku(Xu,this.highlightMode)});const n=e("[data-sim=delay]");n.value=this.delay,n.addEventListener("change",()=>{this.delay=n.value,Ku(wr,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),c=l.insertCell();u.kind==="grid"?c.append(sg(u)):c.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}),...ag(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?t1(r):"",o.hidden=!r}}function sg(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 x1=Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),Gn=360/x1.length,JB="http://www.w3.org/2000/svg";function Je(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 xt(i,e={},t){const n=document.createElementNS(JB,i);for(const[a,s]of Object.entries(e))n.setAttribute(a,String(s));return t!==void 0&&(n.textContent=t),n}function RB(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 ec(i,e){const t=xt("g",{class:e}),n=x1.map((a,s)=>{const r=xt("g",{transform:`rotate(${s*Gn})`});return r.append(xt("text",{x:0,y:-i,"text-anchor":"middle","dominant-baseline":"central"},a)),t.append(r),r});return{group:t,cells:n}}function GB(i,e){let t=i,n=!1,a=-t*Gn;const s=Je("section",{class:"learn-game learn-caesar"});s.append(Je("div",{class:"learn-game-head"},Je("strong",{},p("web_learn_caesar_title")))),s.append(Je("p",{class:"learn-game-status"},p("web_learn_caesar_hint")));const r=xt("svg",{viewBox:"-200 -200 400 400",class:"learn-caesar-disc",role:"img"});r.append(xt("circle",{r:196,class:"outer-disc"})),r.append(xt("path",{d:HB(196,92,Gn/2),class:"window"}));const o=ec(168,"outer-letters");r.append(o.group);for(let A=0;A{o.cells.forEach((M,W)=>M.classList.toggle("marked",W===A)),u.cells.forEach((M,W)=>M.classList.toggle("marked",A!==void 0&&W===(A+t)%26))},T=()=>{c.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),I.textContent=RB(v.value,n?-t:t)||" ";const A=Array.from(v.value.toUpperCase()).reverse().find(W=>x1.includes(W));if(A===void 0)return k();const M=x1.indexOf(A);k(n?(M-t+26)%26:M)},O=A=>{t=(A%26+26)%26,a=-t*Gn,T()};m.addEventListener("click",()=>O(t-1)),d.addEventListener("click",()=>O(t+1)),f.addEventListener("click",()=>{var A;n&&(v.value=((A=I.textContent)==null?void 0:A.trim())??""),n=!1,T()}),b.addEventListener("click",()=>{var A;n||(v.value=((A=I.textContent)==null?void 0:A.trim())??""),n=!0,T()}),v.addEventListener("input",T),o.cells.forEach((A,M)=>A.addEventListener("click",()=>k(M)));let D;const j=A=>{const M=r.getBoundingClientRect();return Math.atan2(A.clientY-(M.top+M.height/2),A.clientX-(M.left+M.width/2))*180/Math.PI};l.addEventListener("pointerdown",A=>{const M=A;D=j(M)-a,l.classList.add("dragging"),r.setPointerCapture(M.pointerId),M.preventDefault()}),r.addEventListener("pointermove",A=>{if(D===void 0)return;a=j(A)-D,l.setAttribute("transform",`rotate(${a})`);const M=Math.round(-a/Gn);if((M%26+26)%26!==t){t=(M%26+26)%26;const W=a;T(),a=W,l.setAttribute("transform",`rotate(${a})`)}});const P=()=>{D!==void 0&&(D=void 0,l.classList.remove("dragging"),O(t))};return r.addEventListener("pointerup",P),r.addEventListener("pointercancel",P),T(),s}function HB(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 r0=i=>p(`web_visubot_part_${i}`),rg=new WeakMap;function og(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=(m,d,h)=>{r.hidden=!1,r.textContent=r0(m),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:m}=await import("./robot3d-F7Of_tVr.js");return{Robot3D:m}},[],import.meta.url).then(({Robot3D:m})=>{const d=new m(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(m=>{console.error(m),s.textContent=p("web_visubot_no_3d")}),c={box:a,ready:u,focus:i,view:e};return rg.set(a,c),c}function VB(i,e,t=!1){return og(i,e,t).box}function qB(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(r0).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 QB(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=Tn(`**${t+1}/${i.length}** ${i[t].question}`)},r=og([],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",r0(l));return}t++,a.className="visubot-quiz-feedback right",t{u.forEach(v=>{window.clearTimeout(v),window.clearInterval(v)}),u=[]},m=()=>{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,I=$("div",{class:"learn-bomb-fuse"},$("span",{})),z=$("span",{class:"learn-bomb-time"}),k=$("div",{class:"learn-bomb","aria-live":"polite"},$("span",{class:"learn-bomb-icon","aria-hidden":"true"},"💣"),z,I),T=$("div",{class:"learn-game-feedback",role:"status"}),O=v.code.split(` -`).map((W,U)=>{const K=$("button",{class:"ln",type:"button"},W||" ");return K.disabled=!W.trim(),K.addEventListener("click",()=>A(U+1===v.wrongLine?"right":"wrong",K)),K}),D=$("div",{class:"learn-game-code learn-bomb-code mono",dir:"ltr"},...O),j=Date.now(),P=()=>{if(!t.isConnected&&Date.now()-j>1e3)return c();const W=Math.max(0,w-(Date.now()-j)/1e3);z.textContent=p("web_game_time_fmt",Math.ceil(W)),I.firstChild.style.width=`${W/w*100}%`,k.classList.toggle("hurry",W<=5),W<=0&&A("time")},A=(W,U)=>{c(),O.forEach((Ie,fe)=>{Ie.disabled=!0,fe+1===v.wrongLine&&Ie.classList.add("right")}),U&&W==="wrong"&&U.classList.add("wrong");const K=W==="right";K&&l++,m(),k.classList.add(K?"defused":"boom"),k.firstChild.textContent=K?"✂️":"💥",T.className=`learn-game-feedback ${K?"right":"wrong"}`;const he=d();T.replaceChildren($("p",{},p(K?"web_game_defused":W==="time"?"web_game_boom_time":"web_game_boom_wrong")),Jn("div",{class:"learn-game-explain"},v.explanation),$("p",{class:"learn-bomb-fix"},`${p("web_game_fix")} `,$("code",{},v.fix.trim())),he),he.focus({preventScroll:!0})};s.replaceChildren(k,Jn("p",{class:"learn-game-question"},v.question),D,T),P();const M=window.setInterval(P,200);u.push(M)},g=()=>{const v=i.rounds[o],w=[];v.code.trim()&&w.push(nc(v.code).element),w.push(Jn("p",{class:"learn-game-question"},v.question),$("p",{class:"learn-order-hint"},p("web_game_order_hint")));const I=$("div",{class:"learn-game-options learn-order"}),z=$("div",{class:"learn-game-feedback",role:"status"});let k=0;const T=$B(v.options.length).map(D=>{const j=$("span",{class:"learn-order-badge","aria-hidden":"true"}),P=$("span",{});P.innerHTML=Pe(v.options[D].text);const A=$("button",{},j,P);return A.addEventListener("click",()=>{if(D!==k)return A.classList.add("wrong"),O(!1);A.classList.add("right"),j.textContent=String(++k),A.disabled=!0,k===v.options.length&&O(!0)}),I.append(A),{k:D,b:A,badge:j}}),O=D=>{for(const{k:P,b:A,badge:M}of[...T].sort((W,U)=>W.k-U.k))A.disabled=!0,M.textContent=String(P+1),I.append(A);D&&l++,m(),z.className=`learn-game-feedback ${D?"right":"wrong"}`;const j=d();z.replaceChildren($("p",{},p(D?"web_game_right":"web_game_wrong_short")),Jn("div",{class:"learn-game-explain"},v.explanation),j),j.focus({preventScroll:!0})};s.replaceChildren(...w,I,z)},f=()=>{if(c(),i.kind==="bombe"||i.kind==="reihenfolge"){m(),i.kind==="bombe"?h():g();return}const v=i.rounds[o];m();const w=nc(v.code),I=[];let z;i.kind==="zuhoerer"?(z=YB(Gh(v.code),w),I.push($("div",{class:"learn-swing-row"},w.element,z.element)),v.clicks.length&&I.push($("p",{class:"learn-swing-clicks"},`${p("web_game_clicks")} `,...v.clicks.flatMap((j,P)=>[...P?[" → "]:[],$("code",{},j)])))):v.code.trim()&&I.push(w.element),I.push(Jn("p",{class:"learn-game-question"},v.question));const k=$("div",{class:`learn-game-options ${i.kind==="layout"?"pictures":""}`}),T=$("div",{class:"learn-game-feedback",role:"status"}),O=v.options.map(j=>{const P=$("button",{});return i.kind==="layout"?P.append(KB(j.text)):j.text.includes(` -`)?P.append(XB(j.text)):P.innerHTML=Pe(j.text),P.addEventListener("click",()=>D(j.right,P)),k.append(P),P}),D=(j,P)=>{O.forEach((M,W)=>{M.disabled=!0,v.options[W].right&&M.classList.add("right")}),j||P.classList.add("wrong"),j&&l++,m(),T.className=`learn-game-feedback ${j?"right":"wrong"}`;const A=d();T.replaceChildren($("p",{},p(j?"web_game_right":"web_game_wrong_short")),Jn("div",{class:"learn-game-explain"},v.explanation)),T.append(A),z&&(u=z.replay(v.clicks,()=>A.before($("p",{class:"learn-swing-try"},p("web_game_try"))))),A.focus({preventScroll:!0})};s.replaceChildren(...I,k,T)},b=()=>{c(),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(Jn("p",{},i.intro),x),t}function $B(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 nc(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 YB(i,e){const t=Hh(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 m of i.labels){const d=$("div",{class:"learn-swing-label"},t.texts[m.name]);s.set(m.name,d),a.append(d)}const r=i.buttons.map(m=>{const d=$("button",{class:"learn-swing-button",disabled:""},t.texts[m.name]);return s.set(m.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=m=>{var h,g;const d=s.get(m.button);d.classList.add("pressed"),window.setTimeout(()=>d.classList.remove("pressed"),350),e.highlight((h=m.listener)==null?void 0:h.from,(g=m.listener)==null?void 0:g.to),o.textContent=m.listener?p("web_game_event_fmt",d.textContent??""):p("web_game_nobody"),o.className=`learn-swing-event ${m.listener?"heard":"nobody"}`;for(const[f,b]of Object.entries(m.texts)){const x=s.get(f);x&&x.textContent!==b&&(x.textContent=b,x.classList.remove("changed"),x.offsetWidth,x.classList.add("changed"))}m.console.length&&(l.hidden=!1,l.textContent+=m.console.map(f=>`${f} -`).join(""))},c=m=>u(Vh(i,t,m));return{element:n,replay(m,d){const h=m.map((g,f)=>window.setTimeout(()=>c(g),(f+.3)*tc));return h.push(window.setTimeout(()=>{i.buttons.forEach((g,f)=>{r[f].disabled=!1,r[f].addEventListener("click",()=>u(qh(i,t,g.name)))}),d()},(m.length+.3)*tc)),h}}}function XB(i){return $("pre",{class:"learn-game-file mono",dir:"ltr"},i)}function KB(i){const e=Rh(i),t=$("div",{class:"learn-layout-window",dir:"ltr"},$("div",{class:"learn-layout-title"})),n=$("div",{class:`learn-layout-body ${e.kind}`}),a=(s,r)=>$("span",{class:"learn-layout-cell",...r?{style:`grid-area:${r}`}:{}},s);if(e.kind==="border")for(const[s,r]of Object.entries(e.areas))n.append(a(r,s));else if(e.kind==="grid"){const s=Math.max(...e.rows.map(r=>r.length));n.style.gridTemplateColumns=`repeat(${s}, 1fr)`;for(const r of e.rows)for(let o=0;oa(r))));return t.append(n),t}function H(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 zn(i,e,t){const n=H(i,e);return n.innerHTML=Pe(t),n}function ic(i){return H("pre",{class:"learn-game-code mono",dir:"ltr"},...i.split(` -`).map(e=>H("div",{class:"ln"},e||" ")))}function eZ(i,e){const t=H("section",{class:"learn-game learn-rescue"}),n=H("div",{class:"learn-game-head"});n.append(H("img",{src:e,alt:"",width:"40",height:"40"}),H("strong",{},i.title));const a=i.stations.length,s=i.stations.map(()=>H("span",{class:"learn-rescue-dot"})),r=H("img",{class:"learn-rescue-ludwig",src:e,alt:"",width:"32",height:"32"}),o=H("span",{class:"learn-rescue-tower","aria-hidden":"true"},"🏰",H("span",{class:"learn-rescue-zora"},"🐐"),H("span",{class:"learn-rescue-fox"},"🦊")),l=H("span",{class:"learn-rescue-free"},"🐐"),u=H("div",{class:"learn-rescue-path","aria-hidden":"true"},r,...s,o),c=H("p",{class:"learn-game-status"}),m=H("div",{class:"learn-game-stage"}),d=tZ(i);t.append(n,u,c,m);let h=0;const g=()=>{s.forEach((z,k)=>z.classList.toggle("done",k{const z=[...i.alphabet].map((k,T)=>H("span",{class:"learn-rescue-letter"},H("b",{},k),H("small",{},String(T))));return{element:H("div",{class:"learn-rescue-alphabet mono",dir:"ltr"},...z),cells:z}},b=z=>{const k=i.stations[z];c.textContent=p("web_learn_rescue_station_fmt",z+1,a,k.name);const T=f(),O=H("input",{type:"text",inputmode:"numeric",autocomplete:"off",class:"learn-rescue-number mono","aria-label":p("web_learn_rescue_number")}),D=H("button",{class:"primary"},p("web_learn_check")),j=H("div",{class:"learn-game-feedback",role:"status"}),P=()=>{const A=O.value.trim();if(!/^-?\d+$/.test(A)){j.className="learn-game-feedback wrong",j.replaceChildren(H("p",{},p("web_learn_rescue_not_number")));return}if(Number(A)!==k.answer){j.className="learn-game-feedback wrong",j.replaceChildren(H("p",{},p("web_learn_rescue_wrong")),...k.hint?[zn("div",{class:"learn-game-explain"},`**${p("web_learn_hint")}:** ${k.hint}`)]:[]),O.select();return}O.disabled=D.disabled=!0;const M=i.alphabet.charAt(k.answer);T.cells[k.answer].classList.add("hit"),d.give(k.row,k.col,M),h++,g();const W=z+1===a,U=H("button",{class:"primary"},p(W?"web_learn_rescue_to_crossword":"web_game_next"));U.addEventListener("click",()=>W?x():b(z+1)),j.className="learn-game-feedback right",j.replaceChildren(H("p",{},p("web_game_right")),H("p",{class:"learn-rescue-charat mono",dir:"ltr"},`alphabet.charAt(${k.answer})`,H("span",{"aria-hidden":"true"}," → "),H("code",{},`'${M}'`)),zn("div",{class:"learn-game-explain"},k.explanation),H("p",{class:"learn-rescue-moved"},p("web_learn_rescue_letter_moved")),U),U.focus({preventScroll:!0})};D.addEventListener("click",P),O.addEventListener("keydown",A=>{A.key==="Enter"&&P()}),m.replaceChildren(ic(k.code),zn("p",{class:"learn-game-question"},k.question),H("div",{class:"learn-rescue-answer"},O,D),j,H("p",{class:"learn-rescue-label"},p("web_learn_rescue_alphabet")),ic(`String alphabet = "${i.alphabet}";`),T.element,d.element),O.focus({preventScroll:!0})},x=()=>{c.textContent=p("web_learn_rescue_crossword");const z=H("div",{class:"learn-game-feedback",role:"status"}),k=H("button",{class:"primary"},p("web_learn_check"));k.addEventListener("click",()=>{if(!d.check()){z.className="learn-game-feedback wrong",z.replaceChildren(H("p",{},p("web_learn_rescue_cw_wrong")));return}k.disabled=!0,d.lock();const T=H("button",{class:"primary"},p("web_learn_rescue_to_gate"));T.addEventListener("click",v),z.className="learn-game-feedback right",z.replaceChildren(H("p",{},p("web_learn_rescue_cw_done")),T),T.focus({preventScroll:!0})}),d.unlock(),m.replaceChildren(zn("p",{},i.crosswordText),d.element,k,z),d.focusFirst()},v=()=>{c.textContent=p("web_learn_rescue_gate");const z=H("input",{type:"text",autocomplete:"off",autocapitalize:"off",spellcheck:"false",class:"learn-rescue-word mono",size:String(i.keyword.length+2),"aria-label":p("web_learn_rescue_word")}),k=i.gateCode.split(` -`).map(j=>{const P=j.indexOf(gs);return P<0?H("div",{class:"ln"},j||" "):H("div",{class:"ln"},j.slice(0,P),z,j.slice(P+gs.length))}),T=H("button",{class:"primary"},p("web_learn_rescue_open")),O=H("div",{class:"learn-game-feedback",role:"status"}),D=()=>{const j=z.value.trim();if(j!==i.keyword){const A=j.toUpperCase()===i.keyword.toUpperCase();O.className="learn-game-feedback wrong",O.replaceChildren(H("p",{},p(A?"web_learn_rescue_gate_case":"web_learn_rescue_gate_wrong"))),z.select();return}z.disabled=T.disabled=!0,t.classList.add("freed"),r.after(l),c.textContent="";const P=H("button",{},p("web_game_again"));P.addEventListener("click",w),O.className="learn-game-feedback right",O.replaceChildren(H("p",{},p("web_learn_rescue_freed")),zn("div",{class:"learn-game-explain"},i.end),P)};T.addEventListener("click",D),z.addEventListener("keydown",j=>{j.key==="Enter"&&D()}),m.replaceChildren(zn("p",{},i.gateText),H("div",{class:"learn-game-code mono learn-rescue-gate",dir:"ltr"},...k),T,O),z.focus({preventScroll:!0})},w=()=>{h=0,t.classList.remove("freed"),l.remove(),d.reset(),g(),b(0)},I=H("button",{class:"primary"},p("web_game_start"));return I.addEventListener("click",w),m.append(zn("p",{},i.intro),I),t}function tZ(i){const e=aB(i),t=new Map(i.solution.map((g,f)=>[`${g.row} ${g.col}`,f])),n=new Map;for(const g of i.words)n.set(`${g.row} ${g.col}`,g.number);const a=new Map,s=H("div",{class:"learn-cw-grid",dir:"ltr"});s.style.gridTemplateColumns=`repeat(${i.cols}, var(--cw-cell))`;let r=!0;const o=(g,f)=>i.words.filter(b=>b.across?b.row===g&&f>=b.col&&f=b.row&&g{var v;const x=r?`${g} ${f+b}`:`${g+b} ${f}`;(v=a.get(x))==null||v.focus()};e.forEach((g,f)=>g.forEach((b,x)=>{if(!b)return s.append(H("span",{class:"learn-cw-empty"}));const v=`${f} ${x}`,w=H("input",{type:"text",maxlength:"1",autocomplete:"off",autocapitalize:"characters",spellcheck:"false","aria-label":p("web_learn_rescue_cell_fmt",f+1,x+1)});w.disabled=!0,w.addEventListener("focus",()=>{const T=o(f,x);T.some(O=>O.across===r)||(r=T[0].across),w.select()}),w.addEventListener("input",()=>{w.value=w.value.slice(-1).toUpperCase(),w.classList.remove("wrong"),m(),w.value&&l(f,x,1)}),w.addEventListener("keydown",T=>{if(T.key==="Backspace"&&!w.value)l(f,x,-1);else if(T.key==="ArrowRight"||T.key==="ArrowLeft")r=!0,l(f,x,T.key==="ArrowRight"?1:-1);else if(T.key==="ArrowDown"||T.key==="ArrowUp")r=!1,l(f,x,T.key==="ArrowDown"?1:-1);else return;T.preventDefault()}),a.set(v,w);const I=t.get(v),z=H("span",{class:`learn-cw-cell${I!==void 0?" key":""}`}),k=n.get(v);k&&z.append(H("small",{class:"learn-cw-number"},String(k))),I!==void 0&&z.append(H("small",{class:"learn-cw-keyindex"},String(I+1))),z.append(w),s.append(z)}));const u=g=>{const f=H("ol",{class:"learn-cw-clues"});for(const b of i.words.filter(x=>x.across===g).sort((x,v)=>x.number-v.number)){const x=zn("li",{value:String(b.number)},`${b.clue} (${b.word.length})`);x.addEventListener("click",()=>{var v;r=b.across,(v=a.get(`${b.row} ${b.col}`))==null||v.focus()}),f.append(x)}return H("div",{},H("strong",{},p(g?"web_learn_rescue_across":"web_learn_rescue_down")),f)},c=i.solution.map(()=>H("span",{class:"learn-cw-keybox"})),m=()=>i.solution.forEach((g,f)=>c[f].textContent=a.get(`${g.row} ${g.col}`).value||" "),d=H("div",{class:"learn-cw"},H("div",{class:"learn-cw-board"},s,H("p",{class:"learn-cw-keyword"},`${p("web_learn_rescue_keyword")} `,H("span",{class:"mono",dir:"ltr"},...c))),H("div",{class:"learn-cw-cluebox"},u(!0),u(!1))),h=new Set;return{element:d,give(g,f,b){const x=a.get(`${g} ${f}`);x.value=b,x.parentElement.classList.add("given","arrived"),h.add(`${g} ${f}`),m()},unlock(){for(const[g,f]of a)f.disabled=h.has(g)},lock(){for(const g of a.values())g.disabled=!0},focusFirst(){var g;(g=[...a].find(([f])=>!h.has(f)))==null||g[1].focus({preventScroll:!0})},check(){let g=!0;for(const[f,b]of a){const[x,v]=f.split(" ").map(Number),w=b.value!==e[x][v];b.classList.toggle("wrong",w),w&&(g=!1)}return g},reset(){h.clear();for(const g of a.values())g.value="",g.disabled=!0,g.classList.remove("wrong"),g.parentElement.classList.remove("given","arrived");m()}}}function St(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 ac(i,e,t){const n=St(i,e);return n.innerHTML=Pe(t),n}function nZ(i){const e=St("section",{class:"learn-cloze"});e.append(St("strong",{class:"learn-cloze-title"},i.title)),i.task&&e.append(ac("p",{},i.task)),e.append(St("p",{class:"learn-cloze-hint"},p("web_learn_cloze_hint")));const t=[];for(const c of i.blocks){const m=St("pre",{class:"learn-cloze-code mono",dir:"ltr"});for(const d of c){const h=St("div",{class:"ln"});for(const g of d){if(typeof g=="string"){h.append(g);continue}const f=St("input",{type:"text",class:"learn-cloze-gap mono",autocomplete:"off",autocapitalize:"off",autocorrect:"off",spellcheck:"false",enterkeyhint:"done","aria-label":`${t.length+1}`});f.style.width=`${Math.max(3,...g.answers.map(b=>b.length))+1}ch`,t.push({input:f,answers:g.answers}),h.append(f)}d.length||h.append(` -`),m.append(h)}e.append(m)}const n=St("p",{class:"learn-cloze-status",role:"status"}),a=i.explanation?ac("p",{class:"learn-explanation"},i.explanation):void 0;a&&(a.hidden=!0);const s=St("button",{class:"learn-cloze-check"},p("web_learn_check")),r=St("button",{},p("web_learn_cloze_solution")),o=St("button",{},p("web_learn_cloze_again"));r.hidden=!0,o.hidden=!0;const l=St("div",{class:"learn-cloze-actions"},s,r,o);e.append(l,n),a&&e.append(a);const u=()=>{var d;let c=0;for(const h of t){const g=cB(h.answers,h.input.value);h.input.classList.toggle("right",g),h.input.classList.toggle("wrong",!g),g&&c++}const m=c===t.length;n.textContent=m?p("web_learn_cloze_all_right"):p("web_learn_cloze_score_fmt",c,t.length),n.className=`learn-cloze-status ${m?"right":"wrong"}`,a&&(a.hidden=!m),m?(t.forEach(h=>h.input.disabled=!0),s.hidden=!0,o.hidden=!1):(r.hidden=!1,(d=t.find(h=>h.input.classList.contains("wrong")))==null||d.input.focus())};return s.addEventListener("click",u),r.addEventListener("click",()=>{for(const c of t)c.input.value=c.answers[0],c.input.classList.remove("right","wrong"),c.input.classList.add("shown"),c.input.disabled=!0;n.textContent="",n.className="learn-cloze-status",a&&(a.hidden=!1),s.hidden=!0,r.hidden=!0,o.hidden=!1}),o.addEventListener("click",()=>{var c;for(const m of t)m.input.value="",m.input.classList.remove("right","wrong","shown"),m.input.disabled=!1;n.textContent="",n.className="learn-cloze-status",a&&(a.hidden=!0),s.hidden=!1,r.hidden=!0,o.hidden=!0,(c=t[0])==null||c.input.focus()}),t.forEach((c,m)=>{c.input.addEventListener("input",()=>c.input.classList.remove("right","wrong")),c.input.addEventListener("keydown",d=>{d.key==="Enter"&&(d.preventDefault(),m1?12:13});return n.forEach((s,r)=>{const o=yt("tspan",{x:e.x,y:e.y+4.5+(r-(n.length-1)/2)*14});o.textContent=s,a.append(o)}),a}function oa(i,e){return yt("polyline",{points:i.map(t=>t.join(",")).join(" "),fill:"none","marker-end":`url(#${e})`})}function sc(i,e,t,n){const a=yt("text",{x:e,y:t,"font-size":12,"font-weight":600,fill:n?"#248a3d":"#d70015"});return a.textContent=i,a}function sZ(i,e){const t=Uh(e,110),n=Math.max(...t.map(u=>u.length)),a=Math.max(70,n*6.6+(i==="raute"?56:26)),s=i==="raute"?48:t.length>1?40:30,r=yt("svg",{viewBox:`0 0 ${a+4} ${s+4}`,width:a+4,height:s+4,"aria-hidden":"true"}),o={x:(a+4)/2,y:(s+4)/2,w:a,h:s},l=l0(i,o);return l.setAttribute("fill",o0[i]),l.setAttribute("stroke","#1c1c1e"),l.setAttribute("stroke-width","1.5"),r.append(l,lg(e,{...o,w:t.length>1?124:a},i)),r}function rZ(i){const e=[...Array(i).keys()];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 i>1&&e.every((t,n)=>t===n)&&e.reverse(),e}function oZ(){const i=qe("dl",{class:"learn-pap-legend"}),e=[["oval","web_learn_pap_legend_oval"],["rechteck","web_learn_pap_legend_rect"],["raute","web_learn_pap_legend_diamond"],["parallelogramm","web_learn_pap_legend_para"]];for(const[t,n]of e){const a=t==="raute"?44:40,s=yt("svg",{viewBox:`0 0 ${a+4} 28`,width:a+4,height:28,"aria-hidden":"true"}),r=l0(t,{x:(a+4)/2,y:14,w:a,h:t==="raute"?24:18});r.setAttribute("fill",o0[t]),r.setAttribute("stroke","#1c1c1e"),r.setAttribute("stroke-width","1.5"),s.append(r),i.append(qe("dt",{},s),qe("dd",{},p(n)))}return i}function lZ(i){const e=qe("section",{class:"learn-pap"});if(e.append(qe("strong",{class:"learn-pap-title"},i.title)),i.task){const J=qe("p");J.innerHTML=Pe(i.task),e.append(J)}e.append(qe("p",{class:"learn-pap-hint"},p("web_learn_pap_hint")));const{boxes:t,height:n}=xB(i),a=t.filter(Boolean),s=Math.min(...a.map(J=>J.x-J.w/2))-4,r=i.nodes.some(J=>J.shape==="raute"),o=Math.max(...a.map(J=>J.x+J.w/2),r?Math.max(...a.map(J=>J.x))+85+40:0)+4,l=yt("svg",{viewBox:`${s} 0 ${o-s} ${n}`,class:"learn-pap-plan",role:"group","aria-label":i.title}),u=`pap-arrow-${++aZ}`;l.innerHTML=``;const c=yt("g",{stroke:"#1c1c1e","stroke-width":2}),m=yt("g"),d=p("web_learn_pap_yes"),h=p("web_learn_pap_no"),g=J=>t[J].y-t[J].h/2,f=J=>t[J].y+t[J].h/2,b=i.nodes.map((J,C)=>C).filter(J=>!i.nodes[J].isSide);b.forEach((J,C)=>{const N=i.nodes[J],q=t[J],Y=b[C+1];if(Y!==void 0&&(c.append(oa([[q.x,f(J)],[q.x,g(Y)-2]],u)),N.shape==="raute"&&m.append(sc(N.sideExit==="nein"?d:h,q.x+6,f(J)+13,N.sideExit==="nein"))),N.shape!=="raute")return;const ue=q.x+q.w/2;if(m.append(sc(N.sideExit==="ja"?d:h,ue+5,q.y-6,N.sideExit==="ja")),N.backTo!==void 0){const X=g(N.backTo)-14;c.append(oa([[ue,q.y],[ue+22,q.y],[ue+22,X],[q.x,X]],u))}else if(N.side!==void 0){const X=t[N.side],ce=g(J)-14;c.append(oa([[ue,q.y],[X.x-X.w/2-2,q.y]],u)),c.append(oa([[X.x,X.y-X.h/2],[X.x,ce],[q.x,ce]],u))}}),l.append(c,m);const x=i.nodes.map(()=>{}),v=[],w=[];let I;const z=qe("p",{class:"learn-pap-status",role:"status"}),k=i.explanation?qe("p",{class:"learn-explanation"}):void 0;k&&(k.innerHTML=Pe(i.explanation),k.hidden=!0);let T=!1;const O=()=>{v.forEach(J=>J.classList.remove("right","wrong")),z.textContent="",z.className="learn-pap-status"},D=J=>{const C=v[J];C.replaceChildren();const N=i.nodes[J],q=x[J],Y=l0(N.shape,t[J]);if(Y.setAttribute("class","learn-pap-shape"),q===void 0)Y.setAttribute("fill","#f7f7f9"),Y.setAttribute("stroke-dasharray","6 4"),C.append(Y),C.setAttribute("aria-label",p("web_learn_pap_empty"));else{const ue=i.nodes[q];Y.setAttribute("fill",o0[ue.shape]),C.append(Y,lg(ue.text,t[J],N.shape)),C.setAttribute("aria-label",ue.text)}},j=()=>{i.nodes.forEach((J,C)=>D(C)),w.forEach((J,C)=>{J.hidden=x.includes(C),J.classList.toggle("selected",I===C)})},P=(J,C)=>{if(T)return;const N=x.indexOf(C);N>=0&&(x[N]=void 0),x[J]=C,I=void 0,O(),j()};i.nodes.forEach((J,C)=>{const N=yt("g",{class:"learn-pap-slot","data-slot":C,tabindex:0,role:"button"}),q=()=>{T||(I!==void 0?P(C,I):x[C]!==void 0&&(x[C]=void 0,O(),j()))};N.addEventListener("click",q),N.addEventListener("keydown",Y=>{Y.key!=="Enter"&&Y.key!==" "||(Y.preventDefault(),q())}),v.push(N),l.append(N)});const A=qe("div",{class:"learn-pap-tray"});let M=!1;for(const J of rZ(i.nodes.length)){const C=i.nodes[J],N=qe("button",{class:"learn-pap-card",type:"button","aria-label":C.text},sZ(C.shape,C.text));w[J]=N,N.addEventListener("click",()=>{M||T||(I=I===J?void 0:J,j())}),N.addEventListener("pointerdown",q=>{if(T)return;M=!1;let Y;const ue=le=>{var Te;!Y&&Math.hypot(le.clientX-q.clientX,le.clientY-q.clientY)<6||(Y||(M=!0,Y=N.cloneNode(!0),Y.classList.add("learn-pap-ghost"),document.body.append(Y),N.classList.add("dragging")),Y.style.left=`${le.clientX}px`,Y.style.top=`${le.clientY}px`,v.forEach(Fe=>Fe.classList.remove("over")),(Te=X(le))==null||Te.classList.add("over"))},X=le=>{var Fe;Y&&(Y.style.display="none");const Te=(Fe=document.elementFromPoint(le.clientX,le.clientY))==null?void 0:Fe.closest("[data-slot]");return Y&&(Y.style.display=""),Te&&v.includes(Te)?Te:void 0},ce=le=>{if(N.removeEventListener("pointermove",ue),N.removeEventListener("pointerup",ce),N.removeEventListener("pointercancel",ce),v.forEach(Fe=>Fe.classList.remove("over")),N.classList.remove("dragging"),!Y)return;const Te=le.type==="pointerup"?X(le):void 0;Y.remove(),Te&&P(Number(Te.getAttribute("data-slot")),J),setTimeout(()=>M=!1)};N.setPointerCapture(q.pointerId),N.addEventListener("pointermove",ue),N.addEventListener("pointerup",ce),N.addEventListener("pointercancel",ce)}),A.append(N)}const W=qe("button",{class:"learn-pap-check"},p("web_learn_check")),U=qe("button",{},p("web_learn_cloze_solution")),K=qe("button",{},p("web_learn_cloze_again"));U.hidden=!0,K.hidden=!0;const he=()=>{T=!0,W.hidden=!0,U.hidden=!0,K.hidden=!1,A.hidden=!0,fe.classList.add("done"),k&&(k.hidden=!1)};W.addEventListener("click",()=>{const J=x.filter(q=>q===void 0).length;let C=0;x.forEach((q,Y)=>{const ue=q!==void 0&&dB(i,Y,q);v[Y].classList.toggle("right",ue),v[Y].classList.toggle("wrong",q!==void 0&&!ue),ue&&C++});const N=C===i.nodes.length;z.textContent=N?p("web_learn_pap_all_right"):J?p("web_learn_pap_missing_fmt",J):p("web_learn_pap_score_fmt",C,i.nodes.length),z.className=`learn-pap-status ${N?"right":"wrong"}`,N?he():J||(U.hidden=!1)}),U.addEventListener("click",()=>{i.nodes.forEach((J,C)=>x[C]=C),I=void 0,j(),O(),v.forEach(J=>J.classList.add("shown")),he()}),K.addEventListener("click",()=>{i.nodes.forEach((J,C)=>x[C]=void 0),T=!1,I=void 0,v.forEach(J=>J.classList.remove("shown")),O(),j(),W.hidden=!1,K.hidden=!0,A.hidden=!1,fe.classList.remove("done"),k&&(k.hidden=!0)}),j();const Ie=qe("div",{class:"learn-pap-left"});Ie.append(l),i.legend&&Ie.append(oZ());const fe=qe("div",{class:"learn-pap-work"},Ie,A);return e.append(fe,qe("div",{class:"learn-pap-actions"},W,U,K),z),k&&e.append(k),e}const uZ="code, pre, a, button, h1, h2, h3, h4, strong, .term, .ui-pointer";function rc(i,e){var s;const t=[...i.querySelectorAll(".learn-text")],n=new Set;for(const r of t.flatMap(o=>[...o.querySelectorAll("strong")])){const o=Lu(e),l=o==null?void 0:o.exec(r.textContent??""),u=l?Eu(e,l[0]):void 0;u&&n.add(u)}let a=e.filter(r=>!n.has(r));for(const r of t){const o=document.createTreeWalker(r,NodeFilter.SHOW_TEXT),l=[];for(;o.nextNode();){const u=o.currentNode;(s=u.parentElement)!=null&&s.closest(uZ)||l.push(u)}for(let u of l)for(;;){const c=Lu(a),m=c==null?void 0:c.exec(u.data),d=m?Eu(a,m[0]):void 0;if(!m||!d)break;const h=u.splitText(m.index);u=h.splitText(m[0].length);const g=document.createElement("span");g.className="term",g.tabIndex=0,g.setAttribute("role","button"),g.setAttribute("aria-describedby","term-tip"),g.dataset.term=d.term,g.dataset.text=d.text,h.replaceWith(g),g.append(h),a=a.filter(f=>f!==d)}}}function cZ(i){const e=document.createElement("div");e.id="term-tip",e.className="term-tip",e.setAttribute("role","tooltip"),e.hidden=!0,document.body.append(e);let t,n=!1;const a=o=>{t=o,e.replaceChildren();const l=document.createElement("strong");l.textContent=o.dataset.term??"",e.append(l,document.createTextNode(" "+(o.dataset.text??""))),e.hidden=!1;const u=o.getBoundingClientRect(),c=e.offsetWidth,m=e.offsetHeight,d=Math.max(8,Math.min(u.left,window.innerWidth-c-8)),h=u.bottom+6;e.style.left=`${d}px`,e.style.top=`${h+m>window.innerHeight-8?Math.max(8,u.top-m-6):h}px`,o.setAttribute("aria-expanded","true")},s=()=>{t==null||t.setAttribute("aria-expanded","false"),t=void 0,n=!1,e.hidden=!0},r=o=>{var l,u;return((u=(l=o.target)==null?void 0:l.closest)==null?void 0:u.call(l,".term"))??void 0};return i.addEventListener("pointerover",o=>{const l=r(o);l&&o.pointerType==="mouse"&&!n&&a(l)}),i.addEventListener("pointerout",o=>{r(o)&&o.pointerType==="mouse"&&!n&&s()}),i.addEventListener("click",o=>{const l=r(o);if(l){if(n&&t===l)return s();a(l),n=!0}}),i.addEventListener("focusin",o=>{const l=r(o);l&&!n&&a(l)}),i.addEventListener("focusout",o=>{r(o)&&!n&&s()}),i.addEventListener("keydown",o=>{const l=r(o);o.key==="Escape"&&t?s():l&&(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),l.click())}),i.addEventListener("scroll",s,!0),document.addEventListener("pointerdown",o=>{t&&!r(o)&&!e.contains(o.target)&&s()}),{hide:s}}const ug={leiste:".topbar > .toolbar",editor:".editor-rail, .columns > .app",werkzeuge:".diagram-tools",dateien:".files-rail, .files",codelive:".live-rail, .livecode",ausfuehren:"[data-run=play]",konsole:".livecode .console",einzelschritt:"[data-run=step]",elemente:".palette",struktogramm:".canvas",objektinspektor:".inspector",reiter:".tabs",titel:".caption",neu:"[data-action=new]",oeffnen:"[data-action=open]",speichern:"[data-action=save]",exportieren:"[data-action=export]",rueckgaengig:"[data-action=undo]",loeschen:"[data-action=delete]",textgroesse:"[data-action=settings]",einstellungen:"[data-action=settings]",lernen:".learn .learn-hide",code:"[data-action=code]",simulation:"[data-action=simulate]"},cg=new Set(["editor","werkzeuge","elemente","struktogramm","objektinspektor","reiter","titel","rueckgaengig","loeschen","exportieren","code","simulation"]),mg=new Set(["ausfuehren","konsole","einzelschritt"]);function Qs(i,e){return[...i.querySelectorAll(".ui-pointer")].some(t=>e.has(t.dataset.target??""))}function oc(i){return i==="elemente"?["editor","palette"]:cg.has(i)?["editor"]:i==="codelive"||mg.has(i)?["livecode"]:i==="dateien"?["files"]:[]}function mZ(i){return Qs(i,new Set(["elemente"]))}function dZ(i){return Qs(i,new Set(["dateien"]))}function hZ(i){return Qs(i,cg)}function gZ(i){return Qs(i,mg)}function lc(i){for(const e of i.querySelectorAll('a[href^="#zeige-"]')){const t=e.getAttribute("href").slice(7);if(!(t in ug))continue;const n=document.createElement("span");n.className="ui-pointer",n.tabIndex=0,n.setAttribute("role","button"),n.dataset.target=t,n.append(...e.childNodes),e.replaceWith(n)}}function pZ(i,e=()=>()=>{}){let t,n,a,s,r;const o=()=>{t==null||t.classList.remove("ui-spot"),t=void 0,window.clearTimeout(n)},l=(h,g)=>{o();const f=[...document.querySelectorAll(ug[h.dataset.target??""]??":not(*)")].find(b=>b.getClientRects().length>0);f&&(t=f,f.classList.add("ui-spot"),g&&(n=window.setTimeout(o,2500)))},u=(h,g)=>requestAnimationFrame(()=>{l(h,g),t==null||t.scrollIntoView({block:"nearest",inline:"nearest"})}),c=()=>{window.clearTimeout(s),window.clearTimeout(r),a==null||a(),a=void 0},m=h=>{window.clearTimeout(s),window.clearTimeout(r),a=void 0,e(oc(h.dataset.target??"")),l(h,!0),u(h,!0)},d=h=>{var g,f;return((f=(g=h.target)==null?void 0:g.closest)==null?void 0:f.call(g,".ui-pointer"))??void 0};return i.addEventListener("pointerover",h=>{const g=d(h);!g||h.pointerType!=="mouse"||(window.clearTimeout(r),l(g,!1),window.clearTimeout(s),s=window.setTimeout(()=>{if(a)return;const f=oc(g.dataset.target??"");f.length!==0&&(a=e(f),u(g,!1))},250))}),i.addEventListener("pointerout",h=>{!d(h)||h.pointerType!=="mouse"||(o(),window.clearTimeout(s),window.clearTimeout(r),r=window.setTimeout(c,400))}),i.addEventListener("click",h=>{const g=d(h);g&&m(g)}),i.addEventListener("focusin",h=>{const g=d(h);g&&l(g,!1)}),i.addEventListener("focusout",h=>{d(h)&&o()}),i.addEventListener("keydown",h=>{const g=d(h);g&&(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),m(g))}),{off:()=>{c(),o()}}}const _t='',fZ=()=>{const i=[];for(const e of Pt){const t=i.at(-1);t&&t.name===e.section?t.lessons.push(e):i.push({name:e.section,lessons:[e]})}return i};function _(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 tt(i,e,t){const n=_(i,e);return n.innerHTML=t,n}const bZ=i=>p(`element_${S[i]}`);function xZ(i){return{caption:i,elements:[Oe(S.anweisung,{textLines:["ø"]})]}}function uc(i){const e=i.start?ti(i.start):void 0;return e?{...e,caption:e.caption||i.title}:xZ(i.title)}class vZ{constructor(e){y(this,"element");y(this,"tab","lessons");y(this,"returnTo");y(this,"lessonId");y(this,"taskId");y(this,"body");y(this,"tips");y(this,"pointers");this.host=e,this.element=_("aside",{class:"learn","aria-label":p("web_learn_title")}),this.tips=cZ(this.element),this.pointers=pZ(this.element,t=>this.host.reveal(t)),fs(Gu(s1())),this.restore()}restore(){const e=be.view();e&&(this.tab=["lessons","tasks","reference"].find(t=>t===e.tab)??"lessons",this.lessonId=Pt.some(t=>t.id===e.lesson)?e.lesson:void 0,this.taskId=An.some(t=>t.id===e.task)?e.task:void 0),this.render()}render(){this.tips.hide(),this.pointers.off(),fs(Gu(s1()));const e=_("div",{class:"segmented learn-tabs",role:"tablist"});for(const[a,s]of[["lessons",p("web_learn_lessons")],["tasks",p("web_learn_tasks")],["reference",p("web_learn_reference")]]){const r=_("button",{role:"tab","aria-pressed":String(this.tab===a),"data-learn-tab":a},s);r.addEventListener("click",()=>{this.tab===a&&(a==="lessons"&&(this.lessonId=void 0),a==="tasks"&&(this.taskId=void 0)),this.tab=a,this.persist(),this.render()}),e.append(r)}const t=tt("button",{class:"learn-hide",title:p("web_learn_hide"),"aria-label":p("web_learn_hide")},_t);t.addEventListener("click",()=>this.host.collapse());const n=_("div",{class:"learn-head"},e,t);if(this.body=_("div",{class:"learn-body"}),this.element.replaceChildren(n,this.body),this.tab==="lessons"){const a=Pt.find(s=>s.id===this.lessonId);a?this.renderLesson(a):this.renderLessonList()}else if(this.tab==="tasks"){const a=An.find(s=>s.id===this.taskId);a?this.renderTask(a):this.renderTaskList()}else{const a=Na.map(r=>`- **${r.term}:** ${r.text}`).join(` + `;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,Ku(Xu,this.highlightMode)});const n=e("[data-sim=delay]");n.value=this.delay,n.addEventListener("change",()=>{this.delay=n.value,Ku(wr,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),c=l.insertCell();u.kind==="grid"?c.append(rg(u)):c.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}),...sg(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?t1(r):"",o.hidden=!r}}function rg(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 x1=Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),Gn=360/x1.length,RB="http://www.w3.org/2000/svg";function Je(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 xt(i,e={},t){const n=document.createElementNS(RB,i);for(const[a,s]of Object.entries(e))n.setAttribute(a,String(s));return t!==void 0&&(n.textContent=t),n}function GB(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 ec(i,e){const t=xt("g",{class:e}),n=x1.map((a,s)=>{const r=xt("g",{transform:`rotate(${s*Gn})`});return r.append(xt("text",{x:0,y:-i,"text-anchor":"middle","dominant-baseline":"central"},a)),t.append(r),r});return{group:t,cells:n}}function HB(i,e){let t=i,n=!1,a=-t*Gn;const s=Je("section",{class:"learn-game learn-caesar"});s.append(Je("div",{class:"learn-game-head"},Je("strong",{},p("web_learn_caesar_title")))),s.append(Je("p",{class:"learn-game-status"},p("web_learn_caesar_hint")));const r=xt("svg",{viewBox:"-200 -200 400 400",class:"learn-caesar-disc",role:"img"});r.append(xt("circle",{r:196,class:"outer-disc"})),r.append(xt("path",{d:VB(196,92,Gn/2),class:"window"}));const o=ec(168,"outer-letters");r.append(o.group);for(let A=0;A{o.cells.forEach((M,W)=>M.classList.toggle("marked",W===A)),u.cells.forEach((M,W)=>M.classList.toggle("marked",A!==void 0&&W===(A+t)%26))},T=()=>{c.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),I.textContent=GB(v.value,n?-t:t)||" ";const A=Array.from(v.value.toUpperCase()).reverse().find(W=>x1.includes(W));if(A===void 0)return k();const M=x1.indexOf(A);k(n?(M-t+26)%26:M)},O=A=>{t=(A%26+26)%26,a=-t*Gn,T()};m.addEventListener("click",()=>O(t-1)),d.addEventListener("click",()=>O(t+1)),f.addEventListener("click",()=>{var A;n&&(v.value=((A=I.textContent)==null?void 0:A.trim())??""),n=!1,T()}),b.addEventListener("click",()=>{var A;n||(v.value=((A=I.textContent)==null?void 0:A.trim())??""),n=!0,T()}),v.addEventListener("input",T),o.cells.forEach((A,M)=>A.addEventListener("click",()=>k(M)));let D;const P=A=>{const M=r.getBoundingClientRect();return Math.atan2(A.clientY-(M.top+M.height/2),A.clientX-(M.left+M.width/2))*180/Math.PI};l.addEventListener("pointerdown",A=>{const M=A;D=P(M)-a,l.classList.add("dragging"),r.setPointerCapture(M.pointerId),M.preventDefault()}),r.addEventListener("pointermove",A=>{if(D===void 0)return;a=P(A)-D,l.setAttribute("transform",`rotate(${a})`);const M=Math.round(-a/Gn);if((M%26+26)%26!==t){t=(M%26+26)%26;const W=a;T(),a=W,l.setAttribute("transform",`rotate(${a})`)}});const j=()=>{D!==void 0&&(D=void 0,l.classList.remove("dragging"),O(t))};return r.addEventListener("pointerup",j),r.addEventListener("pointercancel",j),T(),s}function VB(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 r0=i=>p(`web_visubot_part_${i}`),og=new WeakMap;function lg(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=(m,d,h)=>{r.hidden=!1,r.textContent=r0(m),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:m}=await import("./robot3d-CCjHhNM_.js");return{Robot3D:m}},[],import.meta.url).then(({Robot3D:m})=>{const d=new m(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(m=>{console.error(m),s.textContent=p("web_visubot_no_3d")}),c={box:a,ready:u,focus:i,view:e};return og.set(a,c),c}function qB(i,e,t=!1){return lg(i,e,t).box}function QB(i){const e=i.querySelector(".visubot-model"),t=e&&og.get(e);for(const n of i.querySelectorAll("[data-robot-part]")){const a=(n.dataset.robotPart??"").split(",").filter(Boolean);if(n.title=a.map(r0).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 UB(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=Tn(`**${t+1}/${i.length}** ${i[t].question}`)},r=lg([],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",r0(l));return}t++,a.className="visubot-quiz-feedback right",t{u.forEach(v=>{window.clearTimeout(v),window.clearInterval(v)}),u=[]},m=()=>{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,I=$("div",{class:"learn-bomb-fuse"},$("span",{})),z=$("span",{class:"learn-bomb-time"}),k=$("div",{class:"learn-bomb","aria-live":"polite"},$("span",{class:"learn-bomb-icon","aria-hidden":"true"},"💣"),z,I),T=$("div",{class:"learn-game-feedback",role:"status"}),O=v.code.split(` +`).map((W,U)=>{const K=$("button",{class:"ln",type:"button"},W||" ");return K.disabled=!W.trim(),K.addEventListener("click",()=>A(U+1===v.wrongLine?"right":"wrong",K)),K}),D=$("div",{class:"learn-game-code learn-bomb-code mono",dir:"ltr"},...O),P=Date.now(),j=()=>{if(!t.isConnected&&Date.now()-P>1e3)return c();const W=Math.max(0,w-(Date.now()-P)/1e3);z.textContent=p("web_game_time_fmt",Math.ceil(W)),I.firstChild.style.width=`${W/w*100}%`,k.classList.toggle("hurry",W<=5),W<=0&&A("time")},A=(W,U)=>{c(),O.forEach((Ie,fe)=>{Ie.disabled=!0,fe+1===v.wrongLine&&Ie.classList.add("right")}),U&&W==="wrong"&&U.classList.add("wrong");const K=W==="right";K&&l++,m(),k.classList.add(K?"defused":"boom"),k.firstChild.textContent=K?"✂️":"💥",T.className=`learn-game-feedback ${K?"right":"wrong"}`;const he=d();T.replaceChildren($("p",{},p(K?"web_game_defused":W==="time"?"web_game_boom_time":"web_game_boom_wrong")),Jn("div",{class:"learn-game-explain"},v.explanation),$("p",{class:"learn-bomb-fix"},`${p("web_game_fix")} `,$("code",{},v.fix.trim())),he),he.focus({preventScroll:!0})};s.replaceChildren(k,Jn("p",{class:"learn-game-question"},v.question),D,T),j();const M=window.setInterval(j,200);u.push(M)},g=()=>{const v=i.rounds[o],w=[];v.code.trim()&&w.push(nc(v.code).element),w.push(Jn("p",{class:"learn-game-question"},v.question),$("p",{class:"learn-order-hint"},p("web_game_order_hint")));const I=$("div",{class:"learn-game-options learn-order"}),z=$("div",{class:"learn-game-feedback",role:"status"});let k=0;const T=YB(v.options.length).map(D=>{const P=$("span",{class:"learn-order-badge","aria-hidden":"true"}),j=$("span",{});j.innerHTML=je(v.options[D].text);const A=$("button",{},P,j);return A.addEventListener("click",()=>{if(D!==k)return A.classList.add("wrong"),O(!1);A.classList.add("right"),P.textContent=String(++k),A.disabled=!0,k===v.options.length&&O(!0)}),I.append(A),{k:D,b:A,badge:P}}),O=D=>{for(const{k:j,b:A,badge:M}of[...T].sort((W,U)=>W.k-U.k))A.disabled=!0,M.textContent=String(j+1),I.append(A);D&&l++,m(),z.className=`learn-game-feedback ${D?"right":"wrong"}`;const P=d();z.replaceChildren($("p",{},p(D?"web_game_right":"web_game_wrong_short")),Jn("div",{class:"learn-game-explain"},v.explanation),P),P.focus({preventScroll:!0})};s.replaceChildren(...w,I,z)},f=()=>{if(c(),i.kind==="bombe"||i.kind==="reihenfolge"){m(),i.kind==="bombe"?h():g();return}const v=i.rounds[o];m();const w=nc(v.code),I=[];let z;i.kind==="zuhoerer"?(z=XB(Gh(v.code),w),I.push($("div",{class:"learn-swing-row"},w.element,z.element)),v.clicks.length&&I.push($("p",{class:"learn-swing-clicks"},`${p("web_game_clicks")} `,...v.clicks.flatMap((P,j)=>[...j?[" → "]:[],$("code",{},P)])))):v.code.trim()&&I.push(w.element),I.push(Jn("p",{class:"learn-game-question"},v.question));const k=$("div",{class:`learn-game-options ${i.kind==="layout"?"pictures":""}`}),T=$("div",{class:"learn-game-feedback",role:"status"}),O=v.options.map(P=>{const j=$("button",{});return i.kind==="layout"?j.append(eZ(P.text)):P.text.includes(` +`)?j.append(KB(P.text)):j.innerHTML=je(P.text),j.addEventListener("click",()=>D(P.right,j)),k.append(j),j}),D=(P,j)=>{O.forEach((M,W)=>{M.disabled=!0,v.options[W].right&&M.classList.add("right")}),P||j.classList.add("wrong"),P&&l++,m(),T.className=`learn-game-feedback ${P?"right":"wrong"}`;const A=d();T.replaceChildren($("p",{},p(P?"web_game_right":"web_game_wrong_short")),Jn("div",{class:"learn-game-explain"},v.explanation)),T.append(A),z&&(u=z.replay(v.clicks,()=>A.before($("p",{class:"learn-swing-try"},p("web_game_try"))))),A.focus({preventScroll:!0})};s.replaceChildren(...I,k,T)},b=()=>{c(),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(Jn("p",{},i.intro),x),t}function YB(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 nc(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 XB(i,e){const t=Hh(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 m of i.labels){const d=$("div",{class:"learn-swing-label"},t.texts[m.name]);s.set(m.name,d),a.append(d)}const r=i.buttons.map(m=>{const d=$("button",{class:"learn-swing-button",disabled:""},t.texts[m.name]);return s.set(m.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=m=>{var h,g;const d=s.get(m.button);d.classList.add("pressed"),window.setTimeout(()=>d.classList.remove("pressed"),350),e.highlight((h=m.listener)==null?void 0:h.from,(g=m.listener)==null?void 0:g.to),o.textContent=m.listener?p("web_game_event_fmt",d.textContent??""):p("web_game_nobody"),o.className=`learn-swing-event ${m.listener?"heard":"nobody"}`;for(const[f,b]of Object.entries(m.texts)){const x=s.get(f);x&&x.textContent!==b&&(x.textContent=b,x.classList.remove("changed"),x.offsetWidth,x.classList.add("changed"))}m.console.length&&(l.hidden=!1,l.textContent+=m.console.map(f=>`${f} +`).join(""))},c=m=>u(Vh(i,t,m));return{element:n,replay(m,d){const h=m.map((g,f)=>window.setTimeout(()=>c(g),(f+.3)*tc));return h.push(window.setTimeout(()=>{i.buttons.forEach((g,f)=>{r[f].disabled=!1,r[f].addEventListener("click",()=>u(qh(i,t,g.name)))}),d()},(m.length+.3)*tc)),h}}}function KB(i){return $("pre",{class:"learn-game-file mono",dir:"ltr"},i)}function eZ(i){const e=Rh(i),t=$("div",{class:"learn-layout-window",dir:"ltr"},$("div",{class:"learn-layout-title"})),n=$("div",{class:`learn-layout-body ${e.kind}`}),a=(s,r)=>$("span",{class:"learn-layout-cell",...r?{style:`grid-area:${r}`}:{}},s);if(e.kind==="border")for(const[s,r]of Object.entries(e.areas))n.append(a(r,s));else if(e.kind==="grid"){const s=Math.max(...e.rows.map(r=>r.length));n.style.gridTemplateColumns=`repeat(${s}, 1fr)`;for(const r of e.rows)for(let o=0;oa(r))));return t.append(n),t}function H(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 zn(i,e,t){const n=H(i,e);return n.innerHTML=je(t),n}function ic(i){return H("pre",{class:"learn-game-code mono",dir:"ltr"},...i.split(` +`).map(e=>H("div",{class:"ln"},e||" ")))}function tZ(i,e){const t=H("section",{class:"learn-game learn-rescue"}),n=H("div",{class:"learn-game-head"});n.append(H("img",{src:e,alt:"",width:"40",height:"40"}),H("strong",{},i.title));const a=i.stations.length,s=i.stations.map(()=>H("span",{class:"learn-rescue-dot"})),r=H("img",{class:"learn-rescue-ludwig",src:e,alt:"",width:"32",height:"32"}),o=H("span",{class:"learn-rescue-tower","aria-hidden":"true"},"🏰",H("span",{class:"learn-rescue-zora"},"🐐"),H("span",{class:"learn-rescue-fox"},"🦊")),l=H("span",{class:"learn-rescue-free"},"🐐"),u=H("div",{class:"learn-rescue-path","aria-hidden":"true"},r,...s,o),c=H("p",{class:"learn-game-status"}),m=H("div",{class:"learn-game-stage"}),d=nZ(i);t.append(n,u,c,m);let h=0;const g=()=>{s.forEach((z,k)=>z.classList.toggle("done",k{const z=[...i.alphabet].map((k,T)=>H("span",{class:"learn-rescue-letter"},H("b",{},k),H("small",{},String(T))));return{element:H("div",{class:"learn-rescue-alphabet mono",dir:"ltr"},...z),cells:z}},b=z=>{const k=i.stations[z];c.textContent=p("web_learn_rescue_station_fmt",z+1,a,k.name);const T=f(),O=H("input",{type:"text",inputmode:"numeric",autocomplete:"off",class:"learn-rescue-number mono","aria-label":p("web_learn_rescue_number")}),D=H("button",{class:"primary"},p("web_learn_check")),P=H("div",{class:"learn-game-feedback",role:"status"}),j=()=>{const A=O.value.trim();if(!/^-?\d+$/.test(A)){P.className="learn-game-feedback wrong",P.replaceChildren(H("p",{},p("web_learn_rescue_not_number")));return}if(Number(A)!==k.answer){P.className="learn-game-feedback wrong",P.replaceChildren(H("p",{},p("web_learn_rescue_wrong")),...k.hint?[zn("div",{class:"learn-game-explain"},`**${p("web_learn_hint")}:** ${k.hint}`)]:[]),O.select();return}O.disabled=D.disabled=!0;const M=i.alphabet.charAt(k.answer);T.cells[k.answer].classList.add("hit"),d.give(k.row,k.col,M),h++,g();const W=z+1===a,U=H("button",{class:"primary"},p(W?"web_learn_rescue_to_crossword":"web_game_next"));U.addEventListener("click",()=>W?x():b(z+1)),P.className="learn-game-feedback right",P.replaceChildren(H("p",{},p("web_game_right")),H("p",{class:"learn-rescue-charat mono",dir:"ltr"},`alphabet.charAt(${k.answer})`,H("span",{"aria-hidden":"true"}," → "),H("code",{},`'${M}'`)),zn("div",{class:"learn-game-explain"},k.explanation),H("p",{class:"learn-rescue-moved"},p("web_learn_rescue_letter_moved")),U),U.focus({preventScroll:!0})};D.addEventListener("click",j),O.addEventListener("keydown",A=>{A.key==="Enter"&&j()}),m.replaceChildren(ic(k.code),zn("p",{class:"learn-game-question"},k.question),H("div",{class:"learn-rescue-answer"},O,D),P,H("p",{class:"learn-rescue-label"},p("web_learn_rescue_alphabet")),ic(`String alphabet = "${i.alphabet}";`),T.element,d.element),O.focus({preventScroll:!0})},x=()=>{c.textContent=p("web_learn_rescue_crossword");const z=H("div",{class:"learn-game-feedback",role:"status"}),k=H("button",{class:"primary"},p("web_learn_check"));k.addEventListener("click",()=>{if(!d.check()){z.className="learn-game-feedback wrong",z.replaceChildren(H("p",{},p("web_learn_rescue_cw_wrong")));return}k.disabled=!0,d.lock();const T=H("button",{class:"primary"},p("web_learn_rescue_to_gate"));T.addEventListener("click",v),z.className="learn-game-feedback right",z.replaceChildren(H("p",{},p("web_learn_rescue_cw_done")),T),T.focus({preventScroll:!0})}),d.unlock(),m.replaceChildren(zn("p",{},i.crosswordText),d.element,k,z),d.focusFirst()},v=()=>{c.textContent=p("web_learn_rescue_gate");const z=H("input",{type:"text",autocomplete:"off",autocapitalize:"off",spellcheck:"false",class:"learn-rescue-word mono",size:String(i.keyword.length+2),"aria-label":p("web_learn_rescue_word")}),k=i.gateCode.split(` +`).map(P=>{const j=P.indexOf(gs);return j<0?H("div",{class:"ln"},P||" "):H("div",{class:"ln"},P.slice(0,j),z,P.slice(j+gs.length))}),T=H("button",{class:"primary"},p("web_learn_rescue_open")),O=H("div",{class:"learn-game-feedback",role:"status"}),D=()=>{const P=z.value.trim();if(P!==i.keyword){const A=P.toUpperCase()===i.keyword.toUpperCase();O.className="learn-game-feedback wrong",O.replaceChildren(H("p",{},p(A?"web_learn_rescue_gate_case":"web_learn_rescue_gate_wrong"))),z.select();return}z.disabled=T.disabled=!0,t.classList.add("freed"),r.after(l),c.textContent="";const j=H("button",{},p("web_game_again"));j.addEventListener("click",w),O.className="learn-game-feedback right",O.replaceChildren(H("p",{},p("web_learn_rescue_freed")),zn("div",{class:"learn-game-explain"},i.end),j)};T.addEventListener("click",D),z.addEventListener("keydown",P=>{P.key==="Enter"&&D()}),m.replaceChildren(zn("p",{},i.gateText),H("div",{class:"learn-game-code mono learn-rescue-gate",dir:"ltr"},...k),T,O),z.focus({preventScroll:!0})},w=()=>{h=0,t.classList.remove("freed"),l.remove(),d.reset(),g(),b(0)},I=H("button",{class:"primary"},p("web_game_start"));return I.addEventListener("click",w),m.append(zn("p",{},i.intro),I),t}function nZ(i){const e=sB(i),t=new Map(i.solution.map((g,f)=>[`${g.row} ${g.col}`,f])),n=new Map;for(const g of i.words)n.set(`${g.row} ${g.col}`,g.number);const a=new Map,s=H("div",{class:"learn-cw-grid",dir:"ltr"});s.style.gridTemplateColumns=`repeat(${i.cols}, var(--cw-cell))`;let r=!0;const o=(g,f)=>i.words.filter(b=>b.across?b.row===g&&f>=b.col&&f=b.row&&g{var v;const x=r?`${g} ${f+b}`:`${g+b} ${f}`;(v=a.get(x))==null||v.focus()};e.forEach((g,f)=>g.forEach((b,x)=>{if(!b)return s.append(H("span",{class:"learn-cw-empty"}));const v=`${f} ${x}`,w=H("input",{type:"text",maxlength:"1",autocomplete:"off",autocapitalize:"characters",spellcheck:"false","aria-label":p("web_learn_rescue_cell_fmt",f+1,x+1)});w.disabled=!0,w.addEventListener("focus",()=>{const T=o(f,x);T.some(O=>O.across===r)||(r=T[0].across),w.select()}),w.addEventListener("input",()=>{w.value=w.value.slice(-1).toUpperCase(),w.classList.remove("wrong"),m(),w.value&&l(f,x,1)}),w.addEventListener("keydown",T=>{if(T.key==="Backspace"&&!w.value)l(f,x,-1);else if(T.key==="ArrowRight"||T.key==="ArrowLeft")r=!0,l(f,x,T.key==="ArrowRight"?1:-1);else if(T.key==="ArrowDown"||T.key==="ArrowUp")r=!1,l(f,x,T.key==="ArrowDown"?1:-1);else return;T.preventDefault()}),a.set(v,w);const I=t.get(v),z=H("span",{class:`learn-cw-cell${I!==void 0?" key":""}`}),k=n.get(v);k&&z.append(H("small",{class:"learn-cw-number"},String(k))),I!==void 0&&z.append(H("small",{class:"learn-cw-keyindex"},String(I+1))),z.append(w),s.append(z)}));const u=g=>{const f=H("ol",{class:"learn-cw-clues"});for(const b of i.words.filter(x=>x.across===g).sort((x,v)=>x.number-v.number)){const x=zn("li",{value:String(b.number)},`${b.clue} (${b.word.length})`);x.addEventListener("click",()=>{var v;r=b.across,(v=a.get(`${b.row} ${b.col}`))==null||v.focus()}),f.append(x)}return H("div",{},H("strong",{},p(g?"web_learn_rescue_across":"web_learn_rescue_down")),f)},c=i.solution.map(()=>H("span",{class:"learn-cw-keybox"})),m=()=>i.solution.forEach((g,f)=>c[f].textContent=a.get(`${g.row} ${g.col}`).value||" "),d=H("div",{class:"learn-cw"},H("div",{class:"learn-cw-board"},s,H("p",{class:"learn-cw-keyword"},`${p("web_learn_rescue_keyword")} `,H("span",{class:"mono",dir:"ltr"},...c))),H("div",{class:"learn-cw-cluebox"},u(!0),u(!1))),h=new Set;return{element:d,give(g,f,b){const x=a.get(`${g} ${f}`);x.value=b,x.parentElement.classList.add("given","arrived"),h.add(`${g} ${f}`),m()},unlock(){for(const[g,f]of a)f.disabled=h.has(g)},lock(){for(const g of a.values())g.disabled=!0},focusFirst(){var g;(g=[...a].find(([f])=>!h.has(f)))==null||g[1].focus({preventScroll:!0})},check(){let g=!0;for(const[f,b]of a){const[x,v]=f.split(" ").map(Number),w=b.value!==e[x][v];b.classList.toggle("wrong",w),w&&(g=!1)}return g},reset(){h.clear();for(const g of a.values())g.value="",g.disabled=!0,g.classList.remove("wrong"),g.parentElement.classList.remove("given","arrived");m()}}}function St(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 ac(i,e,t){const n=St(i,e);return n.innerHTML=je(t),n}function iZ(i){const e=St("section",{class:"learn-cloze"});e.append(St("strong",{class:"learn-cloze-title"},i.title)),i.task&&e.append(ac("p",{},i.task)),e.append(St("p",{class:"learn-cloze-hint"},p("web_learn_cloze_hint")));const t=[];for(const c of i.blocks){const m=St("pre",{class:"learn-cloze-code mono",dir:"ltr"});for(const d of c){const h=St("div",{class:"ln"});for(const g of d){if(typeof g=="string"){h.append(g);continue}const f=St("input",{type:"text",class:"learn-cloze-gap mono",autocomplete:"off",autocapitalize:"off",autocorrect:"off",spellcheck:"false",enterkeyhint:"done","aria-label":`${t.length+1}`});f.style.width=`${Math.max(3,...g.answers.map(b=>b.length))+1}ch`,t.push({input:f,answers:g.answers}),h.append(f)}d.length||h.append(` +`),m.append(h)}e.append(m)}const n=St("p",{class:"learn-cloze-status",role:"status"}),a=i.explanation?ac("p",{class:"learn-explanation"},i.explanation):void 0;a&&(a.hidden=!0);const s=St("button",{class:"learn-cloze-check"},p("web_learn_check")),r=St("button",{},p("web_learn_cloze_solution")),o=St("button",{},p("web_learn_cloze_again"));r.hidden=!0,o.hidden=!0;const l=St("div",{class:"learn-cloze-actions"},s,r,o);e.append(l,n),a&&e.append(a);const u=()=>{var d;let c=0;for(const h of t){const g=mB(h.answers,h.input.value);h.input.classList.toggle("right",g),h.input.classList.toggle("wrong",!g),g&&c++}const m=c===t.length;n.textContent=m?p("web_learn_cloze_all_right"):p("web_learn_cloze_score_fmt",c,t.length),n.className=`learn-cloze-status ${m?"right":"wrong"}`,a&&(a.hidden=!m),m?(t.forEach(h=>h.input.disabled=!0),s.hidden=!0,o.hidden=!1):(r.hidden=!1,(d=t.find(h=>h.input.classList.contains("wrong")))==null||d.input.focus())};return s.addEventListener("click",u),r.addEventListener("click",()=>{for(const c of t)c.input.value=c.answers[0],c.input.classList.remove("right","wrong"),c.input.classList.add("shown"),c.input.disabled=!0;n.textContent="",n.className="learn-cloze-status",a&&(a.hidden=!1),s.hidden=!0,r.hidden=!0,o.hidden=!1}),o.addEventListener("click",()=>{var c;for(const m of t)m.input.value="",m.input.classList.remove("right","wrong","shown"),m.input.disabled=!1;n.textContent="",n.className="learn-cloze-status",a&&(a.hidden=!0),s.hidden=!1,r.hidden=!0,o.hidden=!0,(c=t[0])==null||c.input.focus()}),t.forEach((c,m)=>{c.input.addEventListener("input",()=>c.input.classList.remove("right","wrong")),c.input.addEventListener("keydown",d=>{d.key==="Enter"&&(d.preventDefault(),m1?12:13});return n.forEach((s,r)=>{const o=yt("tspan",{x:e.x,y:e.y+4.5+(r-(n.length-1)/2)*14});o.textContent=s,a.append(o)}),a}function oa(i,e){return yt("polyline",{points:i.map(t=>t.join(",")).join(" "),fill:"none","marker-end":`url(#${e})`})}function sc(i,e,t,n){const a=yt("text",{x:e,y:t,"font-size":12,"font-weight":600,fill:n?"#248a3d":"#d70015"});return a.textContent=i,a}function rZ(i,e){const t=Uh(e,110),n=Math.max(...t.map(u=>u.length)),a=Math.max(70,n*6.6+(i==="raute"?56:26)),s=i==="raute"?48:t.length>1?40:30,r=yt("svg",{viewBox:`0 0 ${a+4} ${s+4}`,width:a+4,height:s+4,"aria-hidden":"true"}),o={x:(a+4)/2,y:(s+4)/2,w:a,h:s},l=l0(i,o);return l.setAttribute("fill",o0[i]),l.setAttribute("stroke","#1c1c1e"),l.setAttribute("stroke-width","1.5"),r.append(l,ug(e,{...o,w:t.length>1?124:a},i)),r}function oZ(i){const e=[...Array(i).keys()];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 i>1&&e.every((t,n)=>t===n)&&e.reverse(),e}function lZ(){const i=qe("dl",{class:"learn-pap-legend"}),e=[["oval","web_learn_pap_legend_oval"],["rechteck","web_learn_pap_legend_rect"],["raute","web_learn_pap_legend_diamond"],["parallelogramm","web_learn_pap_legend_para"]];for(const[t,n]of e){const a=t==="raute"?44:40,s=yt("svg",{viewBox:`0 0 ${a+4} 28`,width:a+4,height:28,"aria-hidden":"true"}),r=l0(t,{x:(a+4)/2,y:14,w:a,h:t==="raute"?24:18});r.setAttribute("fill",o0[t]),r.setAttribute("stroke","#1c1c1e"),r.setAttribute("stroke-width","1.5"),s.append(r),i.append(qe("dt",{},s),qe("dd",{},p(n)))}return i}function uZ(i){const e=qe("section",{class:"learn-pap"});if(e.append(qe("strong",{class:"learn-pap-title"},i.title)),i.task){const J=qe("p");J.innerHTML=je(i.task),e.append(J)}e.append(qe("p",{class:"learn-pap-hint"},p("web_learn_pap_hint")));const{boxes:t,height:n}=vB(i),a=t.filter(Boolean),s=Math.min(...a.map(J=>J.x-J.w/2))-4,r=i.nodes.some(J=>J.shape==="raute"),o=Math.max(...a.map(J=>J.x+J.w/2),r?Math.max(...a.map(J=>J.x))+85+40:0)+4,l=yt("svg",{viewBox:`${s} 0 ${o-s} ${n}`,class:"learn-pap-plan",role:"group","aria-label":i.title}),u=`pap-arrow-${++sZ}`;l.innerHTML=``;const c=yt("g",{stroke:"#1c1c1e","stroke-width":2}),m=yt("g"),d=p("web_learn_pap_yes"),h=p("web_learn_pap_no"),g=J=>t[J].y-t[J].h/2,f=J=>t[J].y+t[J].h/2,b=i.nodes.map((J,C)=>C).filter(J=>!i.nodes[J].isSide);b.forEach((J,C)=>{const N=i.nodes[J],q=t[J],Y=b[C+1];if(Y!==void 0&&(c.append(oa([[q.x,f(J)],[q.x,g(Y)-2]],u)),N.shape==="raute"&&m.append(sc(N.sideExit==="nein"?d:h,q.x+6,f(J)+13,N.sideExit==="nein"))),N.shape!=="raute")return;const ue=q.x+q.w/2;if(m.append(sc(N.sideExit==="ja"?d:h,ue+5,q.y-6,N.sideExit==="ja")),N.backTo!==void 0){const X=g(N.backTo)-14;c.append(oa([[ue,q.y],[ue+22,q.y],[ue+22,X],[q.x,X]],u))}else if(N.side!==void 0){const X=t[N.side],ce=g(J)-14;c.append(oa([[ue,q.y],[X.x-X.w/2-2,q.y]],u)),c.append(oa([[X.x,X.y-X.h/2],[X.x,ce],[q.x,ce]],u))}}),l.append(c,m);const x=i.nodes.map(()=>{}),v=[],w=[];let I;const z=qe("p",{class:"learn-pap-status",role:"status"}),k=i.explanation?qe("p",{class:"learn-explanation"}):void 0;k&&(k.innerHTML=je(i.explanation),k.hidden=!0);let T=!1;const O=()=>{v.forEach(J=>J.classList.remove("right","wrong")),z.textContent="",z.className="learn-pap-status"},D=J=>{const C=v[J];C.replaceChildren();const N=i.nodes[J],q=x[J],Y=l0(N.shape,t[J]);if(Y.setAttribute("class","learn-pap-shape"),q===void 0)Y.setAttribute("fill","#f7f7f9"),Y.setAttribute("stroke-dasharray","6 4"),C.append(Y),C.setAttribute("aria-label",p("web_learn_pap_empty"));else{const ue=i.nodes[q];Y.setAttribute("fill",o0[ue.shape]),C.append(Y,ug(ue.text,t[J],N.shape)),C.setAttribute("aria-label",ue.text)}},P=()=>{i.nodes.forEach((J,C)=>D(C)),w.forEach((J,C)=>{J.hidden=x.includes(C),J.classList.toggle("selected",I===C)})},j=(J,C)=>{if(T)return;const N=x.indexOf(C);N>=0&&(x[N]=void 0),x[J]=C,I=void 0,O(),P()};i.nodes.forEach((J,C)=>{const N=yt("g",{class:"learn-pap-slot","data-slot":C,tabindex:0,role:"button"}),q=()=>{T||(I!==void 0?j(C,I):x[C]!==void 0&&(x[C]=void 0,O(),P()))};N.addEventListener("click",q),N.addEventListener("keydown",Y=>{Y.key!=="Enter"&&Y.key!==" "||(Y.preventDefault(),q())}),v.push(N),l.append(N)});const A=qe("div",{class:"learn-pap-tray"});let M=!1;for(const J of oZ(i.nodes.length)){const C=i.nodes[J],N=qe("button",{class:"learn-pap-card",type:"button","aria-label":C.text},rZ(C.shape,C.text));w[J]=N,N.addEventListener("click",()=>{M||T||(I=I===J?void 0:J,P())}),N.addEventListener("pointerdown",q=>{if(T)return;M=!1;let Y;const ue=le=>{var Te;!Y&&Math.hypot(le.clientX-q.clientX,le.clientY-q.clientY)<6||(Y||(M=!0,Y=N.cloneNode(!0),Y.classList.add("learn-pap-ghost"),document.body.append(Y),N.classList.add("dragging")),Y.style.left=`${le.clientX}px`,Y.style.top=`${le.clientY}px`,v.forEach(Fe=>Fe.classList.remove("over")),(Te=X(le))==null||Te.classList.add("over"))},X=le=>{var Fe;Y&&(Y.style.display="none");const Te=(Fe=document.elementFromPoint(le.clientX,le.clientY))==null?void 0:Fe.closest("[data-slot]");return Y&&(Y.style.display=""),Te&&v.includes(Te)?Te:void 0},ce=le=>{if(N.removeEventListener("pointermove",ue),N.removeEventListener("pointerup",ce),N.removeEventListener("pointercancel",ce),v.forEach(Fe=>Fe.classList.remove("over")),N.classList.remove("dragging"),!Y)return;const Te=le.type==="pointerup"?X(le):void 0;Y.remove(),Te&&j(Number(Te.getAttribute("data-slot")),J),setTimeout(()=>M=!1)};N.setPointerCapture(q.pointerId),N.addEventListener("pointermove",ue),N.addEventListener("pointerup",ce),N.addEventListener("pointercancel",ce)}),A.append(N)}const W=qe("button",{class:"learn-pap-check"},p("web_learn_check")),U=qe("button",{},p("web_learn_cloze_solution")),K=qe("button",{},p("web_learn_cloze_again"));U.hidden=!0,K.hidden=!0;const he=()=>{T=!0,W.hidden=!0,U.hidden=!0,K.hidden=!1,A.hidden=!0,fe.classList.add("done"),k&&(k.hidden=!1)};W.addEventListener("click",()=>{const J=x.filter(q=>q===void 0).length;let C=0;x.forEach((q,Y)=>{const ue=q!==void 0&&hB(i,Y,q);v[Y].classList.toggle("right",ue),v[Y].classList.toggle("wrong",q!==void 0&&!ue),ue&&C++});const N=C===i.nodes.length;z.textContent=N?p("web_learn_pap_all_right"):J?p("web_learn_pap_missing_fmt",J):p("web_learn_pap_score_fmt",C,i.nodes.length),z.className=`learn-pap-status ${N?"right":"wrong"}`,N?he():J||(U.hidden=!1)}),U.addEventListener("click",()=>{i.nodes.forEach((J,C)=>x[C]=C),I=void 0,P(),O(),v.forEach(J=>J.classList.add("shown")),he()}),K.addEventListener("click",()=>{i.nodes.forEach((J,C)=>x[C]=void 0),T=!1,I=void 0,v.forEach(J=>J.classList.remove("shown")),O(),P(),W.hidden=!1,K.hidden=!0,A.hidden=!1,fe.classList.remove("done"),k&&(k.hidden=!0)}),P();const Ie=qe("div",{class:"learn-pap-left"});Ie.append(l),i.legend&&Ie.append(lZ());const fe=qe("div",{class:"learn-pap-work"},Ie,A);return e.append(fe,qe("div",{class:"learn-pap-actions"},W,U,K),z),k&&e.append(k),e}const cZ="code, pre, a, button, h1, h2, h3, h4, strong, .term, .ui-pointer";function rc(i,e){var s;const t=[...i.querySelectorAll(".learn-text")],n=new Set;for(const r of t.flatMap(o=>[...o.querySelectorAll("strong")])){const o=Lu(e),l=o==null?void 0:o.exec(r.textContent??""),u=l?Eu(e,l[0]):void 0;u&&n.add(u)}let a=e.filter(r=>!n.has(r));for(const r of t){const o=document.createTreeWalker(r,NodeFilter.SHOW_TEXT),l=[];for(;o.nextNode();){const u=o.currentNode;(s=u.parentElement)!=null&&s.closest(cZ)||l.push(u)}for(let u of l)for(;;){const c=Lu(a),m=c==null?void 0:c.exec(u.data),d=m?Eu(a,m[0]):void 0;if(!m||!d)break;const h=u.splitText(m.index);u=h.splitText(m[0].length);const g=document.createElement("span");g.className="term",g.tabIndex=0,g.setAttribute("role","button"),g.setAttribute("aria-describedby","term-tip"),g.dataset.term=d.term,g.dataset.text=d.text,h.replaceWith(g),g.append(h),a=a.filter(f=>f!==d)}}}function mZ(i){const e=document.createElement("div");e.id="term-tip",e.className="term-tip",e.setAttribute("role","tooltip"),e.hidden=!0,document.body.append(e);let t,n=!1;const a=o=>{t=o,e.replaceChildren();const l=document.createElement("strong");l.textContent=o.dataset.term??"",e.append(l,document.createTextNode(" "+(o.dataset.text??""))),e.hidden=!1;const u=o.getBoundingClientRect(),c=e.offsetWidth,m=e.offsetHeight,d=Math.max(8,Math.min(u.left,window.innerWidth-c-8)),h=u.bottom+6;e.style.left=`${d}px`,e.style.top=`${h+m>window.innerHeight-8?Math.max(8,u.top-m-6):h}px`,o.setAttribute("aria-expanded","true")},s=()=>{t==null||t.setAttribute("aria-expanded","false"),t=void 0,n=!1,e.hidden=!0},r=o=>{var l,u;return((u=(l=o.target)==null?void 0:l.closest)==null?void 0:u.call(l,".term"))??void 0};return i.addEventListener("pointerover",o=>{const l=r(o);l&&o.pointerType==="mouse"&&!n&&a(l)}),i.addEventListener("pointerout",o=>{r(o)&&o.pointerType==="mouse"&&!n&&s()}),i.addEventListener("click",o=>{const l=r(o);if(l){if(n&&t===l)return s();a(l),n=!0}}),i.addEventListener("focusin",o=>{const l=r(o);l&&!n&&a(l)}),i.addEventListener("focusout",o=>{r(o)&&!n&&s()}),i.addEventListener("keydown",o=>{const l=r(o);o.key==="Escape"&&t?s():l&&(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),l.click())}),i.addEventListener("scroll",s,!0),document.addEventListener("pointerdown",o=>{t&&!r(o)&&!e.contains(o.target)&&s()}),{hide:s}}const cg={leiste:".topbar > .toolbar",editor:".editor-rail, .columns > .app",werkzeuge:".diagram-tools",dateien:".files-rail, .files",codelive:".live-rail, .livecode",ausfuehren:"[data-run=play]",konsole:".livecode .console",einzelschritt:"[data-run=step]",elemente:".palette",struktogramm:".canvas",objektinspektor:".inspector",reiter:".tabs",titel:".caption",neu:"[data-action=new]",oeffnen:"[data-action=open]",speichern:"[data-action=save]",exportieren:"[data-action=export]",rueckgaengig:"[data-action=undo]",loeschen:"[data-action=delete]",textgroesse:"[data-action=settings]",einstellungen:"[data-action=settings]",lernen:".learn .learn-hide",code:"[data-action=code]",simulation:"[data-action=simulate]"},mg=new Set(["editor","werkzeuge","elemente","struktogramm","objektinspektor","reiter","titel","rueckgaengig","loeschen","exportieren","code","simulation"]),dg=new Set(["ausfuehren","konsole","einzelschritt"]);function Qs(i,e){return[...i.querySelectorAll(".ui-pointer")].some(t=>e.has(t.dataset.target??""))}function oc(i){return i==="elemente"?["editor","palette"]:mg.has(i)?["editor"]:i==="codelive"||dg.has(i)?["livecode"]:i==="dateien"?["files"]:[]}function dZ(i){return Qs(i,new Set(["elemente"]))}function hZ(i){return Qs(i,new Set(["dateien"]))}function gZ(i){return Qs(i,mg)}function pZ(i){return Qs(i,dg)}function lc(i){for(const e of i.querySelectorAll('a[href^="#zeige-"]')){const t=e.getAttribute("href").slice(7);if(!(t in cg))continue;const n=document.createElement("span");n.className="ui-pointer",n.tabIndex=0,n.setAttribute("role","button"),n.dataset.target=t,n.append(...e.childNodes),e.replaceWith(n)}}function fZ(i,e=()=>()=>{}){let t,n,a,s,r;const o=()=>{t==null||t.classList.remove("ui-spot"),t=void 0,window.clearTimeout(n)},l=(h,g)=>{o();const f=[...document.querySelectorAll(cg[h.dataset.target??""]??":not(*)")].find(b=>b.getClientRects().length>0);f&&(t=f,f.classList.add("ui-spot"),g&&(n=window.setTimeout(o,2500)))},u=(h,g)=>requestAnimationFrame(()=>{l(h,g),t==null||t.scrollIntoView({block:"nearest",inline:"nearest"})}),c=()=>{window.clearTimeout(s),window.clearTimeout(r),a==null||a(),a=void 0},m=h=>{window.clearTimeout(s),window.clearTimeout(r),a=void 0,e(oc(h.dataset.target??"")),l(h,!0),u(h,!0)},d=h=>{var g,f;return((f=(g=h.target)==null?void 0:g.closest)==null?void 0:f.call(g,".ui-pointer"))??void 0};return i.addEventListener("pointerover",h=>{const g=d(h);!g||h.pointerType!=="mouse"||(window.clearTimeout(r),l(g,!1),window.clearTimeout(s),s=window.setTimeout(()=>{if(a)return;const f=oc(g.dataset.target??"");f.length!==0&&(a=e(f),u(g,!1))},250))}),i.addEventListener("pointerout",h=>{!d(h)||h.pointerType!=="mouse"||(o(),window.clearTimeout(s),window.clearTimeout(r),r=window.setTimeout(c,400))}),i.addEventListener("click",h=>{const g=d(h);g&&m(g)}),i.addEventListener("focusin",h=>{const g=d(h);g&&l(g,!1)}),i.addEventListener("focusout",h=>{d(h)&&o()}),i.addEventListener("keydown",h=>{const g=d(h);g&&(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),m(g))}),{off:()=>{c(),o()}}}const _t='',bZ=()=>{const i=[];for(const e of jt){const t=i.at(-1);t&&t.name===e.section?t.lessons.push(e):i.push({name:e.section,lessons:[e]})}return i};function _(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 tt(i,e,t){const n=_(i,e);return n.innerHTML=t,n}const xZ=i=>p(`element_${S[i]}`);function vZ(i){return{caption:i,elements:[Oe(S.anweisung,{textLines:["ø"]})]}}function uc(i){const e=i.start?ti(i.start):void 0;return e?{...e,caption:e.caption||i.title}:vZ(i.title)}class yZ{constructor(e){y(this,"element");y(this,"tab","lessons");y(this,"returnTo");y(this,"lessonId");y(this,"taskId");y(this,"body");y(this,"tips");y(this,"pointers");this.host=e,this.element=_("aside",{class:"learn","aria-label":p("web_learn_title")}),this.tips=mZ(this.element),this.pointers=fZ(this.element,t=>this.host.reveal(t)),fs(Gu(s1())),this.restore()}restore(){const e=be.view();e&&(this.tab=["lessons","tasks","reference"].find(t=>t===e.tab)??"lessons",this.lessonId=jt.some(t=>t.id===e.lesson)?e.lesson:void 0,this.taskId=An.some(t=>t.id===e.task)?e.task:void 0),this.render()}render(){this.tips.hide(),this.pointers.off(),fs(Gu(s1()));const e=_("div",{class:"segmented learn-tabs",role:"tablist"});for(const[a,s]of[["lessons",p("web_learn_lessons")],["tasks",p("web_learn_tasks")],["reference",p("web_learn_reference")]]){const r=_("button",{role:"tab","aria-pressed":String(this.tab===a),"data-learn-tab":a},s);r.addEventListener("click",()=>{this.tab===a&&(a==="lessons"&&(this.lessonId=void 0),a==="tasks"&&(this.taskId=void 0)),this.tab=a,this.persist(),this.render()}),e.append(r)}const t=tt("button",{class:"learn-hide",title:p("web_learn_hide"),"aria-label":p("web_learn_hide")},_t);t.addEventListener("click",()=>this.host.collapse());const n=_("div",{class:"learn-head"},e,t);if(this.body=_("div",{class:"learn-body"}),this.element.replaceChildren(n,this.body),this.tab==="lessons"){const a=jt.find(s=>s.id===this.lessonId);a?this.renderLesson(a):this.renderLessonList()}else if(this.tab==="tasks"){const a=An.find(s=>s.id===this.taskId);a?this.renderTask(a):this.renderTaskList()}else{const a=Na.map(r=>`- **${r.term}:** ${r.text}`).join(` `),s=tt("div",{class:"learn-text learn-reference"},Tn(`${Wa} ## ${p("web_learn_terms")} -${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(){be.setView({tab:this.tab,lesson:this.lessonId,task:this.taskId})}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 fZ()){this.body.append(_("h3",{class:"learn-section"},e.name));const t=_("ol",{class:"learn-list"});for(const n of e.lessons){const a=be.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=be.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((c,m)=>{const d=p("web_learn_step_fmt",m+1,c.title),h=mthis.goToStep(e,m)),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 c=_("button",{class:"learn-return"},`↩ ${p("web_learn_back_to_checklist")}`);return c.addEventListener("click",()=>{this.returnTo=void 0,this.goToStep(e,o.step),this.body.scrollTop=o.scroll}),c};o&&this.body.append(l()),a.blocks.forEach((c,m)=>this.body.append(this.renderBlock(c,`${n}-${m}`,e))),lc(this.body),qB(this.body),this.openNeededColumns(a.blocks),rc(this.body,Na),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",()=>{be.updateLesson(e.id,{done:!0});const l=Pt.find(u=>u.number===e.number+1);this.openLesson(l==null?void 0:l.id)}),s.append(o)}return s}goToStep(e,t){be.updateLesson(e.id,{step:t}),this.render(),this.body.scrollTop=0}openNeededColumns(e){const t=e.flatMap(n=>n.kind==="exercise"?[n.exercise]:[]);hZ(this.body)?(this.host.showEditor(),mZ(this.body)&&this.host.reveal(["palette"])):dZ(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(),gZ(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 An){const n=this.taskExercises(t),a=n.length>0&&n.every(o=>be.exercise(o.id).done),s=Pt.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($u()){e.setAttribute("open","");const s=_("button",{},p("web_learn_teacher_off"));return s.addEventListener("click",()=>{WB(),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 EB(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=Pt.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}`))),lc(this.body),this.openNeededColumns(e.blocks),rc(this.body,Na)}renderBlock(e,t,n){switch(e.kind){case"markdown":return this.withOpenButtons(tt("div",{class:"learn-text"},Tn(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 this.renderGraphic(e.file,e.caption,e.labeled);case"game":return this.renderGame(e.game);case"roundGame":return UB(e.game,ra);case"rescueGame":return eZ(e.game,ra);case"caesar":return GB(e.key,e.text);case"cloze":return nZ(e.cloze);case"pap":return lZ(e.pap);case"textFile":return ig(e.name,e.content);case"robotModel":return VB(e.focus,e.view,e.spin);case"robotQuiz":return QB(e.tasks,e.done)}}renderBrag(e,t=!1){const n=_("aside",{class:"learn-brag"});n.append(_("img",{src:ra,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(tt("div",{class:"learn-text"},Tn(e))),n.append(a),n}renderGame(e){const n=_("section",{class:"learn-game"}),a=_("div",{class:"learn-game-head"});a.append(_("img",{src:ra,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=ux(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,I]of cx(d))h.append(_("code",{},`${w} = ${I}`));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 I=w===d.answer;I&&l++,s.textContent=`${p("web_game_round_fmt",o+1,10)} · ${p("web_game_score_fmt",l)}`,x.className=`learn-game-feedback ${I?"right":"wrong"}`;const z=_("div",{class:"learn-game-steps mono"});ox(d.condition,d.values).forEach((T,O)=>z.append(_("div",{},`${O?"→ ":""}${T}`)));const k=_("button",{class:"primary"},o+1<10?p("web_game_next"):p("web_game_finish"));k.addEventListener("click",()=>{o++,o<10?u():c()}),x.replaceChildren(_("p",{},p(I?"web_game_right":"web_game_wrong")),z,k),k.focus()};f.addEventListener("click",()=>v(!0)),b.addEventListener("click",()=>v(!1)),r.replaceChildren(h,_("div",{class:"learn-game-condition mono"},d.condition),g,x)},c=()=>{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)},m=_("button",{class:"primary"},p("web_game_start"));return m.addEventListener("click",u),r.append(_("p",{},p("web_game_intro")),m),n}renderImages(e,t){const n=_("figure",{class:"learn-figure"}),a=_("div",{class:"learn-images"});for(const s of e){const r=yr(s);r&&a.append(_("img",{src:r,alt:"",loading:"lazy"}))}return n.append(a),t&&n.append(tt("figcaption",{},Pe(t))),n}renderGraphic(e,t,n){const a=_("figure",{class:"learn-figure"}),s=yr(e),r=n?yr(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(tt("figcaption",{},Pe(t))),a}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=ti(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(tt("figcaption",{},Pe(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=()=>be.exercise(e.id),a=_("span",{class:"learn-badge"},`✓ ${p("web_learn_solved")}`);a.hidden=!n().done;const s=e.code==="java"?p("web_learn_solve_in_code",p("web_live_title")):p("web_learn_solve_in_editor",p("web_editor_title"));t.append(_("h4",{},`${p("web_learn_exercise")}: ${e.title}`,a),_("p",{class:"learn-where"},s),tt("div",{class:"learn-text"},Tn(e.task)));const r=_("div",{class:"learn-result",role:"status"}),o=_("div",{class:"learn-hints"}),l=_("div",{class:"group"}),u=_("button",{class:"primary"},p("web_learn_open_exercise"));u.addEventListener("click",()=>{const d=n().xml;let h=uc(e);if(d)try{h=El(d)}catch{}this.host.openExercise(e,h)});const c=_("button",{},p("web_learn_check"));if(c.addEventListener("click",()=>{const d=this.host.exerciseDocument(e.id);if(!d){r.className="learn-result info",r.textContent=p("web_learn_open_first");return}if(d.elements.every(Bl)){r.className="learn-result info",r.textContent=p("web_learn_empty");return}this.host.stopSimulation();const h=nx(d,e.tests,this.host.subprogramsFor(e.id),Fa),g=ix(d),f=e.requires.map(v=>v==="forZaehlSchleife"?"forSchleife":v).filter(v=>v in S&&!g.has(S[v])),b=e.loopDepth!==void 0&&Po(d.elements)v.passed)&&f.length===0&&!b;this.showResult(r,h,f,x,b),x&&(be.updateExercise(e.id,{done:!0}),a.hidden=!1)}),l.append(u,c),e.hints.length>0){const d=_("button",{},p("web_learn_hint"));d.addEventListener("click",()=>{const h=o.children.length;if(h>=e.hints.length)return;const g=e.hints.length>1?`**${p("web_learn_hint_fmt",h+1,e.hints.length)}:** `:"";o.append(tt("aside",{class:"lesson-note"},Tn(g+e.hints[h]))),d.textContent=p("web_learn_hint_more"),d.toggleAttribute("disabled",h+1>=e.hints.length)}),l.append(d)}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}be.resetExercise(e.id),this.host.resetExercise(e.id,uc(e)),a.hidden=!0,r.replaceChildren(),r.className="learn-result",m.dataset.confirm="",m.textContent=p("web_learn_reset")}),l.append(m),t.append(l,o,r),$u()&&e.solution){const d=ti(e.solution);if(d){const h=_("details",{class:"learn-solution"},_("summary",{},p("web_learn_solution")));h.addEventListener("toggle",()=>{if(!h.open||h.querySelector(".learn-preview"))return;const g=this.host.preview(d);g&&h.append(_("div",{class:"learn-preview",dir:"ltr"},g));const f=_("button",{},p("web_learn_open_in_editor"));f.addEventListener("click",()=>{this.host.openDiagram(d,e.solution);for(const b of e.subprograms){const x=ti(b);x&&this.host.openDiagram(x,b)}});for(const b of e.subprograms){const x=ti(b),v=x&&this.host.preview(x);v&&h.append(_("div",{class:"learn-preview",dir:"ltr"},v))}h.append(f)}),t.append(h)}}return t}showResult(e,t,n,a,s){var o,l,u,c,m;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",bZ(S[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",{},X1(d.test.drive)||"–")),_("span",{},`${p("web_learn_actual")}: `,_("code",{},X1(d.result.drive??[])||"–"))),d.test.actions&&b.append(_("span",{},`${p("web_learn_expected")}: `,_("code",{},X1(d.test.actions)||"–")),_("span",{},`${p("web_learn_actual")}: `,_("code",{},X1(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=Fa(d.test.world))==null?void 0:o.goals)!=null&&l.length||(c=(u=Fa(d.test.world))==null?void 0:u.targets)!=null&&c.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",{},Jh((m=d.result.files)==null?void 0:m.get(x.name)).join(" | ")||"–")));d.result.error&&b.append(_("span",{class:"learn-error"},t1(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(tt("li",{},Pe(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 c=`${t}-${u}`,m=n?(v=be.lesson(n.id).checks)==null?void 0:v[c]:void 0;let d=m===!0?"sun":m||void 0;const h=tt("span",{class:"learn-check-text"},Pe(l.text)),g=_("span",{class:"learn-rating",role:"group","aria-label":h.textContent??""}),f=a.map(w=>{const I=_("button",{class:"learn-rating-button",title:w.label,"aria-label":w.label},w.icon);return I.addEventListener("click",()=>{if(d=d===w.value?void 0:w.value,b(),!n)return;const z={...be.lesson(n.id).checks??{}};d?z[c]=d:delete z[c],be.updateLesson(n.id,{checks:Object.keys(z).length?z:void 0})}),I}),b=()=>{f.forEach((w,I)=>w.setAttribute("aria-pressed",String(a[I].value===d))),x.dataset.rating=d??""};g.append(...f);const x=_("li",{},h,g);if(n&&l.step!==void 0){const w=l.step,I=p("web_learn_step_fmt",w+1,n.steps[w].title),z=_("button",{class:"link-button learn-check-link",title:I,"aria-label":`${p("web_learn_review")}: ${I}`},p("web_learn_review"));z.addEventListener("click",()=>{this.returnTo={lesson:n.id,step:be.lesson(n.id).step,scroll:this.body.scrollTop},this.goToStep(n,w)}),x.append(z)}b(),o.append(x)}),s}renderQuiz(e,t,n){const a=_("div",{class:"learn-quiz"}),s=_("p",{class:"learn-score",role:"status"}),r=()=>n?be.lesson(n.id).quiz??{}:{},o=_("div",{class:"learn-review"}),l=()=>{const u=r(),c=(f,b)=>f.pairs?f.pairs.every((x,v)=>u[`${t}-${b}-${v}`]!==void 0):u[`${t}-${b}`]!==void 0,m=(f,b)=>{var x;return!!(f.pairs?f.pairs.every((v,w)=>cc(f)[u[`${t}-${b}-${w}`]]===f.pairs[w].right):(x=f.options[u[`${t}-${b}`]])!=null&&x.correct)},d=e.filter(c).length,h=e.filter(m).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=>m(e[f],f))};return e.forEach((u,c)=>{const m=`${t}-${c}`,d=_("fieldset",{},tt("legend",{},Pe(u.question))),h=tt("p",{class:"learn-explanation"},Pe(u.explanation??""));if(u.pairs){d.append(this.renderMatch(u,m,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=tt("button",{class:"learn-option"},Pe(f.text));x.addEventListener("click",()=>{n&&be.updateLesson(n.id,{quiz:{...r(),[m]:b}}),g(b),l()}),d.append(x)}),d.append(h),g(r()[m]),a.append(d)}),a.append(s,o),l(),a}fillChecklistReview(e,t,n,a){const s={sun:"☀️",cloud:"⛅",umbrella:"☂️"},r=be.lesson(t.id).checks??{},o=[];let l=0;t.steps.forEach((u,c)=>u.blocks.forEach((m,d)=>{m.kind==="checklist"&&m.items.forEach((h,g)=>{const f=r[`${c}-${d}-${g}`],b=f===!0?"sun":f||void 0,x=h.step===void 0?[]:n.map((k,T)=>k.step===h.step?T:-1).filter(k=>k>=0),v=x.filter(k=>!a(k));let w="";b==="sun"&&v.length?w=p("web_learn_review_overrated_fmt",v.map(k=>k+1).join(", ")):b&&b!=="sun"&&x.length&&!v.length&&(w=p("web_learn_review_underrated")),w&&l++;const I=_("li",{class:w?"learn-review-deviation":""}),z=tt("span",{class:"learn-check-text"},Pe(h.text));if(w&&z.append(_("br",{}),_("em",{},w)),I.append(z,_("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 k=h.step,T=_("button",{class:"link-button learn-check-link"},p("web_learn_review"));T.addEventListener("click",()=>{this.returnTo={lesson:t.id,step:be.lesson(t.id).step,scroll:this.body.scrollTop},this.goToStep(t,k)}),I.append(T)}o.push(I)})})),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=cc(e),u=_("div",{class:"learn-match"});let c={};const m=()=>a?n():c,d=b=>a?be.updateLesson(a.id,{quiz:b}):c=b,h=b=>m()[`${t}-${b}`],g=o.map(b=>{const x=_("select",{class:"learn-match-select"});x.append(_("option",{value:""},"–")),l.forEach((w,I)=>x.append(_("option",{value:String(I)},w)));const v=tt("label",{class:"learn-match-left"},Pe(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={...m()};b.value===""?delete v[`${t}-${x}`]:v[`${t}-${x}`]=Number(b.value),d(v),f(),r()})),f(),u}}function cc(i){return(i.pairs??[]).map(e=>e.right).sort((e,t)=>e.localeCompare(t,"de"))}const yZ=""+new URL("visubot-CyGFOI9V.webp",import.meta.url).href,u0="visustruct.visubot";function c0(){try{return localStorage.getItem(u0)}catch{return null}}function ui(){const i=c0();return i==="1"||i==="kurs"?"on":"off"}const dg=()=>c0()==="2";function hg(){try{localStorage.setItem(u0,"2")}catch{}}const wZ=()=>c0()!==null;function Ir(i){try{localStorage.setItem(u0,i==="on"?"1":"0")}catch{}}const zZ=`VisuBot`,Hn=()=>ui()!=="off",mc=i=>i.replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]);function Zo(){const i=dg()?"object":ui(),e=(n,a)=>``,t={off:"web_visubot_world_visustruct_hint",on:"web_visubot_world_visubot_hint",object:"web_visuobject_world_hint"}[i];return`
+${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(){be.setView({tab:this.tab,lesson:this.lessonId,task:this.taskId})}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 bZ()){this.body.append(_("h3",{class:"learn-section"},e.name));const t=_("ol",{class:"learn-list"});for(const n of e.lessons){const a=be.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=be.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((c,m)=>{const d=p("web_learn_step_fmt",m+1,c.title),h=mthis.goToStep(e,m)),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 c=_("button",{class:"learn-return"},`↩ ${p("web_learn_back_to_checklist")}`);return c.addEventListener("click",()=>{this.returnTo=void 0,this.goToStep(e,o.step),this.body.scrollTop=o.scroll}),c};o&&this.body.append(l()),a.blocks.forEach((c,m)=>this.body.append(this.renderBlock(c,`${n}-${m}`,e))),lc(this.body),QB(this.body),this.openNeededColumns(a.blocks),rc(this.body,Na),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",()=>{be.updateLesson(e.id,{done:!0});const l=jt.find(u=>u.number===e.number+1);this.openLesson(l==null?void 0:l.id)}),s.append(o)}return s}goToStep(e,t){be.updateLesson(e.id,{step:t}),this.render(),this.body.scrollTop=0}openNeededColumns(e){const t=e.flatMap(n=>n.kind==="exercise"?[n.exercise]:[]);gZ(this.body)?(this.host.showEditor(),dZ(this.body)&&this.host.reveal(["palette"])):hZ(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(),pZ(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 An){const n=this.taskExercises(t),a=n.length>0&&n.every(o=>be.exercise(o.id).done),s=jt.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($u()){e.setAttribute("open","");const s=_("button",{},p("web_learn_teacher_off"));return s.addEventListener("click",()=>{NB(),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 WB(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=jt.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}`))),lc(this.body),this.openNeededColumns(e.blocks),rc(this.body,Na)}renderBlock(e,t,n){switch(e.kind){case"markdown":return this.withOpenButtons(tt("div",{class:"learn-text"},Tn(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 this.renderGraphic(e.file,e.caption,e.labeled);case"game":return this.renderGame(e.game);case"roundGame":return $B(e.game,ra);case"rescueGame":return tZ(e.game,ra);case"caesar":return HB(e.key,e.text);case"cloze":return iZ(e.cloze);case"pap":return uZ(e.pap);case"textFile":return ag(e.name,e.content);case"robotModel":return qB(e.focus,e.view,e.spin);case"robotQuiz":return UB(e.tasks,e.done)}}renderBrag(e,t=!1){const n=_("aside",{class:"learn-brag"});n.append(_("img",{src:ra,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(tt("div",{class:"learn-text"},Tn(e))),n.append(a),n}renderGame(e){const n=_("section",{class:"learn-game"}),a=_("div",{class:"learn-game-head"});a.append(_("img",{src:ra,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=cx(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,I]of mx(d))h.append(_("code",{},`${w} = ${I}`));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 I=w===d.answer;I&&l++,s.textContent=`${p("web_game_round_fmt",o+1,10)} · ${p("web_game_score_fmt",l)}`,x.className=`learn-game-feedback ${I?"right":"wrong"}`;const z=_("div",{class:"learn-game-steps mono"});lx(d.condition,d.values).forEach((T,O)=>z.append(_("div",{},`${O?"→ ":""}${T}`)));const k=_("button",{class:"primary"},o+1<10?p("web_game_next"):p("web_game_finish"));k.addEventListener("click",()=>{o++,o<10?u():c()}),x.replaceChildren(_("p",{},p(I?"web_game_right":"web_game_wrong")),z,k),k.focus()};f.addEventListener("click",()=>v(!0)),b.addEventListener("click",()=>v(!1)),r.replaceChildren(h,_("div",{class:"learn-game-condition mono"},d.condition),g,x)},c=()=>{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)},m=_("button",{class:"primary"},p("web_game_start"));return m.addEventListener("click",u),r.append(_("p",{},p("web_game_intro")),m),n}renderImages(e,t){const n=_("figure",{class:"learn-figure"}),a=_("div",{class:"learn-images"});for(const s of e){const r=yr(s);r&&a.append(_("img",{src:r,alt:"",loading:"lazy"}))}return n.append(a),t&&n.append(tt("figcaption",{},je(t))),n}renderGraphic(e,t,n){const a=_("figure",{class:"learn-figure"}),s=yr(e),r=n?yr(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(tt("figcaption",{},je(t))),a}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=ti(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(tt("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=()=>be.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),wZ(e),tt("div",{class:"learn-text"},Tn(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 m=n().xml;let d=uc(e);if(m)try{d=El(m)}catch{}this.host.openExercise(e,d)});const u=_("button",{},p("web_learn_check"));if(u.addEventListener("click",()=>{const m=this.host.exerciseDocument(e.id);if(!m){s.className="learn-result info",s.textContent=p("web_learn_open_first");return}if(m.elements.every(Bl)){s.className="learn-result info",s.textContent=p("web_learn_empty");return}this.host.stopSimulation();const d=ix(m,e.tests,this.host.subprogramsFor(e.id),Fa),h=ax(m),g=e.requires.map(x=>x==="forZaehlSchleife"?"forSchleife":x).filter(x=>x in S&&!h.has(S[x])),f=e.loopDepth!==void 0&&jo(m.elements)x.passed)&&g.length===0&&!f;this.showResult(s,d,g,b,f),b&&(be.updateExercise(e.id,{done:!0}),a.hidden=!1)}),o.append(l,u),e.hints.length>0){const m=_("button",{},p("web_learn_hint"));m.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(tt("aside",{class:"lesson-note"},Tn(h+e.hints[d]))),m.textContent=p("web_learn_hint_more"),m.toggleAttribute("disabled",d+1>=e.hints.length)}),o.append(m)}const c=_("button",{class:"danger-text"},p("web_learn_reset"));if(c.addEventListener("click",()=>{if(c.dataset.confirm!=="1"){c.dataset.confirm="1",c.textContent=p("web_learn_reset_confirm"),setTimeout(()=>{c.dataset.confirm="",c.textContent=p("web_learn_reset")},4e3);return}be.resetExercise(e.id),this.host.resetExercise(e.id,uc(e)),a.hidden=!0,s.replaceChildren(),s.className="learn-result",c.dataset.confirm="",c.textContent=p("web_learn_reset")}),o.append(c),t.append(o,r,s),$u()&&e.solution){const m=ti(e.solution);if(m){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(m);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(m,e.solution);for(const f of e.subprograms){const b=ti(f);b&&this.host.openDiagram(b,f)}});for(const f of e.subprograms){const b=ti(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,c,m;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",xZ(S[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",{},X1(d.test.drive)||"–")),_("span",{},`${p("web_learn_actual")}: `,_("code",{},X1(d.result.drive??[])||"–"))),d.test.actions&&b.append(_("span",{},`${p("web_learn_expected")}: `,_("code",{},X1(d.test.actions)||"–")),_("span",{},`${p("web_learn_actual")}: `,_("code",{},X1(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=Fa(d.test.world))==null?void 0:o.goals)!=null&&l.length||(c=(u=Fa(d.test.world))==null?void 0:u.targets)!=null&&c.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",{},Jh((m=d.result.files)==null?void 0:m.get(x.name)).join(" | ")||"–")));d.result.error&&b.append(_("span",{class:"learn-error"},t1(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(tt("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 c=`${t}-${u}`,m=n?(v=be.lesson(n.id).checks)==null?void 0:v[c]:void 0;let d=m===!0?"sun":m||void 0;const h=tt("span",{class:"learn-check-text"},je(l.text)),g=_("span",{class:"learn-rating",role:"group","aria-label":h.textContent??""}),f=a.map(w=>{const I=_("button",{class:"learn-rating-button",title:w.label,"aria-label":w.label},w.icon);return I.addEventListener("click",()=>{if(d=d===w.value?void 0:w.value,b(),!n)return;const z={...be.lesson(n.id).checks??{}};d?z[c]=d:delete z[c],be.updateLesson(n.id,{checks:Object.keys(z).length?z:void 0})}),I}),b=()=>{f.forEach((w,I)=>w.setAttribute("aria-pressed",String(a[I].value===d))),x.dataset.rating=d??""};g.append(...f);const x=_("li",{},h,g);if(n&&l.step!==void 0){const w=l.step,I=p("web_learn_step_fmt",w+1,n.steps[w].title),z=_("button",{class:"link-button learn-check-link",title:I,"aria-label":`${p("web_learn_review")}: ${I}`},p("web_learn_review"));z.addEventListener("click",()=>{this.returnTo={lesson:n.id,step:be.lesson(n.id).step,scroll:this.body.scrollTop},this.goToStep(n,w)}),x.append(z)}b(),o.append(x)}),s}renderQuiz(e,t,n){const a=_("div",{class:"learn-quiz"}),s=_("p",{class:"learn-score",role:"status"}),r=()=>n?be.lesson(n.id).quiz??{}:{},o=_("div",{class:"learn-review"}),l=()=>{const u=r(),c=(f,b)=>f.pairs?f.pairs.every((x,v)=>u[`${t}-${b}-${v}`]!==void 0):u[`${t}-${b}`]!==void 0,m=(f,b)=>{var x;return!!(f.pairs?f.pairs.every((v,w)=>cc(f)[u[`${t}-${b}-${w}`]]===f.pairs[w].right):(x=f.options[u[`${t}-${b}`]])!=null&&x.correct)},d=e.filter(c).length,h=e.filter(m).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=>m(e[f],f))};return e.forEach((u,c)=>{const m=`${t}-${c}`,d=_("fieldset",{},tt("legend",{},je(u.question))),h=tt("p",{class:"learn-explanation"},je(u.explanation??""));if(u.pairs){d.append(this.renderMatch(u,m,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=tt("button",{class:"learn-option"},je(f.text));x.addEventListener("click",()=>{n&&be.updateLesson(n.id,{quiz:{...r(),[m]:b}}),g(b),l()}),d.append(x)}),d.append(h),g(r()[m]),a.append(d)}),a.append(s,o),l(),a}fillChecklistReview(e,t,n,a){const s={sun:"☀️",cloud:"⛅",umbrella:"☂️"},r=be.lesson(t.id).checks??{},o=[];let l=0;t.steps.forEach((u,c)=>u.blocks.forEach((m,d)=>{m.kind==="checklist"&&m.items.forEach((h,g)=>{const f=r[`${c}-${d}-${g}`],b=f===!0?"sun":f||void 0,x=h.step===void 0?[]:n.map((k,T)=>k.step===h.step?T:-1).filter(k=>k>=0),v=x.filter(k=>!a(k));let w="";b==="sun"&&v.length?w=p("web_learn_review_overrated_fmt",v.map(k=>k+1).join(", ")):b&&b!=="sun"&&x.length&&!v.length&&(w=p("web_learn_review_underrated")),w&&l++;const I=_("li",{class:w?"learn-review-deviation":""}),z=tt("span",{class:"learn-check-text"},je(h.text));if(w&&z.append(_("br",{}),_("em",{},w)),I.append(z,_("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 k=h.step,T=_("button",{class:"link-button learn-check-link"},p("web_learn_review"));T.addEventListener("click",()=>{this.returnTo={lesson:t.id,step:be.lesson(t.id).step,scroll:this.body.scrollTop},this.goToStep(t,k)}),I.append(T)}o.push(I)})})),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=cc(e),u=_("div",{class:"learn-match"});let c={};const m=()=>a?n():c,d=b=>a?be.updateLesson(a.id,{quiz:b}):c=b,h=b=>m()[`${t}-${b}`],g=o.map(b=>{const x=_("select",{class:"learn-match-select"});x.append(_("option",{value:""},"–")),l.forEach((w,I)=>x.append(_("option",{value:String(I)},w)));const v=tt("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={...m()};b.value===""?delete v[`${t}-${x}`]:v[`${t}-${x}`]=Number(b.value),d(v),f(),r()})),f(),u}}function cc(i){return(i.pairs??[]).map(e=>e.right).sort((e,t)=>e.localeCompare(t,"de"))}function wZ(i){const e=$h(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 zZ=""+new URL("visubot-CyGFOI9V.webp",import.meta.url).href,u0="visustruct.visubot";function c0(){try{return localStorage.getItem(u0)}catch{return null}}function ui(){const i=c0();return i==="1"||i==="kurs"?"on":"off"}const hg=()=>c0()==="2";function gg(){try{localStorage.setItem(u0,"2")}catch{}}const IZ=()=>c0()!==null;function Ir(i){try{localStorage.setItem(u0,i==="on"?"1":"0")}catch{}}const kZ=`VisuBot`,Hn=()=>ui()!=="off",mc=i=>i.replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]);function Zo(){const i=hg()?"object":ui(),e=(n,a)=>``,t={off:"web_visubot_world_visustruct_hint",on:"web_visubot_world_visubot_hint",object:"web_visuobject_world_hint"}[i];return`
${e("off","VisuStruct")}${e("on","🤖 VisuBot")}${e("object","VisuObject")}
- ${mc(p(t))}`}class IZ{constructor(e=Ii){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 ds(e),this.element=document.createElement("section"),this.element.className="visubot",this.element.innerHTML=`

${p("web_visubot_world")}

${p("web_visubot_world_in_preview")}

${kZ()}${SZ()}`,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=ge.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-F7Of_tVr.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]??Ii,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 ds(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;ge.run(e.dataset.py).then(()=>t?new Promise(a=>setTimeout(a,Number(n))).then(()=>ge.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&&ge.connected;){for(const e of this.check.querySelectorAll("[data-sensor]")){if(!this.check.open||!ge.connected)break;const t=e.dataset.sensor,n=await ge.ask(Ot[t].python).catch(()=>{});n!==void 0&&(e.textContent=typeof Ot[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 ge.connected}async prepareLive(e,t=[]){const n={};for(const a of new Set(["getDistance","getLine",...t])){const s=await ge.ask(Ot[a].python);typeof Ot[a].simulated=="boolean"?n[a]=s===!0||typeof s=="number"&&s!==0:typeof Ot[a].simulated=="string"?n[a]=typeof s=="string"?s:String(Ot[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){ge.disconnect(e instanceof Error?e.message:String(e))}updateLive(){this.liveStatus.textContent=pg(),this.liveStatus.classList.toggle("connected",ge.connected),this.check.hidden=!ge.connected,ge.connected||(this.check.open=!1),this.updateStatus()}follow(e,t){var a,s,r,o;for(;this.appliedl!==0);this.world.tick(i0),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&&ge.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 H1;function gg(i,e){try{H1??(H1=new AudioContext);const t=H1.createOscillator(),n=H1.createGain();t.type="square",t.frequency.value=Math.max(20,Math.min(2e4,i)),n.gain.value=.05,t.connect(n).connect(H1.destination);const a=H1.currentTime+Math.min(Math.max(e,0),5e3)/1e3;t.start(),t.stop(a)}catch{}}function kZ(){const i=(t,n,a,s,r)=>``,e=(t,n,a)=>``;return`
🎛 ${p("web_visubot_controls")} + ${mc(p(t))}`}class SZ{constructor(e=Ii){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 ds(e),this.element=document.createElement("section"),this.element.className="visubot",this.element.innerHTML=`

${p("web_visubot_world")}

${p("web_visubot_world_in_preview")}

${TZ()}${_Z()}`,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=ge.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-CCjHhNM_.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]??Ii,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 ds(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;ge.run(e.dataset.py).then(()=>t?new Promise(a=>setTimeout(a,Number(n))).then(()=>ge.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&&ge.connected;){for(const e of this.check.querySelectorAll("[data-sensor]")){if(!this.check.open||!ge.connected)break;const t=e.dataset.sensor,n=await ge.ask(Ot[t].python).catch(()=>{});n!==void 0&&(e.textContent=typeof Ot[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 ge.connected}async prepareLive(e,t=[]){const n={};for(const a of new Set(["getDistance","getLine",...t])){const s=await ge.ask(Ot[a].python);typeof Ot[a].simulated=="boolean"?n[a]=s===!0||typeof s=="number"&&s!==0:typeof Ot[a].simulated=="string"?n[a]=typeof s=="string"?s:String(Ot[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){ge.disconnect(e instanceof Error?e.message:String(e))}updateLive(){this.liveStatus.textContent=fg(),this.liveStatus.classList.toggle("connected",ge.connected),this.check.hidden=!ge.connected,ge.connected||(this.check.open=!1),this.updateStatus()}follow(e,t){var a,s,r,o;for(;this.appliedl!==0);this.world.tick(i0),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&&ge.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 H1;function pg(i,e){try{H1??(H1=new AudioContext);const t=H1.createOscillator(),n=H1.createGain();t.type="square",t.frequency.value=Math.max(20,Math.min(2e4,i)),n.gain.value=.05,t.connect(n).connect(H1.destination);const a=H1.currentTime+Math.min(Math.max(e,0),5e3)/1e3;t.start(),t.stop(a)}catch{}}function TZ(){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)} @@ -63612,7 +63618,7 @@ ${a}`));this.body.append(s),this.foldReference(s)}}foldReference(e){const t="vis ${e("isJoystickLeft","←","web_visubot_sensor_joy_left")}${e("isJoystickRight","→","web_visubot_sensor_joy_right")} ${e("isShaken",`〰 ${p("web_visubot_shake")}`,"web_visubot_sensor_shake")}
- `}function SZ(){const i=a=>a.replace(/"/g,"""),e=(a,s,r,o=1e3)=>``,t="mbot2.EM_stop('ALL')",n=fg.map(a=>`${p(a.key)}…`).join("");return``}function _Z(){const i=a=>a.replace(/"/g,"""),e=(a,s,r,o=1e3)=>``,t="mbot2.EM_stop('ALL')",n=bg.map(a=>`${p(a.key)}…`).join("");return``}function pg(){return ge.connecting?p("web_visubot_connecting"):ge.connected?`✓ ${p("web_visubot_connected")}`:ge.error?`⚠︎ ${p("web_visubot_link_error")}: ${ge.error}`:""}async function TZ(){if(ge.connected||ge.connecting)return ge.disconnect();try{await ge.connect()}catch(i){await ge.disconnect(i.name==="NotFoundError"?void 0:i.message)}}const ht=i=>()=>Oe(S.anweisung,{textLines:[i]}),_Z=[{key:"web_visubot_el_forward",group:"drive",type:S.anweisung,make:ht("mbot.forward()")},{key:"web_visubot_el_backward",group:"drive",type:S.anweisung,make:ht("mbot.backward()")},{key:"web_visubot_el_right",group:"drive",type:S.anweisung,make:ht("mbot.turnRight()")},{key:"web_visubot_el_left",group:"drive",type:S.anweisung,make:ht("mbot.turnLeft()")},{key:"web_visubot_el_drive",group:"wheels",type:S.anweisung,make:ht("mbot.drive(30, 30)")},{key:"web_visubot_el_stop",group:"wheels",type:S.anweisung,make:ht("mbot.stop()")},{key:"web_visubot_el_led",group:"output",type:S.anweisung,make:ht("mbot.setLed(255, 0, 0)")},{key:"web_visubot_el_led_off",group:"output",type:S.anweisung,make:ht("mbot.ledOff()")},{key:"web_visubot_el_led_color",group:"output",type:S.anweisung,make:ht('mbot.led(0).setColor("grün")')},{key:"web_visubot_el_tone",group:"output",type:S.anweisung,make:ht("mbot.playTone(440, 300)")},{key:"web_visubot_el_text",group:"output",type:S.anweisung,make:ht('mbot.showText("Hallo")')},{key:"web_visubot_el_wait",group:"wait",type:S.anweisung,make:ht("mbot.pause(100)")},{key:"web_visubot_el_emotion",group:"emotion",type:S.anweisung,make:ht('mbot.emotion("smile")')},{key:"web_visubot_el_timer",group:"wait",type:S.anweisung,make:ht("mbot.resetTimer()")}],fg=[{key:"web_visubot_sensor_distance",group:"distance",text:"mbot.getDistance()"},{key:"web_visubot_sensor_line",group:"line",text:"mbot.getLine()"},{key:"web_visubot_sensor_line_left",group:"line",text:"mbot.isLineLeft()"},{key:"web_visubot_sensor_line_right",group:"line",text:"mbot.isLineRight()"},{key:"web_visubot_sensor_color",group:"color",get text(){return`mbot.getColor().equals("${ch("red")}")`}},{key:"web_visubot_sensor_button_a",group:"buttons",text:"mbot.isButtonA()"},{key:"web_visubot_sensor_button_b",group:"buttons",text:"mbot.isButtonB()"},{key:"web_visubot_sensor_joy_up",group:"buttons",text:"mbot.isJoystickUp()"},{key:"web_visubot_sensor_joy_down",group:"buttons",text:"mbot.isJoystickDown()"},{key:"web_visubot_sensor_joy_left",group:"buttons",text:"mbot.isJoystickLeft()"},{key:"web_visubot_sensor_joy_right",group:"buttons",text:"mbot.isJoystickRight()"},{key:"web_visubot_sensor_brightness",group:"light",text:"mbot.getBrightness()"},{key:"web_visubot_sensor_loudness",group:"light",text:"mbot.getLoudness()"},{key:"web_visubot_sensor_pitch",group:"tilt",text:"mbot.getPitch()"},{key:"web_visubot_sensor_roll",group:"tilt",text:"mbot.getRoll()"},{key:"web_visubot_sensor_shake",group:"tilt",text:"mbot.isShaken()"},{key:"web_visubot_sensor_timer",group:"timer",text:"mbot.getTimer()"},{key:"web_visubot_sensor_battery",group:"timer",text:"mbot.getBattery()"}],la=()=>typeof window.showDirectoryPicker=="function";class Us{constructor(e){this.handle=e}get name(){return this.handle.name}async list(){const e=[];for await(const t of this.handle.values())t.name.startsWith(".")||e.push({kind:t.kind,name:t.name});return e}async dir(e,t=!1){return new Us(await this.handle.getDirectoryHandle(e,{create:t}))}async read(e){return(await(await this.handle.getFileHandle(e)).getFile()).text()}async write(e,t){const a=await(await this.handle.getFileHandle(e,{create:!0})).createWritable();await a.write(t),await a.close()}async has(e){try{return await this.handle.getFileHandle(e),!0}catch{try{return await this.handle.getDirectoryHandle(e),!0}catch{return!1}}}async remove(e){await this.handle.removeEntry(e,{recursive:!0})}}const OZ="visustruct-workspace";function AZ(){return new Promise((i,e)=>{const t=indexedDB.open(OZ,1);t.onupgradeneeded=()=>{t.result.createObjectStore("files"),t.result.createObjectStore("meta")},t.onsuccess=()=>i(t.result),t.onerror=()=>e(t.error)})}async function Tt(i,e,t){const n=await AZ();return new Promise((a,s)=>{const r=t(n.transaction(i,e).objectStore(i));r.onsuccess=()=>a(r.result),r.onerror=()=>s(r.error)})}class m0{constructor(e,t){this.name=e,this.path=t}key(e){return this.path+e}async list(){const e=await Tt("files","readonly",n=>n.getAllKeys()),t=new Map;for(const n of e){if(!n.startsWith(this.path)||n===this.path)continue;const a=n.slice(this.path.length),s=a.indexOf("/"),r=s<0?a:a.slice(0,s);t.has(r)||t.set(r,{kind:s<0?"file":"directory",name:r})}return[...t.values()]}async dir(e,t=!1){const n=this.key(e)+"/";if(!(await Tt("files","readonly",s=>s.count(n))>0)){if(!t)throw new DOMException(e,"NotFoundError");await Tt("files","readwrite",s=>s.put("",n))}return new m0(e,n)}async read(e){const t=await Tt("files","readonly",n=>n.get(this.key(e)));if(typeof t!="string")throw new DOMException(e,"NotFoundError");return t}async write(e,t){await Tt("files","readwrite",n=>n.put(t,this.key(e)))}async has(e){const t=await Tt("files","readonly",a=>a.count(this.key(e))),n=await Tt("files","readonly",a=>a.count(this.key(e)+"/"));return t+n>0}async remove(e){const t=this.key(e);await Tt("files","readwrite",n=>n.delete(t)),await Tt("files","readwrite",n=>n.delete(IDBKeyRange.bound(t+"/",t+"/￿")))}}async function CZ(i,e="folder"){const t=await window.showDirectoryPicker({id:e==="folder"?"visustruct-workspace":e,mode:"readwrite"}),n=i&&t.name!==i?await t.getDirectoryHandle(i,{create:!0}):t;return await Tt("meta","readwrite",a=>a.put(n,e)),{kind:"folder",root:new Us(n)}}function dc(){return{kind:"browser",root:new m0("VisuStruct","")}}async function PZ(i="folder"){var e;try{const t=await Tt("meta","readonly",a=>a.get(i));if(!t)return;const n=await((e=t.queryPermission)==null?void 0:e.call(t,{mode:"readwrite"}))??"granted";return{handle:t,ready:n==="granted"}}catch{return}}async function hc(i){var t;return(await((t=i.requestPermission)==null?void 0:t.call(i,{mode:"readwrite"}))??"granted")==="granted"?{kind:"folder",root:new Us(i)}:void 0}async function jZ(i="folder"){try{await Tt("meta","readwrite",e=>e.delete(i))}catch{}}const ua="learnProgress.json",ca="lernstand.json",ma="visustruct.files.mode",gc="visustruct.files.expanded";function DZ(i){try{const e=JSON.parse(bg(i)??"[]");return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}catch{return[]}}function bg(i){try{return localStorage.getItem(i)}catch{return null}}function da(i,e){try{e===null?localStorage.removeItem(i):localStorage.setItem(i,e)}catch{}}const te=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,""");function pc(i){return new Promise(e=>{const t=document.createElement("div");t.className="confirm";const n=(i.choices??[]).map(o=>``).join("");t.innerHTML=``;const a=t.querySelector("form"),s=a.querySelector("input"),r=o=>{t.remove(),e(o)};a.addEventListener("submit",o=>{if(o.preventDefault(),!s)return r("");s.value.trim()?r(s.value):s.focus()}),t.addEventListener("click",o=>{var c;const l=o.target,u=(c=l.closest("[data-choice]"))==null?void 0:c.dataset.choice;u!==void 0?r(u):(l===t||l.closest("[data-cancel]"))&&r(void 0)}),t.addEventListener("keydown",o=>o.key==="Escape"&&r(void 0)),document.body.append(t),(s??a.querySelector("[data-cancel]")).focus()})}class BZ{constructor(e){y(this,"element");y(this,"body");y(this,"workspace");y(this,"pending");y(this,"expanded",new Set(DZ(gc)));y(this,"rendering",0);y(this,"progressWorkspace");y(this,"hadWorkspace",!1);y(this,"progressTimer");this.host=e,this.element=document.createElement("aside"),this.element.className="files",this.build(),be.onChange(()=>this.progressChanged()),this.restore()}rememberExpanded(){da(gc,JSON.stringify([...this.expanded]))}get ready(){return!!this.workspace}build(){this.element.innerHTML=` + `;const a=t.querySelector("form"),s=a.querySelector("input"),r=o=>{t.remove(),e(o)};a.addEventListener("submit",o=>{if(o.preventDefault(),!s)return r("");s.value.trim()?r(s.value):s.focus()}),t.addEventListener("click",o=>{var c;const l=o.target,u=(c=l.closest("[data-choice]"))==null?void 0:c.dataset.choice;u!==void 0?r(u):(l===t||l.closest("[data-cancel]"))&&r(void 0)}),t.addEventListener("keydown",o=>o.key==="Escape"&&r(void 0)),document.body.append(t),(s??a.querySelector("[data-cancel]")).focus()})}class MZ{constructor(e){y(this,"element");y(this,"body");y(this,"workspace");y(this,"pending");y(this,"expanded",new Set(ZZ(gc)));y(this,"rendering",0);y(this,"progressWorkspace");y(this,"hadWorkspace",!1);y(this,"progressTimer");this.host=e,this.element=document.createElement("aside"),this.element.className="files",this.build(),be.onChange(()=>this.progressChanged()),this.restore()}rememberExpanded(){da(gc,JSON.stringify([...this.expanded]))}get ready(){return!!this.workspace}build(){this.element.innerHTML=`

${te(p("web_files_title"))}

@@ -63636,7 +63642,7 @@ ${a}`));this.body.append(s),this.foldReference(s)}}foldReference(e){const t="vis
- `,this.body=this.element.querySelector(".files-body");const e=(t,n)=>this.element.querySelector(`[data-files=${t}]`).addEventListener("click",n);e("hide",()=>this.host.hide()),e("new-folder",()=>void this.newFolder()),e("switch",()=>void this.switchWorkspace()),this.body.addEventListener("click",t=>void this.onTreeClick(t)),this.render()}async restore(){if(bg(ma)==="browser")this.workspace=dc();else if(la()){const e=await PZ();e!=null&&e.ready?this.workspace=await hc(e.handle):this.pending=e==null?void 0:e.handle}await this.render(),this.workspace||this.startDialog()}async startDialog(){var r;const e=p("web_learn_start_folder"),t=(o,l,u=!1,c)=>`${c?`

${te(c)}

`:""}`,n=la()?[this.pending?t("reconnect",`${se.open} ${te(p("web_learn_start_continue_fmt",this.pending.name))}`,!0):"",t("pick",`${se.open} ${te(p("web_learn_start_open"))}`,!this.pending),t("create",`${se.newFolder} ${te(p("web_learn_start_create_fmt",e))}`,!1,p("web_learn_start_create_hint"))]:[t("browser",te(p("web_files_browser")),!0,p("web_files_browser_hint"))],a=document.createElement("div");a.className="confirm",a.innerHTML=``,t.querySelector("[data-action=about-done]").addEventListener("click",()=>t.close()),t.addEventListener("click",n=>n.target===t&&t.close()),t.addEventListener("close",()=>t.remove()),document.body.append(t),t.showModal()}setupSettingsMenu(e,t){const n=a=>{t.hidden=!a,e.setAttribute("aria-expanded",String(a))};e.addEventListener("click",()=>n(t.hidden)),this.closeSettings&&document.removeEventListener("pointerdown",this.closeSettings),this.escapeSettings&&document.removeEventListener("keydown",this.escapeSettings),this.closeSettings=a=>{!t.hidden&&!e.parentElement.contains(a.target)&&n(!1)},document.addEventListener("pointerdown",this.closeSettings),this.escapeSettings=a=>{a.key!=="Escape"||t.hidden||(n(!1),e.focus())},document.addEventListener("keydown",this.escapeSettings)}learnRail(){return this.railButton=me("button",{class:"learn-rail"}),this.labelLearnRail(),this.railButton.addEventListener("click",()=>this.setLearning(!0)),this.railButton}liveRail(){return this.liveRailButton=me("button",{class:"learn-rail live-rail"}),this.labelLiveRail(),this.liveRailButton.addEventListener("click",()=>this.setLiveCoding(!0)),this.liveRailButton}labelLiveRail(){this.liveRailButton&&(this.liveRailButton.title=p("web_live_show"),this.liveRailButton.innerHTML=`${_t}</> ${E(p("web_live_title"))}`)}labelLearnRail(){this.railButton&&(this.railButton.title=p("web_learn_show"),this.railButton.innerHTML=`${_t}🎓 ${E(p("web_learn_title"))}`)}learnHost(){return{collapse:()=>this.setLearning(!1),showEditor:()=>{this.editorHidden&&this.setEditorHidden(!1)},showLiveCode:()=>{this.liveCoding||this.setLiveCoding(!0)},showJava:()=>this.openJavaColumn(),showFiles:()=>{this.shell.classList.contains("files-open")||this.setFilesOpen(!0)},reveal:e=>this.revealAreas(e),openExercise:(e,t)=>{const n=$h(e);n!=="code"&&this.setEditorHidden(!1),n!=="struktogramm"&&this.openJavaColumn();const a=this.tabs.findIndex(r=>r.exerciseId===e.id);if(a>=0){this.switchTab(a),this.setSimulating(!1);return}const s=this.makeTab();s.doc=t,s.exerciseId=e.id,s.selected=t.elements.length>0?[0]:void 0,this.isPristine(this.tab)?this.tabs[this.tabIndex]=s:this.tabs.push(s),this.tabIndex=this.tabs.indexOf(s),this.setSimulating(!1),this.render()},openJavaCode:e=>{this.openJavaColumn();const t=this.makeTab();t.doc=this.live.documentFromJavaText(e),this.isPristine(this.tab)?this.tabs[this.tabIndex]=t:this.tabs.push(t),this.tabIndex=this.tabs.indexOf(t),this.setSimulating(!1),this.live.adoptJava(t.doc,e),this.render()},openDiagram:(e,t)=>{this.setEditorHidden(!1),this.loadXML(u1(e),e.caption.trim()?`${e.caption.trim()}.visustruct`:t)},exerciseDocument:e=>{const t=this.tabs.find(a=>a.exerciseId===e);if(t)return t.doc;const n=this.tab;if(!(n.exerciseId||this.isPristine(n)))return n.exerciseId=e,be.updateExercise(e,{xml:u1(n.doc)}),n.doc},subprogramsFor:e=>{const t=this.tabs.find(n=>n.exerciseId===e);return n=>this.findSubprogram(n,t)},stopSimulation:()=>this.setSimulating(!1),resetExercise:(e,t)=>{const n=this.tabs.find(a=>a.exerciseId===e);n&&(n.undoStack.push(n.doc),n.doc=t,n.redoStack=[],n.selected=[0],n===this.tab&&this.render())},preview:e=>{const t=ud(e,this.metrics,this.measure,0);if(!t)return;const n=t.svg.getAttribute("width");return n&&(t.svg.style.maxWidth=`${n}px`),t.svg.removeAttribute("width"),t.svg.removeAttribute("height"),t.svg}}}isPristine(e){return!e.dirty&&!e.fileName&&!e.exerciseId&&e.undoStack.length===0}rememberExercise(){const e=this.tab;e.exerciseId&&(clearTimeout(this.exerciseSaveTimer),this.exerciseSaveTimer=window.setTimeout(()=>{e.exerciseId&&be.updateExercise(e.exerciseId,{xml:u1(e.doc)})},300))}paletteIcon(e){const t=Se("svg",{viewBox:"0 0 28 20",width:28,height:20,class:"icon"}),n={fill:"none",stroke:"currentColor","stroke-width":1.5};t.append(Se("rect",{x:1,y:1,width:26,height:18,...n}));const a=s=>t.append(Se("path",{d:s,...n}));switch(e){case"verzweigung":a("M1 1 L14 10 L27 1 M14 10 V19");break;case"fallauswahl":a("M1 1 L20 10 L27 1 M1 10 H27 M10 10 V19 M20 10 V19");break;case"forZaehlSchleife":case"whileSchleife":a("M7 7 H27 M7 7 V19");break;case"doUntilSchleife":a("M7 1 V13 H27");break;case"endlosschleife":a("M7 6 H27 M7 6 V14 H27");break;case"aufruf":a("M5 1 V19 M23 1 V19");break;case"aussprung":a("M6 1 L1 10 L6 19");break}return t}render(){const e={...this.doc,elements:this.doc.elements.map(Xa)};this.layout=this.engine.layout(e),this.flat=R2(this.layout.elements),this.selected&&!Jt(this.doc,this.selected)&&(this.selected=void 0);const t=this.zoom,n=this.canvasHost;this.renderedHostSize={width:n.clientWidth,height:n.clientHeight};const a={width:Math.max(320,this.layout.canvasSize.width,Math.floor(n.clientWidth/t)),height:Math.max(240,this.layout.canvasSize.height+60,Math.floor(n.clientHeight/t))};this.pseudocodeBox.checked=!!this.doc.pseudocode,this.renderer.usesSimulationHighlight=this.simulating,this.renderer.fillsSelection=this.liveCoding,this.svg=this.renderer.render(this.layout,a,this.simulating?this.simPath:this.selected),this.svg.setAttribute("width",String(Math.floor(a.width*t))),this.svg.setAttribute("height",String(Math.floor(a.height*t))),this.overlay=Se("g",{class:"drop-overlay"}),this.svg.append(this.overlay),this.canvasHost.replaceChildren(this.svg),document.activeElement!==this.captionInput&&(this.captionInput.value=this.doc.caption),this.undoButton.disabled=this.simulating||this.undoStack.length===0,this.redoButton.disabled=this.simulating||this.redoStack.length===0,this.deleteButton.disabled=this.simulating||!this.selected||!cr(this.doc,this.selected),this.captionInput.readOnly=this.simulating,this.codeButton.disabled=this.simulating,this.exportButton.disabled=this.simulating,this.coding&&this.code.refresh(),this.refreshLive(),this.refreshPreview(),this.renderTabs(),this.renderInspector(),this.updateStatus()}refreshLive(){this.liveCoding&&this.live.refresh(this.doc,this.simulating?this.simPath:this.selected,{owner:this.tab,subprograms:new Set(this.tabs.filter(e=>e!==this.tab).flatMap(e=>{var t;return((t=zt(e.doc.caption))==null?void 0:t.name)??[]})),editable:!this.simulating,resolve:e=>this.findSubprogram(e)})}updateStatus(){this.rememberExercise(),document.title=`${this.dirty?"• ":""}${this.fileName} – VisuStruct Web`,this.statusLine.textContent=`${this.fileName}${this.dirty?` (${p("web_status_modified")})`:""}`}renderInspector(){const e=this.selected,t=e?Jt(this.doc,e):void 0,n=this.inspector;if(!e||!t){n.replaceChildren(me("h2",{},p("web_inspector_title")),me("p",{class:"hint"},p("inspector_no_selection")),me("p",{class:"hint"},p("web_inspector_help_drop")),me("p",{class:"hint"},p("web_inspector_help_files")));return}if(n.replaceChildren(me("h2",{},`${p("web_inspector_title")} · ${io(t.type)}`)),t.type===S.anweisung){const a=$a(t.textLines.join(` `)),s=me("div",{class:"segmented",role:"group","aria-label":p("inspector_io_mode_title")});for(const[r,o]of[["statement",p("inspector_io_mode_statement")],["input",p("inspector_io_mode_input")],["output",p("inspector_io_mode_output")]]){const l=me("button",{"aria-pressed":String(r===a)},o);l.addEventListener("click",()=>{var m,d;const u=((m=Jt(this.doc,e))==null?void 0:m.textLines.join(` -`))??"";if(r===$a(u))return;const c=O2(r,u);this.commit(N1(this.doc,e,c.split(` -`))),(d=this.inspector.querySelector("textarea"))==null||d.focus()}),s.append(l)}n.append(s,me("p",{class:"hint mono-hint"},rR[a]))}if(t.type===S.forSchleife){const a=me("div",{class:"for-fields"}),s=K0(t.textLines);[[p("inspector_for_init"),p("inspector_for_placeholder_init")],[p("inspector_for_condition"),p("inspector_for_placeholder_condition")],[p("inspector_for_step"),p("inspector_for_placeholder_step")]].forEach(([o,l],u)=>{const c=me("input",{placeholder:l,spellcheck:"false",autocomplete:"off"});c.value=s[u],this.liveEdit(c,m=>{const d=Jt(this.doc,e);if(!d)return;const h=K0(d.textLines);return h[u]=P2(m),N1(this.doc,e,h)}),a.append(me("label",{},o,c))}),n.append(a)}else if(t.type!==S.leerElement){const a=sR[t.type];a&&n.append(me("p",{class:"hint mono-hint"},a));const s=fd(t),r=me("textarea",{rows:"3",spellcheck:"false"}),o=t.textLines.join(` -`),l=t.type===S.anweisung,u=s?X0(s,o):o;r.value=l&&u.trim()==="ø"?"":u,r.placeholder=oR(t),this.liveEdit(r,m=>{const d=fd(Jt(this.doc,e)??t);if(l&&!d&&m.trim()==="")return N1(this.doc,e,["ø"]);const h=d?C2(d,X0(d,m)):m;return N1(this.doc,e,h.split(` -`))});const c=me("div",{class:"editor-row"});s&&c.append(me("span",{class:"fixed-prefix"},s)),c.append(r),n.append(c)}this.renderCaseControls(e)}renderCaseControls(e){var l;const t=S2(e,this.doc);if(!t)return;const n=((l=Jt(this.doc,t))==null?void 0:l.cases)??[],a=T2(e,t),s=me("div",{class:"case-controls"});if(a!==void 0&&n[a]){const u=me("input",{placeholder:p("web_case_name_placeholder"),spellcheck:"false",autocomplete:"off"});u.value=n[a].name,this.liveEdit(u,c=>c.trim()===""?void 0:k2(this.doc,t,a,c)),s.append(me("label",{},p("web_case_name"),u))}const r=me("button",{},`+ ${p("inspector_add_case")}`);r.addEventListener("click",()=>{const u=z2(this.doc,t);this.commit(u.doc,u.path)});const o=me("button",{class:"danger-text"},`- ${p("inspector_remove_case")}`);o.disabled=n.length<=2||a===void 0,o.addEventListener("click",()=>{if(a===void 0)return;const u=I2(this.doc,t,a);this.commit(u.doc,u.path)}),s.append(me("div",{class:"group"},r,o)),this.inspector.append(s)}liveEdit(e,t){let n;e.addEventListener("focus",()=>n=this.doc),e.addEventListener("input",()=>{const a=Fd(e.value);if(a!==e.value){const r=e.selectionStart;e.value=a,e.setSelectionRange(r,r)}const s=t(a);s&&(this.doc=s,this.dirty=!0,this.renderDiagramOnly())}),e.addEventListener("blur",()=>{n&&n!==this.doc&&this.pushUndo(n),n=void 0,this.renderDiagramOnly()})}renderDiagramOnly(){const e=this.selected,t=this.inspector,n=document.createElement("aside");this.inspector=n,this.render(),this.inspector=t,this.selected=e}setSimulating(e){var t;e!==this.simulating&&(document.activeElement instanceof HTMLElement&&document.activeElement.blur(),this.endDrag(),this.simulating=e,this.root.classList.toggle("simulating",e),this.simButton.setAttribute("aria-pressed",String(e)),this.simButton.innerHTML=`${e?se.stop:se.play}${E(p(e?"web_simulation_end":"web_simulation_start"))}`,this.simButton.dataset.tip=p(e?"web_simulation_end_title":"web_simulation_start_title"),this.simButton.setAttribute("aria-label",p(e?"web_simulation_end":"web_simulation_start")),e?(this.setCoding(!1),this.setEditorHidden(!1),(t=this.visuBot)==null||t.setWorlds(Zd(this.tab.exerciseId)),this.visuBot&&!this.previewOpen&&(this.setPreviewOpen(!0),this.previewOpenedForSim=!0),this.placeSimulationRobot(),this.sim.begin()):(this.sim.end(),this.placeSimulationRobot(),this.previewOpenedForSim&&this.setPreviewOpen(!1),this.simPath=void 0,!this.selected&&this.doc.elements.length>0&&(this.selected=[0])),this.render())}runRobot(e){return!this.visuBot||!/\bmbot\s*\./u.test(JSON.stringify(this.tabs.map(t=>t.doc)))?!1:(this.simulating?this.sim.reset():this.setSimulating(!0),e?this.sim.step():this.sim.play(),!0)}setCoding(e){e!==this.coding&&(e&&(this.setLiveCoding(!1),this.setEditorHidden(!1)),this.coding=e,this.root.classList.toggle("coding",e),this.codeButton.setAttribute("aria-pressed",String(e)),e?this.code.refresh():this.code.close(),this.renderDiagramOnly())}openJavaColumn(){if(this.live.language!=="java"){const e="[data-action=live-language]",t=this.topbar.querySelector(e)??this.root.querySelector(e);t?(t.value="java",t.dispatchEvent(new Event("change"))):this.live.setTarget("java")}this.liveCoding||this.setLiveCoding(!0)}setCodeMain(e){this.codeMain=e,Ve(_d,e?"1":"0"),e&&!this.liveCoding&&this.setLiveCoding(!0),e&&this.editorHidden&&this.setEditorHidden(!1),this.shell.classList.toggle("code-main",e),this.labelSwap(),this.canvasHost&&this.render()}labelSwap(){const e=p(this.codeMain?"web_swap_to_editor":"web_swap_to_code");for(const t of this.shell.querySelectorAll("[data-action=swap-main]"))t.dataset.tip=e,t.setAttribute("aria-label",e),t.setAttribute("aria-pressed",String(this.codeMain))}setupPreview(){const e=o=>{this.previewOpenedForSim=!1,this.setPreviewOpen(o)};this.preview.onHide=()=>e(!1),this.preview.rail.addEventListener("click",()=>e(!0)),this.preview.onToggleStacked=()=>{this.previewStacked=!this.previewStacked,Ve(Cd,this.previewStacked?"1":"0"),this.previewStacked&&!this.liveCoding&&this.setLiveCoding(!0),this.placePreview()},this.previewStacked=nt(Cd)==="1";const t=nt(Td);this.previewOpen=t===null||t==="1";const n=this.preview.heightBar,a=this.preview.element,s=(o,l)=>{var m;const u=Math.max(160,(((m=a.parentElement)==null?void 0:m.getBoundingClientRect().height)??600)-120),c=o===void 0?void 0:Math.round(Math.max(160,Math.min(o,u)));a.style.height=c===void 0?"":`${c}px`,l&&Ve(jd,c===void 0?"":String(c))},r=Number(nt(jd));r>0&&(a.style.height=`${r}px`),n.addEventListener("pointerdown",o=>{if(o.button!==0)return;o.preventDefault(),n.setPointerCapture(o.pointerId);const l=o.clientY,u=a.getBoundingClientRect().height;this.shell.classList.add("resizing");const c=d=>s(u-(d.clientY-l),!1),m=d=>{n.removeEventListener("pointermove",c),n.removeEventListener("pointerup",m),n.removeEventListener("pointercancel",m),this.shell.classList.remove("resizing"),s(u-(d.clientY-l),!0)};n.addEventListener("pointermove",c),n.addEventListener("pointerup",m),n.addEventListener("pointercancel",m)}),n.addEventListener("dblclick",()=>s(void 0,!0)),n.addEventListener("keydown",o=>{const l=o.key==="ArrowUp"?20:o.key==="ArrowDown"?-20:0;l&&(o.preventDefault(),s(a.getBoundingClientRect().height+l,!0))}),this.placePreview()}setPreviewOpen(e){this.previewOpen=e,Ve(Td,e?"1":"0"),e||this.preview.pause(),this.placePreview(),this.placeSimulationRobot(),this.canvasHost&&this.render()}placeSimulationRobot(){const e=this.visuBot,t=!!e&&this.simulating&&this.previewOpen;this.preview.hostSimulation(t?e.viewport:void 0),t||e==null||e.restoreViewport()}placePreview(){const e=this.previewStacked&&this.liveCoding;this.preview.setStacked(this.previewStacked),this.shell.classList.toggle("preview",this.previewOpen),this.shell.classList.toggle("preview-stacked",e),e?this.preview.element.parentElement!==this.live.element&&this.live.element.append(this.preview.element):this.preview.element.previousElementSibling!==this.previewResizer&&this.previewResizer.after(this.preview.element)}refreshPreview(){!this.previewOpen||!Hn()||this.preview.update(this.doc,e=>this.findSubprogram(e),Zd(this.tab.exerciseId),this.tab.exerciseId??"",this.tabs.map(e=>e.doc))}setLiveCoding(e){e&&this.coding&&this.setCoding(!1),this.liveCoding=e,this.shell.classList.toggle("live",e),this.placePreview(),e||this.live.hideConsole(),Ve(Sd,e?"1":"0"),this.keepAColumnOpen(),this.canvasHost&&this.render()}learnResizer(){return this.panelResizer(this.learn.element,"learn-resizer",kd,p("web_learn_resize"),1)}liveResizer(){return this.panelResizer(this.live.element,"live-resizer",cR,p("web_live_resize"),-1,()=>this.root)}yieldingPanels(){return[{panel:this.preview.element,key:Pd},{panel:this.learn.element,key:kd},{panel:this.files.element,key:Id}].filter(({panel:e})=>e.offsetParent!==null&&e.parentElement===this.live.element.parentElement)}panelResizer(e,t,n,a,s,r){const o=me("div",{class:t,role:"separator","aria-orientation":"vertical",tabindex:"0",title:a}),l=d=>{var b;const h=((b=e.parentElement)==null?void 0:b.getBoundingClientRect().width)??0;if(h===0)return pR(d);const g=[this.files.element,this.learn.element,this.live.element,this.preview.element].filter(x=>x!==e&&x.offsetParent!==null&&getComputedStyle(x).flexGrow==="0").reduce((x,v)=>x+v.getBoundingClientRect().width,0),f=parseFloat(getComputedStyle(e).minWidth)||200;return Math.round(Math.max(f,Math.min(d,h-g-240)))},u=(d,h)=>{e.style.width=d===void 0?"":`${l(d)}px`,h&&Ve(n,d===void 0?"":String(l(d)))},c=Number(nt(n));c>0&&u(c,!1);const m=()=>{const d=typeof s=="function"?s():s;return getComputedStyle(this.shell).direction==="rtl"?-d:d};return o.addEventListener("pointerdown",d=>{if(d.button!==0)return;d.preventDefault(),o.setPointerCapture(d.pointerId);const h=d.clientX,g=e.getBoundingClientRect().width,f=m();this.shell.classList.add("resizing");const b=r?this.pushResize(e,n,r(),g):void 0,x=(I,z)=>(b??u)(g+f*(I.clientX-h),z),v=I=>x(I,!1),w=I=>{o.removeEventListener("pointermove",v),o.removeEventListener("pointerup",w),o.removeEventListener("pointercancel",w),this.shell.classList.remove("resizing"),x(I,!0)};o.addEventListener("pointermove",v),o.addEventListener("pointerup",w),o.addEventListener("pointercancel",w)}),o.addEventListener("dblclick",()=>u(void 0,!0)),o.addEventListener("keydown",d=>{const h=d.key==="ArrowRight"?20:d.key==="ArrowLeft"?-20:0;h&&(d.preventDefault(),u(e.getBoundingClientRect().width+m()*h,!0))}),o}pushResize(e,t,n,a){const s=(c,m)=>Math.max(parseFloat(getComputedStyle(c).minWidth)||0,m),r=s(e,200),o=Math.max(0,n.getBoundingClientRect().width-s(n,240)),l=this.yieldingPanels().map(c=>({...c,start:c.panel.getBoundingClientRect().width,min:s(c.panel,200),changed:!1})),u=l.reduce((c,m)=>c+Math.max(0,m.start-m.min),0);return(c,m)=>{const d=Math.round(Math.max(r,Math.min(c,a+o+u)));let h=Math.max(0,d-a-o,r-c);for(const g of l){const f=Math.min(h,Math.max(0,g.start-g.min));h-=f,g.changed||(g.changed=f>0),g.changed&&(g.panel.style.width=`${Math.round(g.start-f)}px`,m&&Ve(g.key,String(Math.round(g.start-f))))}e.style.width=`${d}px`,m&&Ve(t,String(d))}}findSubprogram(e,t=this.tab){const n=ro(e);if(n==="")return;const a=this.tabs.find(s=>s!==t&&(ro(s.doc.caption)===n||ro(un(s))===n));return a==null?void 0:a.doc}scrollToSimPath(){const e=this.simPath;if(!this.simulating||!e)return;const t=this.flat.find(o=>go(o.idPath,e));if(!t)return;const n=this.canvasHost,a=this.zoom,s={x:t.frame.x*a,y:t.frame.y*a,width:t.frame.width*a,height:t.frame.height*a},r=24;s.yn.scrollTop+n.clientHeight&&(n.scrollTop=s.y-r),(s.xn.scrollLeft+n.clientWidth-r)&&(n.scrollLeft=Math.max(0,s.x-r))}commit(e,t){this.codeTyping=void 0,this.pushUndo(this.doc),this.doc=e,this.dirty=!0,t&&(this.selected=t),this.render()}commitFromCode(e,t){const n=Date.now(),a=this.codeTyping;!a||a.tab!==this.tab||n-a.last>1e3||n-a.start>5e3?(this.pushUndo(this.doc),this.codeTyping={tab:this.tab,start:n,last:n}):a.last=n,this.doc=e,this.dirty=!0,this.selected=mr(t??this.selected,e),this.render()}pushUndo(e){for(this.undoStack.push(e);this.undoStack.length>hR;)this.undoStack.shift();this.tab.redoStack=[]}undo(){const e=this.undoStack.pop();e&&(this.codeTyping=void 0,this.redoStack.push(this.doc),this.doc=e,this.dirty=!0,this.selected=mr(this.selected,this.doc),this.render())}redo(){const e=this.redoStack.pop();e&&(this.codeTyping=void 0,this.undoStack.push(this.doc),this.doc=e,this.dirty=!0,this.selected=mr(this.selected,this.doc),this.render())}resetHistory(){this.setSimulating(!1),this.tab.undoStack=[],this.tab.redoStack=[],this.selected=void 0,this.dirty=!1,this.render()}makeTab(){return{doc:x2(),serial:this.nextTabSerial++,dirty:!1,undoStack:[],redoStack:[],selected:[0]}}addTab(e=this.makeTab()){this.setSimulating(!1),this.tabs.push(e),this.tabIndex=this.tabs.length-1,this.render()}switchTab(e){e===this.tabIndex||!this.tabs[e]||(document.activeElement instanceof HTMLElement&&document.activeElement.blur(),this.setSimulating(!1),this.tabIndex=e,this.render())}async closeTab(e){if(this.tabs.length<=1)return;const t=this.tabs[e];t.dirty&&!t.exerciseId&&(this.switchTab(e),!await this.confirmDiscard())||(this.setSimulating(!1),this.tabs.splice(e,1),(this.tabIndex>e||this.tabIndex>=this.tabs.length)&&(this.tabIndex=Math.max(0,this.tabIndex-1)),this.render())}renderTabs(){const e=this.tabStrip;e.replaceChildren(),this.tabs.forEach((n,a)=>{const s=document.createElement("div");s.className="tab"+(a===this.tabIndex?" active":""),s.setAttribute("role","tab"),s.setAttribute("aria-selected",String(a===this.tabIndex));const r=document.createElement("button");r.className="tab-label",r.textContent=un(n),r.title=n.fileName??un(n),r.addEventListener("click",()=>this.switchTab(a)),s.append(r);const o=n.dirty&&!n.exerciseId;if(this.tabs.length>1){const l=document.createElement("button");l.className="tab-close"+(o?" unsaved":""),l.innerHTML='✕',l.title=p("a11y_close_tab"),l.setAttribute("aria-label",`${p("a11y_close_tab")}: ${un(n)}`),l.addEventListener("click",()=>this.closeTab(a)),s.append(l)}else o&&s.append(Object.assign(document.createElement("span"),{className:"tab-close unsaved",innerHTML:'●'}));o&&r.setAttribute("aria-label",`${un(n)} (${p("web_status_modified")})`),e.append(s)});const t=document.createElement("button");t.className="tab-add",t.textContent="+",t.title=p("a11y_new_diagram_tab"),t.setAttribute("aria-label",p("a11y_new_diagram_tab")),t.addEventListener("click",()=>this.addTab()),e.append(t)}copySelection(){const e=this.selected&&Jt(this.doc,this.selected);return e?(this.clipboard=structuredClone(e),this.showMessage(p("web_copied")),!0):!1}cutSelection(){this.selected&&cr(this.doc,this.selected)&&this.copySelection()&&this.deleteSelection()}paste(){this.clipboard&&this.insertNearSelection(structuredClone(this.clipboard))}deleteSelection(){!this.selected||!cr(this.doc,this.selected)||(this.commit(vi(this.doc,this.selected)),this.selected=void 0,this.render())}insertSensor(e,t=this.selected){if(!t||In(this.doc,t))return;const n=jt(this.doc,t);if(!gd.includes(n.type))return;const a=(n.textLines??[]).join(" ").trim();this.commit(N1(this.doc,t,[a?`${a} ${e}`:e]),t);const s=this.inspector.querySelector("textarea");s&&(s.focus(),s.setSelectionRange(s.value.length,s.value.length))}insertNearSelection(e){const t=this.selected;if(t&&In(this.doc,t))return this.commit(jn(this.doc,t,e),t);if(t){const n=[...t.slice(0,-1),t[t.length-1]+1];return this.commit(lo(this.doc,e,t),n)}if(this.doc.elements.length===1&&In(this.doc,[0]))return this.commit(jn(this.doc,[0],e),[0]);this.commit(ai(this.doc,[],this.doc.elements.length,e),[this.doc.elements.length])}confirmDiscard(){return this.dirty?new Promise(e=>{const t=document.createElement("div");t.className="confirm",t.innerHTML=`
+`))??"";if(r===$a(u))return;const c=A2(r,u);this.commit(N1(this.doc,e,c.split(` +`))),(d=this.inspector.querySelector("textarea"))==null||d.focus()}),s.append(l)}n.append(s,me("p",{class:"hint mono-hint"},lR[a]))}if(t.type===S.forSchleife){const a=me("div",{class:"for-fields"}),s=K0(t.textLines);[[p("inspector_for_init"),p("inspector_for_placeholder_init")],[p("inspector_for_condition"),p("inspector_for_placeholder_condition")],[p("inspector_for_step"),p("inspector_for_placeholder_step")]].forEach(([o,l],u)=>{const c=me("input",{placeholder:l,spellcheck:"false",autocomplete:"off"});c.value=s[u],this.liveEdit(c,m=>{const d=Jt(this.doc,e);if(!d)return;const h=K0(d.textLines);return h[u]=P2(m),N1(this.doc,e,h)}),a.append(me("label",{},o,c))}),n.append(a)}else if(t.type!==S.leerElement){const a=oR[t.type];a&&n.append(me("p",{class:"hint mono-hint"},a));const s=fd(t),r=me("textarea",{rows:"3",spellcheck:"false"}),o=t.textLines.join(` +`),l=t.type===S.anweisung,u=s?X0(s,o):o;r.value=l&&u.trim()==="ø"?"":u,r.placeholder=uR(t),this.liveEdit(r,m=>{const d=fd(Jt(this.doc,e)??t);if(l&&!d&&m.trim()==="")return N1(this.doc,e,["ø"]);const h=d?j2(d,X0(d,m)):m;return N1(this.doc,e,h.split(` +`))});const c=me("div",{class:"editor-row"});s&&c.append(me("span",{class:"fixed-prefix"},s)),c.append(r),n.append(c)}this.renderCaseControls(e)}renderCaseControls(e){var l;const t=T2(e,this.doc);if(!t)return;const n=((l=Jt(this.doc,t))==null?void 0:l.cases)??[],a=_2(e,t),s=me("div",{class:"case-controls"});if(a!==void 0&&n[a]){const u=me("input",{placeholder:p("web_case_name_placeholder"),spellcheck:"false",autocomplete:"off"});u.value=n[a].name,this.liveEdit(u,c=>c.trim()===""?void 0:S2(this.doc,t,a,c)),s.append(me("label",{},p("web_case_name"),u))}const r=me("button",{},`+ ${p("inspector_add_case")}`);r.addEventListener("click",()=>{const u=I2(this.doc,t);this.commit(u.doc,u.path)});const o=me("button",{class:"danger-text"},`- ${p("inspector_remove_case")}`);o.disabled=n.length<=2||a===void 0,o.addEventListener("click",()=>{if(a===void 0)return;const u=k2(this.doc,t,a);this.commit(u.doc,u.path)}),s.append(me("div",{class:"group"},r,o)),this.inspector.append(s)}liveEdit(e,t){let n;e.addEventListener("focus",()=>n=this.doc),e.addEventListener("input",()=>{const a=Fd(e.value);if(a!==e.value){const r=e.selectionStart;e.value=a,e.setSelectionRange(r,r)}const s=t(a);s&&(this.doc=s,this.dirty=!0,this.renderDiagramOnly())}),e.addEventListener("blur",()=>{n&&n!==this.doc&&this.pushUndo(n),n=void 0,this.renderDiagramOnly()})}renderDiagramOnly(){const e=this.selected,t=this.inspector,n=document.createElement("aside");this.inspector=n,this.render(),this.inspector=t,this.selected=e}setSimulating(e){var t;e!==this.simulating&&(document.activeElement instanceof HTMLElement&&document.activeElement.blur(),this.endDrag(),this.simulating=e,this.root.classList.toggle("simulating",e),this.simButton.setAttribute("aria-pressed",String(e)),this.simButton.innerHTML=`${e?se.stop:se.play}${E(p(e?"web_simulation_end":"web_simulation_start"))}`,this.simButton.dataset.tip=p(e?"web_simulation_end_title":"web_simulation_start_title"),this.simButton.setAttribute("aria-label",p(e?"web_simulation_end":"web_simulation_start")),e?(this.setCoding(!1),this.setEditorHidden(!1),(t=this.visuBot)==null||t.setWorlds(Zd(this.tab.exerciseId)),this.visuBot&&!this.previewOpen&&(this.setPreviewOpen(!0),this.previewOpenedForSim=!0),this.placeSimulationRobot(),this.sim.begin()):(this.sim.end(),this.placeSimulationRobot(),this.previewOpenedForSim&&this.setPreviewOpen(!1),this.simPath=void 0,!this.selected&&this.doc.elements.length>0&&(this.selected=[0])),this.render())}runRobot(e){return!this.visuBot||!/\bmbot\s*\./u.test(JSON.stringify(this.tabs.map(t=>t.doc)))?!1:(this.simulating?this.sim.reset():this.setSimulating(!0),e?this.sim.step():this.sim.play(),!0)}setCoding(e){e!==this.coding&&(e&&(this.setLiveCoding(!1),this.setEditorHidden(!1)),this.coding=e,this.root.classList.toggle("coding",e),this.codeButton.setAttribute("aria-pressed",String(e)),e?this.code.refresh():this.code.close(),this.renderDiagramOnly())}openJavaColumn(){if(this.live.language!=="java"){const e="[data-action=live-language]",t=this.topbar.querySelector(e)??this.root.querySelector(e);t?(t.value="java",t.dispatchEvent(new Event("change"))):this.live.setTarget("java")}this.liveCoding||this.setLiveCoding(!0)}setCodeMain(e){this.codeMain=e,Ve(_d,e?"1":"0"),e&&!this.liveCoding&&this.setLiveCoding(!0),e&&this.editorHidden&&this.setEditorHidden(!1),this.shell.classList.toggle("code-main",e),this.labelSwap(),this.canvasHost&&this.render()}labelSwap(){const e=p(this.codeMain?"web_swap_to_editor":"web_swap_to_code");for(const t of this.shell.querySelectorAll("[data-action=swap-main]"))t.dataset.tip=e,t.setAttribute("aria-label",e),t.setAttribute("aria-pressed",String(this.codeMain))}setupPreview(){const e=o=>{this.previewOpenedForSim=!1,this.setPreviewOpen(o)};this.preview.onHide=()=>e(!1),this.preview.rail.addEventListener("click",()=>e(!0)),this.preview.onToggleStacked=()=>{this.previewStacked=!this.previewStacked,Ve(Cd,this.previewStacked?"1":"0"),this.previewStacked&&!this.liveCoding&&this.setLiveCoding(!0),this.placePreview()},this.previewStacked=nt(Cd)==="1";const t=nt(Td);this.previewOpen=t===null||t==="1";const n=this.preview.heightBar,a=this.preview.element,s=(o,l)=>{var m;const u=Math.max(160,(((m=a.parentElement)==null?void 0:m.getBoundingClientRect().height)??600)-120),c=o===void 0?void 0:Math.round(Math.max(160,Math.min(o,u)));a.style.height=c===void 0?"":`${c}px`,l&&Ve(Pd,c===void 0?"":String(c))},r=Number(nt(Pd));r>0&&(a.style.height=`${r}px`),n.addEventListener("pointerdown",o=>{if(o.button!==0)return;o.preventDefault(),n.setPointerCapture(o.pointerId);const l=o.clientY,u=a.getBoundingClientRect().height;this.shell.classList.add("resizing");const c=d=>s(u-(d.clientY-l),!1),m=d=>{n.removeEventListener("pointermove",c),n.removeEventListener("pointerup",m),n.removeEventListener("pointercancel",m),this.shell.classList.remove("resizing"),s(u-(d.clientY-l),!0)};n.addEventListener("pointermove",c),n.addEventListener("pointerup",m),n.addEventListener("pointercancel",m)}),n.addEventListener("dblclick",()=>s(void 0,!0)),n.addEventListener("keydown",o=>{const l=o.key==="ArrowUp"?20:o.key==="ArrowDown"?-20:0;l&&(o.preventDefault(),s(a.getBoundingClientRect().height+l,!0))}),this.placePreview()}setPreviewOpen(e){this.previewOpen=e,Ve(Td,e?"1":"0"),e||this.preview.pause(),this.placePreview(),this.placeSimulationRobot(),this.canvasHost&&this.render()}placeSimulationRobot(){const e=this.visuBot,t=!!e&&this.simulating&&this.previewOpen;this.preview.hostSimulation(t?e.viewport:void 0),t||e==null||e.restoreViewport()}placePreview(){const e=this.previewStacked&&this.liveCoding;this.preview.setStacked(this.previewStacked),this.shell.classList.toggle("preview",this.previewOpen),this.shell.classList.toggle("preview-stacked",e),e?this.preview.element.parentElement!==this.live.element&&this.live.element.append(this.preview.element):this.preview.element.previousElementSibling!==this.previewResizer&&this.previewResizer.after(this.preview.element)}refreshPreview(){!this.previewOpen||!Hn()||this.preview.update(this.doc,e=>this.findSubprogram(e),Zd(this.tab.exerciseId),this.tab.exerciseId??"",this.tabs.map(e=>e.doc))}setLiveCoding(e){e&&this.coding&&this.setCoding(!1),this.liveCoding=e,this.shell.classList.toggle("live",e),this.placePreview(),e||this.live.hideConsole(),Ve(Sd,e?"1":"0"),this.keepAColumnOpen(),this.canvasHost&&this.render()}learnResizer(){return this.panelResizer(this.learn.element,"learn-resizer",kd,p("web_learn_resize"),1)}liveResizer(){return this.panelResizer(this.live.element,"live-resizer",dR,p("web_live_resize"),-1,()=>this.root)}yieldingPanels(){return[{panel:this.preview.element,key:jd},{panel:this.learn.element,key:kd},{panel:this.files.element,key:Id}].filter(({panel:e})=>e.offsetParent!==null&&e.parentElement===this.live.element.parentElement)}panelResizer(e,t,n,a,s,r){const o=me("div",{class:t,role:"separator","aria-orientation":"vertical",tabindex:"0",title:a}),l=d=>{var b;const h=((b=e.parentElement)==null?void 0:b.getBoundingClientRect().width)??0;if(h===0)return bR(d);const g=[this.files.element,this.learn.element,this.live.element,this.preview.element].filter(x=>x!==e&&x.offsetParent!==null&&getComputedStyle(x).flexGrow==="0").reduce((x,v)=>x+v.getBoundingClientRect().width,0),f=parseFloat(getComputedStyle(e).minWidth)||200;return Math.round(Math.max(f,Math.min(d,h-g-240)))},u=(d,h)=>{e.style.width=d===void 0?"":`${l(d)}px`,h&&Ve(n,d===void 0?"":String(l(d)))},c=Number(nt(n));c>0&&u(c,!1);const m=()=>{const d=typeof s=="function"?s():s;return getComputedStyle(this.shell).direction==="rtl"?-d:d};return o.addEventListener("pointerdown",d=>{if(d.button!==0)return;d.preventDefault(),o.setPointerCapture(d.pointerId);const h=d.clientX,g=e.getBoundingClientRect().width,f=m();this.shell.classList.add("resizing");const b=r?this.pushResize(e,n,r(),g):void 0,x=(I,z)=>(b??u)(g+f*(I.clientX-h),z),v=I=>x(I,!1),w=I=>{o.removeEventListener("pointermove",v),o.removeEventListener("pointerup",w),o.removeEventListener("pointercancel",w),this.shell.classList.remove("resizing"),x(I,!0)};o.addEventListener("pointermove",v),o.addEventListener("pointerup",w),o.addEventListener("pointercancel",w)}),o.addEventListener("dblclick",()=>u(void 0,!0)),o.addEventListener("keydown",d=>{const h=d.key==="ArrowRight"?20:d.key==="ArrowLeft"?-20:0;h&&(d.preventDefault(),u(e.getBoundingClientRect().width+m()*h,!0))}),o}pushResize(e,t,n,a){const s=(c,m)=>Math.max(parseFloat(getComputedStyle(c).minWidth)||0,m),r=s(e,200),o=Math.max(0,n.getBoundingClientRect().width-s(n,240)),l=this.yieldingPanels().map(c=>({...c,start:c.panel.getBoundingClientRect().width,min:s(c.panel,200),changed:!1})),u=l.reduce((c,m)=>c+Math.max(0,m.start-m.min),0);return(c,m)=>{const d=Math.round(Math.max(r,Math.min(c,a+o+u)));let h=Math.max(0,d-a-o,r-c);for(const g of l){const f=Math.min(h,Math.max(0,g.start-g.min));h-=f,g.changed||(g.changed=f>0),g.changed&&(g.panel.style.width=`${Math.round(g.start-f)}px`,m&&Ve(g.key,String(Math.round(g.start-f))))}e.style.width=`${d}px`,m&&Ve(t,String(d))}}findSubprogram(e,t=this.tab){const n=ro(e);if(n==="")return;const a=this.tabs.find(s=>s!==t&&(ro(s.doc.caption)===n||ro(un(s))===n));return a==null?void 0:a.doc}scrollToSimPath(){const e=this.simPath;if(!this.simulating||!e)return;const t=this.flat.find(o=>go(o.idPath,e));if(!t)return;const n=this.canvasHost,a=this.zoom,s={x:t.frame.x*a,y:t.frame.y*a,width:t.frame.width*a,height:t.frame.height*a},r=24;s.yn.scrollTop+n.clientHeight&&(n.scrollTop=s.y-r),(s.xn.scrollLeft+n.clientWidth-r)&&(n.scrollLeft=Math.max(0,s.x-r))}commit(e,t){this.codeTyping=void 0,this.pushUndo(this.doc),this.doc=e,this.dirty=!0,t&&(this.selected=t),this.render()}commitFromCode(e,t){const n=Date.now(),a=this.codeTyping;!a||a.tab!==this.tab||n-a.last>1e3||n-a.start>5e3?(this.pushUndo(this.doc),this.codeTyping={tab:this.tab,start:n,last:n}):a.last=n,this.doc=e,this.dirty=!0,this.selected=mr(t??this.selected,e),this.render()}pushUndo(e){for(this.undoStack.push(e);this.undoStack.length>pR;)this.undoStack.shift();this.tab.redoStack=[]}undo(){const e=this.undoStack.pop();e&&(this.codeTyping=void 0,this.redoStack.push(this.doc),this.doc=e,this.dirty=!0,this.selected=mr(this.selected,this.doc),this.render())}redo(){const e=this.redoStack.pop();e&&(this.codeTyping=void 0,this.undoStack.push(this.doc),this.doc=e,this.dirty=!0,this.selected=mr(this.selected,this.doc),this.render())}resetHistory(){this.setSimulating(!1),this.tab.undoStack=[],this.tab.redoStack=[],this.selected=void 0,this.dirty=!1,this.render()}makeTab(){return{doc:v2(),serial:this.nextTabSerial++,dirty:!1,undoStack:[],redoStack:[],selected:[0]}}addTab(e=this.makeTab()){this.setSimulating(!1),this.tabs.push(e),this.tabIndex=this.tabs.length-1,this.render()}switchTab(e){e===this.tabIndex||!this.tabs[e]||(document.activeElement instanceof HTMLElement&&document.activeElement.blur(),this.setSimulating(!1),this.tabIndex=e,this.render())}async closeTab(e){if(this.tabs.length<=1)return;const t=this.tabs[e];t.dirty&&!t.exerciseId&&(this.switchTab(e),!await this.confirmDiscard())||(this.setSimulating(!1),this.tabs.splice(e,1),(this.tabIndex>e||this.tabIndex>=this.tabs.length)&&(this.tabIndex=Math.max(0,this.tabIndex-1)),this.render())}renderTabs(){const e=this.tabStrip;e.replaceChildren(),this.tabs.forEach((n,a)=>{const s=document.createElement("div");s.className="tab"+(a===this.tabIndex?" active":""),s.setAttribute("role","tab"),s.setAttribute("aria-selected",String(a===this.tabIndex));const r=document.createElement("button");r.className="tab-label",r.textContent=un(n),r.title=n.fileName??un(n),r.addEventListener("click",()=>this.switchTab(a)),s.append(r);const o=n.dirty&&!n.exerciseId;if(this.tabs.length>1){const l=document.createElement("button");l.className="tab-close"+(o?" unsaved":""),l.innerHTML='✕',l.title=p("a11y_close_tab"),l.setAttribute("aria-label",`${p("a11y_close_tab")}: ${un(n)}`),l.addEventListener("click",()=>this.closeTab(a)),s.append(l)}else o&&s.append(Object.assign(document.createElement("span"),{className:"tab-close unsaved",innerHTML:'●'}));o&&r.setAttribute("aria-label",`${un(n)} (${p("web_status_modified")})`),e.append(s)});const t=document.createElement("button");t.className="tab-add",t.textContent="+",t.title=p("a11y_new_diagram_tab"),t.setAttribute("aria-label",p("a11y_new_diagram_tab")),t.addEventListener("click",()=>this.addTab()),e.append(t)}copySelection(){const e=this.selected&&Jt(this.doc,this.selected);return e?(this.clipboard=structuredClone(e),this.showMessage(p("web_copied")),!0):!1}cutSelection(){this.selected&&cr(this.doc,this.selected)&&this.copySelection()&&this.deleteSelection()}paste(){this.clipboard&&this.insertNearSelection(structuredClone(this.clipboard))}deleteSelection(){!this.selected||!cr(this.doc,this.selected)||(this.commit(vi(this.doc,this.selected)),this.selected=void 0,this.render())}insertSensor(e,t=this.selected){if(!t||In(this.doc,t))return;const n=Pt(this.doc,t);if(!gd.includes(n.type))return;const a=(n.textLines??[]).join(" ").trim();this.commit(N1(this.doc,t,[a?`${a} ${e}`:e]),t);const s=this.inspector.querySelector("textarea");s&&(s.focus(),s.setSelectionRange(s.value.length,s.value.length))}insertNearSelection(e){const t=this.selected;if(t&&In(this.doc,t))return this.commit(Pn(this.doc,t,e),t);if(t){const n=[...t.slice(0,-1),t[t.length-1]+1];return this.commit(lo(this.doc,e,t),n)}if(this.doc.elements.length===1&&In(this.doc,[0]))return this.commit(Pn(this.doc,[0],e),[0]);this.commit(ai(this.doc,[],this.doc.elements.length,e),[this.doc.elements.length])}confirmDiscard(){return this.dirty?new Promise(e=>{const t=document.createElement("div");t.className="confirm",t.innerHTML=`

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

${E(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=El(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:pd()}),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([u1(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:pd()}),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=ld(this.doc,un(this.tab));return this.offerDownload(`${s}.visustruct`,new Blob([u1(this.doc)],{type:"application/xml"}))}const t=ud(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=ld(this.doc,un(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([i2(t)],{type:"image/svg+xml"}));break}case"png":{const s=await cd(t,a);await this.offerDownload(`${n}.png`,await VJ(s));break}case"pdf":{const s=await cd(t,Math.max(a,3)),r=await UJ($J(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==="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&&go(n.idPath,this.selected);this.selected=n==null?void 0:n.idPath,this.render(),n&&e.pointerType!=="touch"&&!(In(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=jt(this.doc,e.path);t.textContent=`${io(n.type)}: ${Dl(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||In(this.doc,s.idPath)?void 0:gd.includes(jt(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 c=u.frame.y+u.frame.height;return t>c?n.kind==="move"&&n.path.length===1&&n.path[0]===a.length-1?void 0:{kind:"rootAppend",frame:{x:u.frame.x,y:c,width:u.frame.width,height:0}}:t=n.path.length&&n.path.every((u,c)=>r[c]===u)?void 0:In(this.doc,r)?{kind:"replace",path:r,frame:s.frame}:{kind:t"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e])}function Zd(i){if(!i)return[];for(const e of[...Pt.flatMap(t=>t.steps.flatMap(n=>n.blocks)),...An.flatMap(t=>t.blocks)])if(!(e.kind!=="exercise"||e.exercise.id!==i))return e.exercise.tests.flatMap(t=>{const n=t.world?Fa(t.world):void 0;return n?[n]:[]});return[]}let Ft,Cl,Pl;function Md(i){const e=i.dataset.tip;if(!e)return;Ft??(Ft=Object.assign(document.createElement("div"),{className:"tooltip",role:"tooltip"})),Ft.isConnected||document.body.append(Ft),Ft.textContent=e,Ft.hidden=!1;const t=i.getBoundingClientRect(),n=Ft.offsetWidth,a=Ft.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!==Pl&&(oo(),e&&(Pl=e,Cl=window.setTimeout(()=>Md(e),350)))}),document.addEventListener("focusin",i=>{const e=i.target.closest("[data-tip]");oo(),e!=null&&e.matches(":focus-visible")&&Md(e)});for(const i of["pointerdown","focusout","scroll","keydown"])document.addEventListener(i,oo,!0)}const jl="visustruct.reloadedAfterError";function o2(){try{const i=Number(sessionStorage.getItem(jl));if(i&&Date.now()-i<3e4)return!1;sessionStorage.setItem(jl,String(Date.now()))}catch{return!1}return location.reload(),!0}function xR(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=>{o2()&&i.preventDefault()});const vR=$2();Promise.all([ah(vR,!1),ih(Q2(),!1)]).then(()=>{r2(),bR();const i=new URLSearchParams(location.search);i.has("visuobject")&&hg();const e=document.getElementById("app");if(dg()&&!i.has("visustruct")&&!i.has("visubot"))return ee(async()=>{const{ObjectApp:t}=await import("./objectApp-fPb85kNH.js").then(n=>n.g);return{ObjectApp:t}},[],import.meta.url).then(({ObjectApp:t})=>new t(e));new gR(e)}).then(()=>{try{sessionStorage.removeItem(jl)}catch{}}).catch(i=>{/dynamically imported module|Importing a module script failed|error loading dynamically/i.test(String(i))&&o2()||xR(i)});export{Qn as C,yJ as J,Hb as L,ee as _,rJ as a,AJ as b,Uf as c,SR as d,Ir as e,la as f,dR as g,PZ as h,se as i,CZ as j,s1 as k,kR as m,kJ as p,hc as r,MZ as s,p as t,Zo as w}; +
`,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=El(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:pd()}),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([u1(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:pd()}),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=ld(this.doc,un(this.tab));return this.offerDownload(`${s}.visustruct`,new Blob([u1(this.doc)],{type:"application/xml"}))}const t=ud(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=ld(this.doc,un(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([a2(t)],{type:"image/svg+xml"}));break}case"png":{const s=await cd(t,a);await this.offerDownload(`${n}.png`,await QJ(s));break}case"pdf":{const s=await cd(t,Math.max(a,3)),r=await YJ(XJ(s),s.width,s.height,t,i2(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==="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&&go(n.idPath,this.selected);this.selected=n==null?void 0:n.idPath,this.render(),n&&e.pointerType!=="touch"&&!(In(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=Pt(this.doc,e.path);t.textContent=`${io(n.type)}: ${Dl(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||In(this.doc,s.idPath)?void 0:gd.includes(Pt(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 c=u.frame.y+u.frame.height;return t>c?n.kind==="move"&&n.path.length===1&&n.path[0]===a.length-1?void 0:{kind:"rootAppend",frame:{x:u.frame.x,y:c,width:u.frame.width,height:0}}:t=n.path.length&&n.path.every((u,c)=>r[c]===u)?void 0:In(this.doc,r)?{kind:"replace",path:r,frame:s.frame}:{kind:t"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e])}function Zd(i){if(!i)return[];for(const e of[...jt.flatMap(t=>t.steps.flatMap(n=>n.blocks)),...An.flatMap(t=>t.blocks)])if(!(e.kind!=="exercise"||e.exercise.id!==i))return e.exercise.tests.flatMap(t=>{const n=t.world?Fa(t.world):void 0;return n?[n]:[]});return[]}let Ft,Cl,jl;function Md(i){const e=i.dataset.tip;if(!e)return;Ft??(Ft=Object.assign(document.createElement("div"),{className:"tooltip",role:"tooltip"})),Ft.isConnected||document.body.append(Ft),Ft.textContent=e,Ft.hidden=!1;const t=i.getBoundingClientRect(),n=Ft.offsetWidth,a=Ft.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!==jl&&(oo(),e&&(jl=e,Cl=window.setTimeout(()=>Md(e),350)))}),document.addEventListener("focusin",i=>{const e=i.target.closest("[data-tip]");oo(),e!=null&&e.matches(":focus-visible")&&Md(e)});for(const i of["pointerdown","focusout","scroll","keydown"])document.addEventListener(i,oo,!0)}const Pl="visustruct.reloadedAfterError";function l2(){try{const i=Number(sessionStorage.getItem(Pl));if(i&&Date.now()-i<3e4)return!1;sessionStorage.setItem(Pl,String(Date.now()))}catch{return!1}return location.reload(),!0}function yR(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=>{l2()&&i.preventDefault()});const wR=Y2();Promise.all([ah(wR,!1),ih(U2(),!1)]).then(()=>{o2(),vR();const i=new URLSearchParams(location.search);i.has("visuobject")&&gg();const e=document.getElementById("app");if(hg()&&!i.has("visustruct")&&!i.has("visubot"))return ee(async()=>{const{ObjectApp:t}=await import("./objectApp-BAiNGNpM.js").then(n=>n.g);return{ObjectApp:t}},[],import.meta.url).then(({ObjectApp:t})=>new t(e));new fR(e)}).then(()=>{try{sessionStorage.removeItem(Pl)}catch{}}).catch(i=>{/dynamically imported module|Importing a module script failed|error loading dynamically/i.test(String(i))&&l2()||yR(i)});export{Qn as C,zJ as J,Vb as L,ee as _,lJ as a,jJ as b,$f as c,_R as d,Ir as e,la as f,gR as g,DZ as h,se as i,PZ as j,s1 as k,TR as m,TJ as p,hc as r,EZ as s,p as t,Zo as w}; diff --git a/website/app/assets/index-Dn-t64wp.css b/website/app/assets/index-Dn-t64wp.css new file mode 100644 index 00000000..bf566d09 --- /dev/null +++ b/website/app/assets/index-Dn-t64wp.css @@ -0,0 +1 @@ +:root{--bg: #f2f2f7;--panel: #ffffff;--text: #1c1c1e;--muted: #6e6e73;--border: #d1d1d6;--accent: #007aff;--accent-soft: rgba(0, 122, 255, .18);--accent-faint: rgba(0, 122, 255, .08);--accent-glow: rgba(0, 122, 255, .35);--area-editor: #007aff;--area-code: #7c3aed;color-scheme:light}:root.visubot-theme{--bg: #f1f0f8;--text: #2f3454;--muted: #6a6890;--border: #d6d3e8;--accent: #e07000;--accent-soft: rgba(253, 161, 21, .24);--accent-faint: rgba(253, 161, 21, .1);--accent-glow: rgba(224, 112, 0, .35)}:root.visubot-theme .selection-frame{stroke:#e07000e6}*{box-sizing:border-box}html,body{margin:0;height:100%;background:var(--bg);color:var(--text);font:14px/1.4 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.app{display:grid;grid-template:"tools tools" auto "pal work" 1fr "pal insp" auto / var(--palette-width, 210px) minmax(0,1fr);height:100%;flex:1;min-width:0}.shell{display:flex;flex-direction:column;height:100vh;height:100dvh}.columns{display:flex;flex:1;min-height:0}.columns>.app{min-width:240px}.toolbar{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;padding:8px 12px;background:var(--panel);border-bottom:1px solid var(--border)}button.icon{display:inline-flex;align-items:center;justify-content:center;min-width:34px;height:32px;padding:0 7px}button.icon svg{display:block}.tooltip{position:fixed;z-index:1000;max-width:260px;padding:4px 8px;border-radius:6px;background:#1c1c1e;color:#fff;font-size:12px;line-height:1.35;pointer-events:none;box-shadow:0 2px 8px #0003}.tooltip[hidden]{display:none}.diagram-tools{grid-area:tools;display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:5px 8px;background:var(--panel);border-bottom:1px solid var(--border)}.diagram-tools button.icon{min-width:30px;height:30px;padding:0 5px}.diagram-tools .sim-toggle{margin-inline-start:auto;display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 10px;white-space:nowrap}.diagram-tools{container-type:inline-size}@container (max-width: 520px){.diagram-tools .sim-toggle span{display:none}}.diagram-tools .sep{width:1px;height:20px;margin-inline:3px;background:var(--border)}.menu-host{position:relative}.export-menu{position:absolute;top:calc(100% + 4px);inset-inline-end:0;z-index:30;display:grid;min-width:180px;padding:4px;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #00000026}.export-menu[hidden]{display:none}.export-menu button{border:none;background:none;text-align:start;padding:7px 10px;border-radius:6px}.export-menu button:hover,.export-menu button:focus-visible{background:var(--accent-soft)}.settings{position:relative;margin-inline-start:auto}.settings>button{display:inline-flex;align-items:center;padding:6px 8px}.settings-menu{position:absolute;top:calc(100% + 6px);inset-inline-end:0;z-index:30;display:grid;width:290px;max-width:calc(100vw - 24px);max-height:calc(100dvh - 80px);overflow-y:auto;padding:4px 0;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #00000026}.settings-menu[hidden]{display:none}.settings-menu section,.settings-menu footer{display:grid;gap:10px;padding:10px 14px 12px}.settings-menu section+section,.settings-menu footer{border-top:1px solid var(--border)}.settings-menu footer{display:flex;align-items:center;justify-content:space-between;gap:10px}.settings-version{font-size:12px;color:var(--muted)}.settings-menu section[hidden]{display:none}.settings-menu h3{margin:0;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}.settings-menu label{display:grid;gap:4px;font-size:13px;font-weight:600;color:var(--muted)}.settings-menu select{width:100%;max-width:none}.settings-menu label.check{grid-template-columns:auto 1fr;align-items:start;gap:8px;font-weight:500;color:var(--text);cursor:pointer}.settings-menu label.check input{margin:2px 0 0}.settings-menu label small,.settings-menu label.check small{display:block;font-weight:400;color:var(--muted)}.settings-menu .about-button{justify-self:start;padding:6px 10px;font-size:13px}dialog.about{width:min(560px,calc(100vw - 32px));max-height:calc(100dvh - 48px);padding:0;color:var(--text);background:var(--panel);border:1px solid var(--border);border-radius:12px;box-shadow:0 12px 40px #00000040}dialog.about::backdrop{background:#00000059}dialog.about header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;border-bottom:1px solid var(--border)}dialog.about h2{margin:0;font-size:16px}.about-body{padding:20px 24px 24px;font-size:14px;line-height:1.5}.about-body p{margin:0 0 8px;color:var(--muted)}.about-head{display:flex;gap:16px;padding-bottom:16px;margin-bottom:8px;border-bottom:1px solid var(--border)}.about-head .logo{flex:none;width:40px;height:40px;color:var(--accent)}.about-head h3{margin:0 0 6px;font-size:20px}.about-head h3 small{font-weight:400;color:var(--muted)}.about-body .about-version{font-variant-numeric:tabular-nums}.about-body .about-author{color:var(--text);font-weight:600}.about-link{margin:0 0 2px}.about-body h4{margin:16px 0 6px;font-size:15px}.about-body code{font-weight:600;color:var(--text)}.about-body .about-copy{margin-top:16px}.brand{font-weight:700;font-size:16px;display:flex;align-items:center;gap:8px}.visubot-logo{width:auto;height:30px;margin:-4px 0}.visubot-bot{color:#f08a00;margin-left:-8px}.brand small{font-weight:500;color:var(--muted);font-size:12px}.logo{width:20px;height:20px;border:2px solid currentColor;background:linear-gradient(to bottom right,transparent 47%,currentColor 47% 53%,transparent 53%) left / 50% 60% no-repeat,linear-gradient(to bottom left,transparent 47%,currentColor 47% 53%,transparent 53%) right / 50% 60% no-repeat}.group{display:flex;flex-wrap:wrap;gap:6px}button,select{font:inherit;padding:6px 12px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);cursor:pointer;min-height:34px}select{max-width:180px}button:hover:not(:disabled),select:hover{border-color:var(--accent)}button:disabled{opacity:.4;cursor:default}.palette,.inspector{background:var(--panel);padding:12px;overflow-y:auto}.palette{grid-area:pal;border-inline-end:1px solid var(--border)}.inspector{grid-area:insp;border-top:1px solid var(--border);max-height:34vh}h2{font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:0 0 4px}.hint{color:var(--muted);font-size:12px;margin:0 0 10px}.palette ul{list-style:none;margin:0;padding:0;display:grid;gap:6px}.palette-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--border);border-radius:8px;cursor:grab;line-height:1.25;user-select:none;-webkit-user-select:none;touch-action:none}.palette-item:hover,.palette-item:focus-visible{border-color:var(--accent);outline:none}.palette-item .icon{flex:none;color:var(--text)}.workspace{grid-area:work;display:flex;flex-direction:column;min-width:0;min-height:0}.caption{font:600 18px system-ui,-apple-system,sans-serif;border:none;border-bottom:1px solid var(--border);padding:10px 16px;background:var(--panel);outline:none}.canvas{flex:1;overflow:auto;scrollbar-gutter:stable;background:#fafafa}.canvas svg{display:block;user-select:none;-webkit-user-select:none}.dragging,.dragging *{cursor:grabbing!important}.drop-line{fill:var(--accent)}.drop-replace{fill:var(--accent-soft);stroke:var(--accent);stroke-width:3}.drag-ghost{position:fixed;left:0;top:0;z-index:10;pointer-events:none;padding:6px 10px;border-radius:8px;background:var(--accent);color:#fff;font-weight:600;box-shadow:0 4px 14px #0003;white-space:nowrap;max-width:260px;overflow:hidden;text-overflow:ellipsis}.inspector label{display:block;font-weight:600;margin:8px 0 4px}.inspector textarea{width:100%;font:14px ui-monospace,SF Mono,Menlo,Consolas,monospace;padding:8px;border:1px solid var(--border);border-radius:8px;resize:vertical}.statusbar{display:flex;flex-wrap:wrap;gap:2px 16px;align-items:baseline;padding:4px 12px;font-size:12px;color:var(--muted);background:var(--panel);border-top:1px solid var(--border)}.status{flex:1 1 auto;min-width:0}.site-links{display:flex;gap:12px;margin-inline-start:auto}.site-links a{color:inherit}.site-links a:hover,.site-links a:focus-visible{color:var(--accent)}a.brand{color:inherit;text-decoration:none}.file-drag .canvas{outline:3px dashed var(--accent);outline-offset:-8px}@media(min-width:821px){.app.compact-palette{--palette-width: 100px}.app.compact-palette .palette{padding:8px 6px}.app.compact-palette .palette h2{font-size:10px;letter-spacing:0;text-align:center}.app.compact-palette .palette .hint{display:none}.app.compact-palette .palette-item{flex-direction:column;gap:3px;padding:6px 2px;font-size:10.5px;line-height:1.15;text-align:center;overflow-wrap:break-word}}@media(max-width:820px){.app{grid-template:"tools" auto "pal" auto "work" 1fr "insp" auto / minmax(0,1fr)}.palette,.inspector{min-width:0}.palette{border-inline-end:none;border-bottom:1px solid var(--border);padding:8px}.palette .hint,.palette h2{display:none}.palette ul{display:flex;overflow-x:auto;overflow-y:hidden}.palette-item{white-space:nowrap}.inspector{max-height:30vh}}.status.message{color:var(--text);font-weight:600}.confirm{position:fixed;top:0;right:0;bottom:0;left:0;z-index:20;display:grid;place-items:center;background:#00000040;padding:16px}.confirm-card{background:var(--panel);border-radius:12px;padding:16px 18px;max-width:360px;box-shadow:0 10px 30px #0003}.confirm-card p{margin:0 0 8px}.confirm-card .group{justify-content:flex-end;margin-top:12px}.files-ask{width:min(360px,100%)}.files-ask input{width:100%;box-sizing:border-box;margin-top:4px}.files-choices{display:flex;flex-wrap:wrap;gap:6px;margin:4px 0 10px}.files-choice{display:inline-flex;align-items:center;gap:6px}.files-choice svg{width:16px;height:16px}button.danger{background:#d70015;border-color:#d70015;color:#fff}.simpanel{display:none;grid-area:insp;background:var(--panel);border-inline-start:1px solid var(--border);padding:12px;overflow-y:auto}.app.simulating{grid-template:"tools tools" auto "work insp" 1fr / minmax(0,1fr) 320px}.app.simulating.visubot-mode{grid-template:"tools tools" auto "work insp" 1fr / minmax(0,1fr) min(440px,45%)}.app.simulating .palette,.app.simulating .inspector{display:none}.app.simulating .simpanel{display:block}.app.simulating .caption{cursor:default}button.sim-toggle{font-weight:600}button.sim-toggle{background:var(--accent);border-color:var(--accent);color:#fff}.simpanel section{margin-bottom:14px}.sim-buttons{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:6px 0 10px}.sim-option{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px;font-size:13px}.mono,.sim-vars td{font:13px/1.5 ui-monospace,SF Mono,Menlo,Consolas,monospace}.sim-trace,.sim-output,.sim-vars{background:var(--bg);border-radius:8px;padding:8px 10px;overflow-wrap:anywhere}.sim-output{max-height:220px;overflow-y:auto;white-space:pre-wrap}.sim-vars table{border-collapse:collapse;width:100%}.sim-vars td{padding:2px 0;vertical-align:top}.sim-vars td:first-child{color:var(--muted);padding-inline-end:12px;width:1%;white-space:nowrap}.sim-vars table.sim-grid{width:auto}.sim-vars .sim-grid td,.sim-vars .sim-grid td:first-child{border:1px solid var(--border);color:inherit;font-size:11px;padding:0 4px;text-align:center;width:auto}.sim-vars .sim-grid td.sim-grid-true{font-weight:700}.simpanel .placeholder{color:var(--muted);font:13px system-ui,-apple-system,sans-serif;margin:0}.sim-notice{margin:0 0 14px;padding:8px 10px;border-radius:8px;background:#34c75926;font-weight:600}.sim-edit{width:100%;margin:-6px 0 14px}.sim-notice.error{background:#ff3b3026;color:#b0000f}.sim-input.active{padding:8px 10px;margin-left:-10px;margin-right:-10px;border-radius:10px;background:var(--accent-faint);outline:2px solid var(--accent)}.sim-prompt{margin:4px 0 6px;font-weight:600}.sim-input-row{display:flex;gap:6px}.sim-input-row input{flex:1;min-width:0;font:inherit;padding:6px 10px;border:1px solid var(--border);border-radius:8px}.sim-input-error{color:#b0000f;margin:6px 0 0;font-size:13px}@media(max-width:820px){.app.simulating{grid-template:"tools" auto "work" minmax(200px,1fr) "insp" auto / minmax(0,1fr)}.simpanel{border-inline-start:none;border-top:1px solid var(--border);max-height:48vh}}.codepanel{display:none;grid-area:code;background:var(--panel);border-inline-start:1px solid var(--border);padding:12px;overflow-y:auto;min-height:0}.app.coding{grid-template:"tools tools tools" auto "pal work code" 1fr "pal insp code" auto / var(--palette-width, 210px) minmax(0,1fr) 400px}.app.coding .codepanel{display:block}.app.coding .inspector{max-height:34vh}button[data-action=code][aria-pressed=true]{border-color:var(--accent);background:var(--accent-soft)}.code-head,.runner-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.code-close{min-height:28px;padding:2px 10px}.segmented{display:flex;margin-bottom:8px}.segmented button{flex:1;border-radius:0;min-height:30px;padding:4px 8px}.segmented button:first-child{border-radius:8px 0 0 8px}.segmented button:last-child{border-radius:0 8px 8px 0}.segmented button+button{border-inline-start:none}.segmented button[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:#fff}.segmented[hidden]{display:none}.check{display:flex;gap:8px;align-items:center;font-size:13px;margin-bottom:4px}.code-actions{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}.code-actions [hidden]{display:none}button.primary{background:var(--accent);border-color:var(--accent);color:#fff}.code-view,.runner-out{margin:0;padding:10px 12px;border-radius:10px;background:var(--bg);font:13px/1.5 ui-monospace,SF Mono,Menlo,Consolas,monospace;overflow:auto;white-space:pre;-moz-tab-size:4;tab-size:4}.runner{margin:12px 0}.runner-out{background:#0b1220;color:#e5e7eb;min-height:3em;max-height:240px;white-space:pre-wrap}.runner-out.error{outline:2px solid #ff453a}.runner-input{margin-top:8px}.runner-input label{display:block;font-weight:600;margin-bottom:4px}@media(max-width:820px){.app.coding{grid-template:"tools" auto "pal" auto "work" minmax(240px,1fr) "insp" auto "code" auto / minmax(0,1fr)}.codepanel{border-inline-start:none;border-top:1px solid var(--border);max-height:50vh}}.tabs{display:flex;align-items:flex-end;gap:2px;padding:6px 8px 0;background:var(--bg);border-bottom:1px solid var(--border);overflow-x:auto;overflow-y:hidden;scrollbar-width:thin}.tab{display:flex;align-items:center;max-width:220px;border:1px solid var(--border);border-bottom:none;border-radius:8px 8px 0 0;background:#ffffff80}.tab.active{background:var(--panel);margin-bottom:-1px;padding-bottom:1px}.tab button{border:none;background:none;min-height:30px;border-radius:8px 8px 0 0}.tab-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:4px 6px 4px 12px}.tab.active .tab-label{font-weight:600}.tab-close{padding:2px 8px;color:var(--muted);font-size:11px}.tab-close:hover{color:var(--text)}.tab-dot,.tab-close.unsaved .tab-x{display:none}.tab-close.unsaved .tab-dot{display:inline;color:var(--text);font-size:10px}.tab-close.unsaved:hover .tab-dot{display:none}button.tab-close.unsaved:hover .tab-x{display:inline}span.tab-close{padding:2px 10px 2px 4px}.tab-add{min-height:28px;padding:2px 10px;margin:0 0 3px 4px;border-radius:8px}.inspector .segmented{margin:6px 0 4px;max-width:420px}.mono-hint{font:11px/1.45 ui-monospace,SF Mono,Menlo,Consolas,monospace;overflow-wrap:anywhere}.editor-row{display:flex;gap:8px;align-items:flex-start}.editor-row textarea{flex:1;min-width:0}.fixed-prefix{font:14px ui-monospace,SF Mono,Menlo,Consolas,monospace;color:var(--muted);padding-top:9px}.inspector input:not([type]){width:100%;font:14px ui-monospace,SF Mono,Menlo,Consolas,monospace;padding:7px 8px;border:1px solid var(--border);border-radius:8px}.for-fields{display:grid;gap:4px}.for-fields label,.case-controls label{margin:4px 0 0;font-size:12px;color:var(--muted);font-weight:600}.case-controls{margin-top:12px;padding-top:10px;border-top:1px solid var(--border)}.case-controls .group{margin-top:8px}button.danger-text:not(:disabled){color:#d70015}.print-sheet{display:none}.files{display:none;flex:0 1 auto;flex-direction:column;width:260px;min-width:200px;min-height:0;background:var(--panel);border-inline-end:1px solid var(--border)}.shell.files-open .files{display:flex}.shell.files-open .files-rail{display:none}.files-head{display:flex;align-items:center;gap:4px;margin:10px 12px 6px}.files-head h2{flex:1;margin:0;font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.files-head button.icon{min-width:30px;height:30px;padding:0 5px}.files-head [hidden]{display:none}.files-body{flex:1;min-height:0;overflow:auto;padding:0 8px 12px;font-size:14px}.files-where{margin:0 4px 6px;font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.files-hint,.files-empty{margin:8px 4px;font-size:13px;color:var(--muted)}.start-ask .files-start{margin-bottom:2px}.start-ask .hint{font-size:13px;color:var(--muted)}.start-without{display:block;margin:12px auto 0;border:none;background:none;color:var(--accent);text-decoration:underline}.start-without+.hint{text-align:center}.files-start{display:flex;align-items:center;gap:6px;width:100%;margin:8px 0;justify-content:center}.files-row{display:flex;align-items:center;border-radius:6px}.files-row:hover,.files-row:focus-within{background:var(--accent-soft)}.files-row.current>.files-name{font-weight:600}.files-name{flex:1;min-width:0;display:flex;align-items:center;gap:6px;padding:4px 6px 4px calc(6px + var(--depth) * 16px);border:none;background:none;text-align:start;font:inherit;color:var(--text);cursor:pointer}.files-name:disabled{cursor:default;color:var(--muted)}.files-name svg{flex:none;width:16px;height:16px;color:var(--muted)}.files-name span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.files-name small{margin-inline-start:auto;padding:0 6px;border-radius:6px;background:var(--accent);color:#fff;font-size:11px;font-weight:600}.files-row .files-delete{visibility:hidden;min-width:26px;height:26px;padding:0 4px;border:none;background:none;color:var(--muted)}.files-row:hover .files-delete,.files-row:focus-within .files-delete{visibility:visible}.files-error{color:#c62828}.files-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.shell.files-open .files-resizer{display:block}.files-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px}.files-resizer:hover:after,.files-resizer:focus-visible:after{background:var(--accent)}.learn{display:none;flex:0 1 auto;width:400px;min-width:280px;flex-direction:column;background:var(--panel);border-inline-end:1px solid var(--border);min-height:0}.shell.learning .learn{display:flex}.learn-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.shell.learning .learn-resizer{display:block}.learn-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.learn-resizer:hover:after,.learn-resizer:focus-visible:after,.shell.resizing .learn-resizer:after{background:var(--accent)}.learn-resizer:focus-visible{outline:none}.shell.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.learn-head{display:flex;align-items:flex-start;gap:6px;margin:10px 12px 0}.learn-tabs{flex:1;min-width:0}.learn-hide{flex:none;min-height:30px;padding:4px 7px;display:inline-flex;align-items:center;color:var(--muted)}.learn-rail{flex:none;display:flex;flex-direction:column;align-items:center;gap:10px;width:36px;padding:10px 0;border:none;border-radius:0;border-inline-end:1px solid var(--border);background:var(--panel);cursor:pointer}.learn-rail:hover{background:var(--accent-soft)}.learn-rail span{writing-mode:vertical-rl;white-space:nowrap}.shell.learning .learn-rail:not(.live-rail):not(.editor-rail):not(.files-rail):not(.robotpreview-rail):not(.palette-rail){display:none}.live-rail{border-inline-end:none;border-inline-start:1px solid var(--border)}.live-rail svg{transform:scaleX(-1)}.shell.live .live-rail{display:none}.editor-rail{display:none;border-inline-start:1px solid var(--border)}.shell.editor-hidden .editor-rail{display:flex}.shell.editor-hidden .app,.shell.editor-hidden .live-resizer,.shell.editor-hidden:not(.live) .learn-resizer{display:none}.shell.editor-hidden .livecode,.shell.editor-hidden:not(.live) .learn{flex:1 1 0;width:auto!important;min-width:0}.learn-body{overflow-y:auto;scrollbar-gutter:stable;padding:4px 16px 24px;flex:1;min-height:0;line-height:1.5}.learn-body h2.learn-title{display:flex;align-items:center;gap:8px;font-size:20px;text-transform:none;letter-spacing:0;color:var(--text);margin:2px 0 10px}.learn-section{font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:18px 0 6px}.learn-list{list-style:none;padding:0;margin:0;display:grid;gap:6px}.learn-item{display:flex;align-items:center;gap:10px;width:100%;text-align:start;padding:8px 10px}.learn-item.done{border-color:#34c759}.learn-num{flex:none;min-width:28px;height:28px;border-radius:14px;background:var(--accent-soft);color:var(--accent);display:grid;place-items:center;font-weight:700;font-size:12px;padding:0 6px}.learn-item.done .learn-num{background:#34c7592e;color:#248a3d}.learn-item-text{flex:1;display:grid;min-width:0}.learn-item-text small{color:var(--muted)}.learn-status{flex:none;color:var(--muted);font-size:12px}.learn-item.done .learn-status{color:#248a3d;font-weight:700}.learn-back,.link-button{border:none;background:none;padding:6px 0;min-height:0;color:var(--accent)}.link-button{padding:0;text-align:start}.learn-lesson-head{position:sticky;top:-4px;z-index:3;margin:-4px -16px 10px;padding:4px 16px 8px;background:var(--panel);border-bottom:1px solid var(--border)}.learn-lesson-head .learn-progress{margin-bottom:8px}.learn-lesson-head .learn-step-title{margin:0}.learn-head-row{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}.learn-nav.learn-nav-top{margin-top:0;gap:6px}.learn-nav-top button{padding:3px 10px;min-height:0;font-size:13px}.learn-kicker{margin:4px 0 0;color:var(--muted);font-size:12px}.learn-progress{display:flex;gap:4px;margin-bottom:14px}.learn-progress button{flex:1 1 0;min-width:0;padding:3px 0;font-size:13px;font-variant-numeric:tabular-nums;border-radius:6px}.learn-progress button.past{border-color:var(--accent);color:var(--accent)}.learn-progress button.current{border-color:var(--accent);background:var(--accent);color:#fff;font-weight:600}.learn-progress button.robot-step:not(.current){border-color:#0fa3c6;background:#0fa3c61f}.learn-progress button.robot-step.current{border-color:#0fa3c6;background:#0fa3c6}.learn-step-title{font-size:16px;margin:0 0 6px}.learn-text p,.learn-text ul,.learn-text ol{margin:0 0 10px}.learn-text ul,.learn-text ol{padding-inline-start:22px}.learn-text code,.learn-tests code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;background:var(--bg);border-radius:4px;padding:1px 4px}.learn-text h3{font-size:15px;margin:18px 0 4px}.reference-group{border:1px solid var(--border);border-radius:8px;margin:0 0 8px;padding:0 12px}.reference-group summary{cursor:pointer;font-weight:600;padding:9px 0}.reference-group[open] summary{border-bottom:1px solid var(--border)}.reference-group>h3:first-of-type{margin-top:10px}.lesson-code{background:var(--bg);border-radius:8px;padding:8px 10px;margin:0 0 10px;overflow-x:auto;overflow-y:hidden;font-size:12.5px}.learn-open-code{display:block;margin:-4px 0 12px}.lesson-code code{background:none;padding:0}.lesson-note{border-inline-start:3px solid var(--accent);background:var(--accent-soft);border-radius:6px;padding:8px 10px;margin:0 0 10px}.lesson-note p:last-child{margin-bottom:0}.learn-images{display:flex;gap:8px;flex-wrap:wrap}.learn-images img{width:150px;height:200px;object-fit:cover;border-radius:8px}.learn-file{margin:0 0 14px;border:1px solid var(--border);border-radius:10px;overflow:hidden;background:var(--panel)}.learn-file figcaption{display:flex;align-items:center;gap:6px;padding:6px 10px;background:var(--bg);border-bottom:1px solid var(--border);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;font-weight:600}.learn-file-text{margin:0;padding:8px 10px;overflow-x:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;line-height:1.5;white-space:pre}.learn-file.written{margin:8px 0;border-color:#15803d}.learn-file.written figcaption{background:#dcfce7}.learn-file-text .ln{display:inline-block;min-width:2ch;margin-inline-end:10px;color:var(--muted);text-align:end;-webkit-user-select:none;user-select:none}.learn-brag{display:grid;grid-template-columns:48px minmax(0,1fr);gap:10px;align-items:start;border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin:0 0 14px;background:var(--accent-soft)}.learn-brag img{width:48px;height:48px;border-radius:50%}.learn-brag-title{margin:0 0 4px;font-weight:700}.learn-brag .learn-text p:last-child{margin-bottom:0}.learn-game{border:2px solid var(--accent);border-radius:12px;padding:12px 14px;margin:0 0 14px}.learn-game-head{display:flex;align-items:center;gap:10px;font-size:1.05em}.learn-game-head img{width:40px;height:40px;border-radius:50%}.learn-game-status{margin:6px 0;color:var(--muted);font-size:.9em}.learn-game-values{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.learn-game-values code{background:var(--accent-soft);border-radius:6px;padding:2px 8px}.learn-game-condition{font-size:1.15em;font-weight:600;padding:10px 12px;border-radius:8px;background:var(--bg, #f2f2f7);margin-bottom:10px;overflow-wrap:anywhere}.learn-game-answers button{flex:1;font-weight:600;padding-block:10px}.learn-game-true:not(:disabled){border-color:#15803d;color:#15803d}.learn-game-false:not(:disabled){border-color:#b91c1c;color:#b91c1c}.learn-game-feedback:empty{display:none}.learn-game-feedback{margin-top:10px;padding:10px 12px;border-radius:8px}.learn-game-feedback.right{background:#dcfce7}.learn-game-feedback.wrong{background:#fee2e2}.learn-game-feedback p{margin:0 0 6px;font-weight:700}.learn-game-steps{margin-bottom:10px;line-height:1.6}.learn-game-result{font-size:1.2em;font-weight:700}.learn-game-question{font-weight:600;margin:10px 0 8px}.learn-game-code{margin:0 0 8px;padding:8px 0;border-radius:8px;background:var(--bg, #f2f2f7);font-size:13px;line-height:1.5;overflow-x:auto}.learn-game-code .ln{padding:0 10px 0 calc(10px + 2ch);text-indent:-2ch;border-inline-start:3px solid transparent;white-space:pre-wrap;overflow-wrap:anywhere;transition:background .2s}.learn-game-code .ln.hit{background:#fef3c7;border-inline-start-color:#d97706}.learn-bomb{display:flex;align-items:center;gap:10px;margin-bottom:6px;font-weight:700}.learn-bomb-icon{font-size:28px;line-height:1}.learn-bomb.hurry .learn-bomb-icon{animation:learn-bomb-shake .25s infinite alternate}.learn-bomb.boom .learn-bomb-icon{animation:learn-bomb-boom .5s ease-out}@keyframes learn-bomb-shake{0%{transform:rotate(-8deg)}to{transform:rotate(8deg)}}@keyframes learn-bomb-boom{0%{transform:scale(.6)}60%{transform:scale(1.5)}to{transform:scale(1)}}.learn-bomb-time{min-width:7ch;font-variant-numeric:tabular-nums}.learn-bomb-fuse{flex:1;height:8px;border-radius:4px;background:#e5e7eb;overflow:hidden}.learn-bomb-fuse span{display:block;height:100%;background:#f59e0b;transition:width .2s linear}.learn-bomb.hurry .learn-bomb-fuse span{background:#dc2626}.learn-bomb.defused .learn-bomb-fuse span{background:#15803d}.learn-bomb-code .ln{display:block;width:100%;margin:0;border-radius:0;border-block:0;border-inline-end:0;background:none;color:inherit;font:inherit;line-height:inherit;min-height:0;height:auto;padding-block:1px;text-align:start;cursor:pointer}.learn-bomb-code .ln:not(:disabled):hover{background:#fef3c7}.learn-bomb-code .ln:disabled{cursor:default;opacity:1}.learn-bomb-code .ln.right,.learn-bomb-code .ln.right:hover{background:#dcfce7;border-inline-start-color:#15803d}.learn-bomb-code .ln.wrong,.learn-bomb-code .ln.wrong:hover{background:#fee2e2;border-inline-start-color:#b91c1c}.learn-bomb-fix code{white-space:pre-wrap}.learn-game-options{display:grid;gap:6px}.learn-game-options button{text-align:start;padding:8px 12px}.learn-game-options.pictures{grid-template-columns:repeat(auto-fill,minmax(130px,1fr))}.learn-game-options.pictures button{padding:6px}.learn-game-options button.right{border-color:#15803d;background:#dcfce7;color:inherit;opacity:1}.learn-game-options button.wrong{border-color:#b91c1c;background:#fee2e2;color:inherit;opacity:1}.learn-order-hint{margin:0 0 6px;font-size:13px;opacity:.75}.learn-order button{display:flex;align-items:center;gap:10px}.learn-order-badge{flex:none;display:inline-grid;place-items:center;width:24px;height:24px;border-radius:50%;border:1.5px solid currentColor;font-size:13px;font-weight:700;opacity:.5}.learn-order button.right .learn-order-badge,.learn-order button:disabled .learn-order-badge:not(:empty){opacity:1}.learn-game-file{margin:0;padding:2px 0;font-size:13px;line-height:1.45;white-space:pre;background:none}.learn-game-explain{margin-bottom:10px}.learn-swing-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px;align-items:start}.learn-swing-window{border:1px solid var(--border);border-radius:8px;overflow:hidden;background:#fff;color:#1c1c1e}.learn-swing-title{padding:3px 8px;font-size:12px;text-align:center;background:#e5e5ea;border-bottom:1px solid #d1d1d6;min-height:1.4em}.learn-swing-body{display:grid;gap:6px;padding:10px}.learn-swing-label{padding:4px 2px;min-height:1.4em}.learn-swing-label.changed,.learn-swing-button.changed{animation:swing-changed 1s ease-out}@keyframes swing-changed{0%{background:#ffd60acc}}.learn-swing-button{padding:6px 10px;background:#fff;color:#1c1c1e;border:1px solid #a1a1aa;border-radius:6px}.learn-swing-button:disabled{opacity:1;cursor:default}.learn-swing-button.pressed{background:var(--accent);border-color:var(--accent);color:#fff;transform:scale(.96)}.learn-swing-event{margin:0;padding:0 10px 8px;font-size:12px;min-height:1.4em}.learn-swing-event.heard{color:#b45309;font-weight:600}.learn-swing-event.nobody{color:#6b7280;font-style:italic}.learn-swing-console{margin:0 10px 10px;padding:6px 8px;border-radius:6px;background:#1c1c1e;color:#f2f2f7;font-size:12px}.learn-swing-console[hidden]{display:none}.learn-swing-clicks{margin:8px 0 0}.learn-swing-try{font-weight:400!important;font-style:italic}.learn-layout-window{width:100%;border:1px solid #a1a1aa;border-radius:6px;overflow:hidden;background:#fff;color:#1c1c1e}.learn-layout-title{height:10px;background:#e5e5ea;border-bottom:1px solid #d1d1d6}.learn-layout-body{height:80px;padding:3px;gap:3px;font-size:12px}.learn-layout-body.grid{display:grid;grid-auto-rows:1fr}.learn-layout-body.flow{display:flex;flex-direction:column;gap:3px}.learn-layout-row{display:flex;justify-content:center;gap:3px}.learn-layout-body.border{display:grid;grid-template:"N N N" auto "W C E" 1fr "S S S" auto / auto 1fr auto}.learn-layout-cell{display:flex;align-items:center;justify-content:center;min-width:22px;padding:2px 6px;border:1px solid #a1a1aa;border-radius:4px;background:#f4f4f5;font-weight:600}.learn-figure{margin:0 0 14px;display:grid;gap:6px;justify-items:start}.learn-preview{width:100%;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:#fafafa}.learn-preview>svg{display:block;width:100%;margin:0 auto;height:auto}.learn-figure figcaption{color:var(--muted);font-size:13px}.learn-exercise{border:1px solid var(--accent);border-radius:10px;padding:10px 12px;margin:0 0 14px;display:grid;gap:8px}.learn-exercise h4{margin:0;font-size:15px;display:flex;gap:8px;align-items:center}.learn-badge{font-size:12px;color:#248a3d;background:#34c7592e;border-radius:10px;padding:1px 8px}.learn-where{margin:0;font-size:13px;font-weight:600;color:var(--muted)}.area-name{display:inline-block;color:#fff;border-radius:10px;padding:0 8px}.area-name.area-editor{background:var(--area-editor)}.area-name.area-code{background:var(--area-code)}.columns>.app{border-top:3px solid var(--area-editor)}.livecode{border-top:3px solid var(--area-code)}.livecode-head h2,.live-rail span{color:var(--area-code)}.editor-rail span{color:var(--area-editor)}.live-rail,.editor-rail{font-weight:600}.learn-exercise .learn-text p:last-child{margin-bottom:0}.learn-result:empty{display:none}.learn-result{border-radius:8px;padding:8px 10px}.learn-result.ok{background:#34c75924}.learn-result.fail{background:#ff950024}.learn-result.info{background:var(--bg)}.learn-result-head{margin:0 0 6px;font-weight:600}.learn-tests{list-style:none;padding:0;margin:0;display:grid;gap:6px}.learn-test-detail{display:grid;padding-inline-start:16px;font-size:13px}.learn-error{color:#c4291c}.learn-solution summary{cursor:pointer;color:var(--accent)}.learn-solution[open]{display:grid;gap:6px;justify-items:start}.learn-checklist{list-style:none;padding:0;margin:0 0 14px;display:grid;gap:6px}.learn-checklist li{display:flex;gap:8px;align-items:baseline;justify-content:space-between}.learn-checklist li{align-items:center;justify-content:flex-start;padding:4px 6px;border-radius:8px}.learn-check-text{flex:1}.learn-checklist li[data-rating=sun]{background:color-mix(in srgb,#f5b800 14%,transparent)}.learn-checklist li[data-rating=cloud]{background:color-mix(in srgb,#8a97a8 14%,transparent)}.learn-checklist li[data-rating=umbrella]{background:color-mix(in srgb,#3b82f6 12%,transparent)}.learn-rating{display:inline-flex;gap:2px;flex:none}.learn-rating-button{min-width:34px;min-height:34px;padding:2px;font-size:1.15em;line-height:1;border-radius:8px;opacity:.45;filter:grayscale(.7)}.learn-rating-button[aria-pressed=true]{opacity:1;filter:none;border-color:var(--accent);background:var(--accent-soft)}.learn-rating-legend{display:flex;flex-wrap:wrap;gap:4px 14px;margin:0 0 8px;font-size:.9em;color:var(--muted, inherit)}.learn-review{margin:12px 0 0}.learn-review:empty{display:none}.learn-review-title{margin:0 0 4px;font-weight:700}.learn-review-icon{flex:none;width:1.6em;text-align:center}.learn-checklist li.learn-review-deviation{border:1px solid var(--accent);background:var(--accent-soft)}.learn-competences{border:1px solid var(--accent);border-radius:10px;padding:10px 12px;margin:0 0 14px;background:var(--accent-soft)}.learn-competences-title{margin:0 0 4px;font-weight:700}.learn-competences ul{margin:0;padding-left:1.3em}.learn-return{width:100%;margin:0 0 12px;border-color:var(--accent);background:var(--accent-soft)}.learn-nav+.learn-return{margin:12px 0 0}.learn-check-link{flex:none;font-size:13px}.learn-quiz fieldset{border:1px solid var(--border);border-radius:10px;padding:8px 12px 10px;margin:0 0 10px;display:grid;gap:6px}.learn-quiz legend{font-weight:600;padding:0 4px}.learn-option{text-align:start}.learn-option.right{border-color:#34c759;background:#34c75924}.learn-option.wrong{border-color:#ff3b30;background:#ff3b301a}.learn-match{display:grid;gap:6px}.learn-match-left{display:grid;grid-template-columns:8.5em minmax(0,1fr);align-items:center;gap:8px}.learn-match-select{min-width:0;width:100%;max-width:none}.learn-match-select.right{border-color:#34c759;background:#34c75924}.learn-match-select.wrong{border-color:#ff3b30;background:#ff3b301a}.learn-explanation{margin:0;color:var(--muted);font-size:13px}.learn-score{font-weight:600}.learn-nav{display:flex;justify-content:space-between;gap:8px;margin-top:18px}@media(max-width:1100px){.learn{width:340px}}@media(max-width:900px){.learn{width:300px}}.livecode{display:none;flex:0 1 auto;width:420px;min-width:200px;flex-direction:column;gap:6px;padding:10px 12px 12px;background:var(--panel);border-inline-start:1px solid var(--border);min-height:0}.shell.live .livecode{display:flex}.livecode-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px}.livecode-head h2{margin:0;font-size:16px}.livecode-lang{margin-inline-start:auto;padding:2px 8px;border-radius:6px;background:var(--accent-soft);color:var(--accent);font-size:12px;font-weight:600}.livecode .learn-hide svg{transform:scaleX(-1)}.livecode .hint{margin:0}.livecode-view{flex:1;min-height:0;padding:10px 0;font-size:var(--code-size, 14px)}.livecode-view .ln{padding:0 12px;min-height:1.5em;border-inline-start:3px solid transparent}.livecode-view.selectable .ln{cursor:pointer}.livecode-view .ln.sel{background:var(--accent-soft);border-inline-start-color:var(--accent)}.livecode-view .ph{color:var(--muted);font-style:italic}.livecode-editor{flex:1;min-height:0;padding:0;font-size:var(--code-size, 14px);white-space:normal;overflow:hidden;--syn-keyword: #7f0055;--syn-string: #2a00ff;--syn-number: #986801;--syn-comment: #3f7f5f}.livecode-editor[hidden],.livecode-view[hidden],.livecode-problem[hidden]{display:none}.livecode-editor .cm-editor{height:100%;background:transparent}.livecode-editor .cm-editor.cm-focused{outline:2px solid var(--accent-soft);outline-offset:-2px;border-radius:10px}.livecode-editor .cm-scroller{font:inherit;font-family:ui-monospace,SF Mono,Menlo,Consolas,monospace;line-height:1.5}.livecode-editor .cm-gutters{background:transparent;border-inline-end:1px solid var(--border);color:var(--muted)}.livecode-editor .cm-lineNumbers .cm-gutterElement{padding:0 8px 0 10px;min-width:2ch}.livecode-editor .cm-activeLineGutter{background:transparent;color:var(--text)}.livecode-editor .cm-content{padding:10px 0;caret-color:var(--text)}.livecode-editor .cm-line{padding:0 12px;border-inline-start:3px solid transparent}.livecode-editor .cm-scopeLayer .cm-scope{border:1px solid color-mix(in srgb,var(--scope) 28%,transparent);border-left:3px solid var(--scope);border-radius:8px;background:color-mix(in srgb,var(--scope) 9%,#fff)}.livecode-editor .cm-scopeLayer .cm-scope-class{--scope: #34c47c}.livecode-editor .cm-scopeLayer .cm-scope-method{--scope: #f2b100}.livecode-editor .cm-scopeLayer .cm-scope-loop{--scope: #ec5fa6}.livecode-editor .cm-scopeLayer .cm-scope-if{--scope: #3b9cf0}.livecode-editor .cm-scopeLayer .cm-scope-try{--scope: #9a7cf0}:root.no-code-scopes .livecode-editor .cm-scopeLayer .cm-scope:not(.cm-scope-sel){display:none}:root:not(.no-code-scopes) .ns-scope-method{fill:color-mix(in srgb,#f2b100 14%,#fff)}:root:not(.no-code-scopes) .ns-scope-loop{fill:color-mix(in srgb,#ec5fa6 14%,#fff)}:root:not(.no-code-scopes) .ns-scope-if{fill:color-mix(in srgb,#3b9cf0 14%,#fff)}:root:not(.no-code-scopes) .palette-item[data-scope=method]{background:color-mix(in srgb,#f2b100 14%,#fff)}:root:not(.no-code-scopes) .palette-item[data-scope=loop]{background:color-mix(in srgb,#ec5fa6 14%,#fff)}:root:not(.no-code-scopes) .palette-item[data-scope=if]{background:color-mix(in srgb,#3b9cf0 14%,#fff)}.livecode-editor .cm-scopeLayer .cm-scope-sel{background:transparent;border:2px solid var(--accent);box-shadow:0 0 0 3px var(--accent-faint)}.livecode-editor .cm-line.cm-debug-line{background:#ffd60a59;border-inline-start-color:#e0a800}.livecode-editor .cm-breakpoint-gutter .cm-gutterElement,.livecode-editor .cm-lineNumbers .cm-gutterElement{cursor:pointer}.livecode-editor .cm-breakpoint-gutter .cm-gutterElement{display:flex;align-items:center;justify-content:center;width:14px;padding-inline-start:4px}.livecode-editor .cm-breakpoint{display:inline-block;width:10px;height:10px;border-radius:50%;background:#d33}.livecode-editor .cm-breakpoint-gutter .cm-gutterElement:not(:has(.cm-breakpoint)):hover:before{content:"";width:10px;height:10px;border-radius:50%;background:#dd33334d}.livecode-debug{flex:none;max-height:30%;overflow-y:auto}.livecode-debug[hidden]{display:none}.livecode-debug h2{margin:0 0 4px;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.livecode-vars tr.changed td{animation:var-changed 1.6s ease-out;font-weight:700}@keyframes var-changed{0%{background:#ffd60ab3}to{background:transparent}}.livecode-editor .cm-ph,.livecode-editor .cm-ph *{color:var(--muted)!important;font-style:italic;font-weight:400!important}.livecode-editor .cm-err{text-decoration:underline wavy #d33;text-decoration-skip-ink:none;text-underline-offset:3px}.livecode-editor .cm-selectionBackground,.livecode-editor .cm-focused .cm-selectionBackground{background:color-mix(in srgb,var(--accent) 25%,transparent)!important}.livecode-editor .cm-matchingBracket{background:color-mix(in srgb,var(--accent) 20%,transparent);outline:1px solid color-mix(in srgb,var(--accent) 50%,transparent)}.cm-tooltip.cm-tooltip-autocomplete{border:1px solid var(--border);border-radius:8px;background:var(--panel);box-shadow:0 4px 16px #0000001f;overflow:hidden}.cm-tooltip.cm-tooltip-autocomplete>ul{font:14px/1.4 ui-monospace,SF Mono,Menlo,Consolas,monospace;max-height:16em}.cm-tooltip.cm-tooltip-autocomplete>ul>li{padding:4px 10px}.cm-tooltip.cm-tooltip-autocomplete>ul>li[aria-selected]{background:var(--accent);color:#fff}.cm-tooltip-autocomplete .cm-completionDetail{margin-inline-start:12px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-style:normal;color:var(--muted)}.cm-tooltip-autocomplete li[aria-selected] .cm-completionDetail{color:#ffffffd9}.livecode-run{padding:3px 10px;font-size:13px;margin-inline-start:6px}.console{display:flex;flex:none;flex-direction:column;gap:6px;height:180px;min-height:80px;padding:6px 10px 8px;background:var(--bg);border:1px solid var(--border);border-radius:8px}.console[hidden],.console-resizer[hidden]{display:none}.console-head{display:flex;align-items:center;gap:8px}.console-head h2{margin:0;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.console-hide{margin-inline-start:auto;padding:0 8px;font-size:14px}.console-resizer{flex:none;height:10px;margin-block:-5px;cursor:row-resize;touch-action:none;position:relative}.console-resizer:after{content:"";position:absolute;inset-inline:0;top:4px;height:2px}.console-resizer:hover:after,.console-resizer:focus-visible:after,.console-resizer.dragging:after{background:var(--accent)}.console-resizer:focus-visible{outline:none}.livecode-console-lines{flex:1;min-height:0;overflow:auto;font-size:var(--code-size, 14px);white-space:pre-wrap}.livecode-console-lines .typed{color:var(--accent)}.livecode-console-lines .pending:after{content:"▌";color:var(--accent);animation:blink 1s steps(1) infinite}@keyframes blink{50%{opacity:0}}.livecode-console-input{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.livecode-console-input[hidden]{display:none}.livecode-console-input label{display:flex;flex:1;align-items:center;gap:6px;min-width:0;font-size:var(--code-size, 14px)}.livecode-console-input input{flex:1;min-width:60px;padding:4px 8px;font:inherit}.livecode-console-error,.livecode-console-notice{margin:0;font-size:13px;color:var(--muted)}.livecode-console-error{flex-basis:100%;color:#c62828}.livecode-console-notice.error{color:#c62828}.livecode-problem{margin:0;min-height:1.4em;font-size:13px;color:#c62828}.live-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.shell.live .live-resizer{display:block}.live-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.live-resizer:hover:after,.live-resizer:focus-visible:after,.shell.resizing .live-resizer:after{background:var(--accent)}.live-resizer:focus-visible{outline:none}@media(max-width:1100px){.livecode{width:340px}}@media(max-width:700px){.shell.learning .learn-resizer,.shell.live .live-resizer,.shell.files-open .files-resizer{display:none}.shell .files{width:auto!important;max-height:40vh;border-inline-end:none;border-bottom:1px solid var(--border)}.shell .learn,.shell .livecode,.columns>.app{width:auto!important;min-width:0}.livecode{height:40vh;height:40dvh;border-inline-start:none;border-top:1px solid var(--border)}.learn-rail{flex-direction:row;justify-content:center;width:auto;padding:4px 0;border-inline-end:none;border-bottom:1px solid var(--border)}.learn-rail span{writing-mode:horizontal-tb}.live-rail{border-inline-start:none;border-bottom:none;border-top:1px solid var(--border)}.columns{flex-direction:column}.editor-rail{border-inline-start:none;border-bottom:1px solid var(--border)}.learn{width:auto;height:45vh;height:45dvh;border-inline-end:none;border-bottom:1px solid var(--border)}.columns>.app,.shell.editor-hidden .livecode{flex:1;min-height:0;height:auto}}@media print{@page{margin:12mm}body>*:not(.print-sheet){display:none!important}body{background:#fff!important}.print-sheet{display:block}.print-sheet svg{display:block;width:100%;height:auto;max-height:100vh}}.learn .term{text-decoration:underline dotted var(--accent);text-decoration-thickness:2px;text-underline-offset:3px;cursor:help;border-radius:3px}.learn .term:focus-visible,.learn .term[aria-expanded=true]{outline:none;background:var(--accent-soft)}.term-tip{position:fixed;z-index:1000;max-width:min(300px,calc(100vw - 16px));padding:8px 10px;background:var(--panel);color:var(--text);border:1px solid var(--border);border-radius:8px;box-shadow:0 4px 16px #0000002e;font-size:14px;line-height:1.4}.term-tip[hidden]{display:none}.learn .ui-pointer{color:var(--accent);font-weight:600;border-bottom:2px solid var(--accent-soft);cursor:pointer;border-radius:3px}.learn .ui-pointer:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.ui-spot{outline:3px solid var(--accent)!important;outline-offset:-3px;box-shadow:inset 0 0 0 9999px var(--accent-faint);animation:ui-spot-pulse 1.2s ease-in-out infinite}@keyframes ui-spot-pulse{50%{outline-color:var(--accent-glow)}}@media(prefers-reduced-motion:reduce){.ui-spot{animation:none}}.learn-graphic{display:block;width:100%;max-width:440px;height:auto;margin:0 auto;border-radius:8px;border:1px solid var(--border)}.learn-graphic-toggle{display:block;width:100%;padding:0;border:0;background:none;cursor:zoom-in}.learn-graphic-toggle[aria-pressed=true]{cursor:zoom-out}.learn-graphic-hint{margin:4px 0 0;text-align:center;font-size:.85em;color:var(--muted)}.lesson-table{overflow-x:auto;margin:8px 0}.lesson-table table{border-collapse:collapse;font-size:13px;font-variant-numeric:tabular-nums}.lesson-table th,.lesson-table td{border:1px solid var(--border);padding:3px 8px;text-align:start;white-space:nowrap}.lesson-table th{background:var(--bg)}.learn-hints .lesson-note{margin-top:8px}.learn-teacher{margin-top:24px;border-top:1px solid var(--border);padding-top:12px}.learn-teacher summary{cursor:pointer;color:var(--muted)}.learn-teacher input{flex:1;min-width:0}.shell.editor-hidden:not(.live):not(.learning) .files{flex:1 1 0;width:auto!important}.livecode-swing{height:380px}.livecode-swing[hidden]{display:none}.livecode-swing-display{position:relative;flex:1;min-height:0;overflow:hidden;border-radius:6px;background:#e9ecf0}.learn-caesar-stage{display:flex;flex-direction:column;align-items:center;gap:8px}.learn-caesar-disc{width:min(100%,320px);touch-action:none;user-select:none;-webkit-user-select:none}.learn-caesar-disc text{font:600 19px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.learn-caesar-disc .outer-disc{fill:#f3e6c8;stroke:#8a6d3b;stroke-width:3}.learn-caesar-disc .outer-letters text{fill:#3d2f14;cursor:pointer}.learn-caesar-disc .inner{cursor:grab;transition:transform .25s ease}.learn-caesar-disc .inner.dragging{cursor:grabbing;transition:none}.learn-caesar-disc .inner-disc{fill:#6b4f2a;stroke:#3d2f14;stroke-width:2}.learn-caesar-disc .inner-letters text{fill:#fff8e8}.learn-caesar-disc .tick{stroke:#8a6d3b;stroke-width:1;opacity:.6}.learn-caesar-disc .hub{fill:#f3e6c8;stroke:#3d2f14;stroke-width:2}.learn-caesar-disc .window{fill:var(--accent-soft);stroke:var(--accent);stroke-width:2.5}.learn-caesar-disc .marked text{fill:var(--accent);font-size:23px}.learn-caesar-disc .inner-letters .marked text{fill:#ffd54a}.learn-caesar-disc .key{font-size:40px;font-weight:700;fill:#3d2f14}.learn-caesar-disc .key-label{font-size:15px;fill:#6e5a33}.learn-caesar-controls,.learn-caesar-mode{display:flex;justify-content:center;gap:8px}.learn-caesar-controls button{min-width:56px;font-size:1.05em}.learn-caesar-mode{margin:10px 0 6px}.learn-caesar-mode button.active{background:var(--accent);border-color:var(--accent);color:#fff}.learn-caesar-fields{display:grid;gap:8px}.learn-caesar-fields label,.learn-caesar-fields>div{display:grid;gap:3px;color:var(--muted);font-size:.9em}.learn-caesar-fields input,.learn-caesar-output{font:600 1.15em ui-monospace,Menlo,Consolas,monospace;letter-spacing:.08em;padding:6px 8px;border:1px solid var(--border);border-radius:8px;color:var(--text);background:var(--panel);overflow-wrap:anywhere}.learn-caesar-output{background:var(--bg)}.learn-rescue-path{display:flex;align-items:center;gap:6px;margin:8px 0 2px}.learn-rescue-ludwig{width:32px;height:32px;border-radius:50%;flex:none}.learn-rescue-dot{flex:1;height:6px;max-width:48px;border-radius:3px;background:var(--border);transition:background .3s}.learn-rescue-dot.done{background:#15803d}.learn-rescue-tower{position:relative;font-size:34px;line-height:1;margin-inline-start:auto}.learn-rescue-zora,.learn-rescue-fox{position:absolute;font-size:15px}.learn-rescue-zora{top:-4px;left:50%;transform:translate(-50%)}.learn-rescue-fox{bottom:-2px;right:-12px;transition:transform .8s,opacity .8s}.learn-rescue.freed .learn-rescue-fox{transform:translate(60px);opacity:0}.learn-rescue.freed .learn-rescue-zora{display:none}.learn-rescue-free{font-size:24px;line-height:1;animation:learn-rescue-jump .6s ease-out 3}@keyframes learn-rescue-jump{50%{transform:translateY(-12px)}}.learn-rescue-answer{display:flex;gap:8px;align-items:center}.learn-rescue-number{width:6ch;font-size:1.1em;padding:6px 8px;text-align:center}.learn-rescue-label{margin:14px 0 4px;color:var(--muted);font-size:.9em}.learn-rescue-alphabet{display:flex;flex-wrap:wrap;gap:2px;margin-bottom:12px}.learn-rescue-letter{display:inline-flex;flex-direction:column;align-items:center;min-width:22px;padding:2px 0;border-radius:4px;background:var(--bg)}.learn-rescue-letter small{font-size:10px;color:var(--muted)}.learn-rescue-letter.hit{background:#fde68a;outline:2px solid #d97706}.learn-rescue-charat{font-weight:600}.learn-rescue-moved{font-weight:400!important}.learn-rescue-word{font:inherit;padding:1px 4px;border:1px solid var(--accent);border-radius:4px}.learn-rescue-gate{padding:8px 0;margin-bottom:8px}.learn-cw{--cw-cell: 30px;display:flex;flex-wrap:wrap;gap:12px 20px;margin-bottom:10px}.learn-cw-grid{display:grid;gap:2px}.learn-cw-cell{position:relative;width:var(--cw-cell);height:var(--cw-cell)}.learn-cw-cell input{width:100%;height:100%;box-sizing:border-box;padding:0;border:1px solid #6e6e73;border-radius:3px;background:#fff;color:#1c1c1e;text-align:center;font:600 16px/1 ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase}.learn-cw-cell input:disabled{opacity:1;-webkit-text-fill-color:#1c1c1e}.learn-cw-cell.key input{background:#fde68a}.learn-cw-cell.given input{color:#1d4ed8;-webkit-text-fill-color:#1d4ed8}.learn-cw-cell.arrived input{animation:learn-cw-arrive .6s ease-out}.learn-cw-cell input.wrong{border-color:#b91c1c;background:#fee2e2}@keyframes learn-cw-arrive{0%{transform:scale(1.6)}}.learn-cw-number,.learn-cw-keyindex{position:absolute;font-size:8px;line-height:1;pointer-events:none;color:#6e6e73;z-index:1}.learn-cw-number{top:2px;left:2px}.learn-cw-keyindex{bottom:2px;right:2px;color:#b45309}.learn-cw-keyword{margin:8px 0 0;font-weight:600}.learn-cw-keybox{display:inline-block;width:22px;height:24px;margin-inline-end:2px;border-bottom:2px solid #d97706;background:#fef3c7;text-align:center;line-height:24px;white-space:pre}.learn-cw-cluebox{flex:1;min-width:200px}.learn-cw-clues{margin:4px 0 10px;padding-inline-start:24px}.learn-cw-clues li{cursor:pointer}@media(max-width:380px){.learn-cw{--cw-cell: 28px}}.learn-cloze{border:2px solid var(--accent);border-radius:12px;padding:12px 14px;margin:0 0 14px}.learn-cloze-title{display:block;font-size:1.05em;margin-bottom:4px}.learn-cloze p{margin:0 0 8px}.learn-cloze-hint{color:var(--muted);font-size:.9em}.learn-cloze-code{margin:0 0 10px;padding:8px 10px;border-radius:8px;background:var(--bg, #f2f2f7);font-size:13px;line-height:1.9;overflow-x:auto}.learn-cloze-code .ln{white-space:pre;min-height:1.9em}.learn-cloze-gap{font-size:13px;padding:1px 3px;margin:0 1px;min-width:0;max-width:none;border:1px solid #8e8e93;border-bottom-width:2px;border-radius:4px;background:#fff;color:#1c1c1e;text-align:center}.learn-cloze-gap.right{border-color:#34c759;background:#34c75924}.learn-cloze-gap.wrong{border-color:#ff3b30;background:#ff3b301a}.learn-cloze-gap.shown{border-color:#d97706;background:#fef3c7}.learn-cloze-gap:disabled{opacity:1;-webkit-text-fill-color:currentColor}.learn-cloze-actions{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.learn-cloze-check{font-weight:600}.learn-cloze-status:empty{display:none}.learn-cloze-status{padding:8px 12px;border-radius:8px;font-weight:600}.learn-cloze-status.right{background:#dcfce7}.learn-cloze-status.wrong{background:#fee2e2}.learn-pap{border:2px solid var(--accent);border-radius:12px;padding:12px 14px;margin:0 0 14px}.learn-pap-title{display:block;font-size:1.05em;margin-bottom:4px}.learn-pap p{margin:0 0 8px}.learn-pap-hint{color:var(--muted);font-size:.9em}.learn-pap-plan{display:block;width:100%;max-width:420px;margin:0 auto 10px;background:#fff;border-radius:8px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;fill:#1c1c1e}.learn-pap-slot{cursor:pointer;outline:none}.learn-pap-slot .learn-pap-shape{stroke:#8e8e93;stroke-width:2}.learn-pap-slot:focus-visible .learn-pap-shape,.learn-pap-slot.over .learn-pap-shape{stroke:var(--accent);stroke-width:3}.learn-pap-slot.right .learn-pap-shape{stroke:#34c759;stroke-width:3}.learn-pap-slot.wrong .learn-pap-shape{stroke:#ff3b30;stroke-width:3}.learn-pap-slot.shown .learn-pap-shape{stroke:#d97706}.learn-pap-legend{display:grid;grid-template-columns:auto 1fr;gap:4px 10px;align-items:center;max-width:420px;margin:0 auto 12px;padding:8px 10px;border-radius:8px;background:var(--bg, #f2f2f7);font-size:.9em}.learn-pap-legend dt{line-height:0}.learn-pap-legend dd{margin:0}.learn-pap-work{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);gap:8px;align-items:start;margin-bottom:10px}.learn-pap-work.done{grid-template-columns:minmax(0,1fr)}.learn-pap-left .learn-pap-plan{margin-bottom:8px}.learn-pap-tray{position:sticky;top:0;display:flex;flex-direction:column;align-items:center;gap:4px;max-height:100vh;overflow-y:auto;padding:6px 2px;border-radius:8px;background:var(--bg, #f2f2f7)}.learn-pap-tray:empty,.learn-pap-tray:not(:has(.learn-pap-card:not([hidden]))){display:none}.learn-pap-card svg{max-width:100%;height:auto}.learn-pap-card{padding:2px;max-width:100%;border:2px solid transparent;border-radius:10px;background:none;line-height:0;touch-action:none;cursor:grab;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;fill:#1c1c1e}.learn-pap-card.selected{border-color:var(--accent);background:var(--accent-soft)}.learn-pap-card.dragging{opacity:.3}.learn-pap-ghost{position:fixed;z-index:1000;pointer-events:none;transform:translate(-50%,-50%);opacity:.9}.learn-pap-actions{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.learn-pap-check{font-weight:600}.learn-pap-status:empty{display:none}.learn-pap-status{padding:8px 12px;border-radius:8px;font-weight:600}.learn-pap-status.right{background:#dcfce7}.learn-pap-status.wrong{background:#fee2e2}.learn-mark{color:inherit;padding:0 3px;border-radius:3px}.learn-mark.blau{background:#e4f1fd}.learn-mark.orange{background:#ffedd5}.learn-mark.gruen{background:#dcfce7}.learn-mark.gelb{background:#fdf4db}.learn-mark.rosa{background:#fce9f2}.startup-error{max-width:520px;margin:15vh auto 0;padding:0 16px;font:16px/1.5 system-ui,-apple-system,sans-serif;color:var(--text)}.startup-error h1{font-size:22px}.startup-error button{font-size:16px;padding:8px 16px}.startup-error pre{margin-top:24px;color:var(--muted);font-size:12px;white-space:pre-wrap}.visubot-stage{position:relative;height:280px;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:linear-gradient(#dfe9f3,#f6f3ec)}.visubot-live{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 8px;font-size:12px;color:var(--muted)}.visubot-live:empty{display:none}.visubot-live.connected{color:#0f8a5f;font-weight:600}.visubot-worlds{display:flex;gap:6px;margin:0 0 6px}.visubot-worlds button.active{background:var(--accent);border-color:var(--accent);color:#fff}.visubot-canvas{display:block;width:100%;height:100%;touch-action:none}.visubot-status{font-size:12px;color:var(--muted);margin:6px 0 0}.visubot-controls{margin-top:8px;font-size:13px}.visubot-controls summary{cursor:pointer;font-weight:600}.visubot-controls .hint{color:var(--muted);font-size:12px;margin:4px 0 6px}.visubot-controls label{display:grid;grid-template-columns:9.5em 1fr 2.5em;align-items:center;gap:6px;margin:2px 0}.visubot-controls output{text-align:end;font-variant-numeric:tabular-nums}.visubot-presses{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}.visubot-presses button{min-width:2.2em}.visubot-presses button.pressed{background:var(--accent);border-color:var(--accent);color:#fff}.visubot-check{margin-top:8px;font-size:13px}.visubot-check summary{cursor:pointer;font-weight:600}.visubot-check .hint{color:var(--muted);font-size:12px;margin:4px 0 6px}.visubot-check-sensors{margin-top:8px;border-collapse:collapse;font-variant-numeric:tabular-nums}.visubot-check-sensors th{text-align:start;font-weight:400;padding:1px 12px 1px 0}.palette-visubot-title{font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:14px 0 6px}.palette-sensor{display:flex;flex-direction:column;align-items:flex-start;gap:2px;border-style:dashed}.palette-sensor code{font-size:12px;color:var(--muted)}.palette-visubot .palette-item{border-color:#a7a0d3;background:color-mix(in srgb,#a7a0d3 16%,transparent)}.visubot-model{margin:12px 0}.visubot-model .visubot-stage{height:300px}.visubot-model-hint{font-size:13px;margin:4px 0 0}.visubot-part-label{position:absolute;pointer-events:none;padding:2px 8px;border-radius:6px;background:#14181ed9;color:#fff;font-size:13px;white-space:nowrap;z-index:1}.robot-part-link{text-decoration:underline 2px #f2b705;text-underline-offset:3px;cursor:pointer}.robot-part-link:hover,.robot-part-link:focus-visible{background:color-mix(in srgb,#f2b705 25%,transparent);outline:none}.visubot-quiz-question{font-size:15px;margin:12px 0 6px}.visubot-quiz-question.done{color:var(--success, #2f9e44)}.visubot-quiz-feedback{min-height:1.4em;margin:6px 0}.visubot-quiz-feedback.right{color:var(--success, #2f9e44)}.visubot-quiz-feedback.wrong{color:var(--danger, #c92a2a)}.diagram-tools .mbot-link{margin-inline-start:auto;height:30px;padding:0 10px;white-space:nowrap}.diagram-tools .mbot-link:not([hidden])+.sim-toggle,.diagram-tools .mbot-upload:not([hidden])+.sim-toggle{margin-inline-start:6px}.diagram-tools .mbot-upload{margin-inline-start:6px;height:30px;padding:0 10px;white-space:nowrap}.mbot-upload-steps{margin:0 0 12px;padding-inline-start:22px;line-height:1.5}.mbot-upload progress{width:100%;height:10px}.mbot-upload-status.done{color:var(--success, #2f9e44);font-weight:600}.settings-mbot-link{display:grid;gap:4px;margin-top:8px}.settings-mbot-link small{font-size:12px;color:var(--muted)}.world-chooser{margin-bottom:4px}.world-hint{display:block;font-size:12px;color:var(--muted);margin-bottom:8px}.start-world{margin-bottom:14px}.robotpreview,.robotpreview-rail,.preview-resizer{display:none}.shell.robot-world.preview .robotpreview{display:flex}.shell.robot-world:not(.preview) .robotpreview-rail{display:flex;border-inline-end:none;border-inline-start:1px solid var(--border)}.robotpreview-rail svg{transform:scaleX(-1)}.shell.robot-world.preview:not(.preview-stacked) .preview-resizer{display:block}.robotpreview{flex:0 1 auto;width:360px;min-width:220px;flex-direction:column;gap:6px;padding:10px 12px 12px;background:var(--panel);border-inline-start:1px solid var(--border);min-height:0;overflow-y:auto}.robotpreview .hint{margin:0;font-size:.85em;color:var(--muted, inherit)}.robotpreview .robotpreview-stage{flex:1 1 auto;height:auto;min-height:160px}.robotpreview .robotpreview-status{margin:0;min-height:1.3em}.robotpreview-height{display:none}.robotpreview.simulation>.visubot-worlds,.robotpreview.simulation>.robotpreview-stage,.robotpreview.simulation>.robotpreview-status,.robotpreview.simulation .robotpreview-play{display:none}.robotpreview .visubot-viewport{display:flex;flex:1 1 auto;flex-direction:column;min-height:0}.robotpreview .visubot-viewport .visubot-stage{flex:1 1 auto;height:auto;min-height:160px}.visubot-elsewhere{display:none;margin:0 0 8px;font-size:12px;color:var(--muted)}.visubot:not(:has(>.visubot-viewport)) .visubot-elsewhere{display:block}.shell.preview-stacked .robotpreview{flex:0 0 auto;width:auto!important;height:320px;min-width:0;margin:4px -12px -12px;padding-top:0;border-inline-start:none;border-top:1px solid var(--border);overflow:visible}.shell.preview-stacked .robotpreview-height{display:block;height:10px;margin:-5px 0 0;cursor:row-resize;touch-action:none;position:relative}.robotpreview-height:after{content:"";position:absolute;inset-inline:0;top:4px;height:2px;background:transparent;transition:background .15s}.robotpreview-height:hover:after,.robotpreview-height:focus-visible:after,.shell.resizing .robotpreview-height:after{background:var(--accent)}.robotpreview-height:focus-visible{outline:none}.preview-resizer{flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.preview-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.preview-resizer:hover:after,.preview-resizer:focus-visible:after,.shell.resizing .preview-resizer:after{background:var(--accent)}.preview-resizer:focus-visible{outline:none}.palette-group{grid-column:1 / -1}.palette-group button{display:flex;align-items:center;gap:6px;width:100%;margin-top:4px;padding:2px 0;border:none;background:none;color:var(--muted);font-size:12px;font-weight:600;text-align:start;cursor:pointer}.palette-group button:before{content:"▾";transition:transform .15s}.palette-group button[aria-expanded=false]:before{transform:rotate(-90deg)}.palette-item[hidden]{display:none}.editor-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.editor-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.editor-resizer:hover:after,.editor-resizer:focus-visible:after,.shell.resizing .editor-resizer:after{background:var(--accent)}.editor-resizer:focus-visible{outline:none}.shell.code-main.live:not(.editor-hidden) .editor-resizer{display:block}.shell.code-main.live:not(.editor-hidden) .live-resizer{display:none}.shell.code-main.live:not(.editor-hidden) .app{flex:0 1 auto;width:460px;min-width:300px}.shell.code-main.live:not(.editor-hidden) .livecode{flex:1 1 0;width:auto!important;min-width:0}.shell.code-main.live:not(.editor-hidden) .livecode{order:1}.shell.code-main.live:not(.editor-hidden) .editor-resizer{order:2}.shell.code-main.live:not(.editor-hidden) .app{order:3;border-inline-start:1px solid var(--border)}.shell.code-main.live:not(.editor-hidden) .live-rail,.shell.code-main.live:not(.editor-hidden) .preview-resizer,.shell.code-main.live:not(.editor-hidden) .robotpreview,.shell.code-main.live:not(.editor-hidden) .robotpreview-rail{order:4}[data-action=swap-main]{font-size:16px;line-height:1}[data-action=swap-main][aria-pressed=true]{color:var(--accent)}.palette-resizer{grid-area:pal;justify-self:end;width:10px;margin-inline-end:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.palette-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.palette-resizer:hover:after,.palette-resizer:focus-visible:after,.shell.resizing .palette-resizer:after{background:var(--accent)}.palette-resizer:focus-visible{outline:none}.app.simulating .palette-resizer{display:none}:root.visuobject-theme{--bg: #edf4f6;--text: #17292e;--muted: #566a70;--border: #cddde1;--accent: #0e7c86;--accent-soft: rgba(14, 124, 134, .2);--accent-faint: rgba(14, 124, 134, .08);--accent-glow: rgba(14, 124, 134, .35)}.visuobject-obj,.visuobject .brand .logo{color:var(--accent)}.shell.visuobject button.text-button{padding:5px 10px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);font:inherit;cursor:pointer}.shell.visuobject button.text-button:hover{border-color:var(--accent);color:var(--accent)}:root.visuobject-theme{--vo-bar: #e3edf0}.vo-columns{display:grid;grid-template-columns:var(--vo-cols, 260px 1px minmax(0, 45fr) 1px minmax(0, 55fr));flex:1;min-height:0;border-top:1px solid var(--border)}.vo-columns.vo-resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.vo-pane{display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--panel)}.vo-pane.collapsed>:not(.vo-strip){display:none}.vo-strip{display:none;flex:1;align-items:center;justify-content:center;padding:12px 0;border:0;background:var(--vo-bar);color:var(--muted);font:600 14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;writing-mode:vertical-rl;cursor:pointer}.vo-pane.collapsed>.vo-strip{display:flex}.vo-strip:hover,.vo-strip:focus-visible{color:var(--accent);background:var(--accent-faint);outline:none}.vo-splitter{position:relative;z-index:4;background:var(--border);cursor:col-resize;touch-action:none;outline:none}.vo-splitter:after{content:"";position:absolute;top:0;right:-4px;bottom:0;left:-4px}.vo-splitter:hover,.vo-splitter:focus-visible,.vo-resizing .vo-splitter{background:var(--accent)}.vo-splitter.fixed{cursor:default;background:var(--border)}.vo-bar{display:flex;flex-wrap:wrap;align-items:stretch;min-height:40px;background:var(--vo-bar);border-bottom:1px solid var(--border);font-size:14px}.vo-bar-title{display:flex;flex:1;align-items:center;margin:0;text-transform:none;letter-spacing:normal;padding:0 12px;font-size:14px;font-weight:600;color:var(--text)}.vo-bar-actions{display:flex;flex:0 1 auto;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px;padding:4px 4px 4px 0}.shell.visuobject .vo-bar button.text-button{padding:2px 8px;border-radius:6px}.vo-collapse{padding:0 12px;border:0;background:none;color:var(--muted);font-size:16px;font-weight:700;cursor:pointer}.vo-collapse:hover,.vo-collapse:focus-visible{color:var(--accent)}.vo-tabs{display:flex;flex:1;min-width:0;overflow-x:auto}.vo-tab{display:flex;align-items:stretch;border-right:1px solid var(--border);border-bottom:3px solid transparent}.vo-tab.active{background:var(--panel);border-bottom-color:var(--accent)}.vo-tab [role=tab]{padding:0 4px 0 14px;border:0;background:none;color:var(--text);font:13px ui-monospace,SF Mono,Menlo,Consolas,monospace;white-space:nowrap;cursor:pointer}.vo-tab.active [role=tab]{font-weight:700}.vo-tab [role=tab]:hover{color:var(--accent)}.vo-tab-close{padding:0 10px 0 6px;border:0;background:none;color:var(--muted);font-size:15px;cursor:pointer;visibility:hidden}.vo-tab.active .vo-tab-close,.vo-tab:hover .vo-tab-close{visibility:visible}.vo-tab-close:hover{color:var(--accent)}.vo-tab-close .vo-dot,.vo-tab-close.unsaved .vo-x{display:none}.vo-tab-close.unsaved{visibility:visible;color:var(--text)}.vo-tab-close.unsaved .vo-dot{display:inline;font-size:11px}.vo-tab-close.unsaved:hover .vo-dot{display:none}.vo-tab-close.unsaved:hover .vo-x{display:inline}.vo-no-file{display:flex;align-items:center;padding:0 12px;color:var(--muted)}.vo-editor{flex:1;min-height:0;overflow:auto;font-size:14px}.vo-foot{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;padding:6px 12px;border-top:1px solid var(--border);background:var(--vo-bar)}.vo-hint{color:var(--muted);flex:1 1 260px}.vo-canvas{position:relative;flex:1;min-height:0;overflow:auto;background:radial-gradient(circle,var(--border) 1px,transparent 1px) 0 0 / 20px 20px;outline:none}.vo-frames{position:absolute;inset:0 auto auto 0;z-index:0;pointer-events:none;overflow:visible}.vo-package-frame{fill:#0e7c8609;stroke:var(--muted);stroke-width:1.2}.vo-package.current .vo-package-frame{stroke:var(--accent);fill:var(--accent-faint)}.vo-package-name{font:600 12px ui-monospace,SF Mono,Menlo,Consolas,monospace;fill:var(--muted)}.vo-package.current .vo-package-name{fill:var(--accent)}.vo-lines{position:absolute;inset:0 auto auto 0;z-index:3;pointer-events:none;overflow:visible}.vo-rel{stroke:var(--text);stroke-width:1.4;fill:none}.vo-rel.ghost{stroke:var(--accent);stroke-dasharray:4 4}.vo-hit{stroke:transparent;stroke-width:12;pointer-events:stroke;cursor:pointer}.vo-relation:hover .vo-rel,.vo-relation:hover .vo-diamond{stroke:var(--accent)}.vo-relation.selected .vo-rel,.vo-relation.selected .vo-diamond{stroke:var(--accent);stroke-width:2.4}.vo-relation.selected .vo-label-svg{fill:var(--accent)}.vo-diamond{fill:var(--panel);stroke:var(--text);stroke-width:1.4}.vo-diamond.filled{fill:var(--text)}.vo-relation.selected .vo-diamond.filled{fill:var(--accent)}.vo-label-svg.name{font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-style:italic;fill:var(--text)}.vo-rel.dashed{stroke-dasharray:6 4}.vo-hollow,.vo-open{fill:none;stroke:var(--text);stroke-width:1.4}.vo-label-svg{font:12px ui-monospace,SF Mono,Menlo,Consolas,monospace;fill:var(--muted);paint-order:stroke;stroke:var(--panel);stroke-width:4px}.vo-empty{margin:24px;max-width:40ch;color:var(--muted)}.vo-status{margin:0;color:#b3261e}.vo-status:empty{display:none}.vo-status.hint{color:var(--accent)}.uml-class{position:absolute;left:16px;top:16px;min-width:150px;background:var(--panel);border:1.5px solid var(--text);font:13px/1.5 ui-monospace,SF Mono,Menlo,Consolas,monospace;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.uml-connect{position:absolute;right:-11px;top:50%;width:20px;height:20px;margin-top:-10px;padding:0;border:2px solid var(--panel);border-radius:50%;background:var(--accent);box-shadow:0 1px 4px #00000040;cursor:crosshair;touch-action:none}.uml-connect:after{content:"";position:absolute;top:5px;right:4px;bottom:5px;left:5px;background:#fff;clip-path:polygon(0 35%,55% 35%,55% 0,100% 50%,55% 100%,55% 65%,0 65%)}.uml-class.drop{border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}.vo-relmenu{position:absolute;z-index:10;display:grid;min-width:220px;padding:6px;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #0000002e;font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-relmenu p{margin:2px 8px 6px;color:var(--muted);font-size:12px}.vo-relmenu button{display:flex;align-items:center;gap:10px;padding:6px 8px;border:0;border-radius:6px;background:none;color:var(--text);font:inherit;text-align:left;cursor:pointer}.vo-relmenu button:hover,.vo-relmenu button:focus-visible{background:var(--accent-faint);color:var(--accent);outline:none}.vo-relicon{flex:none}.vo-palette{display:flex;flex-wrap:wrap;align-items:stretch;gap:2px;padding:4px 6px;border-bottom:1px solid var(--border);background:var(--panel)}.vo-palette-sep{width:1px;margin:4px;background:var(--border)}.vo-tool{display:grid;justify-items:center;gap:1px;min-width:44px;padding:3px 3px 2px;border:1px solid transparent;border-radius:7px;background:none;color:var(--text);font:11px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer;touch-action:none;-webkit-user-select:none;user-select:none}.vo-tool:hover{background:var(--accent-faint);color:var(--accent)}.vo-tool[aria-pressed=true]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}.vo-tool[data-tool=class],.vo-tool[data-tool=interface]{cursor:grab}.vo-tool-ghost{position:fixed;z-index:1000;display:grid;justify-items:center;min-width:120px;padding:4px 10px 14px;margin:-14px 0 0 -60px;border:1.5px dashed var(--accent);background:#ffffffe6;font:13px ui-monospace,SF Mono,Menlo,Consolas,monospace;pointer-events:none}.vo-tool-ghost small{color:var(--muted);font-size:11px}.vo-canvas:not([data-tool=select])[data-tool]{cursor:crosshair}.vo-canvas:not([data-tool=select])[data-tool] .uml-class{cursor:crosshair}.vo-canvas:not([data-tool=select])[data-tool] .uml-class:hover,.uml-class.source{border-color:var(--accent)}.uml-class.source{box-shadow:0 0 0 4px var(--accent-soft)}.vo-stage{position:relative;display:flex;flex:1;min-height:0}.vo-stage .vo-canvas{flex:1}.vo-hsplit{flex:0 0 6px;margin:-3px 0;position:relative;z-index:5;cursor:row-resize;touch-action:none}.vo-hsplit:after{content:"";position:absolute;left:0;right:0;top:2px;height:2px;background:transparent}.vo-hsplit:hover:after,.vo-hsplit:focus-visible:after{background:var(--accent)}.vo-hsplit:focus-visible{outline:none}.vo-dock.collapsed+.vo-hsplit,.vo-hsplit:has(+.vo-dock.collapsed){cursor:default;pointer-events:none}.vo-dock{border-top:1px solid var(--border);background:var(--panel)}.vo-dock-bar{min-height:30px}.vo-dock-bar .vo-bar-title{font-size:13px}.vo-dock.collapsed .vo-inspector{display:none}.vo-inspector{display:grid;align-content:start;gap:8px;height:32vh;overflow:auto;padding:8px 12px 10px;font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-inspector-row>label.check,.vo-inspector label.check{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;padding-bottom:6px;color:var(--text);font-size:13px}.vo-inspector input[type=checkbox]{width:auto;margin:0;accent-color:var(--accent)}.vo-inspector fieldset.vo-inspector-ifaces{display:flex;flex-wrap:wrap;gap:4px 14px}.vo-inspector-empty{color:var(--muted)}.vo-inspector-row{display:flex;flex-wrap:wrap;align-items:end;gap:8px 12px}.vo-inspector-row>label{flex:1 1 160px;max-width:260px}.vo-inspector-ends{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:8px}.vo-inspector label{display:grid;gap:3px;color:var(--muted);font-size:12px}.vo-inspector input,.vo-inspector select{box-sizing:border-box;width:100%;min-width:0;padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-inspector input:focus,.vo-inspector select:focus{border-color:var(--accent);outline:2px solid var(--accent-soft)}.vo-inspector fieldset{display:grid;grid-template-columns:minmax(0,1fr) 84px;align-items:start;gap:6px;min-width:0;margin:0;padding:6px 8px 8px;border:1px solid var(--border);border-radius:8px}.vo-inspector fieldset .vo-wide{grid-column:1 / -1}.vo-reading{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px;color:var(--muted)}.vo-reading b{color:var(--text)}.shell.visuobject .vo-reading button.text-button{padding:1px 8px;font-size:12px}.vo-inspector legend{padding:0 4px;color:var(--text);font-weight:600}.vo-inspector small{color:var(--muted);font-size:11px}.vo-inspector p{margin:0}.vo-inspector-kind{font-weight:600;padding-top:4px}.shell.visuobject .vo-inspector button.vo-danger{display:inline-flex;align-items:center;justify-self:start;gap:6px;color:#b3261e}.vo-inspector .vo-danger svg{width:15px;height:15px}.vo-insp-head{position:sticky;top:-8px;z-index:1;margin-top:-8px;padding-top:8px;background:var(--panel);display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 12px;border-bottom:1px solid var(--border)}.vo-insp-head .vo-inspector-kind{padding:0}.vo-insp-tabs{display:flex;gap:2px}.shell.visuobject .vo-insp-tabs button{margin-bottom:-1px;padding:5px 12px;border:1px solid transparent;border-bottom:none;border-radius:6px 6px 0 0;background:none;color:var(--muted);font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer}.shell.visuobject .vo-insp-tabs button[aria-selected=true]{border-color:var(--border);background:var(--panel);color:var(--text);font-weight:600}.vo-members{width:100%;border-collapse:collapse}.vo-members th{padding:0 4px 3px;color:var(--muted);font-size:12px;font-weight:500;text-align:left}.vo-members td{padding:2px 4px;vertical-align:middle}.vo-members td.c{width:52px;text-align:center}.vo-members td:first-child{width:112px}.vo-members td:last-child{width:32px}.vo-members .icon svg{width:15px;height:15px}.vo-doc textarea{box-sizing:border-box;width:100%;max-width:780px;padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;resize:vertical}.vo-insp-sep{align-self:stretch;width:1px;margin:0 4px;background:var(--border)}.vo-insp-label{align-self:center;color:var(--muted);font-size:12px}.uml-class.selected{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);z-index:2}.uml-head{display:grid;justify-items:center;padding:4px 10px;font-weight:700}.uml-head small{font-weight:400;font-size:11px;color:var(--muted)}.uml-class.abstract .uml-name,.uml-member.abstract{font-style:italic}.uml-member.static{text-decoration:underline}.uml-class ul{list-style:none;margin:0;padding:3px 0;border-top:1.5px solid var(--text);min-height:12px}.uml-class.selected ul{border-top-color:var(--accent)}.uml-class li{padding:0 10px;white-space:nowrap}.uml-member.selected{background:var(--accent-soft)}.uml-add{color:var(--accent);font-style:italic;cursor:pointer;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:12px}.uml-add:hover{text-decoration:underline}.uml-input{font:inherit;padding:0 4px;margin:0 -5px;border:1px solid var(--accent);border-radius:4px;outline:none;max-width:340px}.uml-tools{display:flex;flex-wrap:wrap;gap:6px 10px;align-items:center;padding:6px 10px;border-top:1px dashed var(--border);font:12px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:default}.uml-tools label{display:inline-flex;gap:4px;align-items:center}.uml-tools button.icon svg{width:16px;height:16px}.vo-ws{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 10px 4px;font-size:13px}.vo-ws[hidden]{display:none}.vo-ws.ask{margin:8px 10px 4px;padding:10px;border:1px solid var(--accent);border-radius:8px;background:var(--bg, #fff)}.vo-ws.ask p{flex-basis:100%;margin:0}.vo-ws.ask .hint{color:var(--muted);font-size:12px;margin-bottom:4px}.vo-ws-name{display:inline-flex;align-items:center;gap:6px;margin-right:auto;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shell.visuobject .vo-ws button.text-button{padding:2px 8px;border-radius:6px}.shell.visuobject .vo-ws button.text-button.primary{background:var(--accent);border-color:var(--accent);color:#fff}.vo-lines .vo-end-hit{fill:transparent;pointer-events:all;cursor:context-menu}.vo-lines .vo-label-svg.editable{pointer-events:all;cursor:pointer}.vo-lines .vo-label-svg.editable:hover{fill:var(--accent);text-decoration:underline}.vo-lines .vo-label-svg.placeholder{fill:var(--muted);opacity:.6;font-style:italic}.vo-endpop{position:absolute;z-index:12;display:grid;gap:8px;width:min(330px,calc(100% - 16px));box-sizing:border-box;padding:10px 12px;background:var(--panel);border:1px solid var(--accent);border-radius:10px;box-shadow:0 8px 24px #00000029;font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-endpop p{margin:0}.vo-endpop label{display:grid;gap:3px;color:var(--muted);font-size:12px}.vo-endpop input{box-sizing:border-box;min-width:0;padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-endpop-row{display:flex;flex-wrap:wrap;align-items:center;gap:4px}.vo-endpop-row>span{flex-basis:100%;color:var(--muted);font-size:12px}.vo-endpop-row button{padding:2px 8px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:12px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer}.vo-endpop-row button[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:#fff}.vo-endpop-row input{width:64px}.vo-new{position:relative}.vo-new-menu{position:absolute;top:calc(100% + 4px);left:0;z-index:30;display:grid;min-width:190px;padding:4px;background:var(--panel);border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 24px #00000024}.vo-new-menu[hidden]{display:none}.vo-new-menu button{display:flex;align-items:center;gap:8px;padding:6px 8px;border:0;border-radius:6px;background:none;color:var(--text);font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;text-align:left;cursor:pointer}.vo-new-menu button:hover,.vo-new-menu button:focus-visible{background:var(--accent-soft);outline:none}.vo-badge.folder.source{box-shadow:inset 0 3px #ffffff59,inset -5px -4px #8a6d2b}.confirm-card.vo-wizard{display:grid;gap:10px;width:min(520px,100%);max-width:none;max-height:calc(100vh - 32px);overflow:auto;box-sizing:border-box;font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-wizard h2{margin:0;font-size:17px}.vo-wizard .hint{margin:0;color:var(--muted);font-size:13px}.vo-wizard>label{display:grid;grid-template-columns:130px minmax(0,1fr);align-items:center;gap:8px;color:var(--muted);font-size:13px}.vo-wizard input[type=text],.vo-wizard select{box-sizing:border-box;width:100%;min-width:0;padding:5px 7px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:inherit}.vo-wizard fieldset{margin:0;padding:6px 10px 8px;border:1px solid var(--border);border-radius:8px}.vo-wizard legend{padding:0 4px;color:var(--muted);font-size:13px}.vo-wizard-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px}.vo-wizard-row select,.vo-wizard-row input[type=text]{width:auto;flex:1 1 160px}.vo-wizard-list{display:grid;gap:4px}.vo-wizard .check{display:inline-flex;align-items:center;gap:6px}.vo-wizard code{font-size:12px}.vo-wizard-error{min-height:1em;margin:0;color:#b3261e;font-size:13px}.vo-wizard .group button.primary{background:var(--accent);border-color:var(--accent);color:#fff}@media(max-width:560px){.vo-wizard>label{grid-template-columns:1fr}}.vo-dirty{color:var(--accent)}.vo-tree-tools{display:flex;flex-wrap:wrap;gap:6px;padding:8px 10px 4px}.shell.visuobject .vo-tree-tools button.text-button{padding:2px 8px;border-radius:6px}.vo-tree{flex:1;min-height:0;overflow:auto;padding:6px;font:13px/1.3 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-tree ul{list-style:none;margin:0;padding:0}.vo-row{display:flex;align-items:center;gap:6px;min-height:28px;padding:0 6px 0 calc(4px + var(--depth, 0) * 14px);border-radius:7px;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;outline:none}.vo-row:hover{background:var(--accent-faint)}.vo-row:focus-visible{box-shadow:inset 0 0 0 2px var(--accent-soft)}.vo-row.active .vo-label{font-weight:600}.vo-row.selected{background:var(--accent-soft);color:var(--text)}.vo-twisty,.vo-twisty-space{flex:none;width:18px;height:18px}.vo-twisty{display:grid;place-items:center;padding:0;border:0;border-radius:4px;background:none;color:var(--muted);cursor:pointer}.vo-twisty svg{transition:transform .15s ease}[aria-expanded=true]>.vo-row .vo-twisty svg{transform:rotate(90deg)}.vo-twisty:hover{color:var(--accent)}.vo-label{min-width:0;overflow:hidden;text-overflow:ellipsis}.vo-type{color:var(--muted);font-size:12px;overflow:hidden;text-overflow:ellipsis}.vo-row .uml-input{margin:0;font:inherit}.vo-row-delete{margin-left:auto;visibility:hidden}.vo-tree button.vo-row-delete{width:24px;height:24px}.vo-tree button.vo-row-delete svg{width:14px;height:14px}.vo-row:hover .vo-row-delete,.vo-row.selected .vo-row-delete{visibility:visible}.vo-tree-empty{padding:6px 10px 6px 52px;color:var(--muted);font-size:12px;white-space:normal}.vo-badge{flex:none;display:inline-grid;place-items:center;width:16px;height:16px;border-radius:4px;font:700 10px/1 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#fff}.vo-badge.project{background:var(--accent);border-radius:5px;box-shadow:inset 0 -5px #0000002e}.vo-badge.project.closed{opacity:.55}.vo-badge.folder{width:17px;height:13px;border-radius:2px 4px 3px 3px;background:#e0a63b;box-shadow:inset 0 3px #ffffff59}.vo-badge.package{width:14px;height:14px;border-radius:3px;background:#b07a2a;transform:rotate(45deg) scale(.82)}.vo-badge.package.empty{background:none;border:1.5px solid #b07a2a}.vo-badge.file{background:#e66a2c;border-radius:3px 6px 3px 3px}.vo-badge.type.class{background:#2f7d32;border-radius:50%}.vo-badge.type.class.abstract{background:#6a9c3a;font-style:italic}.vo-badge.type.interface{background:#7b4fb0;border-radius:50%}.vo-badge.field,.vo-badge.method{width:9px;height:9px;margin:0 3px}.vo-badge.field{border-radius:2px}.vo-badge.method{border-radius:50%}.vo-badge.public{background:#2f9e44}.vo-badge.private{background:#d6453d}.vo-badge.protected{background:#e0a63b}.vo-badge.package.field,.vo-badge.package.method{background:#3b82c4;transform:none;border:0}.vo-badge.static{box-shadow:0 0 0 2px var(--panel),0 0 0 3px currentColor;color:var(--muted)}@media(max-width:760px){.vo-columns{grid-template-columns:1fr;grid-auto-rows:auto;overflow:auto}.vo-splitter{display:none}.vo-explorer:not(.collapsed){height:260px}.vo-code:not(.collapsed){height:320px}.vo-diagram:not(.collapsed){min-height:420px}.vo-pane{border-bottom:1px solid var(--border)}.vo-strip{writing-mode:horizontal-tb;padding:10px}}.shell.visuobject .vo-run-group button.vo-run{color:var(--accent);font-weight:600}.vo-console{display:flex;flex-direction:column;height:32vh;min-height:120px;border-top:1px solid var(--border)}.vo-console[hidden],.vo-swing[hidden]{display:none}.vo-console .vo-dock-bar{gap:10px}.vo-console-status{flex:1;color:var(--muted);font-size:12px}.vo-console-status.error{color:#b3261e}.vo-swing{display:flex;height:60%;padding:6px}.vo-console-lines{flex:1;min-height:0;overflow:auto;margin:0;padding:6px 12px;font-size:13px;white-space:pre-wrap}.uml-note{position:absolute;min-width:120px;max-width:260px;padding:8px 22px 8px 10px;background:#fffbe6;border:1.2px solid var(--text);clip-path:polygon(0 0,calc(100% - 14px) 0,100% 14px,100% 100%,0 100%);font:13px/1.45 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#17292e;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none;z-index:1}.uml-note:after{content:"";position:absolute;top:0;right:0;width:14px;height:14px;background:linear-gradient(to bottom left,transparent 50%,#e9dfae 50%);border-left:1.2px solid var(--text);border-bottom:1.2px solid var(--text)}.uml-note.selected{outline:3px solid var(--accent-soft);border-color:var(--accent);clip-path:none}.uml-note .uml-connect{z-index:2}.uml-note-text{white-space:pre-wrap;overflow-wrap:anywhere}.uml-note-text.placeholder{color:#8a8a8a;font-style:italic}.uml-note-edit{box-sizing:border-box;width:220px;border:1px solid var(--accent);background:#fffef5;font:inherit;resize:both}.vo-note-link{stroke-dasharray:5 4}.vo-canvas[hidden],.vo-palette[hidden]{display:none}.vo-diagram-switch{display:flex;gap:2px;padding:2px;border:1px solid var(--border);border-radius:8px;background:var(--panel)}.shell.visuobject .vo-diagram-switch button{padding:3px 10px;border:none;border-radius:6px;background:none;color:var(--muted);font:600 13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer}.shell.visuobject .vo-diagram-switch button[aria-selected=true]{background:var(--accent);color:#fff}.vo-obj-palette{align-items:center;gap:8px;padding:6px 10px}.vo-obj-new{display:flex;align-items:center;gap:6px;font-size:13px}.vo-obj-new select{padding:3px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.uml-object .uml-objname{text-decoration:underline;font-weight:600}.uml-object.unknown{border-style:dashed}.uml-object .uml-member.changed,.vo-objlink.changed{animation:vo-changed 1.2s ease-out}.uml-object .uml-member.changed{background:#fff3b0}@keyframes vo-changed{0%{background:#ffe066}}.vo-obj-values td:first-child{width:auto;white-space:nowrap}.vo-obj-values td:last-child{width:50%}.vo-dbg-controls{display:inline-flex;gap:2px}.vo-dbg-controls[hidden]{display:none}.vo-console-lines .vo-out-err{color:#b3261e}.vo-console-lines .vo-out-in{color:var(--accent);font-weight:600}.vo-console-input{display:flex;align-items:center;gap:6px;padding:4px 12px 8px;color:var(--accent)}.vo-console-input[hidden]{display:none}.vo-console-input input{flex:1;font-size:13px;padding:4px 6px;border:1px solid var(--accent);border-radius:4px}.vo-dbg{display:grid;grid-template-columns:minmax(160px,1fr) minmax(220px,2fr);gap:12px;padding:8px 12px}.vo-dbg h3{margin:0 0 6px;font-size:12px;font-weight:600;color:var(--muted)}.vo-dbg ol{list-style:none;margin:0;padding:0}.vo-dbg-frame{display:block;width:100%;text-align:start;padding:3px 6px;border:0;border-radius:4px;background:none;color:inherit;font:inherit;cursor:pointer}.vo-dbg-frame.on{background:var(--accent-soft)}.vo-dbg-frame small{color:var(--muted)}.vo-dbg-vars tr.changed td{background:#ffd60a59}@media(max-width:760px){.vo-dbg{grid-template-columns:1fr}}.vo-seqcanvas{overflow:auto}.vo-seqcanvas .vo-empty[hidden]{display:none}.vo-seq{display:block;font:12px ui-monospace,SFMono-Regular,Menlo,monospace}.vo-seq-head rect{fill:var(--panel);stroke:var(--text);stroke-width:1.2}.vo-seq-head text{fill:var(--text);text-decoration:underline}.vo-seq-head.static text{text-decoration:none;font-weight:600}.vo-seq-life{stroke:var(--muted);stroke-dasharray:5 4}.vo-seq-bar{fill:var(--panel);stroke:var(--text);stroke-width:1}.vo-seq-bar.running{fill:var(--accent-soft)}.vo-seq-msg{cursor:pointer}.vo-seq-msg line,.vo-seq-msg path{stroke:var(--text);stroke-width:1.2}.vo-seq-msg .head.filled{fill:var(--text)}.vo-seq-msg text{fill:var(--text)}.vo-seq-msg.return line,.vo-seq-msg.create line{stroke-dasharray:6 4}.vo-seq-msg.exception line,.vo-seq-msg.exception text{stroke:#b3261e;fill:#b3261e}.vo-seq-msg.current line,.vo-seq-msg.current path{stroke:#e0a800;stroke-width:2.4}.vo-seq-msg.current .head.filled{fill:#e0a800}.vo-seq-msg.current text{font-weight:700}.vo-seq-msg:hover text{fill:var(--accent)}.vo-seq-more{fill:var(--muted)}.palette-head{display:flex;align-items:center;gap:4px;margin:0 0 4px}.palette-head h2{flex:1;min-width:0;margin:0}.palette-hide{min-height:26px;padding:2px 5px}.app.compact-palette .palette-head{flex-direction:column;gap:2px}.palette-rail{display:none;grid-area:pal;width:auto}.app.palette-hidden .palette,.app.palette-hidden .palette-resizer{display:none}.app.palette-hidden:not(.simulating) .palette-rail{display:flex}@media(max-width:820px){.palette-head{display:none}.app.palette-hidden .palette{display:block}.app.palette-hidden .palette-rail{display:none!important}}.diagram-tools .pseudocode-toggle{gap:4px;margin:0 4px;white-space:nowrap;cursor:pointer} diff --git a/website/app/assets/objectApp-fPb85kNH.js b/website/app/assets/objectApp-BAiNGNpM.js similarity index 99% rename from website/app/assets/objectApp-fPb85kNH.js rename to website/app/assets/objectApp-BAiNGNpM.js index b04a017e..a668a454 100644 --- a/website/app/assets/objectApp-fPb85kNH.js +++ b/website/app/assets/objectApp-BAiNGNpM.js @@ -1,5 +1,5 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./projectZip-d7JtxgDL.js","./index-CqnqsqSP.js","./index-3atjocI4.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,_ as wt,f as $t,h as Js,r as _t,j as Ks,k as ct}from"./index-CqnqsqSP.js";function Xs(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,_ as wt,f as $t,h as Js,r as _t,j as Ks,k as ct}from"./index-CBJVdWXq.js";function Xs(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 Gs(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=Xs(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=Gs(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 Zs(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 Qs=/^[\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 ei={"+":"public ","-":"private ","#":"protected ","~":""};function ti(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?"":ei[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.13.36"))} + ${b(d("web_about_version_fmt").replace("%@","0.13.37"))}
@@ -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}=Ci(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){e!=="object"&&(Us(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>xn&&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 Ui([...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-d7JtxgDL.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-d7JtxgDL.js");return{projectToZip:s}},__vite__mapDeps([0,1,2]),import.meta.url),t=e(this.project);jn(`${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 Js(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 gn(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 $n(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 nn(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(mi(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(pi(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(tn(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>xn&&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 Ui([...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-UnR2rfE2.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-UnR2rfE2.js");return{projectToZip:s}},__vite__mapDeps([0,1,2]),import.meta.url),t=e(this.project);jn(`${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 Js(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 gn(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 $n(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 nn(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(mi(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(pi(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(tn(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-d7JtxgDL.js b/website/app/assets/projectZip-UnR2rfE2.js similarity index 99% rename from website/app/assets/projectZip-d7JtxgDL.js rename to website/app/assets/projectZip-UnR2rfE2.js index 0891fe72..5d1305ef 100644 --- a/website/app/assets/projectZip-d7JtxgDL.js +++ b/website/app/assets/projectZip-UnR2rfE2.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-fPb85kNH.js";import"./index-CqnqsqSP.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-BAiNGNpM.js";import"./index-CBJVdWXq.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/pt-PT-DYKlzJlW.js b/website/app/assets/pt-PT-ClEeb4rA.js similarity index 99% rename from website/app/assets/pt-PT-DYKlzJlW.js rename to website/app/assets/pt-PT-ClEeb4rA.js index 7726b302..4e93cc33 100644 --- a/website/app/assets/pt-PT-DYKlzJlW.js +++ b/website/app/assets/pt-PT-ClEeb4rA.js @@ -68,6 +68,7 @@ const e=`/* Textos que só existem na versão web. Tudo o resto vem dos Localiza "web_learn_open_exercise" = "Abrir no editor"; "web_learn_solve_in_editor" = "Resolve este exercício na área %@."; "web_learn_solve_in_code" = "Resolve este exercício na área %@."; +"web_learn_solve_in_both" = "Resolve este exercício nas áreas %1$@ e %2$@."; "web_learn_open_in_editor" = "Abrir no editor"; "web_learn_graphic_labels" = "👆 Clica na imagem para mostrar ou esconder as legendas"; "web_learn_check" = "Verificar"; @@ -139,13 +140,13 @@ const e=`/* Textos que só existem na versão web. Tudo o resto vem dos Localiza "web_site_privacy" = "Privacidade"; /* Programmieren (früher „Code live“) */ -"web_live_title" = "Programação"; -"web_live_hide" = "Ocultar programação"; +"web_live_title" = "Código"; +"web_live_hide" = "Ocultar código"; "web_scale_canvas" = "Tamanho do texto: estrutograma"; -"web_scale_code" = "Tamanho do texto: Programação"; +"web_scale_code" = "Tamanho do texto: Código"; "web_live_indent" = "Indentar"; "web_live_indent_title" = "Indentar o código: quatro espaços por nível (linhas selecionadas, senão tudo)"; -"web_live_show" = "Mostrar programação"; +"web_live_show" = "Mostrar código"; "web_live_resize" = "Alterar a largura da área de código (duplo clique: repor)"; "web_live_hint" = "O código cresce com o teu diagrama. Cinzento = marcador: escreve no inspetor de objetos e o teu texto aparece aí. Clica numa linha para selecionar o elemento."; "web_live_ph_selector" = "variável"; @@ -403,7 +404,7 @@ const e=`/* Textos que só existem na versão web. Tudo o resto vem dos Localiza "web_visubot_preview_hide" = "Recolher mBot2 ao vivo"; "web_visubot_preview_show" = "Mostrar mBot2 ao vivo"; "web_visubot_preview_resize" = "Alterar o tamanho de mBot2 ao vivo"; -"web_visubot_preview_stack" = "Por baixo do código em Programação"; +"web_visubot_preview_stack" = "Por baixo do código na área Código"; "web_visubot_preview_side" = "Como coluna própria"; "web_visubot_preview_distance_fmt" = "Percurso: %d cm"; "web_visubot_preview_input" = "precisa de uma entrada, inicia a simulação para isso"; @@ -420,8 +421,8 @@ const e=`/* Textos que só existem na versão web. Tudo o resto vem dos Localiza "web_visubot_group_light" = "Luz e volume"; "web_visubot_group_tilt" = "Inclinação e abanar"; "web_visubot_group_timer" = "Cronómetro e bateria"; -"web_swap_to_code" = "Programação grande, diagrama estreito"; -"web_swap_to_editor" = "Diagrama grande, programação estreita"; +"web_swap_to_code" = "Código grande, diagrama estreito"; +"web_swap_to_editor" = "Diagrama grande, código estreito"; "web_editor_resize" = "Alterar a largura do diagrama"; "web_palette_resize" = "Alterar a largura dos elementos (duplo clique: repor)"; "web_palette_hide" = "Ocultar elementos"; diff --git a/website/app/assets/robot3d-F7Of_tVr.js b/website/app/assets/robot3d-CCjHhNM_.js similarity index 99% rename from website/app/assets/robot3d-F7Of_tVr.js rename to website/app/assets/robot3d-CCjHhNM_.js index f3d45691..96934bdb 100644 --- a/website/app/assets/robot3d-F7Of_tVr.js +++ b/website/app/assets/robot3d-CCjHhNM_.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-CqnqsqSP.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-CBJVdWXq.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 b6347139..9f335028 100644 --- a/website/app/index.html +++ b/website/app/index.html @@ -6,8 +6,8 @@ VisuStruct Web - - + +
From 4890b3ddffce41634564aa674fe72493fadc7f60 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 30 Oct 2026 23:28:49 +0000 Subject: [PATCH 2/3] =?UTF-8?q?Konflikte=20sauber=20aufgel=C3=B6st,=20webs?= =?UTF-8?q?ite/app=20neu=20gebaut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Ugz28WsFncnVqF96ZZJzbu --- CHANGELOG.md | 4 - web/package-lock.json | 8 - web/package.json | 4 - website/app/assets/Java-Bpx1Vwvg.js | 226 + website/app/assets/Localizable-1QZ0wfvJ.js | 240 + website/app/assets/Localizable-BAutdlBb.js | 153 + website/app/assets/Localizable-BJ55WGVD.js | 153 + website/app/assets/Localizable-BM86Igqt.js | 241 + website/app/assets/Localizable-BYJK0mdR.js | 241 + website/app/assets/Localizable-BudCXCER.js | 241 + website/app/assets/Localizable-ByPZS4RL.js | 241 + website/app/assets/Localizable-CHv0OL9S.js | 256 + website/app/assets/Localizable-CaVEL1es.js | 241 + website/app/assets/Localizable-CkJEmEEP.js | 241 + website/app/assets/Localizable-CxCno28C.js | 241 + website/app/assets/Localizable-DBLIUcBd.js | 255 + website/app/assets/Localizable-DSvkBkp-.js | 153 + website/app/assets/Localizable-DXAPah1g.js | 241 + website/app/assets/Localizable-Dk8F86qS.js | 255 + website/app/assets/Localizable-DqIDp_hh.js | 241 + website/app/assets/Localizable-LSTVB2Q5.js | 241 + website/app/assets/Localizable-M33nNbEe.js | 153 + website/app/assets/Localizable-R-16GCrk.js | 241 + website/app/assets/Localizable-UGog_aku.js | 238 + website/app/assets/Localizable-rqA-20hM.js | 238 + website/app/assets/ar-DeE-RHam.js | 180 + .../aufgabe-mehrwertsteuer-C-TFTrWz.svg | 79 + .../aufgabe-mehrwertsteuer-CnrZ00ny.svg | 79 + .../aufgabe-mehrwertsteuer-KUkerRBd.svg | 79 + .../app/assets/ben-shneiderman-Cev5hrqS.jpg | Bin 0 -> 19298 bytes website/app/assets/caesar-ascii-Bix93F5i.svg | 98 + .../app/assets/caesar-scheibe-CMRPZI6Y.svg | 62 + .../assets/caesar-verschiebung-DIR-lDbs.svg | 133 + website/app/assets/da-D4INXE4p.js | 180 + website/app/assets/de-3XOrIl-I.js | 744 + website/app/assets/el-CtIZyj0I.js | 180 + website/app/assets/en-sZM_O17d.js | 744 + website/app/assets/es-BAduFB3L.js | 180 + website/app/assets/flowApp-C_31XWhB.js | 50 + website/app/assets/fr-C_mSEvw5.js | 180 + website/app/assets/he-BAg3LrWK.js | 180 + website/app/assets/ike-nassi-D2w47gvX.jpg | Bin 0 -> 19505 bytes website/app/assets/index-Bmqo_CbG.js | 64473 ++++++++++++++++ website/app/assets/index-DaVEKYYQ.css | 1 + website/app/assets/it-ClGS2uQV.js | 180 + website/app/assets/ja-JQ8MwNFB.js | 180 + website/app/assets/kino-saal-BOvcmdzb.svg | 32 + website/app/assets/kino-saal-C8zaJk4X.svg | 32 + website/app/assets/kino-saal-CYMOok4_.svg | 32 + .../app/assets/kino-schleifen-Ci9yPnbo.svg | 49 + .../app/assets/kino-schleifen-D7sfo9iK.svg | 49 + .../app/assets/kino-schleifen-DrTQV7dq.svg | 49 + website/app/assets/ko-tfdKG8Fb.js | 180 + website/app/assets/l03-lochkarte-BB3rWQOm.svg | 998 + website/app/assets/l03-lochkarte-BSn6oWaS.svg | 994 + .../l03-lochkarte-beschriftet-7hmU_7ct.svg | 1016 + .../l03-lochkarte-beschriftet-BjBFZjzb.svg | 1019 + .../l03-lochkarte-beschriftet-D1QjqGFo.svg | 1015 + website/app/assets/l03-lochkarte-gzfFEatc.svg | 995 + website/app/assets/ludwig-Cus1i402.webp | Bin 0 -> 14066 bytes website/app/assets/mvc-klick-BIA_bYzu.svg | 75 + website/app/assets/mvc-klick-DKonBpbs.svg | 75 + website/app/assets/mvc-klick-KmFKqxH-.svg | 75 + website/app/assets/nb-BpibUAkX.js | 180 + website/app/assets/nl-HArZjiga.js | 180 + website/app/assets/objectApp-Cf8h-zzC.js | 421 + website/app/assets/pl-C3HmQqUD.js | 180 + website/app/assets/projectZip-DZMCzW4J.js | 1 + website/app/assets/pt-PT-De0Ipirm.js | 742 + website/app/assets/robot3d-DZxNwb67.js | 3955 + website/app/assets/ru-B4vTuE57.js | 180 + .../app/assets/schiffe-versenken-CXt1SF0S.svg | 55 + .../app/assets/schiffe-versenken-iEBDHIxD.svg | 55 + .../app/assets/ss-binaere-suche-CPsLGldq.svg | 67 + .../app/assets/ss-binaere-suche-D02W1TH_.svg | 67 + .../app/assets/ss-binaere-suche-DVVS2SNc.svg | 67 + website/app/assets/ss-bubblesort-AFDcFDah.svg | 35 + website/app/assets/ss-bubblesort-CmKEoNfO.svg | 35 + website/app/assets/ss-bubblesort-Dic2ZfaT.svg | 35 + website/app/assets/ss-vergleiche-DRqzU2TZ.svg | 22 + website/app/assets/ss-vergleiche-DWgkIvLr.svg | 22 + website/app/assets/ss-vergleiche-UczNldcC.svg | 22 + website/app/assets/sv-Dau75zUV.js | 180 + website/app/assets/tr-DrZsTe-O.js | 180 + website/app/assets/uk-DQrOpK2W.js | 180 + website/app/assets/visubot-CyGFOI9V.webp | Bin 0 -> 9042 bytes website/app/assets/zh-Hans-CeIYjS3N.js | 180 + website/app/assets/zh-Hant-7-ScZHAu.js | 180 + website/app/assets/zk-zeichen-8efNmpGx.svg | 31 + website/app/assets/zk-zeichen-CgUEhNoK.svg | 29 + website/app/assets/zk-zeichen-vYvc3iJg.svg | 27 + website/app/index.html | 9 +- 92 files changed, 86948 insertions(+), 23 deletions(-) create mode 100644 website/app/assets/Java-Bpx1Vwvg.js create mode 100644 website/app/assets/Localizable-1QZ0wfvJ.js create mode 100644 website/app/assets/Localizable-BAutdlBb.js create mode 100644 website/app/assets/Localizable-BJ55WGVD.js create mode 100644 website/app/assets/Localizable-BM86Igqt.js create mode 100644 website/app/assets/Localizable-BYJK0mdR.js create mode 100644 website/app/assets/Localizable-BudCXCER.js create mode 100644 website/app/assets/Localizable-ByPZS4RL.js create mode 100644 website/app/assets/Localizable-CHv0OL9S.js create mode 100644 website/app/assets/Localizable-CaVEL1es.js create mode 100644 website/app/assets/Localizable-CkJEmEEP.js create mode 100644 website/app/assets/Localizable-CxCno28C.js create mode 100644 website/app/assets/Localizable-DBLIUcBd.js create mode 100644 website/app/assets/Localizable-DSvkBkp-.js create mode 100644 website/app/assets/Localizable-DXAPah1g.js create mode 100644 website/app/assets/Localizable-Dk8F86qS.js create mode 100644 website/app/assets/Localizable-DqIDp_hh.js create mode 100644 website/app/assets/Localizable-LSTVB2Q5.js create mode 100644 website/app/assets/Localizable-M33nNbEe.js create mode 100644 website/app/assets/Localizable-R-16GCrk.js create mode 100644 website/app/assets/Localizable-UGog_aku.js create mode 100644 website/app/assets/Localizable-rqA-20hM.js create mode 100644 website/app/assets/ar-DeE-RHam.js create mode 100644 website/app/assets/aufgabe-mehrwertsteuer-C-TFTrWz.svg create mode 100644 website/app/assets/aufgabe-mehrwertsteuer-CnrZ00ny.svg create mode 100644 website/app/assets/aufgabe-mehrwertsteuer-KUkerRBd.svg create mode 100644 website/app/assets/ben-shneiderman-Cev5hrqS.jpg create mode 100644 website/app/assets/caesar-ascii-Bix93F5i.svg create mode 100644 website/app/assets/caesar-scheibe-CMRPZI6Y.svg create mode 100644 website/app/assets/caesar-verschiebung-DIR-lDbs.svg create mode 100644 website/app/assets/da-D4INXE4p.js create mode 100644 website/app/assets/de-3XOrIl-I.js create mode 100644 website/app/assets/el-CtIZyj0I.js create mode 100644 website/app/assets/en-sZM_O17d.js create mode 100644 website/app/assets/es-BAduFB3L.js create mode 100644 website/app/assets/flowApp-C_31XWhB.js create mode 100644 website/app/assets/fr-C_mSEvw5.js create mode 100644 website/app/assets/he-BAg3LrWK.js create mode 100644 website/app/assets/ike-nassi-D2w47gvX.jpg create mode 100644 website/app/assets/index-Bmqo_CbG.js create mode 100644 website/app/assets/index-DaVEKYYQ.css create mode 100644 website/app/assets/it-ClGS2uQV.js create mode 100644 website/app/assets/ja-JQ8MwNFB.js create mode 100644 website/app/assets/kino-saal-BOvcmdzb.svg create mode 100644 website/app/assets/kino-saal-C8zaJk4X.svg create mode 100644 website/app/assets/kino-saal-CYMOok4_.svg create mode 100644 website/app/assets/kino-schleifen-Ci9yPnbo.svg create mode 100644 website/app/assets/kino-schleifen-D7sfo9iK.svg create mode 100644 website/app/assets/kino-schleifen-DrTQV7dq.svg create mode 100644 website/app/assets/ko-tfdKG8Fb.js create mode 100644 website/app/assets/l03-lochkarte-BB3rWQOm.svg create mode 100644 website/app/assets/l03-lochkarte-BSn6oWaS.svg create mode 100644 website/app/assets/l03-lochkarte-beschriftet-7hmU_7ct.svg create mode 100644 website/app/assets/l03-lochkarte-beschriftet-BjBFZjzb.svg create mode 100644 website/app/assets/l03-lochkarte-beschriftet-D1QjqGFo.svg create mode 100644 website/app/assets/l03-lochkarte-gzfFEatc.svg create mode 100644 website/app/assets/ludwig-Cus1i402.webp create mode 100644 website/app/assets/mvc-klick-BIA_bYzu.svg create mode 100644 website/app/assets/mvc-klick-DKonBpbs.svg create mode 100644 website/app/assets/mvc-klick-KmFKqxH-.svg create mode 100644 website/app/assets/nb-BpibUAkX.js create mode 100644 website/app/assets/nl-HArZjiga.js create mode 100644 website/app/assets/objectApp-Cf8h-zzC.js create mode 100644 website/app/assets/pl-C3HmQqUD.js create mode 100644 website/app/assets/projectZip-DZMCzW4J.js create mode 100644 website/app/assets/pt-PT-De0Ipirm.js create mode 100644 website/app/assets/robot3d-DZxNwb67.js create mode 100644 website/app/assets/ru-B4vTuE57.js create mode 100644 website/app/assets/schiffe-versenken-CXt1SF0S.svg create mode 100644 website/app/assets/schiffe-versenken-iEBDHIxD.svg create mode 100644 website/app/assets/ss-binaere-suche-CPsLGldq.svg create mode 100644 website/app/assets/ss-binaere-suche-D02W1TH_.svg create mode 100644 website/app/assets/ss-binaere-suche-DVVS2SNc.svg create mode 100644 website/app/assets/ss-bubblesort-AFDcFDah.svg create mode 100644 website/app/assets/ss-bubblesort-CmKEoNfO.svg create mode 100644 website/app/assets/ss-bubblesort-Dic2ZfaT.svg create mode 100644 website/app/assets/ss-vergleiche-DRqzU2TZ.svg create mode 100644 website/app/assets/ss-vergleiche-DWgkIvLr.svg create mode 100644 website/app/assets/ss-vergleiche-UczNldcC.svg create mode 100644 website/app/assets/sv-Dau75zUV.js create mode 100644 website/app/assets/tr-DrZsTe-O.js create mode 100644 website/app/assets/uk-DQrOpK2W.js create mode 100644 website/app/assets/visubot-CyGFOI9V.webp create mode 100644 website/app/assets/zh-Hans-CeIYjS3N.js create mode 100644 website/app/assets/zh-Hant-7-ScZHAu.js create mode 100644 website/app/assets/zk-zeichen-8efNmpGx.svg create mode 100644 website/app/assets/zk-zeichen-CgUEhNoK.svg create mode 100644 website/app/assets/zk-zeichen-vYvc3iJg.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index fdb7ecb4..7dfe521e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,12 +16,8 @@ The format is loosely inspired by Keep a Changelog. ### Added - **Web 0.14.1, area „Code“ and area colours:** the area „Programmieren“ is now called „Code“ (en „Code“, pt „Código“) in the app, all lessons, VisuBot lessons, tasks and glossary. Struktogramm and Code each have a colour (blue #007aff, violet #7c3aed): a coloured top edge, the slim strip when collapsed, and the area names on the exercise card („Löse diese Übung im Struktogramm und im Code.“). New exercise key `bereich: struktogramm | code | beide`: the card names the area(s) and „Im Editor öffnen“ opens exactly those (nothing is closed). Lesson 20 „Countdown“ and „Fakultät aus Java“ use `beide` (de/en/pt). -<<<<<<< HEAD -- **Web 0.13.39, area „Code“ and area colours:** the area „Programmieren“ is now called „Code“ (en „Code“, pt „Código“) in the app, all lessons, VisuBot lessons, tasks and glossary. Struktogramm and Code each have a colour (blue #007aff, violet #7c3aed): a coloured top edge, the slim strip when collapsed, and the area names on the exercise card („Löse diese Übung im Struktogramm und im Code.“). New exercise key `bereich: struktogramm | code | beide`: the card names the area(s) and „Im Editor öffnen“ opens exactly those (nothing is closed). Lesson 20 „Countdown“ and „Fakultät aus Java“ use `beide` (de/en/pt). -======= - **Web 0.14.0, new world VisuFlow: draw flowcharts:** fourth world next to VisuStruct, VisuBot and VisuObject (…/app/?visuflow, colour violet, chosen at the start or in the gear menu; the world chooser now has two rows). Only drawing, no simulation and no code: drag the DIN 66001 symbols (Start, Anweisung, Ein-/Ausgabe, Verzweigung, Unterprogramm, Ende) from the bar onto the canvas, or tap a symbol to add it below the selected one, joined by an arrow; type the text right in the symbol (tap again or double click to change it). Drag an arrow from the dot at an exit to the next symbol; the diamond has the exits ja and nein (button „ja/nein tauschen“ swaps their sides), arrows run at right angles, loops go around on the right. Move with the mouse, finger or arrow keys on a 20 px grid, delete, undo/redo, title above the canvas, example „Tee kochen“ from lesson 1. Save and open as `.visuflow` file (the last plan stays in the browser), export as PNG, SVG or PDF (A4). Texts de/en/pt. - **Web 0.13.38, comments in Java:** lesson 6 has a new step „Kommentare im Code“ after „Jetzt in Java“: single-line `//` and multi-line `/* … */` comments, Java skips them and the structure chart stays the same; Javadoc `/** … */` is only mentioned. The IPO example (with „Im Editor öffnen“) shows the task in a multi-line comment, `// Eingabe`, `// Verarbeitung`, `// Ausgabe`, an explanation after a line, the expected output and a note for next time; plus a fill-in-the-gaps exercise, an Angeberwissen (PL/I 1964, BCPL 1967), a competence, a checklist line and two quiz questions. Lesson 14 marks closing brackets with `} // Ende if` / `} // Ende for`, lesson 20 the class frame with `} // Ende main` / `} // Ende Klasse`. New glossary entry Kommentar and Nachschlagen section „Java › Kommentare“ (de/en/pt). ->>>>>>> origin/main - **Web 0.13.36, sequence diagram in lesson 5:** step „Schritt für Schritt“ now shows a sequence as a structure chart: four boxes one below the other (`laenge`, `breite`, `flaeche = laenge * breite`, output 15) with a short caption that each box runs exactly once from top to bottom (de/en/pt). - **Web 0.13.35, open Java examples in the editor:** a Java example in a lesson can now carry the button „Im Editor öffnen“. It opens the example in a new tab with Programmieren set to Java, so students can run it, change values and try again; the structure chart builds itself from the code. Lesson 4 step „Text in Java“ (Mia, 14, 1.62) uses it and says how to try it (de/en/pt). For authors: write ```` ```java editor ```` instead of ```` ```java ````; a test checks that every such example parses without errors. - **Web 0.13.32, every exercise says where to solve it:** below the title of each exercise card a small label names the area: „Löse diese Übung im Struktogramm.“ or, for `code: java` exercises, „Löse diese Übung in Programmieren.“ The area names are taken from the on-screen headings, so they always match (de/en/pt; applies to all VisuStruct, VisuBot and task-area exercises). diff --git a/web/package-lock.json b/web/package-lock.json index dcf007e7..685fae41 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,20 +1,12 @@ { "name": "visustruct-web", -<<<<<<< HEAD - "version": "0.13.39", -======= "version": "0.14.1", ->>>>>>> origin/main "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "visustruct-web", -<<<<<<< HEAD - "version": "0.13.39", -======= "version": "0.14.1", ->>>>>>> origin/main "dependencies": { "@codemirror/autocomplete": "^6.20.4", "@codemirror/commands": "^6.11.1", diff --git a/web/package.json b/web/package.json index 664d370f..65abe83f 100644 --- a/web/package.json +++ b/web/package.json @@ -1,11 +1,7 @@ { "name": "visustruct-web", "private": true, -<<<<<<< HEAD - "version": "0.13.39", -======= "version": "0.14.1", ->>>>>>> origin/main "type": "module", "scripts": { "dev": "vite", diff --git a/website/app/assets/Java-Bpx1Vwvg.js b/website/app/assets/Java-Bpx1Vwvg.js new file mode 100644 index 00000000..587f4c9b --- /dev/null +++ b/website/app/assets/Java-Bpx1Vwvg.js @@ -0,0 +1,226 @@ +const e=`/* VisuStruct Java-Desktop-Preset (kein .lproj — gültig für App Store; Tabelle „Java“). */ + +/* Palette — short labels like Java */ +"palette_header" = "Blocks"; + +/* Actions */ +"action_share_png" = "Share Graphic…"; +"action_share_document" = "Share File…"; +"action_export_pdf" = "Preview PDF…"; +"action_generate_code" = "Generate Code…"; +"action_simulation" = "Simulation"; +"action_diagram" = "Diagram"; +"simulation_placeholder_body" = "The simulation mode will run the diagram step by step, highlight the current element, and show variable values and output."; +"simulation_controls" = "Controls"; +"simulation_highlight_label" = "Highlight"; +"simulation_highlight_last" = "Last step"; +"simulation_highlight_next" = "Next step"; +"simulation_not_available" = "Play runs the simulation automatically with a 0.5 second pause per step."; +"simulation_play" = "Play"; +"simulation_pause" = "Pause"; +"simulation_step" = "Step"; +"simulation_stop" = "Stop"; +"simulation_input" = "Input"; +"simulation_input_placeholder" = "No input required."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Please enter a whole number."; +"simulation_trace" = "Last Step"; +"simulation_trace_placeholder" = "The last executed step will be explained here."; +"simulation_variables" = "Variables"; +"simulation_variables_placeholder" = "Current variable values will be shown here later."; +"simulation_output" = "Output"; +"simulation_output_placeholder" = "The simulation output will appear here later."; +"action_delete_selection" = "Delete Selection"; +"ctx_copy" = "Copy"; +"ctx_cut" = "Cut"; +"ctx_paste" = "Paste"; +"action_settings" = "Settings"; +"action_about" = "About VisuStruct"; +"recent_files_menu" = "Recent Files"; +"recent_files_empty" = "No recent files"; +"recent_files_clear" = "Clear List"; +"recent_files_unavailable" = "File is no longer available."; + +/* In-app settings */ +"settings_language_title" = "Language"; +"settings_language_de" = "German"; +"settings_language_en" = "English"; +"settings_language_es" = "Spanish"; +"settings_language_fr" = "French"; +"settings_language_it" = "Italian"; +"settings_language_pl" = "Polish"; +"settings_language_tr" = "Turkish"; +"settings_language_ko" = "Korean"; +"settings_language_ja" = "Japanese"; +"settings_language_el" = "Greek"; +"settings_language_uk" = "Ukrainian"; +"settings_language_ar" = "Arabic"; +"settings_language_ru" = "Russian"; +"settings_language_he" = "Hebrew"; +"settings_language_zh_hans" = "Chinese (Simplified)"; +"settings_language_zh_hant" = "Chinese (Traditional)"; +"settings_language_ptpt" = "Portuguese"; +"settings_language_java" = "Java (keywords)"; + + + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "File name suggestion"; +"settings_export_filename_picker" = "Format"; +"settings_export_filename_date_title" = "With date"; +"settings_export_filename_title_only" = "Without date"; +"settings_export_filename_footer_with_date" = "With date: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Without date: Filename.visustruct"; + + +/* Error overlay */ +"error_title" = "Error"; +"error_back_editor" = "Back to Editor"; + +/* Toolbar */ +"toolbar_undo" = "Undo"; +"toolbar_redo" = "Redo"; +"toolbar_new" = "New"; +"menu_open" = "Open…"; +"menu_save" = "Save"; +"menu_save_as" = "Save As…"; +"menu_print" = "Print…"; +"menu_file" = "File"; +"menu_new" = "New"; +"menu_close" = "Close"; + +/* Accessibility */ +"a11y_generate_code" = "Generate code from the structure chart"; +"a11y_generate_code_locked" = "Generate code, available after purchase"; +"a11y_unsaved_changes" = "Unsaved changes"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Generate code"; +"codegen_gate_body" = "Java, Python, and JavaScript code from your diagram will unlock via in-app purchase (coming soon)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Code generator"; +"codegen_placeholder_body" = "Generated code will appear here."; +"codegen_placeholder_compare" = "Switch between Java, Python, and JavaScript to compare syntax (sample below)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (condition) {\\n statement();\\n} else {\\n alternative();\\n}"; +"codegen_preview_python" = "if condition:\\n statement()\\nelse:\\n alternative()"; +"codegen_generated_hint" = "Preview from the current structure chart (Java 17, Python 3.10+, modern JavaScript)."; +"codegen_copy" = "Copy"; +"codegen_run_in_browser" = "Test in browser"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "New diagram tab"; +"a11y_close_tab" = "Close tab"; + +"close_unsaved_title" = "Unsaved Changes"; +"close_unsaved_message" = "This diagram contains unsaved changes. Do you want to save them before closing?"; +"close_unsaved_discard" = "Discard"; +"close_unsaved_cancel" = "Cancel"; +"a11y_placeholder_drop" = "Drop an element here to replace the placeholder. Press and hold to drag and move."; +"a11y_node_drop" = "Press and hold a block, then drag: drop on the top or bottom edge of a target to insert before or after. Center drop only on a ø placeholder."; +"a11y_codegen_panel_drag" = "Drag to move code generator panel"; + +/* Diagram */ +"diagram_title_label" = "Title"; +"diagram_title_placeholder" = "No title"; + +/* Inspector */ +"inspector_no_selection" = "No element selected — tap a tile."; +"inspector_apply_text" = "Apply Text"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; +"inspector_io_mode_title" = "Kind"; +"inspector_io_mode_statement" = "Statement"; +"inspector_io_mode_input" = "Input"; +"inspector_io_mode_output" = "Output"; +"inspector_io_mode_help_java_like" = "Input: input: … | Output: output: …"; +"inspector_add_case" = "Add Case"; +"inspector_remove_case" = "Remove Case"; +"inspector_group_element" = "Element text"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Insert condition…"; +"inspector_placeholder_selector" = "Insert selector…"; +"inspector_placeholder_call" = "Insert call…"; +"inspector_placeholder_break" = "Comment (optional)"; + +/* Element types — JAVA_STANDARD_PALETTE_LABELS (palette + inspector title) */ +"element_anweisung" = "Statement"; +"element_verzweigung" = "if"; +"element_fallauswahl" = "switch"; +"element_forSchleife" = "for"; +"element_whileSchleife" = "while"; +"element_doUntilSchleife" = "do"; +"element_endlosschleife" = "while(true)"; +"element_aussprung" = "break"; +"element_aufruf" = "call"; +"element_leerElement" = "ø"; + +/* Tabs */ +"tab_title_format" = "Diagram %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Empty structure chart"; +"canvas_empty_hint" = "Drag a block from “Blocks” here."; + +/* New block stubs — PRESETS[PRESET_ENGLISH_JAVA] */ +"canvas_stub_anweisung" = "Statement"; +"canvas_stub_condition" = "condition"; +"canvas_stub_fallauswahl" = "selector"; +"canvas_stub_for" = "i = 0; i < n; i++"; +"canvas_stub_while" = "condition"; +"canvas_stub_until" = "condition"; +"canvas_stub_endless" = "∞"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "method()"; + +/* About */ +"about_version_fmt" = "Version %@ (%@)"; +"about_nav_title" = "About VisuStruct"; +"about_features_heading" = "Features"; +"about_bullet_palette" = "Insert blocks from the palette or drag them into the diagram"; +"about_bullet_edit" = "Edit the chart: change text, select elements, and remove them if needed"; +"about_bullet_tabs" = "Several diagrams in tabs — each with its own title"; +"about_bullet_file" = "Save and reopen diagrams as .visustruct files"; +"about_bullet_share" = "Share the structure chart as an image (PNG)"; +"about_dateiformat_heading" = "File format"; +"about_dateiformat_part1" = "VisuStruct’s native format uses the extension "; +"about_dateiformat_part2" = ". You can keep diagrams and exchange them with other apps that support the same format."; +"about_dateiformat_strk" = "Files with the .strk extension can also be opened."; +"about_project_github_label" = "Java app (source & releases):"; +"about_web_label" = "Web:"; +"about_developer_label" = "Developer:"; +"about_lineage_heading" = "Lineage"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "Done"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Cancel insert"; +"phone_show_text_editor" = "Edit text"; + +/* Alerts */ +"err_save_failed_fmt" = "Could not save: %@"; +"err_share_prepare_failed_fmt" = "Could not prepare sharing: %@"; +"err_diagram_too_small_export" = "The diagram is too small — nothing to export."; +"err_image_render_failed" = "Could not create the image."; +"err_diagram_too_small_print" = "The diagram is too small — nothing to print."; +"err_print_unavailable" = "Printing is not available on this device."; + +"inspector_header" = "Object Inspector"; +`;export{e as default}; diff --git a/website/app/assets/Localizable-1QZ0wfvJ.js b/website/app/assets/Localizable-1QZ0wfvJ.js new file mode 100644 index 00000000..5db9238a --- /dev/null +++ b/website/app/assets/Localizable-1QZ0wfvJ.js @@ -0,0 +1,240 @@ +const e=`/* Palette */ +"palette_header" = "Элементы"; +"inspector_header" = "Инспектор объектов"; + +/* Actions */ +"action_share_png" = "Поделиться изображением…"; +"action_share_document" = "Поделиться файлом…"; +"action_export_pdf" = "Предпросмотр PDF…"; +"action_generate_code" = "Сгенерировать код…"; +"action_simulation" = "Симуляция"; +"action_diagram" = "Диаграмма"; +"simulation_placeholder_body" = "Режим симуляции выполняет диаграмму шаг за шагом, подсвечивает текущий элемент и показывает значения переменных и вывод."; +"simulation_controls" = "Управление"; +"simulation_highlight_label" = "Подсветка"; +"simulation_highlight_last" = "Последний шаг"; +"simulation_highlight_next" = "Следующий шаг"; +"simulation_not_available" = "Play автоматически выполняет симуляцию с паузой 0,5 секунды на шаг."; +"simulation_play" = "Пуск"; +"simulation_pause" = "Пауза"; +"simulation_step" = "Шаг"; +"simulation_stop" = "Стоп"; +"simulation_input" = "Ввод"; +"simulation_input_placeholder" = "Ввод не требуется."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Введите целое число."; +"simulation_trace" = "Последний шаг"; +"simulation_trace_placeholder" = "Ещё не выполнено ни одного шага."; +"simulation_variables" = "Переменные"; +"simulation_variables_placeholder" = "Переменных пока нет."; +"simulation_output" = "Вывод"; +"simulation_output_placeholder" = "Вывода пока нет."; +"action_delete_selection" = "Удалить выделение"; +"ctx_copy" = "Копировать"; +"ctx_cut" = "Вырезать"; +"ctx_paste" = "Вставить"; +"action_settings" = "Настройки"; +"action_about" = "О VisuStruct"; +"recent_files_menu" = "Недавние файлы"; +"recent_files_empty" = "Нет недавних файлов"; +"recent_files_clear" = "Очистить список"; +"recent_files_unavailable" = "Файл больше недоступен."; + +/* In-app settings */ +"settings_language_title" = "Язык"; +"settings_language_de" = "Немецкий"; +"settings_language_en" = "Английский"; +"settings_language_es" = "Испанский"; +"settings_language_fr" = "Французский"; +"settings_language_it" = "Итальянский"; +"settings_language_pl" = "Польский"; +"settings_language_tr" = "Турецкий"; +"settings_language_ko" = "Корейский"; +"settings_language_ja" = "Японский"; +"settings_language_el" = "Греческий"; +"settings_language_uk" = "Украинский"; +"settings_language_ar" = "Арабский"; +"settings_language_ru" = "Русский"; +"settings_language_zh_hans" = "Китайский (упрощённый)"; +"settings_language_zh_hant" = "Китайский (традиционный)"; +"settings_language_ptpt" = "Португальский"; +"settings_language_java" = "Java (ключевые слова)"; + + +/* Error overlay */ +"error_title" = "Ошибка"; +"error_back_editor" = "Назад в редактор"; + +/* Toolbar */ +"toolbar_undo" = "Отменить"; +"toolbar_redo" = "Повторить"; +"toolbar_new" = "Новый"; +"menu_open" = "Открыть…"; +"menu_save" = "Сохранить"; +"menu_save_as" = "Сохранить как…"; +"menu_print" = "Печать…"; +"menu_file" = "Файл"; +"menu_new" = "Создать"; +"menu_close" = "Закрыть"; + +/* Accessibility */ +"a11y_generate_code" = "Сгенерировать код по схеме"; +"a11y_generate_code_locked" = "Сгенерировать код (после покупки)"; +"a11y_unsaved_changes" = "Несохранённые изменения"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Сгенерировать код"; +"codegen_gate_body" = "Код Java, Python и JavaScript по вашей схеме будет разблокирован через покупку в приложении (скоро)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Генератор кода"; +"codegen_placeholder_body" = "Сгенерированный код появится здесь."; +"codegen_placeholder_compare" = "Переключайтесь между Java, Python и JavaScript, чтобы сравнить синтаксис (пример ниже)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (условие) {\\n statement();\\n} else {\\n alternative();\\n}"; +"codegen_preview_python" = "if условие:\\n statement()\\nelse:\\n alternative()"; +"codegen_copy" = "Копировать"; +"codegen_run_in_browser" = "Проверить в браузере"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "Новая вкладка схемы"; +"a11y_close_tab" = "Закрыть вкладку"; + +"close_unsaved_title" = "Несохранённые изменения"; +"close_unsaved_message" = "В этой диаграмме есть несохранённые изменения. Сохранить их перед закрытием?"; +"close_unsaved_discard" = "Отбросить"; +"close_unsaved_cancel" = "Отмена"; +"a11y_placeholder_drop" = "Перетащите элемент сюда, чтобы заменить заполнитель. Нажмите и удерживайте, чтобы перемещать."; +"a11y_node_drop" = "Нажмите и удерживайте блок, затем перетащите: отпустите на верхнем или нижнем крае цели, чтобы вставить до или после. Сброс в центр — только на заполнителе ø."; +"a11y_codegen_panel_drag" = "Перетащите панель генератора кода"; + +/* Diagram */ +"diagram_title_label" = "Название"; +"diagram_title_placeholder" = "Без названия"; + +/* Inspector */ +"inspector_no_selection" = "Элемент не выбран — нажмите на плитку."; +"inspector_apply_text" = "Применить текст"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Вид"; +"inspector_io_mode_statement" = "Инструкция"; +"inspector_io_mode_input" = "Ввод"; +"inspector_io_mode_output" = "Вывод"; +"inspector_io_mode_help_java_like" = "Ввод: input: … | Вывод: output: …"; +"inspector_add_case" = "Добавить вариант"; +"inspector_remove_case" = "Удалить вариант"; +"inspector_group_element" = "Текст элемента"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Вставить условие…"; +"inspector_placeholder_selector" = "Вставить селектор…"; +"inspector_placeholder_call" = "Вставить вызов…"; +"inspector_placeholder_break" = "Комментарий (необязательно)"; + +/* Element types (Russian + keyword hint) */ +"element_anweisung" = "Оператор (statement)"; +"element_verzweigung" = "Условие (if/else)"; +"element_fallauswahl" = "Выбор (switch)"; +"element_forSchleife" = "Цикл (for)"; +"element_whileSchleife" = "Цикл (while)"; +"element_doUntilSchleife" = "Цикл (do-while)"; +"element_endlosschleife" = "Бесконечный цикл (while true)"; +"element_aussprung" = "Выход (break)"; +"element_aufruf" = "Вызов (call)"; +"element_leerElement" = "Пустой элемент"; + +/* Tabs */ +"tab_title_format" = "Схема %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Пустая структурная схема"; +"canvas_empty_hint" = "Перетащите элемент из «Элементы» сюда."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "Выбор (switch)"; +"canvas_stub_anweisung" = "Оператор (statement)"; +"canvas_stub_condition" = "Условие"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "бесконечно"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Вызов()"; + +/* About */ +"about_version_fmt" = "Версия %@ (%@)"; +"about_nav_title" = "О VisuStruct"; +"about_features_heading" = "Возможности"; +"about_bullet_palette" = "Вставляйте блоки из палитры или перетаскивайте их в схему"; +"about_bullet_edit" = "Редактируйте схему: меняйте текст, выбирайте элементы и удаляйте при необходимости"; +"about_bullet_tabs" = "Несколько схем во вкладках — каждая со своим названием"; +"about_bullet_file" = "Сохраняйте и открывайте схемы как файлы .visustruct"; +"about_bullet_share" = "Делитесь схемой как изображением (PNG)"; +"about_dateiformat_heading" = "Формат файла"; +"about_dateiformat_part1" = "Родной формат VisuStruct использует расширение "; +"about_dateiformat_part2" = ". Вы можете сохранять схемы и обмениваться ими с другими приложениями, поддерживающими этот формат."; +"about_dateiformat_strk" = "Файлы с расширением .strk также можно открывать."; +"about_project_github_label" = "Java‑приложение (исходники и релизы):"; +"about_web_label" = "Веб:"; +"about_developer_label" = "Разработчик:"; +"about_lineage_heading" = "Происхождение"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "Готово"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Отменить вставку"; +"phone_show_text_editor" = "Редактировать текст"; +"phone_hide_text_editor" = "Свернуть"; +"phone_title_done" = "Готово"; + +/* Alerts */ +"err_save_failed_fmt" = "Не удалось сохранить: %@"; +"err_share_prepare_failed_fmt" = "Не удалось подготовить общий доступ: %@"; +"err_diagram_too_small_export" = "Схема слишком мала — нечего экспортировать."; +"err_image_render_failed" = "Не удалось создать изображение."; +"err_diagram_too_small_print" = "Схема слишком мала — нечего печатать."; +"err_print_unavailable" = "Печать недоступна на этом устройстве."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Имя файла (предложение)"; +"settings_export_filename_picker" = "Формат"; +"settings_export_filename_date_title" = "С датой"; +"settings_export_filename_title_only" = "Без даты"; +"settings_export_filename_footer_with_date" = "С датой: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Без даты: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Симуляция завершена."; +"sim_notice_infinite_loop_empty" = "У бесконечного цикла нет тела."; +"sim_notice_unsupported_statement_fmt" = "Неподдерживаемая инструкция: %@"; +"sim_notice_invalid_expression_fmt" = "Недопустимое выражение: %@"; +"sim_notice_unknown_variable_fmt" = "Неизвестная переменная: %@"; +"sim_notice_division_by_zero" = "Деление на ноль."; +"sim_notice_whole_number_expected" = "Введите целое число."; +"sim_notice_number_expected" = "Введите число."; +"sim_notice_boolean_expected" = "Введите true или false."; +"sim_notice_subprogram_not_found_fmt" = "Нет открытой диаграммы с именем %@. Вызов пропущен."; +"sim_notice_call_too_deep" = "Слишком много вложенных вызовов. Подпрограмма вызывает сама себя?"; + +"codegen_pseudocode_toggle" = "Псевдокод (не исполняемый код)"; +"codegen_pseudocode_note" = "Псевдокод – не исполняемая программа"; +"codegen_pseudocode_hint" = "Эта диаграмма отмечена как псевдокод. Код — лишь набросок, его нельзя запустить."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-BAutdlBb.js b/website/app/assets/Localizable-BAutdlBb.js new file mode 100644 index 00000000..ab6b7d13 --- /dev/null +++ b/website/app/assets/Localizable-BAutdlBb.js @@ -0,0 +1,153 @@ +const e=`/* NOTE: Initial Danish localization. */ +"palette_header" = "Elementer"; +"inspector_header" = "Objektinspektør"; + +/* Actions */ +"action_share_png" = "Del billede…"; +"action_share_document" = "Del fil…"; +"action_export_pdf" = "Vis PDF…"; +"action_generate_code" = "Generér kode…"; +"action_simulation" = "Simulering"; +"action_diagram" = "Diagram"; +"simulation_placeholder_body" = "Simuleringstilstanden kører diagrammet trin for trin, fremhæver det aktuelle element og viser variabelværdier og output."; +"simulation_controls" = "Kontroller"; +"simulation_highlight_label" = "Fremhævning"; +"simulation_highlight_last" = "Sidste trin"; +"simulation_highlight_next" = "Næste trin"; +"simulation_not_available" = "Play kører simuleringen automatisk med en pause på 0,5 sekund pr. trin."; +"simulation_play" = "Afspil"; +"simulation_pause" = "Pause"; +"simulation_step" = "Trin"; +"simulation_stop" = "Stop"; +"simulation_input" = "Input"; +"simulation_input_placeholder" = "Ingen input påkrævet."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Indtast et heltal."; +"simulation_trace" = "Sidste trin"; +"simulation_trace_placeholder" = "Intet trin udført endnu."; +"simulation_variables" = "Variabler"; +"simulation_variables_placeholder" = "Ingen variabler endnu."; +"simulation_output" = "Output"; +"simulation_output_placeholder" = "Intet output endnu."; +"action_delete_selection" = "Slet markering"; +"ctx_copy" = "Kopiér"; +"ctx_cut" = "Klip"; +"ctx_paste" = "Indsæt"; +"action_settings" = "Indstillinger"; +"action_about" = "Om VisuStruct"; +"recent_files_menu" = "Seneste filer"; +"recent_files_empty" = "Ingen seneste filer"; +"recent_files_clear" = "Ryd liste"; +"recent_files_unavailable" = "Filen er ikke længere tilgængelig."; + +/* In-app settings */ +"settings_language_title" = "Sprog"; + +/* Toolbar */ +"toolbar_undo" = "Fortryd"; +"toolbar_redo" = "Annuller fortryd"; +"toolbar_new" = "Ny"; +"menu_open" = "Åbn…"; +"menu_save" = "Gem"; +"menu_save_as" = "Gem som…"; +"menu_print" = "Udskriv…"; +"menu_file" = "Arkiv"; +"menu_new" = "Ny"; +"menu_close" = "Luk"; + +/* Inspector */ +"inspector_no_selection" = "Intet valgt — tryk på en flise."; +"inspector_apply_text" = "Anvend tekst"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Type"; +"inspector_io_mode_statement" = "Sætning"; +"inspector_io_mode_input" = "Input"; +"inspector_io_mode_output" = "Output"; +"inspector_io_mode_help_java_like" = "Input: input: … | Output: output: …"; +"inspector_add_case" = "Tilføj case"; +"inspector_remove_case" = "Fjern case"; +"inspector_group_element" = "Elementtekst"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Indtast condition…"; +"inspector_placeholder_selector" = "Indtast selector…"; +"inspector_placeholder_call" = "Indtast call…"; +"inspector_placeholder_break" = "Kommentar (valgfrit)"; + +/* Element types */ +"element_anweisung" = "Sætning"; +"element_verzweigung" = "Betingelse (if/else)"; +"element_fallauswahl" = "Valg (switch)"; +"element_forSchleife" = "For-løkke"; +"element_whileSchleife" = "While-løkke"; +"element_doUntilSchleife" = "Do-while-løkke"; +"element_endlosschleife" = "Uendelig løkke"; +"element_aussprung" = "Break"; +"element_aufruf" = "Kald"; +"element_leerElement" = "Tomt element"; + +/* Diagram */ +"diagram_title_label" = "Titel"; +"diagram_title_placeholder" = "Ingen titel"; +"canvas_empty_title" = "Tomt struktogram"; +"canvas_empty_hint" = "Træk et element fra “Elementer” hertil."; + +/* Diagram stubs */ +"canvas_stub_anweisung" = "statement"; +"canvas_stub_condition" = "condition"; +"canvas_stub_fallauswahl" = "switch"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "endless"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Kald()"; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Forslag til filnavn"; +"settings_export_filename_picker" = "Format"; +"settings_export_filename_date_title" = "Med dato"; +"settings_export_filename_title_only" = "Uden dato"; +"settings_export_filename_footer_with_date" = "Med dato: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Uden dato: Filename.visustruct"; + +"close_unsaved_title" = "Ikke-gemte ændringer"; +"close_unsaved_message" = "Dette diagram indeholder ikke-gemte ændringer. Vil du gemme dem før lukning?"; +"close_unsaved_discard" = "Kassér"; +"close_unsaved_cancel" = "Annuller"; + +/* Accessibility — code generator floating panel */ +"a11y_codegen_panel_drag" = "Træk for at flytte kodegeneratorpanelet"; +"about_dateiformat_strk" = "Filer med endelsen .strk kan også åbnes."; + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simuleringen er færdig."; +"sim_notice_infinite_loop_empty" = "Den uendelige løkke har intet indhold."; +"sim_notice_unsupported_statement_fmt" = "Sætning understøttes ikke: %@"; +"sim_notice_invalid_expression_fmt" = "Ugyldigt udtryk: %@"; +"sim_notice_unknown_variable_fmt" = "Ukendt variabel: %@"; +"sim_notice_division_by_zero" = "Division med nul."; +"sim_notice_whole_number_expected" = "Indtast et heltal."; +"sim_notice_number_expected" = "Indtast et tal."; +"sim_notice_boolean_expected" = "Indtast true eller false."; +"sim_notice_subprogram_not_found_fmt" = "Intet åbent diagram hedder %@. Kaldet blev sprunget over."; +"sim_notice_call_too_deep" = "For mange indlejrede kald. Kalder et underprogram sig selv?"; +"phone_hide_text_editor" = "Skjul"; +"phone_title_done" = "Færdig"; + +"codegen_pseudocode_toggle" = "Pseudokode (ikke kørbar kode)"; +"codegen_pseudocode_note" = "Pseudokode – ikke et kørbart program"; +"codegen_pseudocode_hint" = "Dette diagram er markeret som pseudokode. Koden er kun en skitse og kan ikke køres."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-BJ55WGVD.js b/website/app/assets/Localizable-BJ55WGVD.js new file mode 100644 index 00000000..2d294726 --- /dev/null +++ b/website/app/assets/Localizable-BJ55WGVD.js @@ -0,0 +1,153 @@ +const e=`/* NOTE: Initial Dutch localization. */ +"palette_header" = "Elementen"; +"inspector_header" = "Objectinspector"; + +/* Actions */ +"action_share_png" = "Deel afbeelding…"; +"action_share_document" = "Deel bestand…"; +"action_export_pdf" = "PDF-voorbeeld…"; +"action_generate_code" = "Genereer code…"; +"action_simulation" = "Simulatie"; +"action_diagram" = "Diagram"; +"simulation_placeholder_body" = "De simulatiemodus voert het diagram stap voor stap uit, markeert het huidige element en toont variabele waarden en uitvoer."; +"simulation_controls" = "Besturing"; +"simulation_highlight_label" = "Highlight"; +"simulation_highlight_last" = "Last step"; +"simulation_highlight_next" = "Next step"; +"simulation_not_available" = "Play voert de simulatie automatisch uit met een pauze van 0,5 seconde per stap."; +"simulation_play" = "Afspelen"; +"simulation_pause" = "Pauze"; +"simulation_step" = "Stap"; +"simulation_stop" = "Stop"; +"simulation_input" = "Invoer"; +"simulation_input_placeholder" = "Geen invoer vereist."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Voer een geheel getal in."; +"simulation_trace" = "Laatste stap"; +"simulation_trace_placeholder" = "Nog geen stap uitgevoerd."; +"simulation_variables" = "Variabelen"; +"simulation_variables_placeholder" = "Nog geen variabelen."; +"simulation_output" = "Uitvoer"; +"simulation_output_placeholder" = "Nog geen uitvoer."; +"action_delete_selection" = "Selectie verwijderen"; +"ctx_copy" = "Kopiëren"; +"ctx_cut" = "Knippen"; +"ctx_paste" = "Plakken"; +"action_settings" = "Instellingen"; +"action_about" = "Over VisuStruct"; +"recent_files_menu" = "Recente bestanden"; +"recent_files_empty" = "Geen recente bestanden"; +"recent_files_clear" = "Lijst wissen"; +"recent_files_unavailable" = "Bestand is niet meer beschikbaar."; + +/* In-app settings */ +"settings_language_title" = "Taal"; + +/* Toolbar */ +"toolbar_undo" = "Ongedaan maken"; +"toolbar_redo" = "Opnieuw"; +"toolbar_new" = "Nieuw"; +"menu_open" = "Open…"; +"menu_save" = "Bewaar"; +"menu_save_as" = "Bewaar als…"; +"menu_print" = "Print…"; +"menu_file" = "Bestand"; +"menu_new" = "Nieuw"; +"menu_close" = "Sluit"; + +/* Inspector */ +"inspector_no_selection" = "Geen element geselecteerd — tik op een tegel."; +"inspector_apply_text" = "Tekst toepassen"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Soort"; +"inspector_io_mode_statement" = "Opdracht"; +"inspector_io_mode_input" = "Invoer"; +"inspector_io_mode_output" = "Uitvoer"; +"inspector_io_mode_help_java_like" = "Invoer: input: … | Uitvoer: output: …"; +"inspector_add_case" = "Case toevoegen"; +"inspector_remove_case" = "Case verwijderen"; +"inspector_group_element" = "Elementtekst"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Voer condition in…"; +"inspector_placeholder_selector" = "Voer selector in…"; +"inspector_placeholder_call" = "Voer call in…"; +"inspector_placeholder_break" = "Opmerking (optioneel)"; + +/* Element types */ +"element_anweisung" = "Instructie"; +"element_verzweigung" = "Voorwaarde (if/else)"; +"element_fallauswahl" = "Keuze (switch)"; +"element_forSchleife" = "For-lus"; +"element_whileSchleife" = "While-lus"; +"element_doUntilSchleife" = "Do-while-lus"; +"element_endlosschleife" = "Oneindige lus"; +"element_aussprung" = "Break"; +"element_aufruf" = "Aanroep"; +"element_leerElement" = "Leeg element"; + +/* Diagram */ +"diagram_title_label" = "Titel"; +"diagram_title_placeholder" = "Geen titel"; +"canvas_empty_title" = "Leeg structogram"; +"canvas_empty_hint" = "Sleep een element uit “Elementen” hierheen."; + +/* Diagram stubs */ +"canvas_stub_anweisung" = "statement"; +"canvas_stub_condition" = "condition"; +"canvas_stub_fallauswahl" = "switch"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "endless"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Aanroep()"; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Bestandsnaamsuggestie"; +"settings_export_filename_picker" = "Indeling"; +"settings_export_filename_date_title" = "Met datum"; +"settings_export_filename_title_only" = "Zonder datum"; +"settings_export_filename_footer_with_date" = "Met datum: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Zonder datum: Filename.visustruct"; + +"close_unsaved_title" = "Niet-opgeslagen wijzigingen"; +"close_unsaved_message" = "Dit diagram bevat niet-opgeslagen wijzigingen. Wil je ze opslaan voordat je sluit?"; +"close_unsaved_discard" = "Verwerpen"; +"close_unsaved_cancel" = "Annuleren"; + +/* Accessibility — code generator floating panel */ +"a11y_codegen_panel_drag" = "Sleep om het codegeneratorpaneel te verplaatsen"; +"about_dateiformat_strk" = "Bestanden met de extensie .strk kunnen ook worden geopend."; + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simulatie voltooid."; +"sim_notice_infinite_loop_empty" = "De oneindige lus heeft geen inhoud."; +"sim_notice_unsupported_statement_fmt" = "Niet-ondersteunde opdracht: %@"; +"sim_notice_invalid_expression_fmt" = "Ongeldige expressie: %@"; +"sim_notice_unknown_variable_fmt" = "Onbekende variabele: %@"; +"sim_notice_division_by_zero" = "Deling door nul."; +"sim_notice_whole_number_expected" = "Voer een geheel getal in."; +"sim_notice_number_expected" = "Voer een getal in."; +"sim_notice_boolean_expected" = "Voer true of false in."; +"sim_notice_subprogram_not_found_fmt" = "Er is geen open diagram met de naam %@. De aanroep is overgeslagen."; +"sim_notice_call_too_deep" = "Te veel geneste aanroepen. Roept een subprogramma zichzelf aan?"; +"phone_hide_text_editor" = "Inklappen"; +"phone_title_done" = "Gereed"; + +"codegen_pseudocode_toggle" = "Pseudocode (geen uitvoerbare code)"; +"codegen_pseudocode_note" = "Pseudocode – geen uitvoerbaar programma"; +"codegen_pseudocode_hint" = "Dit diagram is gemarkeerd als pseudocode. De code is alleen een schets en kan niet worden uitgevoerd."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-BM86Igqt.js b/website/app/assets/Localizable-BM86Igqt.js new file mode 100644 index 00000000..e5a53b6f --- /dev/null +++ b/website/app/assets/Localizable-BM86Igqt.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "Öğeler"; +"inspector_header" = "Nesne denetçisi"; + +/* Actions */ +"action_share_png" = "Görseli paylaş…"; +"action_share_document" = "Dosyayı paylaş…"; +"action_export_pdf" = "PDF önizleme…"; +"action_generate_code" = "Kod üret…"; +"action_simulation" = "Simülasyon"; +"action_diagram" = "Diyagram"; +"simulation_placeholder_body" = "Simülasyon modu diyagramı adım adım çalıştırır, geçerli öğeyi vurgular ve değişken değerlerini ve çıktıyı gösterir."; +"simulation_controls" = "Kontroller"; +"simulation_highlight_label" = "Vurgu"; +"simulation_highlight_last" = "Son adım"; +"simulation_highlight_next" = "Sonraki adım"; +"simulation_not_available" = "Play simülasyonu adım başına 0,5 saniye duraklamayla otomatik çalıştırır."; +"simulation_play" = "Oynat"; +"simulation_pause" = "Duraklat"; +"simulation_step" = "Adım"; +"simulation_stop" = "Durdur"; +"simulation_input" = "Girdi"; +"simulation_input_placeholder" = "Girdi gerekli değil."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Lütfen bir tam sayı girin."; +"simulation_trace" = "Son Adım"; +"simulation_trace_placeholder" = "Henüz adım çalıştırılmadı."; +"simulation_variables" = "Değişkenler"; +"simulation_variables_placeholder" = "Henüz değişken yok."; +"simulation_output" = "Çıktı"; +"simulation_output_placeholder" = "Henüz çıktı yok."; +"action_delete_selection" = "Seçimi sil"; +"ctx_copy" = "Kopyala"; +"ctx_cut" = "Kes"; +"ctx_paste" = "Yapıştır"; +"action_settings" = "Ayarlar"; +"action_about" = "VisuStruct Hakkında"; +"recent_files_menu" = "Son Kullanılanlar"; +"recent_files_empty" = "Son kullanılan dosya yok"; +"recent_files_clear" = "Listeyi temizle"; +"recent_files_unavailable" = "Dosya artık kullanılamıyor."; + +/* In-app settings */ +"settings_language_title" = "Dil"; +"settings_language_de" = "Almanca"; +"settings_language_en" = "İngilizce"; +"settings_language_es" = "İspanyolca"; +"settings_language_fr" = "Fransızca"; +"settings_language_it" = "İtalyanca"; +"settings_language_pl" = "Lehçe"; +"settings_language_tr" = "Türkçe"; +"settings_language_ko" = "Korece"; +"settings_language_ja" = "Japonca"; +"settings_language_el" = "Yunanca"; +"settings_language_uk" = "Ukraynaca"; +"settings_language_ar" = "Arapça"; +"settings_language_ru" = "Rusça"; +"settings_language_he" = "İbranice"; +"settings_language_zh_hans" = "Çince (Basitleştirilmiş)"; +"settings_language_zh_hant" = "Çince (Geleneksel)"; +"settings_language_ptpt" = "Portekizce"; +"settings_language_java" = "Java (anahtar kelimeler)"; + + +/* Error overlay */ +"error_title" = "Hata"; +"error_back_editor" = "Düzenleyiciye dön"; + +/* Toolbar */ +"toolbar_undo" = "Geri al"; +"toolbar_redo" = "Yinele"; +"toolbar_new" = "Yeni"; +"menu_open" = "Aç…"; +"menu_save" = "Kaydet"; +"menu_save_as" = "Farklı kaydet…"; +"menu_print" = "Yazdır…"; +"menu_file" = "Dosya"; +"menu_new" = "Yeni"; +"menu_close" = "Kapat"; + +/* Accessibility */ +"a11y_generate_code" = "Yapı şemasından kod üret"; +"a11y_generate_code_locked" = "Kod üret, satın alma sonrası kullanılabilir"; +"a11y_unsaved_changes" = "Kaydedilmemiş değişiklikler"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Kod üret"; +"codegen_gate_body" = "Diyagramınızdan Java, Python ve JavaScript kodu uygulama içi satın alma ile açılacak (yakında)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Kod üretici"; +"codegen_placeholder_body" = "Üretilen kod burada görünecek."; +"codegen_placeholder_compare" = "Sözdizimini karşılaştırmak için Java, Python ve JavaScript arasında geçiş yapın (aşağıda örnek)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (koşul) {\\n ifade();\\n} else {\\n alternatif();\\n}"; +"codegen_preview_python" = "if koşul:\\n ifade()\\nelse:\\n alternatif()"; +"codegen_copy" = "Kopyala"; +"codegen_run_in_browser" = "Tarayıcıda test et"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "Yeni diyagram sekmesi"; +"a11y_close_tab" = "Sekmeyi kapat"; + +"close_unsaved_title" = "Kaydedilmemiş değişiklikler"; +"close_unsaved_message" = "Bu diyagram kaydedilmemiş değişiklikler içeriyor. Kapatmadan önce kaydetmek ister misiniz?"; +"close_unsaved_discard" = "Vazgeç"; +"close_unsaved_cancel" = "İptal"; +"a11y_placeholder_drop" = "Yer tutucuyu değiştirmek için buraya bir öğe bırakın. Sürükleyip taşımak için basılı tutun."; +"a11y_node_drop" = "Bir bloğa basılı tutup sürükleyin: önce/sonra eklemek için hedefin üst veya alt kenarına bırakın. Ortaya bırakma yalnızca ø yer tutucuda."; +"a11y_codegen_panel_drag" = "Kod üretici panelini taşımak için sürükleyin"; + +/* Diagram */ +"diagram_title_label" = "Başlık"; +"diagram_title_placeholder" = "Başlıksız"; + +/* Inspector */ +"inspector_no_selection" = "Seçili öğe yok — bir kutucuğa dokunun."; +"inspector_apply_text" = "Metni uygula"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Tür"; +"inspector_io_mode_statement" = "Komut"; +"inspector_io_mode_input" = "Giriş"; +"inspector_io_mode_output" = "Çıkış"; +"inspector_io_mode_help_java_like" = "Giriş: input: … | Çıkış: output: …"; +"inspector_add_case" = "Durum ekle"; +"inspector_remove_case" = "Durumu kaldır"; +"inspector_group_element" = "Öğe metni"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Koşul ekle…"; +"inspector_placeholder_selector" = "Seçici ekle…"; +"inspector_placeholder_call" = "Çağrı ekle…"; +"inspector_placeholder_break" = "Açıklama (isteğe bağlı)"; + +/* Element types */ +"element_anweisung" = "İfade"; +"element_verzweigung" = "Dal"; +"element_fallauswahl" = "Seçim"; +"element_forSchleife" = "for döngüsü"; +"element_whileSchleife" = "while döngüsü"; +"element_doUntilSchleife" = "do-while döngüsü"; +"element_endlosschleife" = "Sonsuz döngü"; +"element_aussprung" = "Çık"; +"element_aufruf" = "Çağrı"; +"element_leerElement" = "Boş öğe"; + +/* Tabs */ +"tab_title_format" = "Diyagram %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Boş yapı şeması"; +"canvas_empty_hint" = "“Öğeler”den bir öğeyi buraya sürükleyin."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "Seçim"; +"canvas_stub_anweisung" = "İfade"; +"canvas_stub_condition" = "Koşul"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "sonsuz"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Çağrı()"; + +/* About */ +"about_version_fmt" = "Sürüm %@ (%@)"; +"about_nav_title" = "VisuStruct Hakkında"; +"about_features_heading" = "Özellikler"; +"about_bullet_palette" = "Paletten blok ekleyin veya diyagrama sürükleyin"; +"about_bullet_edit" = "Şemayı düzenleyin: metni değiştirin, öğeleri seçin ve gerekirse silin"; +"about_bullet_tabs" = "Sekmelerde birden fazla diyagram — her birinin kendi başlığı var"; +"about_bullet_file" = "Diyagramları .visustruct dosyaları olarak kaydedin ve yeniden açın"; +"about_bullet_share" = "Yapı şemasını görsel olarak paylaşın (PNG)"; +"about_dateiformat_heading" = "Dosya biçimi"; +"about_dateiformat_part1" = "VisuStruct’ün yerel biçimi şu uzantıyı kullanır: "; +"about_dateiformat_part2" = ". Diyagramları saklayabilir ve aynı biçimi destekleyen diğer uygulamalarla paylaşabilirsiniz."; +"about_dateiformat_strk" = ".strk uzantılı dosyalar da açılabilir."; +"about_project_github_label" = "Java uygulaması (kaynak ve sürümler):"; +"about_web_label" = "Web:"; +"about_developer_label" = "Geliştirici:"; +"about_lineage_heading" = "Köken"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "Bitti"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Ekleme iptal"; +"phone_show_text_editor" = "Metni düzenle"; +"phone_hide_text_editor" = "Daralt"; +"phone_title_done" = "Bitti"; + +/* Alerts */ +"err_save_failed_fmt" = "Kaydedilemedi: %@"; +"err_share_prepare_failed_fmt" = "Paylaşım hazırlanamadı: %@"; +"err_diagram_too_small_export" = "Diyagram çok küçük — dışa aktarılacak bir şey yok."; +"err_image_render_failed" = "Görsel oluşturulamadı."; +"err_diagram_too_small_print" = "Diyagram çok küçük — yazdırılacak bir şey yok."; +"err_print_unavailable" = "Bu aygıtta yazdırma kullanılamıyor."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Dosya adı önerisi"; +"settings_export_filename_picker" = "Biçim"; +"settings_export_filename_date_title" = "Tarihli"; +"settings_export_filename_title_only" = "Tarihsiz"; +"settings_export_filename_footer_with_date" = "Tarihli: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Tarihsiz: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simülasyon tamamlandı."; +"sim_notice_infinite_loop_empty" = "Sonsuz döngünün gövdesi yok."; +"sim_notice_unsupported_statement_fmt" = "Desteklenmeyen komut: %@"; +"sim_notice_invalid_expression_fmt" = "Geçersiz ifade: %@"; +"sim_notice_unknown_variable_fmt" = "Bilinmeyen değişken: %@"; +"sim_notice_division_by_zero" = "Sıfıra bölme."; +"sim_notice_whole_number_expected" = "Lütfen bir tam sayı girin."; +"sim_notice_number_expected" = "Lütfen bir sayı girin."; +"sim_notice_boolean_expected" = "true veya false girin."; +"sim_notice_subprogram_not_found_fmt" = "%@ adında açık bir diyagram yok. Çağrı atlandı."; +"sim_notice_call_too_deep" = "Çok fazla iç içe çağrı. Bir alt program kendini mi çağırıyor?"; + +"codegen_pseudocode_toggle" = "Sözde kod (çalıştırılamaz kod)"; +"codegen_pseudocode_note" = "Sözde kod – çalıştırılabilir bir program değil"; +"codegen_pseudocode_hint" = "Bu diyagram sözde kod olarak işaretlendi. Kod yalnızca bir taslaktır ve çalıştırılamaz."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-BYJK0mdR.js b/website/app/assets/Localizable-BYJK0mdR.js new file mode 100644 index 00000000..b6e04f44 --- /dev/null +++ b/website/app/assets/Localizable-BYJK0mdR.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "Elementy"; +"inspector_header" = "Inspektor obiektów"; + +/* Actions */ +"action_share_png" = "Udostępnij obraz…"; +"action_share_document" = "Udostępnij plik…"; +"action_export_pdf" = "Podgląd PDF…"; +"action_generate_code" = "Generuj kod…"; +"action_simulation" = "Symulacja"; +"action_diagram" = "Diagram"; +"simulation_placeholder_body" = "Tryb symulacji uruchamia diagram krok po kroku, podświetla bieżący element oraz pokazuje wartości zmiennych i wyjście."; +"simulation_controls" = "Sterowanie"; +"simulation_highlight_label" = "Podświetlenie"; +"simulation_highlight_last" = "Ostatni krok"; +"simulation_highlight_next" = "Następny krok"; +"simulation_not_available" = "Play uruchamia symulację automatycznie z pauzą 0,5 sekundy na krok."; +"simulation_play" = "Odtwórz"; +"simulation_pause" = "Pauza"; +"simulation_step" = "Krok"; +"simulation_stop" = "Stop"; +"simulation_input" = "Wejście"; +"simulation_input_placeholder" = "Brak wymaganych danych wejściowych."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Wpisz liczbę całkowitą."; +"simulation_trace" = "Ostatni krok"; +"simulation_trace_placeholder" = "Nie wykonano jeszcze żadnego kroku."; +"simulation_variables" = "Zmienne"; +"simulation_variables_placeholder" = "Brak zmiennych."; +"simulation_output" = "Wyjście"; +"simulation_output_placeholder" = "Brak wyjścia."; +"action_delete_selection" = "Usuń zaznaczenie"; +"ctx_copy" = "Kopiuj"; +"ctx_cut" = "Wytnij"; +"ctx_paste" = "Wklej"; +"action_settings" = "Ustawienia"; +"action_about" = "O VisuStruct"; +"recent_files_menu" = "Ostatnie pliki"; +"recent_files_empty" = "Brak ostatnich plików"; +"recent_files_clear" = "Wyczyść listę"; +"recent_files_unavailable" = "Plik nie jest już dostępny."; + +/* In-app settings */ +"settings_language_title" = "Język"; +"settings_language_de" = "Niemiecki"; +"settings_language_en" = "Angielski"; +"settings_language_es" = "Hiszpański"; +"settings_language_fr" = "Francuski"; +"settings_language_it" = "Włoski"; +"settings_language_pl" = "Polski"; +"settings_language_tr" = "Turecki"; +"settings_language_ko" = "Koreański"; +"settings_language_ja" = "Japoński"; +"settings_language_el" = "Grecki"; +"settings_language_uk" = "Ukraiński"; +"settings_language_ar" = "Arabski"; +"settings_language_ru" = "Rosyjski"; +"settings_language_he" = "Hebrajski"; +"settings_language_zh_hans" = "Chiński (uproszczony)"; +"settings_language_zh_hant" = "Chiński (tradycyjny)"; +"settings_language_ptpt" = "Portugalski"; +"settings_language_java" = "Java (słowa kluczowe)"; + + +/* Error overlay */ +"error_title" = "Błąd"; +"error_back_editor" = "Powrót do edytora"; + +/* Toolbar */ +"toolbar_undo" = "Cofnij"; +"toolbar_redo" = "Ponów"; +"toolbar_new" = "Nowe"; +"menu_open" = "Otwórz…"; +"menu_save" = "Zapisz"; +"menu_save_as" = "Zapisz jako…"; +"menu_print" = "Drukuj…"; +"menu_file" = "Plik"; +"menu_new" = "Nowy"; +"menu_close" = "Zamknij"; + +/* Accessibility */ +"a11y_generate_code" = "Generuj kod z diagramu"; +"a11y_generate_code_locked" = "Generuj kod, dostępne po zakupie"; +"a11y_unsaved_changes" = "Niezapisane zmiany"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Generuj kod"; +"codegen_gate_body" = "Kod Java, Python i JavaScript z Twojego diagramu odblokuje zakup w aplikacji (wkrótce)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Generator kodu"; +"codegen_placeholder_body" = "Tutaj pojawi się wygenerowany kod."; +"codegen_placeholder_compare" = "Przełączaj między Java, Python i JavaScript, aby porównać składnię (przykład poniżej)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (warunek) {\\n instrukcja();\\n} else {\\n alternatywa();\\n}"; +"codegen_preview_python" = "if warunek:\\n instrukcja()\\nelse:\\n alternatywa()"; +"codegen_copy" = "Kopiuj"; +"codegen_run_in_browser" = "Testuj w przeglądarce"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "Nowa karta diagramu"; +"a11y_close_tab" = "Zamknij kartę"; + +"close_unsaved_title" = "Niezapisane zmiany"; +"close_unsaved_message" = "Ten diagram zawiera niezapisane zmiany. Czy chcesz je zapisać przed zamknięciem?"; +"close_unsaved_discard" = "Odrzuć"; +"close_unsaved_cancel" = "Anuluj"; +"a11y_placeholder_drop" = "Upuść element tutaj, aby zastąpić symbol zastępczy. Naciśnij i przytrzymaj, aby przeciągnąć i przenieść."; +"a11y_node_drop" = "Naciśnij i przytrzymaj blok, a następnie przeciągnij: upuść na górnej lub dolnej krawędzi celu, aby wstawić przed lub po. Upuszczenie na środku tylko na symbolu ø."; +"a11y_codegen_panel_drag" = "Przeciągnij, aby przesunąć panel generatora kodu"; + +/* Diagram */ +"diagram_title_label" = "Tytuł"; +"diagram_title_placeholder" = "Bez tytułu"; + +/* Inspector */ +"inspector_no_selection" = "Nie wybrano elementu — stuknij kafelek."; +"inspector_apply_text" = "Zastosuj tekst"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Rodzaj"; +"inspector_io_mode_statement" = "Instrukcja"; +"inspector_io_mode_input" = "Wejście"; +"inspector_io_mode_output" = "Wyjście"; +"inspector_io_mode_help_java_like" = "Wejście: input: … | Wyjście: output: …"; +"inspector_add_case" = "Dodaj przypadek"; +"inspector_remove_case" = "Usuń przypadek"; +"inspector_group_element" = "Tekst elementu"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Wstaw warunek…"; +"inspector_placeholder_selector" = "Wstaw selektor…"; +"inspector_placeholder_call" = "Wstaw wywołanie…"; +"inspector_placeholder_break" = "Komentarz (opcjonalnie)"; + +/* Element types */ +"element_anweisung" = "Instrukcja"; +"element_verzweigung" = "Rozgałęzienie"; +"element_fallauswahl" = "Wybór"; +"element_forSchleife" = "Pętla for"; +"element_whileSchleife" = "Pętla while"; +"element_doUntilSchleife" = "Pętla do-while"; +"element_endlosschleife" = "Pętla nieskończona"; +"element_aussprung" = "Wyjście"; +"element_aufruf" = "Wywołanie"; +"element_leerElement" = "Pusty element"; + +/* Tabs */ +"tab_title_format" = "Diagram %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Pusty diagram"; +"canvas_empty_hint" = "Przeciągnij element z „Elementy” tutaj."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "Wybór"; +"canvas_stub_anweisung" = "Instrukcja"; +"canvas_stub_condition" = "Warunek"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "nieskończona"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Wywołanie()"; + +/* About */ +"about_version_fmt" = "Wersja %@ (%@)"; +"about_nav_title" = "O VisuStruct"; +"about_features_heading" = "Funkcje"; +"about_bullet_palette" = "Wstawiaj bloki z palety lub przeciągaj je do diagramu"; +"about_bullet_edit" = "Edytuj diagram: zmieniaj tekst, wybieraj elementy i usuwaj je w razie potrzeby"; +"about_bullet_tabs" = "Kilka diagramów w kartach — każdy z własnym tytułem"; +"about_bullet_file" = "Zapisuj i otwieraj diagramy jako pliki .visustruct"; +"about_bullet_share" = "Udostępniaj diagram jako obraz (PNG)"; +"about_dateiformat_heading" = "Format pliku"; +"about_dateiformat_part1" = "Natywny format VisuStruct używa rozszerzenia "; +"about_dateiformat_part2" = ". Możesz zachować diagramy i wymieniać je z innymi aplikacjami obsługującymi ten sam format."; +"about_dateiformat_strk" = "Można także otwierać pliki z rozszerzeniem .strk."; +"about_project_github_label" = "Aplikacja Java (źródła i wydania):"; +"about_web_label" = "WWW:"; +"about_developer_label" = "Programista:"; +"about_lineage_heading" = "Pochodzenie"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "Gotowe"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Anuluj wstawianie"; +"phone_show_text_editor" = "Edytuj tekst"; +"phone_hide_text_editor" = "Zwiń"; +"phone_title_done" = "Gotowe"; + +/* Alerts */ +"err_save_failed_fmt" = "Nie można zapisać: %@"; +"err_share_prepare_failed_fmt" = "Nie można przygotować udostępniania: %@"; +"err_diagram_too_small_export" = "Diagram jest zbyt mały — nic do eksportu."; +"err_image_render_failed" = "Nie można utworzyć obrazu."; +"err_diagram_too_small_print" = "Diagram jest zbyt mały — nic do drukowania."; +"err_print_unavailable" = "Drukowanie nie jest dostępne na tym urządzeniu."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Propozycja nazwy pliku"; +"settings_export_filename_picker" = "Format"; +"settings_export_filename_date_title" = "Z datą"; +"settings_export_filename_title_only" = "Bez daty"; +"settings_export_filename_footer_with_date" = "Z datą: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Bez daty: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Symulacja zakończona."; +"sim_notice_infinite_loop_empty" = "Pętla nieskończona nie ma treści."; +"sim_notice_unsupported_statement_fmt" = "Nieobsługiwana instrukcja: %@"; +"sim_notice_invalid_expression_fmt" = "Nieprawidłowe wyrażenie: %@"; +"sim_notice_unknown_variable_fmt" = "Nieznana zmienna: %@"; +"sim_notice_division_by_zero" = "Dzielenie przez zero."; +"sim_notice_whole_number_expected" = "Wprowadź liczbę całkowitą."; +"sim_notice_number_expected" = "Wprowadź liczbę."; +"sim_notice_boolean_expected" = "Wpisz true lub false."; +"sim_notice_subprogram_not_found_fmt" = "Żaden otwarty diagram nie nazywa się %@. Wywołanie pominięto."; +"sim_notice_call_too_deep" = "Zbyt wiele zagnieżdżonych wywołań. Czy podprogram wywołuje sam siebie?"; + +"codegen_pseudocode_toggle" = "Pseudokod (kod niewykonywalny)"; +"codegen_pseudocode_note" = "Pseudokod – to nie jest wykonywalny program"; +"codegen_pseudocode_hint" = "Ten diagram jest oznaczony jako pseudokod. Kod jest tylko szkicem i nie można go uruchomić."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-BudCXCER.js b/website/app/assets/Localizable-BudCXCER.js new file mode 100644 index 00000000..5dd80e26 --- /dev/null +++ b/website/app/assets/Localizable-BudCXCER.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "요소"; +"inspector_header" = "개체 검사기"; + +/* Actions */ +"action_share_png" = "이미지 공유…"; +"action_share_document" = "파일 공유…"; +"action_export_pdf" = "PDF 미리보기…"; +"action_generate_code" = "코드 생성…"; +"action_simulation" = "시뮬레이션"; +"action_diagram" = "다이어그램"; +"simulation_placeholder_body" = "시뮬레이션 모드는 다이어그램을 단계별로 실행하고 현재 요소를 강조 표시하며 변수 값과 출력을 보여줍니다."; +"simulation_controls" = "제어"; +"simulation_highlight_label" = "강조 표시"; +"simulation_highlight_last" = "마지막 단계"; +"simulation_highlight_next" = "다음 단계"; +"simulation_not_available" = "Play는 각 단계마다 0.5초씩 쉬면서 시뮬레이션을 자동으로 실행합니다."; +"simulation_play" = "재생"; +"simulation_pause" = "일시정지"; +"simulation_step" = "단계"; +"simulation_stop" = "정지"; +"simulation_input" = "입력"; +"simulation_input_placeholder" = "입력이 필요하지 않습니다."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "정수를 입력하세요."; +"simulation_trace" = "마지막 단계"; +"simulation_trace_placeholder" = "아직 실행된 단계가 없습니다."; +"simulation_variables" = "변수"; +"simulation_variables_placeholder" = "아직 변수가 없습니다."; +"simulation_output" = "출력"; +"simulation_output_placeholder" = "아직 출력이 없습니다."; +"action_delete_selection" = "선택 삭제"; +"ctx_copy" = "복사"; +"ctx_cut" = "잘라내기"; +"ctx_paste" = "붙여넣기"; +"action_settings" = "설정"; +"action_about" = "VisuStruct 정보"; +"recent_files_menu" = "최근 파일"; +"recent_files_empty" = "최근 파일 없음"; +"recent_files_clear" = "목록 지우기"; +"recent_files_unavailable" = "파일을 더 이상 사용할 수 없습니다."; + +/* In-app settings */ +"settings_language_title" = "언어"; +"settings_language_de" = "독일어"; +"settings_language_en" = "영어"; +"settings_language_es" = "스페인어"; +"settings_language_fr" = "프랑스어"; +"settings_language_it" = "이탈리아어"; +"settings_language_pl" = "폴란드어"; +"settings_language_tr" = "터키어"; +"settings_language_ko" = "한국어"; +"settings_language_ja" = "일본어"; +"settings_language_el" = "그리스어"; +"settings_language_uk" = "우크라이나어"; +"settings_language_ar" = "아랍어"; +"settings_language_ru" = "러시아어"; +"settings_language_he" = "히브리어"; +"settings_language_zh_hans" = "중국어(간체)"; +"settings_language_zh_hant" = "중국어(번체)"; +"settings_language_ptpt" = "포르투갈어"; +"settings_language_java" = "Java(키워드)"; + + +/* Error overlay */ +"error_title" = "오류"; +"error_back_editor" = "편집기로 돌아가기"; + +/* Toolbar */ +"toolbar_undo" = "실행 취소"; +"toolbar_redo" = "다시 실행"; +"toolbar_new" = "새로 만들기"; +"menu_open" = "열기…"; +"menu_save" = "저장"; +"menu_save_as" = "다른 이름으로 저장…"; +"menu_print" = "인쇄…"; +"menu_file" = "파일"; +"menu_new" = "새로 만들기"; +"menu_close" = "닫기"; + +/* Accessibility */ +"a11y_generate_code" = "구조도에서 코드 생성"; +"a11y_generate_code_locked" = "코드 생성(구매 후 사용 가능)"; +"a11y_unsaved_changes" = "저장되지 않은 변경 사항"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "코드 생성"; +"codegen_gate_body" = "다이어그램에서 생성된 Java, Python, JavaScript 코드는 앱 내 구매로 잠금 해제됩니다(곧 제공)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "코드 생성기"; +"codegen_placeholder_body" = "생성된 코드는 여기에 표시됩니다."; +"codegen_placeholder_compare" = "Java, Python, JavaScript 간에 전환하여 문법을 비교하세요(아래 예시)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (조건) {\\n 문장();\\n} else {\\n 대안();\\n}"; +"codegen_preview_python" = "if 조건:\\n 문장()\\nelse:\\n 대안()"; +"codegen_copy" = "복사"; +"codegen_run_in_browser" = "브라우저에서 테스트"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "새 다이어그램 탭"; +"a11y_close_tab" = "탭 닫기"; + +"close_unsaved_title" = "저장되지 않은 변경사항"; +"close_unsaved_message" = "이 다이어그램에 저장되지 않은 변경사항이 있습니다. 닫기 전에 저장하시겠습니까?"; +"close_unsaved_discard" = "버리기"; +"close_unsaved_cancel" = "취소"; +"a11y_placeholder_drop" = "자리 표시자를 바꾸려면 여기에 요소를 놓으세요. 길게 눌러 드래그하여 이동할 수 있습니다."; +"a11y_node_drop" = "블록을 길게 누른 뒤 드래그하세요: 대상의 위/아래 가장자리에 놓으면 앞/뒤에 삽입됩니다. 가운데 놓기는 ø 자리 표시자에서만 가능합니다."; +"a11y_codegen_panel_drag" = "코드 생성기 패널을 움직이려면 드래그하세요"; + +/* Diagram */ +"diagram_title_label" = "제목"; +"diagram_title_placeholder" = "제목 없음"; + +/* Inspector */ +"inspector_no_selection" = "선택된 요소가 없습니다 — 타일을 탭하세요."; +"inspector_apply_text" = "텍스트 적용"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "종류"; +"inspector_io_mode_statement" = "명령문"; +"inspector_io_mode_input" = "입력"; +"inspector_io_mode_output" = "출력"; +"inspector_io_mode_help_java_like" = "입력: input: … | 출력: output: …"; +"inspector_add_case" = "케이스 추가"; +"inspector_remove_case" = "케이스 제거"; +"inspector_group_element" = "요소 텍스트"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "조건 입력…"; +"inspector_placeholder_selector" = "선택식 입력…"; +"inspector_placeholder_call" = "호출 입력…"; +"inspector_placeholder_break" = "주석(선택)"; + +/* Element types (Korean + keyword hint) */ +"element_anweisung" = "문장 (statement)"; +"element_verzweigung" = "조건문 (if/else)"; +"element_fallauswahl" = "선택문 (switch)"; +"element_forSchleife" = "반복문 (for)"; +"element_whileSchleife" = "반복문 (while)"; +"element_doUntilSchleife" = "반복문 (do-while)"; +"element_endlosschleife" = "무한 반복 (while true)"; +"element_aussprung" = "탈출 (break)"; +"element_aufruf" = "호출 (call)"; +"element_leerElement" = "빈 요소"; + +/* Tabs */ +"tab_title_format" = "다이어그램 %d"; + +/* Empty canvas */ +"canvas_empty_title" = "빈 구조도"; +"canvas_empty_hint" = "“요소”에서 블록을 여기로 드래그하세요."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "선택문 (switch)"; +"canvas_stub_anweisung" = "문장 (statement)"; +"canvas_stub_condition" = "조건"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "무한"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "호출()"; + +/* About */ +"about_version_fmt" = "버전 %@ (%@)"; +"about_nav_title" = "VisuStruct 정보"; +"about_features_heading" = "기능"; +"about_bullet_palette" = "팔레트에서 블록을 추가하거나 다이어그램으로 드래그하세요"; +"about_bullet_edit" = "다이어그램 편집: 텍스트 변경, 요소 선택, 필요 시 삭제"; +"about_bullet_tabs" = "탭에서 여러 다이어그램 — 각각 제목 포함"; +"about_bullet_file" = ".visustruct 파일로 저장하고 다시 열기"; +"about_bullet_share" = "구조도를 이미지(PNG)로 공유"; +"about_dateiformat_heading" = "파일 형식"; +"about_dateiformat_part1" = "VisuStruct의 기본 형식은 확장자 "; +"about_dateiformat_part2" = "를 사용합니다. 같은 형식을 지원하는 다른 앱과 교환할 수 있습니다."; +"about_dateiformat_strk" = ".strk 확장자 파일도 열 수 있습니다."; +"about_project_github_label" = "Java 앱(소스 및 릴리스):"; +"about_web_label" = "웹:"; +"about_developer_label" = "개발자:"; +"about_lineage_heading" = "계보"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java 업스트림:"; +"about_done" = "완료"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "삽입 취소"; +"phone_show_text_editor" = "텍스트 편집"; +"phone_hide_text_editor" = "접기"; +"phone_title_done" = "완료"; + +/* Alerts */ +"err_save_failed_fmt" = "저장할 수 없음: %@"; +"err_share_prepare_failed_fmt" = "공유를 준비할 수 없음: %@"; +"err_diagram_too_small_export" = "다이어그램이 너무 작아 내보낼 수 없습니다."; +"err_image_render_failed" = "이미지를 만들 수 없습니다."; +"err_diagram_too_small_print" = "다이어그램이 너무 작아 인쇄할 수 없습니다."; +"err_print_unavailable" = "이 기기에서는 인쇄를 사용할 수 없습니다."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "파일 이름 제안"; +"settings_export_filename_picker" = "형식"; +"settings_export_filename_date_title" = "날짜 포함"; +"settings_export_filename_title_only" = "날짜 없음"; +"settings_export_filename_footer_with_date" = "날짜 포함: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "날짜 없음: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "시뮬레이션이 끝났습니다."; +"sim_notice_infinite_loop_empty" = "무한 루프에 본문이 없습니다."; +"sim_notice_unsupported_statement_fmt" = "지원되지 않는 명령문: %@"; +"sim_notice_invalid_expression_fmt" = "잘못된 식: %@"; +"sim_notice_unknown_variable_fmt" = "알 수 없는 변수: %@"; +"sim_notice_division_by_zero" = "0으로 나눌 수 없습니다."; +"sim_notice_whole_number_expected" = "정수를 입력하세요."; +"sim_notice_number_expected" = "숫자를 입력하세요."; +"sim_notice_boolean_expected" = "true 또는 false를 입력하세요."; +"sim_notice_subprogram_not_found_fmt" = "%@(이)라는 열린 다이어그램이 없습니다. 호출을 건너뛰었습니다."; +"sim_notice_call_too_deep" = "중첩 호출이 너무 많습니다. 서브프로그램이 자기 자신을 호출하나요?"; + +"codegen_pseudocode_toggle" = "의사 코드(실행할 수 없는 코드)"; +"codegen_pseudocode_note" = "의사 코드 – 실행 가능한 프로그램이 아닙니다"; +"codegen_pseudocode_hint" = "이 다이어그램은 의사 코드로 표시되어 있습니다. 코드는 초안일 뿐이며 실행할 수 없습니다."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-ByPZS4RL.js b/website/app/assets/Localizable-ByPZS4RL.js new file mode 100644 index 00000000..e17162dd --- /dev/null +++ b/website/app/assets/Localizable-ByPZS4RL.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "Éléments"; +"inspector_header" = "Inspecteur d’objets"; + +/* Actions */ +"action_share_png" = "Partager l’image…"; +"action_share_document" = "Partager le fichier…"; +"action_export_pdf" = "Aperçu PDF…"; +"action_generate_code" = "Générer le code…"; +"action_simulation" = "Simulation"; +"action_diagram" = "Diagramme"; +"simulation_placeholder_body" = "Le mode simulation exécute le diagramme étape par étape, met en évidence l’élément actuel et affiche les valeurs des variables et les sorties."; +"simulation_controls" = "Commandes"; +"simulation_highlight_label" = "Surlignage"; +"simulation_highlight_last" = "Dernière étape"; +"simulation_highlight_next" = "Étape suivante"; +"simulation_not_available" = "Play exécute automatiquement la simulation avec une pause de 0,5 seconde par étape."; +"simulation_play" = "Lecture"; +"simulation_pause" = "Pause"; +"simulation_step" = "Pas"; +"simulation_stop" = "Arrêt"; +"simulation_input" = "Entrée"; +"simulation_input_placeholder" = "Aucune entrée requise."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Veuillez saisir un nombre entier."; +"simulation_trace" = "Dernière étape"; +"simulation_trace_placeholder" = "Aucune étape exécutée pour l’instant."; +"simulation_variables" = "Variables"; +"simulation_variables_placeholder" = "Aucune variable pour l’instant."; +"simulation_output" = "Sortie"; +"simulation_output_placeholder" = "Aucune sortie pour l’instant."; +"action_delete_selection" = "Supprimer la sélection"; +"ctx_copy" = "Copier"; +"ctx_cut" = "Couper"; +"ctx_paste" = "Coller"; +"action_settings" = "Réglages"; +"action_about" = "À propos de VisuStruct"; +"recent_files_menu" = "Fichiers récents"; +"recent_files_empty" = "Aucun fichier récent"; +"recent_files_clear" = "Effacer la liste"; +"recent_files_unavailable" = "Le fichier n’est plus disponible."; + +/* In-app settings */ +"settings_language_title" = "Langue"; +"settings_language_de" = "Allemand"; +"settings_language_en" = "Anglais"; +"settings_language_es" = "Espagnol"; +"settings_language_fr" = "Français"; +"settings_language_it" = "Italien"; +"settings_language_pl" = "Polonais"; +"settings_language_tr" = "Turc"; +"settings_language_ko" = "Coréen"; +"settings_language_ja" = "Japonais"; +"settings_language_el" = "Grec"; +"settings_language_uk" = "Ukrainien"; +"settings_language_ar" = "Arabe"; +"settings_language_ru" = "Russe"; +"settings_language_he" = "Hébreu"; +"settings_language_zh_hans" = "Chinois (simplifié)"; +"settings_language_zh_hant" = "Chinois (traditionnel)"; +"settings_language_ptpt" = "Portugais"; +"settings_language_java" = "Java (mots‑clés)"; + + +/* Error overlay */ +"error_title" = "Erreur"; +"error_back_editor" = "Retour à l’éditeur"; + +/* Toolbar */ +"toolbar_undo" = "Annuler"; +"toolbar_redo" = "Rétablir"; +"toolbar_new" = "Nouveau"; +"menu_open" = "Ouvrir…"; +"menu_save" = "Enregistrer"; +"menu_save_as" = "Enregistrer sous…"; +"menu_print" = "Imprimer…"; +"menu_file" = "Fichier"; +"menu_new" = "Nouveau"; +"menu_close" = "Fermer"; + +/* Accessibility */ +"a11y_generate_code" = "Générer du code à partir de l’organigramme"; +"a11y_generate_code_locked" = "Générer du code, disponible après achat"; +"a11y_unsaved_changes" = "Modifications non enregistrées"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Générer le code"; +"codegen_gate_body" = "Le code Java, Python et JavaScript à partir de votre diagramme sera déverrouillé via un achat intégré (bientôt)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Générateur de code"; +"codegen_placeholder_body" = "Le code généré apparaîtra ici."; +"codegen_placeholder_compare" = "Passez entre Java, Python et JavaScript pour comparer la syntaxe (exemple ci‑dessous)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (condition) {\\n instruction();\\n} else {\\n alternative();\\n}"; +"codegen_preview_python" = "if condition:\\n instruction()\\nelse:\\n alternative()"; +"codegen_copy" = "Copier"; +"codegen_run_in_browser" = "Tester dans le navigateur"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "Nouvel onglet de diagramme"; +"a11y_close_tab" = "Fermer l’onglet"; + +"close_unsaved_title" = "Modifications non enregistrées"; +"close_unsaved_message" = "Ce diagramme contient des modifications non enregistrées. Voulez-vous les enregistrer avant de fermer ?"; +"close_unsaved_discard" = "Ignorer"; +"close_unsaved_cancel" = "Annuler"; +"a11y_placeholder_drop" = "Déposez un élément ici pour remplacer l’espace réservé. Appuyez longuement pour glisser et déplacer."; +"a11y_node_drop" = "Appuyez longuement sur un bloc, puis faites glisser : déposez sur le bord haut ou bas pour insérer avant ou après. Dépôt au centre uniquement sur un espace réservé ø."; +"a11y_codegen_panel_drag" = "Glisser pour déplacer le panneau du générateur de code"; + +/* Diagram */ +"diagram_title_label" = "Titre"; +"diagram_title_placeholder" = "Sans titre"; + +/* Inspector */ +"inspector_no_selection" = "Aucun élément sélectionné — touchez une tuile."; +"inspector_apply_text" = "Appliquer le texte"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Type"; +"inspector_io_mode_statement" = "Instruction"; +"inspector_io_mode_input" = "Entrée"; +"inspector_io_mode_output" = "Sortie"; +"inspector_io_mode_help_java_like" = "Entrée: input: … | Sortie: output: …"; +"inspector_add_case" = "Ajouter un cas"; +"inspector_remove_case" = "Supprimer le cas"; +"inspector_group_element" = "Texte de l’élément"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Insérer une condition…"; +"inspector_placeholder_selector" = "Insérer un sélecteur…"; +"inspector_placeholder_call" = "Insérer un appel…"; +"inspector_placeholder_break" = "Commentaire (facultatif)"; + +/* Element types */ +"element_anweisung" = "Instruction"; +"element_verzweigung" = "Branche"; +"element_fallauswahl" = "Sélection"; +"element_forSchleife" = "Boucle for"; +"element_whileSchleife" = "Boucle while"; +"element_doUntilSchleife" = "Boucle do‑while"; +"element_endlosschleife" = "Boucle infinie"; +"element_aussprung" = "Sortie"; +"element_aufruf" = "Appel"; +"element_leerElement" = "Élément vide"; + +/* Tabs */ +"tab_title_format" = "Diagramme %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Organigramme vide"; +"canvas_empty_hint" = "Glissez un élément depuis « Éléments » ici."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "Sélection"; +"canvas_stub_anweisung" = "Instruction"; +"canvas_stub_condition" = "Condition"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "infini"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Appel()"; + +/* About */ +"about_version_fmt" = "Version %@ (%@)"; +"about_nav_title" = "À propos de VisuStruct"; +"about_features_heading" = "Fonctionnalités"; +"about_bullet_palette" = "Insérer des blocs depuis la palette ou les glisser dans le diagramme"; +"about_bullet_edit" = "Modifier le diagramme : changer le texte, sélectionner des éléments et les supprimer si nécessaire"; +"about_bullet_tabs" = "Plusieurs diagrammes en onglets — chacun avec son titre"; +"about_bullet_file" = "Enregistrer et rouvrir des diagrammes en fichiers .visustruct"; +"about_bullet_share" = "Partager le diagramme comme image (PNG)"; +"about_dateiformat_heading" = "Format de fichier"; +"about_dateiformat_part1" = "Le format natif de VisuStruct utilise l’extension "; +"about_dateiformat_part2" = ". Vous pouvez conserver vos diagrammes et les échanger avec d’autres apps compatibles."; +"about_dateiformat_strk" = "Les fichiers avec l’extension .strk peuvent également être ouverts."; +"about_project_github_label" = "Application Java (code & versions) :"; +"about_web_label" = "Web :"; +"about_developer_label" = "Développeur :"; +"about_lineage_heading" = "Origine"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Upstream Java :"; +"about_done" = "Terminé"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Annuler l’insertion"; +"phone_show_text_editor" = "Modifier le texte"; +"phone_hide_text_editor" = "Réduire"; +"phone_title_done" = "OK"; + +/* Alerts */ +"err_save_failed_fmt" = "Impossible d’enregistrer : %@"; +"err_share_prepare_failed_fmt" = "Impossible de préparer le partage : %@"; +"err_diagram_too_small_export" = "Le diagramme est trop petit — rien à exporter."; +"err_image_render_failed" = "Impossible de créer l’image."; +"err_diagram_too_small_print" = "Le diagramme est trop petit — rien à imprimer."; +"err_print_unavailable" = "L’impression n’est pas disponible sur cet appareil."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Suggestion de nom de fichier"; +"settings_export_filename_picker" = "Format"; +"settings_export_filename_date_title" = "Avec date"; +"settings_export_filename_title_only" = "Sans date"; +"settings_export_filename_footer_with_date" = "Avec date: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Sans date: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simulation terminée."; +"sim_notice_infinite_loop_empty" = "La boucle infinie n’a pas de corps."; +"sim_notice_unsupported_statement_fmt" = "Instruction non prise en charge : %@"; +"sim_notice_invalid_expression_fmt" = "Expression non valide : %@"; +"sim_notice_unknown_variable_fmt" = "Variable inconnue : %@"; +"sim_notice_division_by_zero" = "Division par zéro."; +"sim_notice_whole_number_expected" = "Saisissez un nombre entier."; +"sim_notice_number_expected" = "Saisissez un nombre."; +"sim_notice_boolean_expected" = "Saisissez true ou false."; +"sim_notice_subprogram_not_found_fmt" = "Aucun diagramme ouvert ne s’appelle %@. L’appel a été ignoré."; +"sim_notice_call_too_deep" = "Trop d’appels imbriqués. Un sous-programme s’appelle-t-il lui-même ?"; + +"codegen_pseudocode_toggle" = "Pseudo-code (code non exécutable)"; +"codegen_pseudocode_note" = "Pseudo-code – pas un programme exécutable"; +"codegen_pseudocode_hint" = "Ce diagramme est marqué comme pseudo-code. Le code n’est qu’une ébauche et ne peut pas être exécuté."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-CHv0OL9S.js b/website/app/assets/Localizable-CHv0OL9S.js new file mode 100644 index 00000000..e34630d6 --- /dev/null +++ b/website/app/assets/Localizable-CHv0OL9S.js @@ -0,0 +1,256 @@ +const e=`/* Paleta */ +"palette_header" = "Elementos"; +"inspector_header" = "Inspetor de objetos"; + +/* Ações */ +"action_share_png" = "Partilhar gráfico…"; +"action_share_document" = "Partilhar ficheiro…"; +"action_export_pdf" = "Pré-visualizar PDF…"; +"action_generate_code" = "Gerar código…"; +"action_simulation" = "Simulação"; +"action_diagram" = "Diagrama"; +"simulation_placeholder_body" = "O modo de simulação executa o diagrama passo a passo, destaca o elemento atual e mostra os valores das variáveis e a saída."; +"simulation_controls" = "Controlos"; +"simulation_highlight_label" = "Destaque"; +"simulation_highlight_last" = "Último passo"; +"simulation_highlight_next" = "Próximo passo"; +"simulation_not_available" = "Play executa a simulação automaticamente com uma pausa de 0,5 segundos por passo."; +"simulation_play" = "Reproduzir"; +"simulation_pause" = "Pausa"; +"simulation_step" = "Passo"; +"simulation_stop" = "Parar"; +"simulation_input" = "Entrada"; +"simulation_input_placeholder" = "Nenhuma entrada necessária."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Introduza um número inteiro."; +"simulation_trace" = "Último passo"; +"simulation_trace_placeholder" = "Ainda não foi executado nenhum passo."; +"simulation_variables" = "Variáveis"; +"simulation_variables_placeholder" = "Ainda não há variáveis."; +"simulation_output" = "Saída"; +"simulation_output_placeholder" = "Ainda não há saída."; +"action_delete_selection" = "Eliminar seleção"; +"ctx_copy" = "Copiar"; +"ctx_cut" = "Cortar"; +"ctx_paste" = "Colar"; +"action_settings" = "Definições"; +"action_about" = "Acerca do VisuStruct"; +"recent_files_menu" = "Recentes"; +"recent_files_empty" = "Sem ficheiros recentes"; +"recent_files_clear" = "Limpar lista"; +"recent_files_unavailable" = "O ficheiro já não está disponível."; + +/* Definições (na app) */ +"settings_language_title" = "Idioma"; +"settings_language_de" = "Alemão"; +"settings_language_en" = "Inglês"; +"settings_language_es" = "Espanhol"; +"settings_language_fr" = "Francês"; +"settings_language_it" = "Italiano"; +"settings_language_pl" = "Polaco"; +"settings_language_tr" = "Turco"; +"settings_language_ko" = "Coreano"; +"settings_language_ja" = "Japonês"; +"settings_language_el" = "Grego"; +"settings_language_uk" = "Ucraniano"; +"settings_language_ar" = "Árabe"; +"settings_language_ru" = "Russo"; +"settings_language_he" = "Hebraico"; +"settings_language_zh_hans" = "Chinês (simplificado)"; +"settings_language_zh_hant" = "Chinês (tradicional)"; +"settings_language_ptpt" = "Português"; +"settings_language_java" = "Java (palavras-chave)"; + + + +/* Erro */ +"error_title" = "Erro"; +"error_back_editor" = "Voltar ao editor"; + +/* Barra de ferramentas */ +"toolbar_undo" = "Anular"; +"toolbar_redo" = "Refazer"; +"toolbar_new" = "Novo"; +"menu_open" = "Abrir…"; +"menu_save" = "Guardar"; +"menu_save_as" = "Guardar como…"; +"menu_print" = "Imprimir…"; +"menu_file" = "Ficheiro"; +"menu_new" = "Novo"; +"menu_close" = "Fechar"; + +/* Acessibilidade */ +"a11y_generate_code" = "Gerar código a partir do diagrama"; +"a11y_generate_code_locked" = "Gerar código, disponível após comprar"; +"a11y_unsaved_changes" = "Alterações não guardadas"; + +/* Gerador de código (compra na app em breve) */ +"codegen_gate_title" = "Gerar código"; +"codegen_gate_body" = "O código Java, Python e JavaScript a partir do diagrama ficará disponível com uma compra na aplicação (em breve)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Gerador de código"; +"codegen_placeholder_body" = "O código gerado aparecerá aqui."; +"codegen_placeholder_compare" = "Alterne entre Java, Python e JavaScript para comparar a sintaxe (exemplo abaixo)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (condicao) {\\n instrucao();\\n} else {\\n alternativa();\\n}"; +"codegen_preview_python" = "if condicao:\\n instrucao()\\nelse:\\n alternativa()"; +"codegen_generated_hint" = "Pré-visualização a partir do diagrama atual (Java 17, Python 3.10+, JavaScript moderno)."; +"codegen_copy" = "Copiar"; +"codegen_run_in_browser" = "Testar no navegador"; +"codegen_save_java" = "Guardar Java…"; +"codegen_java_output_mode" = "Saída Java"; +"codegen_java_output_snippet" = "Excerto"; +"codegen_java_output_class" = "Classe"; +"a11y_new_diagram_tab" = "Novo separador de diagrama"; +"a11y_close_tab" = "Fechar separador"; + +"close_unsaved_title" = "Alterações não guardadas"; +"close_unsaved_message" = "Este diagrama contém alterações não guardadas. Pretende guardá-las antes de fechar?"; +"close_unsaved_discard" = "Descartar"; +"close_unsaved_cancel" = "Cancelar"; +"a11y_placeholder_drop" = "Largue aqui um elemento para substituir o marcador. Mantenha premido para arrastar e mover."; +"a11y_node_drop" = "Mantenha premido um bloco e arraste: largue na borda superior ou inferior do destino (antes/depois). No centro só em marcador ø."; +"a11y_codegen_panel_drag" = "Arraste para mover o painel do gerador de código"; + +/* Diagrama */ +"diagram_title_label" = "Título"; +"diagram_title_placeholder" = "Sem título"; + +/* Inspetor */ +"inspector_no_selection" = "Nenhum elemento selecionado — toque num bloco."; +"inspector_apply_text" = "Aplicar texto"; +"inspector_for_init" = "Início"; +"inspector_for_condition" = "Condição"; +"inspector_for_step" = "Passo"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Tipo"; +"inspector_io_mode_statement" = "Instrução"; +"inspector_io_mode_input" = "Entrada"; +"inspector_io_mode_output" = "Saída"; +"inspector_io_mode_help_java_like" = "Entrada: input: … | Saída: output: …"; +"inspector_add_case" = "Adicionar caso"; +"inspector_remove_case" = "Remover caso"; +"inspector_group_element" = "Texto do elemento"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Inserir condição…"; +"inspector_placeholder_selector" = "Inserir seletor…"; +"inspector_placeholder_call" = "Inserir chamada…"; +"inspector_placeholder_break" = "Comentário (opcional)"; + +/* Tipos de elemento */ +"element_anweisung" = "Instrução"; +"element_verzweigung" = "Decisão"; +"element_fallauswahl" = "Seleção"; +"element_forSchleife" = "Ciclo for"; +"element_whileSchleife" = "Ciclo while"; +"element_doUntilSchleife" = "Ciclo do-while"; +"element_endlosschleife" = "Ciclo infinito"; +"element_aussprung" = "Interrupção"; +"element_aufruf" = "Chamada"; +"element_leerElement" = "Elemento vazio"; + +/* Separadores */ +"tab_title_format" = "Diagrama %d"; + +/* Ecrã vazio */ +"canvas_empty_title" = "Diagrama vazio"; +"canvas_empty_hint" = "Arraste um elemento de «Elementos» para aqui."; + +/* Diagrama: textos de elementos novos e cabeçalhos de coluna (exibição) */ +"canvas_stub_fallauswahl" = "Seleção"; +"canvas_stub_anweisung" = "Instrução"; +"canvas_stub_condition" = "Condição"; +"canvas_stub_for" = "for 0 < i < quantidade"; +"canvas_stub_while" = "enquanto …"; +"canvas_stub_until" = "até …"; +"canvas_stub_endless" = "infinito"; +"canvas_stub_break" = "parar"; +"canvas_stub_call" = "Chamada()"; + +/* Acerca */ +"about_version_fmt" = "Versão %@ (%@)"; +"about_nav_title" = "Acerca do VisuStruct"; +"about_features_heading" = "Funcionalidades"; +"about_bullet_palette" = "Inserir blocos a partir da paleta ou arrastá-los para o diagrama"; +"about_bullet_edit" = "Editar o diagrama: alterar textos, selecionar elementos e removê-los se necessário"; +"about_bullet_tabs" = "Vários diagramas em separadores — cada um com o seu título"; +"about_bullet_file" = "Guardar e reabrir diagramas como ficheiros .visustruct"; +"about_bullet_share" = "Partilhar o diagrama estruturado como imagem (PNG)"; +"about_dateiformat_heading" = "Formato do ficheiro"; +"about_dateiformat_part1" = "O formato nativo do VisuStruct utiliza a extensão "; +"about_dateiformat_part2" = ". Pode guardar diagramas e trocá-los com outras apps que suportem o mesmo formato."; +"about_dateiformat_strk" = "Também é possível abrir ficheiros com a extensão .strk."; +"about_project_github_label" = "App Java (código-fonte e releases):"; +"about_web_label" = "Web:"; +"about_developer_label" = "Programador:"; +"about_lineage_heading" = "Origem"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Upstream Java:"; +"about_done" = "Concluído"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: inserir por toque */ +"phone_insert_cancel" = "Cancelar inserção"; +"phone_show_text_editor" = "Editar texto"; +"phone_hide_text_editor" = "Recolher"; +"phone_title_done" = "OK"; + +/* Alertas */ +"err_save_failed_fmt" = "Não foi possível guardar: %@"; +"err_share_prepare_failed_fmt" = "Não foi possível preparar a partilha: %@"; +"err_diagram_too_small_export" = "O diagrama é demasiado pequeno — nada para exportar."; +"err_image_render_failed" = "Não foi possível criar a imagem."; +"err_diagram_too_small_print" = "O diagrama é demasiado pequeno — nada para imprimir."; +"err_print_unavailable" = "A impressão não está disponível neste dispositivo."; + +"settings_ui_scale_section" = "Tamanho do texto"; +"settings_ui_scale_canvas" = "Diagrama"; +"settings_ui_scale_inspector" = "Introdução de texto em baixo"; +"settings_ui_scale_small" = "Pequeno"; +"settings_ui_scale_medium" = "Médio"; +"settings_ui_scale_large" = "Grande"; +"settings_ui_scale_extra_large" = "Muito grande"; + +"settings_export_filename_section" = "Sugestão de nome de ficheiro"; +"settings_export_filename_picker" = "Formato"; +"settings_export_filename_date_title" = "Com data"; +"settings_export_filename_title_only" = "Sem data"; +"settings_export_filename_footer_with_date" = "Com data: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Sem data: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simulação terminada."; +"sim_notice_infinite_loop_empty" = "O ciclo infinito não tem corpo."; +"sim_notice_unsupported_statement_fmt" = "Instrução não suportada: %@"; +"sim_notice_invalid_expression_fmt" = "Expressão inválida: %@"; +"sim_notice_unknown_variable_fmt" = "Variável desconhecida: %@"; +"sim_notice_division_by_zero" = "Divisão por zero."; +"sim_notice_whole_number_expected" = "Introduza um número inteiro."; +"sim_notice_number_expected" = "Introduza um número."; +"sim_notice_boolean_expected" = "Introduza true ou false."; +"sim_notice_subprogram_not_found_fmt" = "Nenhum diagrama aberto se chama %@. A chamada foi ignorada."; +"sim_notice_call_too_deep" = "Demasiadas chamadas aninhadas. Um subprograma chama-se a si próprio?"; + +"codegen_pseudocode_toggle" = "Pseudocódigo (código não executável)"; +"codegen_pseudocode_note" = "Pseudocódigo – não é um programa executável"; +"codegen_pseudocode_hint" = "Este diagrama está marcado como pseudocódigo. O código é apenas um esboço e não pode ser executado."; + +"course_title" = "Curso"; +"course_intro" = "Aprender a programar passo a passo: do primeiro diagrama ao teu próprio programa em Java."; +"course_bullet_lessons" = "Todas as lições com explicações, testes e exercícios"; +"course_bullet_java" = "Tarefas de programação «Agora em Java» em cada lição"; +"course_bullet_games" = "Jogos de aprendizagem e dicas graduais"; +"course_bullet_once" = "Compra uma vez e usa no iPhone, iPad e Mac"; +"course_unlocked" = "Curso desbloqueado – obrigado!"; +"course_free_note" = "Criar diagramas, a simulação e a exportação de código continuam gratuitos."; +"course_restore" = "Restaurar compras"; +"course_restore_done" = "A tua compra do curso foi restaurada."; +"course_restore_none" = "Não foi encontrada nenhuma compra do curso para esta Conta Apple."; +"course_unavailable" = "Neste momento não é possível carregar o curso da App Store. Verifica a ligação à internet e tenta mais tarde."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-CaVEL1es.js b/website/app/assets/Localizable-CaVEL1es.js new file mode 100644 index 00000000..74e69fc5 --- /dev/null +++ b/website/app/assets/Localizable-CaVEL1es.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "元素"; +"inspector_header" = "对象检查器"; + +/* Actions */ +"action_share_png" = "分享图片…"; +"action_share_document" = "分享文件…"; +"action_export_pdf" = "PDF 预览…"; +"action_generate_code" = "生成代码…"; +"action_simulation" = "模拟"; +"action_diagram" = "图表"; +"simulation_placeholder_body" = "模拟模式会逐步运行图表,突出显示当前元素,并显示变量值和输出。"; +"simulation_controls" = "控制"; +"simulation_highlight_label" = "高亮"; +"simulation_highlight_last" = "上一步"; +"simulation_highlight_next" = "下一步"; +"simulation_not_available" = "Play 会自动运行模拟,每步暂停 0.5 秒。"; +"simulation_play" = "播放"; +"simulation_pause" = "暂停"; +"simulation_step" = "单步"; +"simulation_stop" = "停止"; +"simulation_input" = "输入"; +"simulation_input_placeholder" = "不需要输入。"; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "请输入一个整数。"; +"simulation_trace" = "上一步"; +"simulation_trace_placeholder" = "尚未执行任何步骤。"; +"simulation_variables" = "变量"; +"simulation_variables_placeholder" = "暂无变量。"; +"simulation_output" = "输出"; +"simulation_output_placeholder" = "暂无输出。"; +"action_delete_selection" = "删除所选"; +"ctx_copy" = "复制"; +"ctx_cut" = "剪切"; +"ctx_paste" = "粘贴"; +"action_settings" = "设置"; +"action_about" = "关于 VisuStruct"; +"recent_files_menu" = "最近文件"; +"recent_files_empty" = "没有最近文件"; +"recent_files_clear" = "清除列表"; +"recent_files_unavailable" = "文件不再可用。"; + +/* In-app settings */ +"settings_language_title" = "语言"; +"settings_language_de" = "德语"; +"settings_language_en" = "英语"; +"settings_language_es" = "西班牙语"; +"settings_language_fr" = "法语"; +"settings_language_it" = "意大利语"; +"settings_language_pl" = "波兰语"; +"settings_language_tr" = "土耳其语"; +"settings_language_ko" = "韩语"; +"settings_language_ja" = "日语"; +"settings_language_el" = "希腊语"; +"settings_language_uk" = "乌克兰语"; +"settings_language_ar" = "阿拉伯语"; +"settings_language_ru" = "俄语"; +"settings_language_he" = "希伯来语"; +"settings_language_zh_hans" = "中文(简体)"; +"settings_language_zh_hant" = "中文(繁體)"; +"settings_language_ptpt" = "葡萄牙语"; +"settings_language_java" = "Java(关键词)"; + + +/* Error overlay */ +"error_title" = "错误"; +"error_back_editor" = "返回编辑器"; + +/* Toolbar */ +"toolbar_undo" = "撤销"; +"toolbar_redo" = "重做"; +"toolbar_new" = "新建"; +"menu_open" = "打开…"; +"menu_save" = "保存"; +"menu_save_as" = "另存为…"; +"menu_print" = "打印…"; +"menu_file" = "文件"; +"menu_new" = "新建"; +"menu_close" = "关闭"; + +/* Accessibility */ +"a11y_generate_code" = "从结构图生成代码"; +"a11y_generate_code_locked" = "生成代码(购买后可用)"; +"a11y_unsaved_changes" = "未保存的更改"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "生成代码"; +"codegen_gate_body" = "将通过应用内购买解锁从图表生成的 Java、Python 和 JavaScript 代码(即将推出)。"; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "代码生成器"; +"codegen_placeholder_body" = "生成的代码会显示在这里。"; +"codegen_placeholder_compare" = "在 Java、Python 和 JavaScript 之间切换以比较语法(下方示例)。"; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (条件) {\\n 语句();\\n} else {\\n 替代();\\n}"; +"codegen_preview_python" = "if 条件:\\n 语句()\\nelse:\\n 替代()"; +"codegen_copy" = "复制"; +"codegen_run_in_browser" = "在浏览器中测试"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "新建图表标签页"; +"a11y_close_tab" = "关闭标签页"; + +"close_unsaved_title" = "未保存的更改"; +"close_unsaved_message" = "此图表包含未保存的更改。关闭前要保存吗?"; +"close_unsaved_discard" = "放弃"; +"close_unsaved_cancel" = "取消"; +"a11y_placeholder_drop" = "将元素拖放到这里以替换占位符。长按可拖动移动。"; +"a11y_node_drop" = "长按块并拖动:在目标上边缘或下边缘放下以插入到前/后。仅在 ø 占位符上可居中放下。"; +"a11y_codegen_panel_drag" = "拖移以移动代码生成器面板"; + +/* Diagram */ +"diagram_title_label" = "标题"; +"diagram_title_placeholder" = "无标题"; + +/* Inspector */ +"inspector_no_selection" = "未选择元素 — 点击一个块。"; +"inspector_apply_text" = "应用文本"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "类型"; +"inspector_io_mode_statement" = "语句"; +"inspector_io_mode_input" = "输入"; +"inspector_io_mode_output" = "输出"; +"inspector_io_mode_help_java_like" = "输入: input: … | 输出: output: …"; +"inspector_add_case" = "添加分支"; +"inspector_remove_case" = "移除分支"; +"inspector_group_element" = "元素文本"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "输入条件…"; +"inspector_placeholder_selector" = "输入选择式…"; +"inspector_placeholder_call" = "输入调用…"; +"inspector_placeholder_break" = "注释(可选)"; + +/* Element types */ +"element_anweisung" = "语句"; +"element_verzweigung" = "分支"; +"element_fallauswahl" = "选择"; +"element_forSchleife" = "for 循环"; +"element_whileSchleife" = "while 循环"; +"element_doUntilSchleife" = "do-while 循环"; +"element_endlosschleife" = "无限循环"; +"element_aussprung" = "跳出"; +"element_aufruf" = "调用"; +"element_leerElement" = "空元素"; + +/* Tabs */ +"tab_title_format" = "图表 %d"; + +/* Empty canvas */ +"canvas_empty_title" = "空结构图"; +"canvas_empty_hint" = "从“元素”中拖拽一个块到这里。"; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "选择"; +"canvas_stub_anweisung" = "语句"; +"canvas_stub_condition" = "条件"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "无限"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "调用()"; + +/* About */ +"about_version_fmt" = "版本 %@ (%@)"; +"about_nav_title" = "关于 VisuStruct"; +"about_features_heading" = "功能"; +"about_bullet_palette" = "从调色板插入块,或拖入图表"; +"about_bullet_edit" = "编辑图表:修改文本、选择元素,必要时删除"; +"about_bullet_tabs" = "多个图表标签页——每个都有自己的标题"; +"about_bullet_file" = "将图表保存并以 .visustruct 文件重新打开"; +"about_bullet_share" = "将结构图分享为图片(PNG)"; +"about_dateiformat_heading" = "文件格式"; +"about_dateiformat_part1" = "VisuStruct 的原生格式使用扩展名 "; +"about_dateiformat_part2" = "。你可以保存图表,并与支持相同格式的应用交换。"; +"about_dateiformat_strk" = "也可以打开 .strk 扩展名的文件。"; +"about_project_github_label" = "Java 应用(源码与版本):"; +"about_web_label" = "网页:"; +"about_developer_label" = "开发者:"; +"about_lineage_heading" = "来源"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java 上游:"; +"about_done" = "完成"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "取消插入"; +"phone_show_text_editor" = "编辑文本"; +"phone_hide_text_editor" = "收起"; +"phone_title_done" = "完成"; + +/* Alerts */ +"err_save_failed_fmt" = "无法保存:%@"; +"err_share_prepare_failed_fmt" = "无法准备分享:%@"; +"err_diagram_too_small_export" = "图表太小——无内容可导出。"; +"err_image_render_failed" = "无法创建图片。"; +"err_diagram_too_small_print" = "图表太小——无内容可打印。"; +"err_print_unavailable" = "此设备不支持打印。"; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "文件名建议"; +"settings_export_filename_picker" = "格式"; +"settings_export_filename_date_title" = "含日期"; +"settings_export_filename_title_only" = "不含日期"; +"settings_export_filename_footer_with_date" = "含日期: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "不含日期: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "模拟已结束。"; +"sim_notice_infinite_loop_empty" = "无限循环没有循环体。"; +"sim_notice_unsupported_statement_fmt" = "不支持的语句:%@"; +"sim_notice_invalid_expression_fmt" = "无效的表达式:%@"; +"sim_notice_unknown_variable_fmt" = "未知变量:%@"; +"sim_notice_division_by_zero" = "除数为零。"; +"sim_notice_whole_number_expected" = "请输入整数。"; +"sim_notice_number_expected" = "请输入数字。"; +"sim_notice_boolean_expected" = "请输入 true 或 false。"; +"sim_notice_subprogram_not_found_fmt" = "没有名为 %@ 的已打开图表。已跳过该调用。"; +"sim_notice_call_too_deep" = "嵌套调用过多。是否有子程序调用了自身?"; + +"codegen_pseudocode_toggle" = "伪代码(不可运行的代码)"; +"codegen_pseudocode_note" = "伪代码 – 不是可运行的程序"; +"codegen_pseudocode_hint" = "此图已标记为伪代码。代码只是草稿,无法运行。"; +`;export{e as default}; diff --git a/website/app/assets/Localizable-CkJEmEEP.js b/website/app/assets/Localizable-CkJEmEEP.js new file mode 100644 index 00000000..32b34aa8 --- /dev/null +++ b/website/app/assets/Localizable-CkJEmEEP.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "要素"; +"inspector_header" = "オブジェクトインスペクタ"; + +/* Actions */ +"action_share_png" = "画像を共有…"; +"action_share_document" = "ファイルを共有…"; +"action_export_pdf" = "PDF をプレビュー…"; +"action_generate_code" = "コード生成…"; +"action_simulation" = "シミュレーション"; +"action_diagram" = "図"; +"simulation_placeholder_body" = "シミュレーションモードは図をステップごとに実行し、現在の要素を強調表示して、変数の値と出力を表示します。"; +"simulation_controls" = "操作"; +"simulation_highlight_label" = "ハイライト"; +"simulation_highlight_last" = "前のステップ"; +"simulation_highlight_next" = "次のステップ"; +"simulation_not_available" = "Play は各ステップごとに0.5秒停止しながらシミュレーションを自動実行します。"; +"simulation_play" = "再生"; +"simulation_pause" = "一時停止"; +"simulation_step" = "ステップ"; +"simulation_stop" = "停止"; +"simulation_input" = "入力"; +"simulation_input_placeholder" = "入力は不要です。"; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "整数を入力してください。"; +"simulation_trace" = "最後のステップ"; +"simulation_trace_placeholder" = "まだステップは実行されていません。"; +"simulation_variables" = "変数"; +"simulation_variables_placeholder" = "まだ変数はありません。"; +"simulation_output" = "出力"; +"simulation_output_placeholder" = "まだ出力はありません。"; +"action_delete_selection" = "選択を削除"; +"ctx_copy" = "コピー"; +"ctx_cut" = "切り取り"; +"ctx_paste" = "貼り付け"; +"action_settings" = "設定"; +"action_about" = "VisuStruct について"; +"recent_files_menu" = "最近使ったファイル"; +"recent_files_empty" = "最近使ったファイルはありません"; +"recent_files_clear" = "リストを消去"; +"recent_files_unavailable" = "ファイルは利用できなくなりました。"; + +/* In-app settings */ +"settings_language_title" = "言語"; +"settings_language_de" = "ドイツ語"; +"settings_language_en" = "英語"; +"settings_language_es" = "スペイン語"; +"settings_language_fr" = "フランス語"; +"settings_language_it" = "イタリア語"; +"settings_language_pl" = "ポーランド語"; +"settings_language_tr" = "トルコ語"; +"settings_language_ko" = "韓国語"; +"settings_language_ja" = "日本語"; +"settings_language_el" = "ギリシャ語"; +"settings_language_uk" = "ウクライナ語"; +"settings_language_ar" = "アラビア語"; +"settings_language_ru" = "ロシア語"; +"settings_language_he" = "ヘブライ語"; +"settings_language_zh_hans" = "中国語(簡体字)"; +"settings_language_zh_hant" = "中国語(繁体字)"; +"settings_language_ptpt" = "ポルトガル語"; +"settings_language_java" = "Java(キーワード)"; + + +/* Error overlay */ +"error_title" = "エラー"; +"error_back_editor" = "エディタに戻る"; + +/* Toolbar */ +"toolbar_undo" = "取り消し"; +"toolbar_redo" = "やり直し"; +"toolbar_new" = "新規"; +"menu_open" = "開く…"; +"menu_save" = "保存"; +"menu_save_as" = "別名で保存…"; +"menu_print" = "印刷…"; +"menu_file" = "ファイル"; +"menu_new" = "新規"; +"menu_close" = "閉じる"; + +/* Accessibility */ +"a11y_generate_code" = "構造図からコードを生成"; +"a11y_generate_code_locked" = "コード生成(購入後に利用可能)"; +"a11y_unsaved_changes" = "未保存の変更"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "コード生成"; +"codegen_gate_body" = "図から生成される Java、Python、JavaScript のコードはアプリ内課金で利用可能になります(近日公開)。"; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "コード生成"; +"codegen_placeholder_body" = "生成されたコードはここに表示されます。"; +"codegen_placeholder_compare" = "Java、Python、JavaScript を切り替えて構文を比較できます(下の例)。"; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (条件) {\\n 文();\\n} else {\\n 代替();\\n}"; +"codegen_preview_python" = "if 条件:\\n 文()\\nelse:\\n 代替()"; +"codegen_copy" = "コピー"; +"codegen_run_in_browser" = "ブラウザでテスト"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "新しい図のタブ"; +"a11y_close_tab" = "タブを閉じる"; + +"close_unsaved_title" = "未保存の変更"; +"close_unsaved_message" = "この図には未保存の変更があります。閉じる前に保存しますか?"; +"close_unsaved_discard" = "破棄"; +"close_unsaved_cancel" = "キャンセル"; +"a11y_placeholder_drop" = "要素をここにドロップしてプレースホルダーを置き換えます。長押ししてドラッグし移動できます。"; +"a11y_node_drop" = "ブロックを長押ししてドラッグ:対象の上端/下端にドロップすると前/後に挿入。中央へのドロップは ø プレースホルダーのみ。"; +"a11y_codegen_panel_drag" = "ドラッグしてコード生成パネルを移動"; + +/* Diagram */ +"diagram_title_label" = "タイトル"; +"diagram_title_placeholder" = "タイトルなし"; + +/* Inspector */ +"inspector_no_selection" = "要素が選択されていません — タイルをタップしてください。"; +"inspector_apply_text" = "テキストを適用"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "種類"; +"inspector_io_mode_statement" = "文"; +"inspector_io_mode_input" = "入力"; +"inspector_io_mode_output" = "出力"; +"inspector_io_mode_help_java_like" = "入力: input: … | 出力: output: …"; +"inspector_add_case" = "ケースを追加"; +"inspector_remove_case" = "ケースを削除"; +"inspector_group_element" = "要素テキスト"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "条件を入力…"; +"inspector_placeholder_selector" = "セレクタを入力…"; +"inspector_placeholder_call" = "呼び出しを入力…"; +"inspector_placeholder_break" = "コメント(任意)"; + +/* Element types (Japanese + keyword hint) */ +"element_anweisung" = "文 (statement)"; +"element_verzweigung" = "条件分岐 (if/else)"; +"element_fallauswahl" = "選択 (switch)"; +"element_forSchleife" = "繰り返し (for)"; +"element_whileSchleife" = "繰り返し (while)"; +"element_doUntilSchleife" = "繰り返し (do-while)"; +"element_endlosschleife" = "無限ループ (while true)"; +"element_aussprung" = "脱出 (break)"; +"element_aufruf" = "呼び出し (call)"; +"element_leerElement" = "空の要素"; + +/* Tabs */ +"tab_title_format" = "図 %d"; + +/* Empty canvas */ +"canvas_empty_title" = "空の構造図"; +"canvas_empty_hint" = "「要素」からブロックをここにドラッグしてください。"; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "選択 (switch)"; +"canvas_stub_anweisung" = "文 (statement)"; +"canvas_stub_condition" = "条件"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "無限"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "呼び出し()"; + +/* About */ +"about_version_fmt" = "バージョン %@ (%@)"; +"about_nav_title" = "VisuStruct について"; +"about_features_heading" = "機能"; +"about_bullet_palette" = "パレットからブロックを挿入、または図へドラッグ&ドロップ"; +"about_bullet_edit" = "図を編集:テキスト変更、要素選択、必要に応じて削除"; +"about_bullet_tabs" = "複数の図をタブで管理(それぞれタイトル付き)"; +"about_bullet_file" = ".visustruct ファイルとして保存し再度開く"; +"about_bullet_share" = "構造図を画像(PNG)として共有"; +"about_dateiformat_heading" = "ファイル形式"; +"about_dateiformat_part1" = "VisuStruct のネイティブ形式は拡張子 "; +"about_dateiformat_part2" = " を使用します。同じ形式をサポートする他のアプリと交換できます。"; +"about_dateiformat_strk" = ".strk 拡張子のファイルも開けます。"; +"about_project_github_label" = "Java アプリ(ソース&リリース):"; +"about_web_label" = "Web:"; +"about_developer_label" = "開発者:"; +"about_lineage_heading" = "系譜"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "完了"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "挿入をキャンセル"; +"phone_show_text_editor" = "テキストを編集"; +"phone_hide_text_editor" = "折りたたむ"; +"phone_title_done" = "完了"; + +/* Alerts */ +"err_save_failed_fmt" = "保存できませんでした:%@"; +"err_share_prepare_failed_fmt" = "共有の準備ができませんでした:%@"; +"err_diagram_too_small_export" = "図が小さすぎます — エクスポートできません。"; +"err_image_render_failed" = "画像を作成できませんでした。"; +"err_diagram_too_small_print" = "図が小さすぎます — 印刷できません。"; +"err_print_unavailable" = "このデバイスでは印刷できません。"; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "ファイル名の候補"; +"settings_export_filename_picker" = "形式"; +"settings_export_filename_date_title" = "日付あり"; +"settings_export_filename_title_only" = "日付なし"; +"settings_export_filename_footer_with_date" = "日付あり: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "日付なし: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "シミュレーションが終了しました。"; +"sim_notice_infinite_loop_empty" = "無限ループに本体がありません。"; +"sim_notice_unsupported_statement_fmt" = "サポートされていない文: %@"; +"sim_notice_invalid_expression_fmt" = "無効な式: %@"; +"sim_notice_unknown_variable_fmt" = "不明な変数: %@"; +"sim_notice_division_by_zero" = "0 で割ることはできません。"; +"sim_notice_whole_number_expected" = "整数を入力してください。"; +"sim_notice_number_expected" = "数値を入力してください。"; +"sim_notice_boolean_expected" = "true または false を入力してください。"; +"sim_notice_subprogram_not_found_fmt" = "%@ という名前の開いている図はありません。呼び出しをスキップしました。"; +"sim_notice_call_too_deep" = "呼び出しの入れ子が多すぎます。サブプログラムが自分自身を呼び出していませんか?"; + +"codegen_pseudocode_toggle" = "疑似コード(実行できないコード)"; +"codegen_pseudocode_note" = "疑似コード – 実行可能なプログラムではありません"; +"codegen_pseudocode_hint" = "この図は疑似コードとしてマークされています。コードは下書きにすぎず、実行できません。"; +`;export{e as default}; diff --git a/website/app/assets/Localizable-CxCno28C.js b/website/app/assets/Localizable-CxCno28C.js new file mode 100644 index 00000000..61b9585a --- /dev/null +++ b/website/app/assets/Localizable-CxCno28C.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "العناصر"; +"inspector_header" = "مفتش الكائنات"; + +/* Actions */ +"action_share_png" = "مشاركة الصورة…"; +"action_share_document" = "مشاركة الملف…"; +"action_export_pdf" = "معاينة PDF…"; +"action_generate_code" = "إنشاء الشفرة…"; +"action_simulation" = "محاكاة"; +"action_diagram" = "مخطط"; +"simulation_placeholder_body" = "يشغّل وضع المحاكاة المخطط خطوة بخطوة، ويبرز العنصر الحالي، ويعرض قيم المتغيرات والمخرجات."; +"simulation_controls" = "عناصر التحكم"; +"simulation_highlight_label" = "تمييز"; +"simulation_highlight_last" = "آخر خطوة"; +"simulation_highlight_next" = "الخطوة التالية"; +"simulation_not_available" = "يقوم Play بتشغيل المحاكاة تلقائيًا مع توقف 0.5 ثانية لكل خطوة."; +"simulation_play" = "تشغيل"; +"simulation_pause" = "إيقاف مؤقت"; +"simulation_step" = "خطوة"; +"simulation_stop" = "إيقاف"; +"simulation_input" = "إدخال"; +"simulation_input_placeholder" = "لا يلزم إدخال."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "يرجى إدخال عدد صحيح."; +"simulation_trace" = "آخر خطوة"; +"simulation_trace_placeholder" = "لم يُنفَّذ أي خطوة بعد."; +"simulation_variables" = "المتغيرات"; +"simulation_variables_placeholder" = "لا توجد متغيرات بعد."; +"simulation_output" = "المخرجات"; +"simulation_output_placeholder" = "لا يوجد إخراج بعد."; +"action_delete_selection" = "حذف التحديد"; +"ctx_copy" = "نسخ"; +"ctx_cut" = "قص"; +"ctx_paste" = "لصق"; +"action_settings" = "الإعدادات"; +"action_about" = "حول VisuStruct"; +"recent_files_menu" = "الملفات الأخيرة"; +"recent_files_empty" = "لا توجد ملفات حديثة"; +"recent_files_clear" = "مسح القائمة"; +"recent_files_unavailable" = "لم يعد الملف متاحًا."; + +/* In-app settings */ +"settings_language_title" = "اللغة"; +"settings_language_de" = "الألمانية"; +"settings_language_en" = "الإنجليزية"; +"settings_language_es" = "الإسبانية"; +"settings_language_fr" = "الفرنسية"; +"settings_language_it" = "الإيطالية"; +"settings_language_pl" = "البولندية"; +"settings_language_tr" = "التركية"; +"settings_language_ko" = "الكورية"; +"settings_language_ja" = "اليابانية"; +"settings_language_el" = "اليونانية"; +"settings_language_uk" = "الأوكرانية"; +"settings_language_ar" = "العربية"; +"settings_language_ru" = "الروسية"; +"settings_language_he" = "العبرية"; +"settings_language_zh_hans" = "الصينية (مبسطة)"; +"settings_language_zh_hant" = "الصينية (تقليدية)"; +"settings_language_ptpt" = "البرتغالية"; +"settings_language_java" = "Java (كلمات مفتاحية)"; + + +/* Error overlay */ +"error_title" = "خطأ"; +"error_back_editor" = "العودة إلى المحرر"; + +/* Toolbar */ +"toolbar_undo" = "تراجع"; +"toolbar_redo" = "إعادة"; +"toolbar_new" = "جديد"; +"menu_open" = "فتح…"; +"menu_save" = "حفظ"; +"menu_save_as" = "حفظ باسم…"; +"menu_print" = "طباعة…"; +"menu_file" = "ملف"; +"menu_new" = "جديد"; +"menu_close" = "إغلاق"; + +/* Accessibility */ +"a11y_generate_code" = "إنشاء شفرة من المخطط"; +"a11y_generate_code_locked" = "إنشاء الشفرة، متاح بعد الشراء"; +"a11y_unsaved_changes" = "تغييرات غير محفوظة"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "إنشاء الشفرة"; +"codegen_gate_body" = "سيتم فتح شفرة Java وPython وJavaScript من المخطط عبر عملية شراء داخل التطبيق (قريبًا)."; +"codegen_gate_ok" = "حسنًا"; +"codegen_placeholder_title" = "مولّد الشفرة"; +"codegen_placeholder_body" = "ستظهر الشفرة المُولَّدة هنا."; +"codegen_placeholder_compare" = "بدّل بين Java وPython وJavaScript لمقارنة الصياغة (مثال بالأسفل)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (الشرط) {\\n statement();\\n} else {\\n alternative();\\n}"; +"codegen_preview_python" = "if الشرط:\\n statement()\\nelse:\\n alternative()"; +"codegen_copy" = "نسخ"; +"codegen_run_in_browser" = "اختبار في المتصفح"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "علامة تبويب جديدة للمخطط"; +"a11y_close_tab" = "إغلاق علامة التبويب"; + +"close_unsaved_title" = "تغييرات غير محفوظة"; +"close_unsaved_message" = "يحتوي هذا المخطط على تغييرات غير محفوظة. هل تريد حفظها قبل الإغلاق؟"; +"close_unsaved_discard" = "تجاهل"; +"close_unsaved_cancel" = "إلغاء"; +"a11y_placeholder_drop" = "أفلت عنصرًا هنا لاستبدال العنصر النائب. اضغط مطولًا للسحب والتحريك."; +"a11y_node_drop" = "اضغط مطولًا على كتلة ثم اسحب: أفلت على الحافة العلوية أو السفلية لإدراجها قبل أو بعد. الإسقاط في الوسط فقط على عنصر نائب ø."; +"a11y_codegen_panel_drag" = "اسحب لتحريك لوحة مولّد الشفرة"; + +/* Diagram */ +"diagram_title_label" = "العنوان"; +"diagram_title_placeholder" = "بدون عنوان"; + +/* Inspector */ +"inspector_no_selection" = "لا يوجد عنصر محدد — اضغط على كتلة."; +"inspector_apply_text" = "تطبيق النص"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "النوع"; +"inspector_io_mode_statement" = "تعليمة"; +"inspector_io_mode_input" = "إدخال"; +"inspector_io_mode_output" = "إخراج"; +"inspector_io_mode_help_java_like" = "إدخال: input: … | إخراج: output: …"; +"inspector_add_case" = "إضافة حالة"; +"inspector_remove_case" = "إزالة الحالة"; +"inspector_group_element" = "نص العنصر"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "أدخل condition…"; +"inspector_placeholder_selector" = "أدخل selector…"; +"inspector_placeholder_call" = "أدخل call…"; +"inspector_placeholder_break" = "تعليق (اختياري)"; + +/* Element types — keep Java-like (LTR) to reduce RTL confusion */ +"element_anweisung" = "Statement"; +"element_verzweigung" = "if"; +"element_fallauswahl" = "switch"; +"element_forSchleife" = "for"; +"element_whileSchleife" = "while"; +"element_doUntilSchleife" = "do"; +"element_endlosschleife" = "while(true)"; +"element_aussprung" = "break"; +"element_aufruf" = "استدعاء"; +"element_leerElement" = "ø"; + +/* Tabs */ +"tab_title_format" = "مخطط %d"; + +/* Empty canvas */ +"canvas_empty_title" = "مخطط فارغ"; +"canvas_empty_hint" = "اسحب عنصرًا من «العناصر» إلى هنا."; + +/* Diagram: new element stubs & column headers — keep Java-like */ +"canvas_stub_anweisung" = "Statement"; +"canvas_stub_condition" = "condition"; +"canvas_stub_fallauswahl" = "selector"; +"canvas_stub_for" = "i = 0; i < n; i++"; +"canvas_stub_while" = "condition"; +"canvas_stub_until" = "condition"; +"canvas_stub_endless" = "∞"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "استدعاء()"; + +/* About */ +"about_version_fmt" = "الإصدار %@ (%@)"; +"about_nav_title" = "حول VisuStruct"; +"about_features_heading" = "الميزات"; +"about_bullet_palette" = "أدرج الكتل من اللوحة أو اسحبها إلى المخطط"; +"about_bullet_edit" = "حرّر المخطط: غيّر النص، حدّد العناصر وأزلها عند الحاجة"; +"about_bullet_tabs" = "عدة مخططات في علامات تبويب — لكل مخطط عنوانه"; +"about_bullet_file" = "احفظ وأعد فتح المخططات كملفات .visustruct"; +"about_bullet_share" = "شارك المخطط كصورة (PNG)"; +"about_dateiformat_heading" = "تنسيق الملف"; +"about_dateiformat_part1" = "يستخدم تنسيق VisuStruct الأصلي الامتداد "; +"about_dateiformat_part2" = ". يمكنك حفظ المخططات وتبادلها مع تطبيقات أخرى تدعم نفس التنسيق."; +"about_dateiformat_strk" = "يمكن أيضًا فتح الملفات ذات الامتداد .strk."; +"about_project_github_label" = "تطبيق Java (المصدر والإصدارات):"; +"about_web_label" = "الويب:"; +"about_developer_label" = "المطوّر:"; +"about_lineage_heading" = "الأصل"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "تم"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "إلغاء الإدراج"; +"phone_show_text_editor" = "تحرير النص"; +"phone_hide_text_editor" = "طيّ"; +"phone_title_done" = "تم"; + +/* Alerts */ +"err_save_failed_fmt" = "تعذر الحفظ: %@"; +"err_share_prepare_failed_fmt" = "تعذر تجهيز المشاركة: %@"; +"err_diagram_too_small_export" = "المخطط صغير جدًا — لا يوجد ما يمكن تصديره."; +"err_image_render_failed" = "تعذر إنشاء الصورة."; +"err_diagram_too_small_print" = "المخطط صغير جدًا — لا يوجد ما يمكن طباعته."; +"err_print_unavailable" = "الطباعة غير متاحة على هذا الجهاز."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "اقتراح اسم الملف"; +"settings_export_filename_picker" = "النمط"; +"settings_export_filename_date_title" = "مع التاريخ"; +"settings_export_filename_title_only" = "بدون تاريخ"; +"settings_export_filename_footer_with_date" = "مع التاريخ: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "بدون تاريخ: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "انتهت المحاكاة."; +"sim_notice_infinite_loop_empty" = "الحلقة اللانهائية ليس لها جسم."; +"sim_notice_unsupported_statement_fmt" = "تعليمة غير مدعومة: %@"; +"sim_notice_invalid_expression_fmt" = "تعبير غير صالح: %@"; +"sim_notice_unknown_variable_fmt" = "متغير غير معروف: %@"; +"sim_notice_division_by_zero" = "القسمة على صفر."; +"sim_notice_whole_number_expected" = "أدخل عددًا صحيحًا."; +"sim_notice_number_expected" = "أدخل رقمًا."; +"sim_notice_boolean_expected" = "أدخل true أو false."; +"sim_notice_subprogram_not_found_fmt" = "لا يوجد مخطط مفتوح باسم %@. تم تخطي الاستدعاء."; +"sim_notice_call_too_deep" = "استدعاءات متداخلة كثيرة جدًا. هل يستدعي برنامج فرعي نفسه؟"; + +"codegen_pseudocode_toggle" = "شبه كود (ليس كودًا قابلًا للتشغيل)"; +"codegen_pseudocode_note" = "شبه كود – ليس برنامجًا قابلًا للتشغيل"; +"codegen_pseudocode_hint" = "هذا المخطط معلَّم كشبه كود. الكود مجرد مسودة ولا يمكن تشغيله."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-DBLIUcBd.js b/website/app/assets/Localizable-DBLIUcBd.js new file mode 100644 index 00000000..3e1e935f --- /dev/null +++ b/website/app/assets/Localizable-DBLIUcBd.js @@ -0,0 +1,255 @@ +const e=`/* Palette */ +"palette_header" = "Elements"; +"inspector_header" = "Object Inspector"; + +/* Actions */ +"action_share_png" = "Share Graphic…"; +"action_share_document" = "Share File…"; +"action_export_pdf" = "Preview PDF…"; +"action_generate_code" = "Generate Code…"; +"action_simulation" = "Simulation"; +"action_diagram" = "Diagram"; +"simulation_placeholder_body" = "The simulation mode will run the diagram step by step, highlight the current element, and show variable values and output."; +"simulation_controls" = "Controls"; +"simulation_highlight_label" = "Highlight"; +"simulation_highlight_last" = "Last step"; +"simulation_highlight_next" = "Next step"; +"simulation_not_available" = "Play runs the simulation automatically with a 0.5 second pause per step."; +"simulation_play" = "Play"; +"simulation_pause" = "Pause"; +"simulation_step" = "Step"; +"simulation_stop" = "Stop"; +"simulation_input" = "Input"; +"simulation_input_placeholder" = "No input required."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Please enter a whole number."; +"simulation_trace" = "Last Step"; +"simulation_trace_placeholder" = "No step executed yet."; +"simulation_variables" = "Variables"; +"simulation_variables_placeholder" = "No variables yet."; +"simulation_output" = "Output"; +"simulation_output_placeholder" = "No output yet."; +"action_delete_selection" = "Delete Selection"; +"ctx_copy" = "Copy"; +"ctx_cut" = "Cut"; +"ctx_paste" = "Paste"; +"action_settings" = "Settings"; +"action_about" = "About VisuStruct"; +"recent_files_menu" = "Recent Files"; +"recent_files_empty" = "No recent files"; +"recent_files_clear" = "Clear List"; +"recent_files_unavailable" = "File is no longer available."; + +/* In-app settings */ +"settings_language_title" = "Language"; +"settings_language_de" = "German"; +"settings_language_en" = "English"; +"settings_language_es" = "Spanish"; +"settings_language_fr" = "French"; +"settings_language_it" = "Italian"; +"settings_language_pl" = "Polish"; +"settings_language_tr" = "Turkish"; +"settings_language_ko" = "Korean"; +"settings_language_ja" = "Japanese"; +"settings_language_el" = "Greek"; +"settings_language_uk" = "Ukrainian"; +"settings_language_ar" = "Arabic"; +"settings_language_ru" = "Russian"; +"settings_language_he" = "Hebrew"; +"settings_language_zh_hans" = "Chinese (Simplified)"; +"settings_language_zh_hant" = "Chinese (Traditional)"; +"settings_language_ptpt" = "Portuguese"; +"settings_language_java" = "Java (keywords)"; + + + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "File name suggestion"; +"settings_export_filename_picker" = "Format"; +"settings_export_filename_date_title" = "With date"; +"settings_export_filename_title_only" = "Without date"; +"settings_export_filename_footer_with_date" = "With date: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Without date: Filename.visustruct"; + + +/* Error overlay */ +"error_title" = "Error"; +"error_back_editor" = "Back to Editor"; + +/* Toolbar */ +"toolbar_undo" = "Undo"; +"toolbar_redo" = "Redo"; +"toolbar_new" = "New"; +"menu_open" = "Open…"; +"menu_save" = "Save"; +"menu_save_as" = "Save As…"; +"menu_print" = "Print…"; +"menu_file" = "File"; +"menu_new" = "New"; +"menu_close" = "Close"; + +/* Accessibility */ +"a11y_generate_code" = "Generate code from the structure chart"; +"a11y_generate_code_locked" = "Generate code, available after purchase"; +"a11y_unsaved_changes" = "Unsaved changes"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Generate code"; +"codegen_gate_body" = "Java, Python, and JavaScript code from your diagram will unlock via in-app purchase (coming soon)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Code generator"; +"codegen_placeholder_body" = "Generated code will appear here."; +"codegen_placeholder_compare" = "Switch between Java, Python, and JavaScript to compare syntax (sample below)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (condition) {\\n statement();\\n} else {\\n alternative();\\n}"; +"codegen_preview_python" = "if condition:\\n statement()\\nelse:\\n alternative()"; +"codegen_generated_hint" = "Preview from the current structure chart (Java 17, Python 3.10+, modern JavaScript)."; +"codegen_copy" = "Copy"; +"codegen_run_in_browser" = "Test in browser"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "New diagram tab"; +"a11y_close_tab" = "Close tab"; + +"close_unsaved_title" = "Unsaved Changes"; +"close_unsaved_message" = "This diagram contains unsaved changes. Do you want to save them before closing?"; +"close_unsaved_discard" = "Discard"; +"close_unsaved_cancel" = "Cancel"; +"a11y_placeholder_drop" = "Drop an element here to replace the placeholder. Press and hold to drag and move."; +"a11y_node_drop" = "Press and hold a block, then drag: drop on the top or bottom edge of a target to insert before or after. Center drop only on a ø placeholder."; +"a11y_codegen_panel_drag" = "Drag to move code generator panel"; + +/* Diagram */ +"diagram_title_label" = "Title"; +"diagram_title_placeholder" = "No title"; + +/* Inspector */ +"inspector_no_selection" = "No element selected — tap a tile."; +"inspector_apply_text" = "Apply Text"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; +"inspector_io_mode_title" = "Kind"; +"inspector_io_mode_statement" = "Statement"; +"inspector_io_mode_input" = "Input"; +"inspector_io_mode_output" = "Output"; +"inspector_io_mode_help_java_like" = "Input: input: … | Output: output: …"; +"inspector_add_case" = "Add Case"; +"inspector_remove_case" = "Remove Case"; +"inspector_group_element" = "Element text"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Insert condition…"; +"inspector_placeholder_selector" = "Insert selector…"; +"inspector_placeholder_call" = "Insert call…"; +"inspector_placeholder_break" = "Comment (optional)"; + +/* Element types */ +"element_anweisung" = "Statement"; +"element_verzweigung" = "Branch"; +"element_fallauswahl" = "Switch"; +"element_forSchleife" = "For loop"; +"element_whileSchleife" = "While loop"; +"element_doUntilSchleife" = "Do-while loop"; +"element_endlosschleife" = "Endless loop"; +"element_aussprung" = "Break"; +"element_aufruf" = "Call"; +"element_leerElement" = "Empty element"; + +/* Tabs */ +"tab_title_format" = "Diagram %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Empty structure chart"; +"canvas_empty_hint" = "Drag an element from “Elements” here."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "Switch"; +"canvas_stub_anweisung" = "Statement"; +"canvas_stub_condition" = "Condition"; +"canvas_stub_for" = "for 0 < i < count"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "endless"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Call()"; + +/* About */ +"about_version_fmt" = "Version %@ (%@)"; +"about_nav_title" = "About VisuStruct"; +"about_features_heading" = "Features"; +"about_bullet_palette" = "Insert blocks from the palette or drag them into the diagram"; +"about_bullet_edit" = "Edit the chart: change text, select elements, and remove them if needed"; +"about_bullet_tabs" = "Several diagrams in tabs — each with its own title"; +"about_bullet_file" = "Save and reopen diagrams as .visustruct files"; +"about_bullet_share" = "Share the structure chart as an image (PNG)"; +"about_dateiformat_heading" = "File format"; +"about_dateiformat_part1" = "VisuStruct’s native format uses the extension "; +"about_dateiformat_part2" = ". You can keep diagrams and exchange them with other apps that support the same format."; +"about_dateiformat_strk" = "Files with the .strk extension can also be opened."; +"about_project_github_label" = "Java app (source & releases):"; +"about_web_label" = "Web:"; +"about_developer_label" = "Developer:"; +"about_lineage_heading" = "Lineage"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "Done"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Cancel insert"; +"phone_show_text_editor" = "Edit text"; +"phone_hide_text_editor" = "Collapse"; +"phone_title_done" = "Done"; + +/* Alerts */ +"err_save_failed_fmt" = "Could not save: %@"; +"err_share_prepare_failed_fmt" = "Could not prepare sharing: %@"; +"err_diagram_too_small_export" = "The diagram is too small — nothing to export."; +"err_image_render_failed" = "Could not create the image."; +"err_diagram_too_small_print" = "The diagram is too small — nothing to print."; +"err_print_unavailable" = "Printing is not available on this device."; + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simulation finished."; +"sim_notice_infinite_loop_empty" = "Infinite loop has no body."; +"sim_notice_unsupported_statement_fmt" = "Unsupported statement: %@"; +"sim_notice_invalid_expression_fmt" = "Invalid expression: %@"; +"sim_notice_unknown_variable_fmt" = "Unknown variable: %@"; +"sim_notice_division_by_zero" = "Division by zero."; +"sim_notice_whole_number_expected" = "Please enter a whole number."; +"sim_notice_number_expected" = "Please enter a number."; +"sim_notice_boolean_expected" = "Please enter true or false."; +"sim_notice_subprogram_not_found_fmt" = "No open diagram is called %@. The call was skipped."; +"sim_notice_call_too_deep" = "Too many nested calls. Does a subprogram call itself?"; + +"codegen_pseudocode_toggle" = "Pseudocode (not runnable code)"; +"codegen_pseudocode_note" = "Pseudocode – not a runnable program"; +"codegen_pseudocode_hint" = "This diagram is marked as pseudocode. The code is only a sketch and cannot be run."; + +"course_title" = "Course"; +"course_intro" = "Learn programming step by step: from the first structure chart to your own Java programs."; +"course_bullet_lessons" = "All lessons with explanations, quizzes and exercises"; +"course_bullet_java" = "“Now in Java” programming tasks in every lesson"; +"course_bullet_games" = "Learning games and step-by-step hints"; +"course_bullet_once" = "Pay once, use it on iPhone, iPad and Mac"; +"course_unlocked" = "Course unlocked – thank you!"; +"course_free_note" = "Creating structure charts, simulation and code export stay free."; +"course_restore" = "Restore purchases"; +"course_restore_done" = "Your course purchase has been restored."; +"course_restore_none" = "No course purchase was found for this Apple Account."; +"course_unavailable" = "The course can’t be loaded from the App Store right now. Please check your internet connection and try again later."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-DSvkBkp-.js b/website/app/assets/Localizable-DSvkBkp-.js new file mode 100644 index 00000000..d381e295 --- /dev/null +++ b/website/app/assets/Localizable-DSvkBkp-.js @@ -0,0 +1,153 @@ +const e=`/* NOTE: Initial Norwegian Bokmål localization. */ +"palette_header" = "Elementer"; +"inspector_header" = "Objektinspektør"; + +/* Actions */ +"action_share_png" = "Del bilde…"; +"action_share_document" = "Del fil…"; +"action_export_pdf" = "Forhåndsvis PDF…"; +"action_generate_code" = "Generer kode…"; +"action_simulation" = "Simulering"; +"action_diagram" = "Diagram"; +"simulation_placeholder_body" = "Simuleringsmodus kjører diagrammet trinn for trinn, markerer gjeldende element og viser variabelverdier og utdata."; +"simulation_controls" = "Kontroller"; +"simulation_highlight_label" = "Markering"; +"simulation_highlight_last" = "Siste steg"; +"simulation_highlight_next" = "Neste steg"; +"simulation_not_available" = "Play kjører simuleringen automatisk med en pause på 0,5 sekund per steg."; +"simulation_play" = "Spill av"; +"simulation_pause" = "Pause"; +"simulation_step" = "Trinn"; +"simulation_stop" = "Stopp"; +"simulation_input" = "Inndata"; +"simulation_input_placeholder" = "Ingen inndata kreves."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Skriv inn et heltall."; +"simulation_trace" = "Siste steg"; +"simulation_trace_placeholder" = "Ingen trinn er utført ennå."; +"simulation_variables" = "Variabler"; +"simulation_variables_placeholder" = "Ingen variabler ennå."; +"simulation_output" = "Utdata"; +"simulation_output_placeholder" = "Ingen utdata ennå."; +"action_delete_selection" = "Slett markering"; +"ctx_copy" = "Kopier"; +"ctx_cut" = "Klipp ut"; +"ctx_paste" = "Lim inn"; +"action_settings" = "Innstillinger"; +"action_about" = "Om VisuStruct"; +"recent_files_menu" = "Nylige filer"; +"recent_files_empty" = "Ingen nylige filer"; +"recent_files_clear" = "Tøm liste"; +"recent_files_unavailable" = "Filen er ikke lenger tilgjengelig."; + +/* In-app settings */ +"settings_language_title" = "Språk"; + +/* Toolbar */ +"toolbar_undo" = "Angre"; +"toolbar_redo" = "Gjør om"; +"toolbar_new" = "Ny"; +"menu_open" = "Åpne…"; +"menu_save" = "Lagre"; +"menu_save_as" = "Lagre som…"; +"menu_print" = "Skriv ut…"; +"menu_file" = "Arkiv"; +"menu_new" = "Ny"; +"menu_close" = "Lukk"; + +/* Inspector */ +"inspector_no_selection" = "Ingen valgt — trykk på en rute."; +"inspector_apply_text" = "Bruk tekst"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Type"; +"inspector_io_mode_statement" = "Setning"; +"inspector_io_mode_input" = "Inndata"; +"inspector_io_mode_output" = "Utdata"; +"inspector_io_mode_help_java_like" = "Inndata: input: … | Utdata: output: …"; +"inspector_add_case" = "Legg til case"; +"inspector_remove_case" = "Fjern case"; +"inspector_group_element" = "Elementtekst"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Skriv condition…"; +"inspector_placeholder_selector" = "Skriv selector…"; +"inspector_placeholder_call" = "Skriv call…"; +"inspector_placeholder_break" = "Kommentar (valgfritt)"; + +/* Element types */ +"element_anweisung" = "Setning"; +"element_verzweigung" = "Betingelse (if/else)"; +"element_fallauswahl" = "Valg (switch)"; +"element_forSchleife" = "For-løkke"; +"element_whileSchleife" = "While-løkke"; +"element_doUntilSchleife" = "Do-while-løkke"; +"element_endlosschleife" = "Uendelig løkke"; +"element_aussprung" = "Break"; +"element_aufruf" = "Kall"; +"element_leerElement" = "Tomt element"; + +/* Diagram */ +"diagram_title_label" = "Tittel"; +"diagram_title_placeholder" = "Ingen tittel"; +"canvas_empty_title" = "Tomt struktogram"; +"canvas_empty_hint" = "Dra et element fra “Elementer” hit."; + +/* Diagram stubs */ +"canvas_stub_anweisung" = "statement"; +"canvas_stub_condition" = "condition"; +"canvas_stub_fallauswahl" = "switch"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "endless"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Kall()"; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Forslag til filnavn"; +"settings_export_filename_picker" = "Format"; +"settings_export_filename_date_title" = "Med dato"; +"settings_export_filename_title_only" = "Uten dato"; +"settings_export_filename_footer_with_date" = "Med dato: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Uten dato: Filename.visustruct"; + +"close_unsaved_title" = "Ulagrede endringer"; +"close_unsaved_message" = "Dette diagrammet inneholder ulagrede endringer. Vil du lagre dem før du lukker?"; +"close_unsaved_discard" = "Forkast"; +"close_unsaved_cancel" = "Avbryt"; + +/* Accessibility — code generator floating panel */ +"a11y_codegen_panel_drag" = "Dra for å flytte kodegeneratorpanelet"; +"about_dateiformat_strk" = "Filer med endelsen .strk kan også åpnes."; + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simuleringen er ferdig."; +"sim_notice_infinite_loop_empty" = "Den uendelige løkken har ikke noe innhold."; +"sim_notice_unsupported_statement_fmt" = "Setning støttes ikke: %@"; +"sim_notice_invalid_expression_fmt" = "Ugyldig uttrykk: %@"; +"sim_notice_unknown_variable_fmt" = "Ukjent variabel: %@"; +"sim_notice_division_by_zero" = "Divisjon med null."; +"sim_notice_whole_number_expected" = "Skriv inn et heltall."; +"sim_notice_number_expected" = "Skriv inn et tall."; +"sim_notice_boolean_expected" = "Skriv inn true eller false."; +"sim_notice_subprogram_not_found_fmt" = "Ingen åpne diagrammer heter %@. Kallet ble hoppet over."; +"sim_notice_call_too_deep" = "For mange nøstede kall. Kaller et underprogram seg selv?"; +"phone_hide_text_editor" = "Skjul"; +"phone_title_done" = "Ferdig"; + +"codegen_pseudocode_toggle" = "Pseudokode (ikke kjørbar kode)"; +"codegen_pseudocode_note" = "Pseudokode – ikke et kjørbart program"; +"codegen_pseudocode_hint" = "Dette diagrammet er merket som pseudokode. Koden er bare en skisse og kan ikke kjøres."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-DXAPah1g.js b/website/app/assets/Localizable-DXAPah1g.js new file mode 100644 index 00000000..0e75f8f3 --- /dev/null +++ b/website/app/assets/Localizable-DXAPah1g.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "Elementi"; +"inspector_header" = "Ispettore oggetti"; + +/* Actions */ +"action_share_png" = "Condividi immagine…"; +"action_share_document" = "Condividi file…"; +"action_export_pdf" = "Anteprima PDF…"; +"action_generate_code" = "Genera codice…"; +"action_simulation" = "Simulazione"; +"action_diagram" = "Diagramma"; +"simulation_placeholder_body" = "La modalità simulazione esegue il diagramma passo dopo passo, evidenzia l’elemento corrente e mostra i valori delle variabili e l’output."; +"simulation_controls" = "Controlli"; +"simulation_highlight_label" = "Evidenziazione"; +"simulation_highlight_last" = "Ultimo passo"; +"simulation_highlight_next" = "Prossimo passo"; +"simulation_not_available" = "Play esegue automaticamente la simulazione con una pausa di 0,5 secondi per passo."; +"simulation_play" = "Avvia"; +"simulation_pause" = "Pausa"; +"simulation_step" = "Passo"; +"simulation_stop" = "Stop"; +"simulation_input" = "Input"; +"simulation_input_placeholder" = "Nessun input richiesto."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Inserisci un numero intero."; +"simulation_trace" = "Ultimo passo"; +"simulation_trace_placeholder" = "Nessun passo ancora eseguito."; +"simulation_variables" = "Variabili"; +"simulation_variables_placeholder" = "Nessuna variabile per ora."; +"simulation_output" = "Output"; +"simulation_output_placeholder" = "Nessun output per ora."; +"action_delete_selection" = "Elimina selezione"; +"ctx_copy" = "Copia"; +"ctx_cut" = "Taglia"; +"ctx_paste" = "Incolla"; +"action_settings" = "Impostazioni"; +"action_about" = "Informazioni su VisuStruct"; +"recent_files_menu" = "File recenti"; +"recent_files_empty" = "Nessun file recente"; +"recent_files_clear" = "Cancella elenco"; +"recent_files_unavailable" = "Il file non è più disponibile."; + +/* In-app settings */ +"settings_language_title" = "Lingua"; +"settings_language_de" = "Tedesco"; +"settings_language_en" = "Inglese"; +"settings_language_es" = "Spagnolo"; +"settings_language_fr" = "Francese"; +"settings_language_it" = "Italiano"; +"settings_language_pl" = "Polacco"; +"settings_language_tr" = "Turco"; +"settings_language_ko" = "Coreano"; +"settings_language_ja" = "Giapponese"; +"settings_language_el" = "Greco"; +"settings_language_uk" = "Ucraino"; +"settings_language_ar" = "Arabo"; +"settings_language_ru" = "Russo"; +"settings_language_he" = "Ebraico"; +"settings_language_zh_hans" = "Cinese (semplificato)"; +"settings_language_zh_hant" = "Cinese (tradizionale)"; +"settings_language_ptpt" = "Portoghese"; +"settings_language_java" = "Java (parole chiave)"; + + +/* Error overlay */ +"error_title" = "Errore"; +"error_back_editor" = "Torna all’editor"; + +/* Toolbar */ +"toolbar_undo" = "Annulla"; +"toolbar_redo" = "Ripeti"; +"toolbar_new" = "Nuovo"; +"menu_open" = "Apri…"; +"menu_save" = "Salva"; +"menu_save_as" = "Salva con nome…"; +"menu_print" = "Stampa…"; +"menu_file" = "File"; +"menu_new" = "Nuovo"; +"menu_close" = "Chiudi"; + +/* Accessibility */ +"a11y_generate_code" = "Genera codice dal diagramma"; +"a11y_generate_code_locked" = "Genera codice, disponibile dopo l’acquisto"; +"a11y_unsaved_changes" = "Modifiche non salvate"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Genera codice"; +"codegen_gate_body" = "Il codice Java, Python e JavaScript dal diagramma si sbloccherà con un acquisto in-app (in arrivo)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Generatore di codice"; +"codegen_placeholder_body" = "Il codice generato apparirà qui."; +"codegen_placeholder_compare" = "Passa tra Java, Python e JavaScript per confrontare la sintassi (esempio sotto)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (condizione) {\\n istruzione();\\n} else {\\n alternativa();\\n}"; +"codegen_preview_python" = "if condizione:\\n istruzione()\\nelse:\\n alternativa()"; +"codegen_copy" = "Copia"; +"codegen_run_in_browser" = "Prova nel browser"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "Nuova scheda diagramma"; +"a11y_close_tab" = "Chiudi scheda"; + +"close_unsaved_title" = "Modifiche non salvate"; +"close_unsaved_message" = "Questo diagramma contiene modifiche non salvate. Vuoi salvarle prima di chiudere?"; +"close_unsaved_discard" = "Scarta"; +"close_unsaved_cancel" = "Annulla"; +"a11y_placeholder_drop" = "Rilascia un elemento qui per sostituire il segnaposto. Tieni premuto per trascinare e spostare."; +"a11y_node_drop" = "Tieni premuto un blocco, poi trascina: rilascia sul bordo superiore o inferiore per inserire prima o dopo. Rilascio al centro solo su un segnaposto ø."; +"a11y_codegen_panel_drag" = "Trascina per spostare il pannello del generatore di codice"; + +/* Diagram */ +"diagram_title_label" = "Titolo"; +"diagram_title_placeholder" = "Senza titolo"; + +/* Inspector */ +"inspector_no_selection" = "Nessun elemento selezionato — tocca un riquadro."; +"inspector_apply_text" = "Applica testo"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Tipo"; +"inspector_io_mode_statement" = "Istruzione"; +"inspector_io_mode_input" = "Input"; +"inspector_io_mode_output" = "Output"; +"inspector_io_mode_help_java_like" = "Input: input: … | Output: output: …"; +"inspector_add_case" = "Aggiungi caso"; +"inspector_remove_case" = "Rimuovi caso"; +"inspector_group_element" = "Testo dell’elemento"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Inserisci condizione…"; +"inspector_placeholder_selector" = "Inserisci selettore…"; +"inspector_placeholder_call" = "Inserisci chiamata…"; +"inspector_placeholder_break" = "Commento (opzionale)"; + +/* Element types */ +"element_anweisung" = "Istruzione"; +"element_verzweigung" = "Ramo"; +"element_fallauswahl" = "Selezione"; +"element_forSchleife" = "Ciclo for"; +"element_whileSchleife" = "Ciclo while"; +"element_doUntilSchleife" = "Ciclo do-while"; +"element_endlosschleife" = "Ciclo infinito"; +"element_aussprung" = "Uscita"; +"element_aufruf" = "Chiamata"; +"element_leerElement" = "Elemento vuoto"; + +/* Tabs */ +"tab_title_format" = "Diagramma %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Diagramma vuoto"; +"canvas_empty_hint" = "Trascina un elemento da “Elementi” qui."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "Selezione"; +"canvas_stub_anweisung" = "Istruzione"; +"canvas_stub_condition" = "Condizione"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "infinito"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Chiamata()"; + +/* About */ +"about_version_fmt" = "Versione %@ (%@)"; +"about_nav_title" = "Informazioni su VisuStruct"; +"about_features_heading" = "Funzionalità"; +"about_bullet_palette" = "Inserisci blocchi dalla tavolozza o trascinali nel diagramma"; +"about_bullet_edit" = "Modifica il diagramma: cambia il testo, seleziona elementi e rimuovili se necessario"; +"about_bullet_tabs" = "Più diagrammi in schede — ognuno con il proprio titolo"; +"about_bullet_file" = "Salva e riapri diagrammi come file .visustruct"; +"about_bullet_share" = "Condividi il diagramma come immagine (PNG)"; +"about_dateiformat_heading" = "Formato file"; +"about_dateiformat_part1" = "Il formato nativo di VisuStruct usa l’estensione "; +"about_dateiformat_part2" = ". Puoi conservare i diagrammi e scambiarli con altre app che supportano lo stesso formato."; +"about_dateiformat_strk" = "È possibile aprire anche i file con estensione .strk."; +"about_project_github_label" = "App Java (sorgente e release):"; +"about_web_label" = "Web:"; +"about_developer_label" = "Sviluppatore:"; +"about_lineage_heading" = "Origine"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "Fine"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Annulla inserimento"; +"phone_show_text_editor" = "Modifica testo"; +"phone_hide_text_editor" = "Comprimi"; +"phone_title_done" = "Fine"; + +/* Alerts */ +"err_save_failed_fmt" = "Impossibile salvare: %@"; +"err_share_prepare_failed_fmt" = "Impossibile preparare la condivisione: %@"; +"err_diagram_too_small_export" = "Il diagramma è troppo piccolo — niente da esportare."; +"err_image_render_failed" = "Impossibile creare l’immagine."; +"err_diagram_too_small_print" = "Il diagramma è troppo piccolo — niente da stampare."; +"err_print_unavailable" = "La stampa non è disponibile su questo dispositivo."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Suggerimento nome file"; +"settings_export_filename_picker" = "Formato"; +"settings_export_filename_date_title" = "Con data"; +"settings_export_filename_title_only" = "Senza data"; +"settings_export_filename_footer_with_date" = "Con data: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Senza data: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simulazione terminata."; +"sim_notice_infinite_loop_empty" = "Il ciclo infinito non ha corpo."; +"sim_notice_unsupported_statement_fmt" = "Istruzione non supportata: %@"; +"sim_notice_invalid_expression_fmt" = "Espressione non valida: %@"; +"sim_notice_unknown_variable_fmt" = "Variabile sconosciuta: %@"; +"sim_notice_division_by_zero" = "Divisione per zero."; +"sim_notice_whole_number_expected" = "Inserisci un numero intero."; +"sim_notice_number_expected" = "Inserisci un numero."; +"sim_notice_boolean_expected" = "Inserisci true o false."; +"sim_notice_subprogram_not_found_fmt" = "Nessun diagramma aperto si chiama %@. La chiamata è stata saltata."; +"sim_notice_call_too_deep" = "Troppe chiamate annidate. Un sottoprogramma chiama se stesso?"; + +"codegen_pseudocode_toggle" = "Pseudocodice (codice non eseguibile)"; +"codegen_pseudocode_note" = "Pseudocodice – non è un programma eseguibile"; +"codegen_pseudocode_hint" = "Questo diagramma è contrassegnato come pseudocodice. Il codice è solo una bozza e non può essere eseguito."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-Dk8F86qS.js b/website/app/assets/Localizable-Dk8F86qS.js new file mode 100644 index 00000000..f5ef6ff8 --- /dev/null +++ b/website/app/assets/Localizable-Dk8F86qS.js @@ -0,0 +1,255 @@ +const e=`/* Palette */ +"palette_header" = "Elemente"; +"inspector_header" = "Objektinspektor"; + +/* Aktionen */ +"action_share_png" = "Grafik teilen …"; +"action_share_document" = "Datei teilen …"; +"action_export_pdf" = "PDF-Vorschau …"; +"action_generate_code" = "Code erzeugen …"; +"action_simulation" = "Simulation"; +"action_diagram" = "Diagramm"; +"simulation_placeholder_body" = "Der Simulationsmodus führt das Diagramm Schritt für Schritt aus, markiert das aktuelle Element und zeigt Variablenwerte und Ausgaben."; +"simulation_controls" = "Steuerung"; +"simulation_highlight_label" = "Markierung"; +"simulation_highlight_last" = "Letzter Schritt"; +"simulation_highlight_next" = "Nächster Schritt"; +"simulation_not_available" = "Play führt die Simulation automatisch mit 0,5 Sekunden Pause pro Schritt aus."; +"simulation_play" = "Start"; +"simulation_pause" = "Pause"; +"simulation_step" = "Schritt"; +"simulation_stop" = "Stopp"; +"simulation_input" = "Eingabe"; +"simulation_input_placeholder" = "Keine Eingabe erforderlich."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Bitte eine ganze Zahl eingeben."; +"simulation_trace" = "Letzter Schritt"; +"simulation_trace_placeholder" = "Noch kein Schritt ausgeführt."; +"simulation_variables" = "Variablen"; +"simulation_variables_placeholder" = "Noch keine Variablen."; +"simulation_output" = "Ausgabe"; +"simulation_output_placeholder" = "Noch keine Ausgabe."; +"action_delete_selection" = "Auswahl löschen"; +"ctx_copy" = "Kopieren"; +"ctx_cut" = "Ausschneiden"; +"ctx_paste" = "Einfügen"; +"action_settings" = "Einstellungen"; +"action_about" = "Über VisuStruct"; +"recent_files_menu" = "Zuletzt verwendet"; +"recent_files_empty" = "Keine zuletzt verwendeten Dateien"; +"recent_files_clear" = "Liste leeren"; +"recent_files_unavailable" = "Datei ist nicht mehr verfügbar."; + +/* Einstellungen (In-App) */ +"settings_language_title" = "Sprache"; +"settings_language_de" = "Deutsch"; +"settings_language_en" = "Englisch"; +"settings_language_es" = "Spanisch"; +"settings_language_fr" = "Französisch"; +"settings_language_it" = "Italienisch"; +"settings_language_pl" = "Polnisch"; +"settings_language_tr" = "Türkisch"; +"settings_language_ko" = "Koreanisch"; +"settings_language_ja" = "Japanisch"; +"settings_language_el" = "Griechisch"; +"settings_language_uk" = "Ukrainisch"; +"settings_language_ar" = "Arabisch"; +"settings_language_ru" = "Russisch"; +"settings_language_he" = "Hebräisch"; +"settings_language_zh_hans" = "Chinesisch (vereinfacht)"; +"settings_language_zh_hant" = "Chinesisch (traditionell)"; +"settings_language_ptpt" = "Portugiesisch"; +"settings_language_java" = "Java (Schlüsselwörter)"; + + + +"settings_ui_scale_section" = "Textgröße"; +"settings_ui_scale_canvas" = "Struktogramm"; +"settings_ui_scale_inspector" = "Eingabe unten"; +"settings_ui_scale_small" = "Klein"; +"settings_ui_scale_medium" = "Mittel"; +"settings_ui_scale_large" = "Groß"; +"settings_ui_scale_extra_large" = "Sehr groß"; + +"settings_export_filename_section" = "Dateivorschlag"; +"settings_export_filename_picker" = "Format"; +"settings_export_filename_date_title" = "Mit Datum"; +"settings_export_filename_title_only" = "Ohne Datum"; +"settings_export_filename_footer_with_date" = "Mit Datum: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Ohne Datum: Filename.visustruct"; + + +/* Fehler-Overlay */ +"error_title" = "Fehler"; +"error_back_editor" = "Zurück zum Editor"; + +/* Toolbar */ +"toolbar_undo" = "Rückgängig"; +"toolbar_redo" = "Wiederholen"; +"toolbar_new" = "Neu"; +"menu_open" = "Öffnen …"; +"menu_save" = "Speichern"; +"menu_save_as" = "Speichern unter …"; +"menu_print" = "Drucken …"; +"menu_file" = "Ablage"; +"menu_new" = "Neu"; +"menu_close" = "Schließen"; + +/* Barrierefreiheit */ +"a11y_generate_code" = "Code aus dem Struktogramm erzeugen"; +"a11y_generate_code_locked" = "Code erzeugen, nach dem Kauf verfügbar"; +"a11y_unsaved_changes" = "Ungespeicherte Änderungen"; + +/* Code-Generator (IAP folgt) */ +"codegen_gate_title" = "Code erzeugen"; +"codegen_gate_body" = "Java-, Python- und JavaScript-Code aus dem Struktogramm wird über einen In-App-Kauf freigeschaltet (demnächst)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Code-Generator"; +"codegen_placeholder_body" = "Hier erscheint später der erzeugte Code."; +"codegen_placeholder_compare" = "Zwischen Java, Python und JavaScript wechseln, um die Syntax zu vergleichen (Beispiel unten)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (bedingung) {\\n anweisung();\\n} else {\\n alternative();\\n}"; +"codegen_preview_python" = "if bedingung:\\n anweisung()\\nelse:\\n alternative()"; +"codegen_generated_hint" = "Vorschau aus dem aktuellen Struktogramm (Java 17, Python 3.10+, modernes JavaScript)."; +"codegen_copy" = "Kopieren"; +"codegen_run_in_browser" = "Im Browser testen"; +"codegen_save_java" = "Java speichern …"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "Weiteres Struktogramm"; +"a11y_close_tab" = "Reiter schließen"; + +"close_unsaved_title" = "Ungespeicherte Änderungen"; +"close_unsaved_message" = "Dieses Diagramm enthält ungespeicherte Änderungen. Möchtest du sie vor dem Schließen speichern?"; +"close_unsaved_discard" = "Verwerfen"; +"close_unsaved_cancel" = "Abbrechen"; +"a11y_placeholder_drop" = "Element hier ablegen, um den Platzhalter zu ersetzen. Lang drücken und ziehen zum Verschieben."; +"a11y_node_drop" = "Block lang drücken, dann ziehen: am Ziel am oberen oder unteren Rand ablegen (davor/danach). In die Mitte nur auf Platzhalter ø."; +"a11y_codegen_panel_drag" = "Codegenerator-Panel verschieben"; + +/* Diagramm */ +"diagram_title_label" = "Titel"; +"diagram_title_placeholder" = "Ohne Titel"; + +/* Inspector */ +"inspector_no_selection" = "Kein Element gewählt — tippe auf eine Kachel."; +"inspector_apply_text" = "Text übernehmen"; +"inspector_for_init" = "Start"; +"inspector_for_condition" = "Bedingung"; +"inspector_for_step" = "Schritt"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; +"inspector_io_mode_title" = "Art"; +"inspector_io_mode_statement" = "Anweisung"; +"inspector_io_mode_input" = "Eingabe"; +"inspector_io_mode_output" = "Ausgabe"; +"inspector_io_mode_help_java_like" = "Eingabe: input: … | Ausgabe: output: …"; +"inspector_add_case" = "Weiteren Fall hinzufügen"; +"inspector_remove_case" = "Fall entfernen"; +"inspector_group_element" = "Elementtext"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Bedingung einfügen …"; +"inspector_placeholder_selector" = "Auswahl einfügen …"; +"inspector_placeholder_call" = "Aufruf einfügen …"; +"inspector_placeholder_break" = "Kommentar (optional)"; + +/* Elementtypen (Palette + Inspector) */ +"element_anweisung" = "Anweisung"; +"element_verzweigung" = "Verzweigung"; +"element_fallauswahl" = "Fallauswahl"; +"element_forSchleife" = "For-Schleife"; +"element_whileSchleife" = "While-Schleife"; +"element_doUntilSchleife" = "Do-while-Schleife"; +"element_endlosschleife" = "Endlosschleife"; +"element_aussprung" = "Aussprung"; +"element_aufruf" = "Aufruf"; +"element_leerElement" = "Leeres Element"; + +/* Tabs */ +"tab_title_format" = "Diagramm %d"; + +/* Leeres Canvas */ +"canvas_empty_title" = "Leeres Struktogramm"; +"canvas_empty_hint" = "Element aus „Elemente“ hierher ziehen."; + +/* Diagramm: Texte neuer Elemente & Spaltenköpfe (Anzeige) */ +"canvas_stub_fallauswahl" = "Fallauswahl"; +"canvas_stub_anweisung" = "Anweisung"; +"canvas_stub_condition" = "Bedingung"; +"canvas_stub_for" = "for 0 < i < anzahl"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "endless"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Aufruf()"; + +/* Über */ +"about_version_fmt" = "Version %@ (%@)"; +"about_nav_title" = "Über VisuStruct"; +"about_features_heading" = "Funktionen"; +"about_bullet_palette" = "Bausteine aus der Palette einfügen oder per Drag & Drop ins Diagramm ziehen"; +"about_bullet_edit" = "Struktogramm bearbeiten: Texte anpassen, Elemente auswählen und bei Bedarf entfernen"; +"about_bullet_tabs" = "Mehrere Diagramme in Tabs – jeweils mit eigenem Titel"; +"about_bullet_file" = "Diagramme als .visustruct-Datei speichern und wieder öffnen"; +"about_bullet_share" = "Struktogramm als Grafik teilen (PNG)"; +"about_dateiformat_heading" = "Dateiformat"; +"about_dateiformat_part1" = "Das native Dateiformat von VisuStruct nutzt die Endung "; +"about_dateiformat_part2" = ". So kannst du Diagramme sichern und mit anderen Programmen austauschen, die dasselbe Format unterstützen."; +"about_dateiformat_strk" = "Zusätzlich können Dateien mit der Endung .strk geöffnet werden."; +"about_project_github_label" = "Java-App (Quellen & Releases):"; +"about_web_label" = "Web:"; +"about_developer_label" = "Entwickler:"; +"about_lineage_heading" = "Herkunft"; +"about_lineage_body" = "VisuStruct entstand ursprünglich als Java-Desktop-App und bleibt für den schulischen Einsatz plattformübergreifend verfügbar. Die aktuelle Swift/SwiftUI-Version ist die moderne native App für Mac, iPad und iPhone und bleibt kompatibel mit dem .visustruct-Dateiformat. Sie basiert auf der ursprünglichen Open-Source-Arbeit von Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java-Upstream:"; +"about_done" = "Fertig"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: Einfügen per Tap */ +"phone_insert_cancel" = "Einfügen abbrechen"; +"phone_show_text_editor" = "Text bearbeiten"; +"phone_hide_text_editor" = "Einklappen"; +"phone_title_done" = "Fertig"; + +/* Meldungen */ +"err_save_failed_fmt" = "Speichern fehlgeschlagen: %@"; +"err_share_prepare_failed_fmt" = "Teilen konnte nicht vorbereitet werden: %@"; +"err_diagram_too_small_export" = "Diagramm ist zu klein — nichts zu exportieren."; +"err_image_render_failed" = "Grafik konnte nicht erzeugt werden."; +"err_diagram_too_small_print" = "Diagramm ist zu klein — nichts zu drucken."; +"err_print_unavailable" = "Drucken ist auf diesem Gerät nicht verfügbar."; + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simulation beendet."; +"sim_notice_infinite_loop_empty" = "Die Endlosschleife hat keinen Rumpf."; +"sim_notice_unsupported_statement_fmt" = "Nicht unterstützte Anweisung: %@"; +"sim_notice_invalid_expression_fmt" = "Ungültiger Ausdruck: %@"; +"sim_notice_unknown_variable_fmt" = "Unbekannte Variable: %@"; +"sim_notice_division_by_zero" = "Division durch null."; +"sim_notice_whole_number_expected" = "Bitte eine ganze Zahl eingeben."; +"sim_notice_number_expected" = "Bitte eine Zahl eingeben."; +"sim_notice_boolean_expected" = "Bitte true oder false eingeben."; +"sim_notice_subprogram_not_found_fmt" = "Kein offenes Diagramm heißt %@. Der Aufruf wurde übersprungen."; +"sim_notice_call_too_deep" = "Zu viele verschachtelte Aufrufe. Ruft sich ein Unterprogramm selbst auf?"; + +"codegen_pseudocode_toggle" = "Pseudocode (kein lauffähiger Code)"; +"codegen_pseudocode_note" = "Pseudocode – kein lauffähiges Programm"; +"codegen_pseudocode_hint" = "Dieses Diagramm ist als Pseudocode markiert. Der Code ist nur eine Skizze und lässt sich nicht ausführen."; + +"course_title" = "Kurs"; +"course_intro" = "Programmieren lernen, Schritt für Schritt: vom ersten Struktogramm bis zum eigenen Java-Programm."; +"course_bullet_lessons" = "Alle Lektionen mit Erklärungen, Wissenstests und Übungen"; +"course_bullet_java" = "In jeder Lektion Programmieraufgaben „Jetzt in Java“"; +"course_bullet_games" = "Lernspiele und gestufte Tipps"; +"course_bullet_once" = "Einmal kaufen, auf iPhone, iPad und Mac nutzen"; +"course_unlocked" = "Kurs freigeschaltet – danke!"; +"course_free_note" = "Struktogramme erstellen, Simulation und Code-Export bleiben kostenlos."; +"course_restore" = "Käufe wiederherstellen"; +"course_restore_done" = "Dein Kurs-Kauf wurde wiederhergestellt."; +"course_restore_none" = "Für diesen Apple Account wurde kein Kurs-Kauf gefunden."; +"course_unavailable" = "Der Kurs kann gerade nicht aus dem App Store geladen werden. Bitte prüfe die Internetverbindung und versuche es später noch einmal."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-DqIDp_hh.js b/website/app/assets/Localizable-DqIDp_hh.js new file mode 100644 index 00000000..7a8b5baa --- /dev/null +++ b/website/app/assets/Localizable-DqIDp_hh.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "元素"; +"inspector_header" = "物件檢閱器"; + +/* Actions */ +"action_share_png" = "分享圖片…"; +"action_share_document" = "分享檔案…"; +"action_export_pdf" = "PDF 預覽…"; +"action_generate_code" = "產生程式碼…"; +"action_simulation" = "模擬"; +"action_diagram" = "圖表"; +"simulation_placeholder_body" = "模擬模式會逐步執行圖表,醒目提示目前元素,並顯示變數值和輸出。"; +"simulation_controls" = "控制"; +"simulation_highlight_label" = "醒目提示"; +"simulation_highlight_last" = "上一步"; +"simulation_highlight_next" = "下一步"; +"simulation_not_available" = "Play 會自動執行模擬,每步暫停 0.5 秒。"; +"simulation_play" = "播放"; +"simulation_pause" = "暫停"; +"simulation_step" = "單步"; +"simulation_stop" = "停止"; +"simulation_input" = "輸入"; +"simulation_input_placeholder" = "不需要輸入。"; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "請輸入一個整數。"; +"simulation_trace" = "上一步"; +"simulation_trace_placeholder" = "尚未執行任何步驟。"; +"simulation_variables" = "變數"; +"simulation_variables_placeholder" = "暫無變數。"; +"simulation_output" = "輸出"; +"simulation_output_placeholder" = "暫無輸出。"; +"action_delete_selection" = "刪除選取項目"; +"ctx_copy" = "複製"; +"ctx_cut" = "剪下"; +"ctx_paste" = "貼上"; +"action_settings" = "設定"; +"action_about" = "關於 VisuStruct"; +"recent_files_menu" = "最近檔案"; +"recent_files_empty" = "沒有最近檔案"; +"recent_files_clear" = "清除列表"; +"recent_files_unavailable" = "檔案已無法使用。"; + +/* In-app settings */ +"settings_language_title" = "語言"; +"settings_language_de" = "德文"; +"settings_language_en" = "英文"; +"settings_language_es" = "西班牙文"; +"settings_language_fr" = "法文"; +"settings_language_it" = "義大利文"; +"settings_language_pl" = "波蘭文"; +"settings_language_tr" = "土耳其文"; +"settings_language_ko" = "韓文"; +"settings_language_ja" = "日文"; +"settings_language_el" = "希臘文"; +"settings_language_uk" = "烏克蘭文"; +"settings_language_ar" = "阿拉伯文"; +"settings_language_ru" = "俄文"; +"settings_language_he" = "希伯來文"; +"settings_language_zh_hans" = "中文(簡體)"; +"settings_language_zh_hant" = "中文(繁體)"; +"settings_language_ptpt" = "葡萄牙文"; +"settings_language_java" = "Java(關鍵字)"; + + +/* Error overlay */ +"error_title" = "錯誤"; +"error_back_editor" = "回到編輯器"; + +/* Toolbar */ +"toolbar_undo" = "復原"; +"toolbar_redo" = "重做"; +"toolbar_new" = "新增"; +"menu_open" = "開啟…"; +"menu_save" = "儲存"; +"menu_save_as" = "另存新檔…"; +"menu_print" = "列印…"; +"menu_file" = "檔案"; +"menu_new" = "新增"; +"menu_close" = "關閉"; + +/* Accessibility */ +"a11y_generate_code" = "從結構圖產生程式碼"; +"a11y_generate_code_locked" = "產生程式碼(購買後可用)"; +"a11y_unsaved_changes" = "未儲存的變更"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "產生程式碼"; +"codegen_gate_body" = "將透過 App 內購買解鎖從圖表產生的 Java、Python 與 JavaScript 程式碼(即將推出)。"; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "程式碼產生器"; +"codegen_placeholder_body" = "產生的程式碼會顯示在這裡。"; +"codegen_placeholder_compare" = "在 Java、Python 與 JavaScript 之間切換以比較語法(下方範例)。"; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (條件) {\\n 陳述式();\\n} else {\\n 替代();\\n}"; +"codegen_preview_python" = "if 條件:\\n 陳述式()\\nelse:\\n 替代()"; +"codegen_copy" = "複製"; +"codegen_run_in_browser" = "在瀏覽器中測試"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "新增圖表分頁"; +"a11y_close_tab" = "關閉分頁"; + +"close_unsaved_title" = "未儲存的變更"; +"close_unsaved_message" = "此圖表包含未儲存的變更。關閉前要儲存嗎?"; +"close_unsaved_discard" = "捨棄"; +"close_unsaved_cancel" = "取消"; +"a11y_placeholder_drop" = "將元素拖放到這裡以取代佔位符。長按可拖曳移動。"; +"a11y_node_drop" = "長按區塊並拖曳:放到目標上緣或下緣以插入到前/後。僅能在 ø 佔位符上置中放下。"; +"a11y_codegen_panel_drag" = "拖移以移動程式碼產生器面板"; + +/* Diagram */ +"diagram_title_label" = "標題"; +"diagram_title_placeholder" = "無標題"; + +/* Inspector */ +"inspector_no_selection" = "未選取任何元素 — 點一下區塊。"; +"inspector_apply_text" = "套用文字"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "類型"; +"inspector_io_mode_statement" = "敘述"; +"inspector_io_mode_input" = "輸入"; +"inspector_io_mode_output" = "輸出"; +"inspector_io_mode_help_java_like" = "輸入: input: … | 輸出: output: …"; +"inspector_add_case" = "新增分支"; +"inspector_remove_case" = "移除分支"; +"inspector_group_element" = "元素文字"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "輸入條件…"; +"inspector_placeholder_selector" = "輸入選擇式…"; +"inspector_placeholder_call" = "輸入呼叫…"; +"inspector_placeholder_break" = "註解(選填)"; + +/* Element types */ +"element_anweisung" = "陳述式"; +"element_verzweigung" = "分支"; +"element_fallauswahl" = "選擇"; +"element_forSchleife" = "for 迴圈"; +"element_whileSchleife" = "while 迴圈"; +"element_doUntilSchleife" = "do-while 迴圈"; +"element_endlosschleife" = "無限迴圈"; +"element_aussprung" = "跳出"; +"element_aufruf" = "呼叫"; +"element_leerElement" = "空元素"; + +/* Tabs */ +"tab_title_format" = "圖表 %d"; + +/* Empty canvas */ +"canvas_empty_title" = "空結構圖"; +"canvas_empty_hint" = "從「元素」拖曳一個區塊到這裡。"; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "選擇"; +"canvas_stub_anweisung" = "陳述式"; +"canvas_stub_condition" = "條件"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "無限"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "呼叫()"; + +/* About */ +"about_version_fmt" = "版本 %@ (%@)"; +"about_nav_title" = "關於 VisuStruct"; +"about_features_heading" = "功能"; +"about_bullet_palette" = "從調色盤插入區塊,或拖曳到圖表"; +"about_bullet_edit" = "編輯圖表:修改文字、選取元素,必要時刪除"; +"about_bullet_tabs" = "多個圖表分頁——每個都有自己的標題"; +"about_bullet_file" = "將圖表儲存並以 .visustruct 檔案重新開啟"; +"about_bullet_share" = "將結構圖分享為圖片(PNG)"; +"about_dateiformat_heading" = "檔案格式"; +"about_dateiformat_part1" = "VisuStruct 的原生格式使用副檔名 "; +"about_dateiformat_part2" = "。你可以保存圖表,並與支援相同格式的其他 App 交換。"; +"about_dateiformat_strk" = "也可以開啟 .strk 副檔名的檔案。"; +"about_project_github_label" = "Java App(原始碼與版本):"; +"about_web_label" = "網站:"; +"about_developer_label" = "開發者:"; +"about_lineage_heading" = "沿革"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java 上游:"; +"about_done" = "完成"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "取消插入"; +"phone_show_text_editor" = "編輯文字"; +"phone_hide_text_editor" = "收合"; +"phone_title_done" = "完成"; + +/* Alerts */ +"err_save_failed_fmt" = "無法儲存:%@"; +"err_share_prepare_failed_fmt" = "無法準備分享:%@"; +"err_diagram_too_small_export" = "圖表太小——沒有可匯出的內容。"; +"err_image_render_failed" = "無法建立圖片。"; +"err_diagram_too_small_print" = "圖表太小——沒有可列印的內容。"; +"err_print_unavailable" = "此裝置不支援列印。"; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "檔名建議"; +"settings_export_filename_picker" = "格式"; +"settings_export_filename_date_title" = "含日期"; +"settings_export_filename_title_only" = "不含日期"; +"settings_export_filename_footer_with_date" = "含日期: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "不含日期: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "模擬已結束。"; +"sim_notice_infinite_loop_empty" = "無限迴圈沒有迴圈主體。"; +"sim_notice_unsupported_statement_fmt" = "不支援的敘述:%@"; +"sim_notice_invalid_expression_fmt" = "無效的運算式:%@"; +"sim_notice_unknown_variable_fmt" = "未知變數:%@"; +"sim_notice_division_by_zero" = "除數為零。"; +"sim_notice_whole_number_expected" = "請輸入整數。"; +"sim_notice_number_expected" = "請輸入數字。"; +"sim_notice_boolean_expected" = "請輸入 true 或 false。"; +"sim_notice_subprogram_not_found_fmt" = "沒有名為 %@ 的已開啟圖表。已略過該呼叫。"; +"sim_notice_call_too_deep" = "巢狀呼叫過多。是否有子程式呼叫了自己?"; + +"codegen_pseudocode_toggle" = "虛擬碼(無法執行的程式碼)"; +"codegen_pseudocode_note" = "虛擬碼 – 不是可執行的程式"; +"codegen_pseudocode_hint" = "此圖已標示為虛擬碼。程式碼只是草稿,無法執行。"; +`;export{e as default}; diff --git a/website/app/assets/Localizable-LSTVB2Q5.js b/website/app/assets/Localizable-LSTVB2Q5.js new file mode 100644 index 00000000..1ac68831 --- /dev/null +++ b/website/app/assets/Localizable-LSTVB2Q5.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "Elementos"; +"inspector_header" = "Inspector de objetos"; + +/* Actions */ +"action_share_png" = "Compartir imagen…"; +"action_share_document" = "Compartir archivo…"; +"action_export_pdf" = "Vista previa PDF…"; +"action_generate_code" = "Generar código…"; +"action_simulation" = "Simulación"; +"action_diagram" = "Diagrama"; +"simulation_placeholder_body" = "El modo de simulación ejecuta el diagrama paso a paso, resalta el elemento actual y muestra los valores de variables y las salidas."; +"simulation_controls" = "Controles"; +"simulation_highlight_label" = "Resaltado"; +"simulation_highlight_last" = "Último paso"; +"simulation_highlight_next" = "Siguiente paso"; +"simulation_not_available" = "Play ejecuta la simulación automáticamente con una pausa de 0,5 segundos por paso."; +"simulation_play" = "Reproducir"; +"simulation_pause" = "Pausa"; +"simulation_step" = "Paso"; +"simulation_stop" = "Detener"; +"simulation_input" = "Entrada"; +"simulation_input_placeholder" = "No se requiere entrada."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Introduce un número entero."; +"simulation_trace" = "Último paso"; +"simulation_trace_placeholder" = "Aún no se ha ejecutado ningún paso."; +"simulation_variables" = "Variables"; +"simulation_variables_placeholder" = "Aún no hay variables."; +"simulation_output" = "Salida"; +"simulation_output_placeholder" = "Aún no hay salida."; +"action_delete_selection" = "Eliminar selección"; +"ctx_copy" = "Copiar"; +"ctx_cut" = "Cortar"; +"ctx_paste" = "Pegar"; +"action_settings" = "Ajustes"; +"action_about" = "Acerca de VisuStruct"; +"recent_files_menu" = "Recientes"; +"recent_files_empty" = "No hay archivos recientes"; +"recent_files_clear" = "Borrar lista"; +"recent_files_unavailable" = "El archivo ya no está disponible."; + +/* In-app settings */ +"settings_language_title" = "Idioma"; +"settings_language_de" = "Alemán"; +"settings_language_en" = "Inglés"; +"settings_language_es" = "Español"; +"settings_language_fr" = "Francés"; +"settings_language_it" = "Italiano"; +"settings_language_pl" = "Polaco"; +"settings_language_tr" = "Turco"; +"settings_language_ko" = "Coreano"; +"settings_language_ja" = "Japonés"; +"settings_language_el" = "Griego"; +"settings_language_uk" = "Ucraniano"; +"settings_language_ar" = "Árabe"; +"settings_language_ru" = "Ruso"; +"settings_language_he" = "Hebreo"; +"settings_language_zh_hans" = "Chino (simplificado)"; +"settings_language_zh_hant" = "Chino (tradicional)"; +"settings_language_ptpt" = "Portugués"; +"settings_language_java" = "Java (palabras clave)"; + + +/* Error overlay */ +"error_title" = "Error"; +"error_back_editor" = "Volver al editor"; + +/* Toolbar */ +"toolbar_undo" = "Deshacer"; +"toolbar_redo" = "Rehacer"; +"toolbar_new" = "Nuevo"; +"menu_open" = "Abrir…"; +"menu_save" = "Guardar"; +"menu_save_as" = "Guardar como…"; +"menu_print" = "Imprimir…"; +"menu_file" = "Archivo"; +"menu_new" = "Nuevo"; +"menu_close" = "Cerrar"; + +/* Accessibility */ +"a11y_generate_code" = "Generar código a partir del diagrama"; +"a11y_generate_code_locked" = "Generar código, disponible tras la compra"; +"a11y_unsaved_changes" = "Cambios sin guardar"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Generar código"; +"codegen_gate_body" = "El código Java, Python y JavaScript a partir de tu diagrama estará disponible mediante una compra integrada (próximamente)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Generador de código"; +"codegen_placeholder_body" = "Aquí aparecerá el código generado."; +"codegen_placeholder_compare" = "Cambia entre Java, Python y JavaScript para comparar la sintaxis (ejemplo abajo)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (condición) {\\n instrucción();\\n} else {\\n alternativa();\\n}"; +"codegen_preview_python" = "if condición:\\n instrucción()\\nelse:\\n alternativa()"; +"codegen_copy" = "Copiar"; +"codegen_run_in_browser" = "Probar en el navegador"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "Nueva pestaña de diagrama"; +"a11y_close_tab" = "Cerrar pestaña"; + +"close_unsaved_title" = "Cambios sin guardar"; +"close_unsaved_message" = "Este diagrama contiene cambios sin guardar. ¿Quieres guardarlos antes de cerrar?"; +"close_unsaved_discard" = "Descartar"; +"close_unsaved_cancel" = "Cancelar"; +"a11y_placeholder_drop" = "Suelta un elemento aquí para reemplazar el marcador. Mantén pulsado para arrastrar y mover."; +"a11y_node_drop" = "Mantén pulsado un bloque y arrastra: suelta en el borde superior o inferior para insertar antes o después. Suelta en el centro solo sobre un marcador ø."; +"a11y_codegen_panel_drag" = "Arrastra para mover el panel del generador de código"; + +/* Diagram */ +"diagram_title_label" = "Título"; +"diagram_title_placeholder" = "Sin título"; + +/* Inspector */ +"inspector_no_selection" = "Ningún elemento seleccionado — toca una pieza."; +"inspector_apply_text" = "Aplicar texto"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Tipo"; +"inspector_io_mode_statement" = "Instrucción"; +"inspector_io_mode_input" = "Entrada"; +"inspector_io_mode_output" = "Salida"; +"inspector_io_mode_help_java_like" = "Entrada: input: … | Salida: output: …"; +"inspector_add_case" = "Añadir caso"; +"inspector_remove_case" = "Eliminar caso"; +"inspector_group_element" = "Texto del elemento"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Insertar condición…"; +"inspector_placeholder_selector" = "Insertar selector…"; +"inspector_placeholder_call" = "Insertar llamada…"; +"inspector_placeholder_break" = "Comentario (opcional)"; + +/* Element types */ +"element_anweisung" = "Instrucción"; +"element_verzweigung" = "Decisión"; +"element_fallauswahl" = "Selección"; +"element_forSchleife" = "Bucle for"; +"element_whileSchleife" = "Bucle while"; +"element_doUntilSchleife" = "Bucle do-while"; +"element_endlosschleife" = "Bucle infinito"; +"element_aussprung" = "Salida"; +"element_aufruf" = "Llamada"; +"element_leerElement" = "Elemento vacío"; + +/* Tabs */ +"tab_title_format" = "Diagrama %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Diagrama vacío"; +"canvas_empty_hint" = "Arrastra un elemento de «Elementos» aquí."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "Selección"; +"canvas_stub_anweisung" = "Instrucción"; +"canvas_stub_condition" = "Condición"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "infinito"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Llamada()"; + +/* About */ +"about_version_fmt" = "Versión %@ (%@)"; +"about_nav_title" = "Acerca de VisuStruct"; +"about_features_heading" = "Funciones"; +"about_bullet_palette" = "Insertar bloques desde la paleta o arrastrarlos al diagrama"; +"about_bullet_edit" = "Editar el diagrama: cambiar texto, seleccionar elementos y eliminarlos si es necesario"; +"about_bullet_tabs" = "Varios diagramas en pestañas — cada uno con su propio título"; +"about_bullet_file" = "Guardar y volver a abrir diagramas como archivos .visustruct"; +"about_bullet_share" = "Compartir el diagrama como imagen (PNG)"; +"about_dateiformat_heading" = "Formato de archivo"; +"about_dateiformat_part1" = "El formato nativo de VisuStruct usa la extensión "; +"about_dateiformat_part2" = ". Puedes guardar diagramas e intercambiarlos con otras apps compatibles."; +"about_dateiformat_strk" = "También se pueden abrir archivos con la extensión .strk."; +"about_project_github_label" = "App Java (código y versiones):"; +"about_web_label" = "Web:"; +"about_developer_label" = "Desarrollador:"; +"about_lineage_heading" = "Origen"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "Hecho"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Cancelar inserción"; +"phone_show_text_editor" = "Editar texto"; +"phone_hide_text_editor" = "Contraer"; +"phone_title_done" = "Listo"; + +/* Alerts */ +"err_save_failed_fmt" = "No se pudo guardar: %@"; +"err_share_prepare_failed_fmt" = "No se pudo preparar para compartir: %@"; +"err_diagram_too_small_export" = "El diagrama es demasiado pequeño — nada que exportar."; +"err_image_render_failed" = "No se pudo crear la imagen."; +"err_diagram_too_small_print" = "El diagrama es demasiado pequeño — nada que imprimir."; +"err_print_unavailable" = "La impresión no está disponible en este dispositivo."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Sugerencia de nombre de archivo"; +"settings_export_filename_picker" = "Formato"; +"settings_export_filename_date_title" = "Con fecha"; +"settings_export_filename_title_only" = "Sin fecha"; +"settings_export_filename_footer_with_date" = "Con fecha: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Sin fecha: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simulación terminada."; +"sim_notice_infinite_loop_empty" = "El bucle infinito no tiene cuerpo."; +"sim_notice_unsupported_statement_fmt" = "Instrucción no admitida: %@"; +"sim_notice_invalid_expression_fmt" = "Expresión no válida: %@"; +"sim_notice_unknown_variable_fmt" = "Variable desconocida: %@"; +"sim_notice_division_by_zero" = "División por cero."; +"sim_notice_whole_number_expected" = "Introduce un número entero."; +"sim_notice_number_expected" = "Introduce un número."; +"sim_notice_boolean_expected" = "Introduce true o false."; +"sim_notice_subprogram_not_found_fmt" = "Ningún diagrama abierto se llama %@. Se omitió la llamada."; +"sim_notice_call_too_deep" = "Demasiadas llamadas anidadas. ¿Un subprograma se llama a sí mismo?"; + +"codegen_pseudocode_toggle" = "Pseudocódigo (código no ejecutable)"; +"codegen_pseudocode_note" = "Pseudocódigo – no es un programa ejecutable"; +"codegen_pseudocode_hint" = "Este diagrama está marcado como pseudocódigo. El código es solo un esbozo y no se puede ejecutar."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-M33nNbEe.js b/website/app/assets/Localizable-M33nNbEe.js new file mode 100644 index 00000000..ca1fdc43 --- /dev/null +++ b/website/app/assets/Localizable-M33nNbEe.js @@ -0,0 +1,153 @@ +const e=`/* NOTE: Initial Swedish localization. */ +"palette_header" = "Element"; +"inspector_header" = "Objektinspektör"; + +/* Actions */ +"action_share_png" = "Dela bild…"; +"action_share_document" = "Dela fil…"; +"action_export_pdf" = "Förhandsvisa PDF…"; +"action_generate_code" = "Generera kod…"; +"action_simulation" = "Simulering"; +"action_diagram" = "Diagram"; +"simulation_placeholder_body" = "Simuleringsläget kör diagrammet steg för steg, markerar det aktuella elementet och visar variabelvärden och utdata."; +"simulation_controls" = "Kontroller"; +"simulation_highlight_label" = "Markering"; +"simulation_highlight_last" = "Senaste steg"; +"simulation_highlight_next" = "Nästa steg"; +"simulation_not_available" = "Play kör simuleringen automatiskt med 0,5 sekunders paus per steg."; +"simulation_play" = "Spela"; +"simulation_pause" = "Paus"; +"simulation_step" = "Steg"; +"simulation_stop" = "Stopp"; +"simulation_input" = "Inmatning"; +"simulation_input_placeholder" = "Ingen inmatning krävs."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Ange ett heltal."; +"simulation_trace" = "Senaste steg"; +"simulation_trace_placeholder" = "Inget steg har körts ännu."; +"simulation_variables" = "Variabler"; +"simulation_variables_placeholder" = "Inga variabler ännu."; +"simulation_output" = "Utdata"; +"simulation_output_placeholder" = "Ingen utmatning ännu."; +"action_delete_selection" = "Radera markering"; +"ctx_copy" = "Kopiera"; +"ctx_cut" = "Klipp ut"; +"ctx_paste" = "Klistra in"; +"action_settings" = "Inställningar"; +"action_about" = "Om VisuStruct"; +"recent_files_menu" = "Senaste filer"; +"recent_files_empty" = "Inga senaste filer"; +"recent_files_clear" = "Rensa lista"; +"recent_files_unavailable" = "Filen är inte längre tillgänglig."; + +/* In-app settings */ +"settings_language_title" = "Språk"; + +/* Toolbar */ +"toolbar_undo" = "Ångra"; +"toolbar_redo" = "Gör om"; +"toolbar_new" = "Ny"; +"menu_open" = "Öppna…"; +"menu_save" = "Spara"; +"menu_save_as" = "Spara som…"; +"menu_print" = "Skriv ut…"; +"menu_file" = "Arkiv"; +"menu_new" = "Ny"; +"menu_close" = "Stäng"; + +/* Inspector */ +"inspector_no_selection" = "Ingen markering — tryck på en ruta."; +"inspector_apply_text" = "Tillämpa text"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Typ"; +"inspector_io_mode_statement" = "Sats"; +"inspector_io_mode_input" = "Inmatning"; +"inspector_io_mode_output" = "Utmatning"; +"inspector_io_mode_help_java_like" = "Inmatning: input: … | Utmatning: output: …"; +"inspector_add_case" = "Lägg till case"; +"inspector_remove_case" = "Ta bort case"; +"inspector_group_element" = "Elementtext"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Skriv condition…"; +"inspector_placeholder_selector" = "Skriv selector…"; +"inspector_placeholder_call" = "Skriv call…"; +"inspector_placeholder_break" = "Kommentar (valfritt)"; + +/* Element types */ +"element_anweisung" = "Sats"; +"element_verzweigung" = "Villkor (if/else)"; +"element_fallauswahl" = "Val (switch)"; +"element_forSchleife" = "For-loop"; +"element_whileSchleife" = "While-loop"; +"element_doUntilSchleife" = "Do-while-loop"; +"element_endlosschleife" = "Oändlig loop"; +"element_aussprung" = "Break"; +"element_aufruf" = "Anrop"; +"element_leerElement" = "Tomt element"; + +/* Diagram */ +"diagram_title_label" = "Titel"; +"diagram_title_placeholder" = "Ingen titel"; +"canvas_empty_title" = "Tomt struktogram"; +"canvas_empty_hint" = "Dra ett element från “Element” hit."; + +/* Diagram stubs */ +"canvas_stub_anweisung" = "statement"; +"canvas_stub_condition" = "condition"; +"canvas_stub_fallauswahl" = "switch"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "endless"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Anrop()"; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Förslag på filnamn"; +"settings_export_filename_picker" = "Format"; +"settings_export_filename_date_title" = "Med datum"; +"settings_export_filename_title_only" = "Utan datum"; +"settings_export_filename_footer_with_date" = "Med datum: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Utan datum: Filename.visustruct"; + +"close_unsaved_title" = "Osparade ändringar"; +"close_unsaved_message" = "Det här diagrammet innehåller osparade ändringar. Vill du spara dem innan du stänger?"; +"close_unsaved_discard" = "Kasta"; +"close_unsaved_cancel" = "Avbryt"; + +/* Accessibility — code generator floating panel */ +"a11y_codegen_panel_drag" = "Dra för att flytta kodgeneratorpanelen"; +"about_dateiformat_strk" = "Filer med tillägget .strk kan också öppnas."; + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Simuleringen är klar."; +"sim_notice_infinite_loop_empty" = "Den oändliga loopen saknar innehåll."; +"sim_notice_unsupported_statement_fmt" = "Sats som inte stöds: %@"; +"sim_notice_invalid_expression_fmt" = "Ogiltigt uttryck: %@"; +"sim_notice_unknown_variable_fmt" = "Okänd variabel: %@"; +"sim_notice_division_by_zero" = "Division med noll."; +"sim_notice_whole_number_expected" = "Ange ett heltal."; +"sim_notice_number_expected" = "Ange ett tal."; +"sim_notice_boolean_expected" = "Ange true eller false."; +"sim_notice_subprogram_not_found_fmt" = "Inget öppet diagram heter %@. Anropet hoppades över."; +"sim_notice_call_too_deep" = "För många nästlade anrop. Anropar ett underprogram sig självt?"; +"phone_hide_text_editor" = "Fäll ihop"; +"phone_title_done" = "Klar"; + +"codegen_pseudocode_toggle" = "Pseudokod (inte körbar kod)"; +"codegen_pseudocode_note" = "Pseudokod – inte ett körbart program"; +"codegen_pseudocode_hint" = "Det här diagrammet är markerat som pseudokod. Koden är bara en skiss och kan inte köras."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-R-16GCrk.js b/website/app/assets/Localizable-R-16GCrk.js new file mode 100644 index 00000000..2d8f645d --- /dev/null +++ b/website/app/assets/Localizable-R-16GCrk.js @@ -0,0 +1,241 @@ +const e=`/* Palette */ +"palette_header" = "רכיבים"; +"inspector_header" = "מפקח אובייקטים"; + +/* Actions */ +"action_share_png" = "שיתוף תמונה…"; +"action_share_document" = "שיתוף קובץ…"; +"action_export_pdf" = "תצוגה מקדימה של PDF…"; +"action_generate_code" = "יצירת קוד…"; +"action_simulation" = "סימולציה"; +"action_diagram" = "תרשים"; +"simulation_placeholder_body" = "מצב הסימולציה מריץ את התרשים צעד אחר צעד, מדגיש את הרכיב הנוכחי ומציג ערכי משתנים ופלט."; +"simulation_controls" = "פקדים"; +"simulation_highlight_label" = "הדגשה"; +"simulation_highlight_last" = "הצעד האחרון"; +"simulation_highlight_next" = "הצעד הבא"; +"simulation_not_available" = "Play מריץ את הסימולציה אוטומטית עם השהיה של 0.5 שניות לכל צעד."; +"simulation_play" = "הפעלה"; +"simulation_pause" = "השהיה"; +"simulation_step" = "צעד"; +"simulation_stop" = "עצירה"; +"simulation_input" = "קלט"; +"simulation_input_placeholder" = "לא נדרש קלט."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "הזינו מספר שלם."; +"simulation_trace" = "הצעד האחרון"; +"simulation_trace_placeholder" = "עדיין לא בוצע אף צעד."; +"simulation_variables" = "משתנים"; +"simulation_variables_placeholder" = "עדיין אין משתנים."; +"simulation_output" = "פלט"; +"simulation_output_placeholder" = "עדיין אין פלט."; +"action_delete_selection" = "מחיקת בחירה"; +"ctx_copy" = "העתק"; +"ctx_cut" = "גזור"; +"ctx_paste" = "הדבק"; +"action_settings" = "הגדרות"; +"action_about" = "אודות VisuStruct"; +"recent_files_menu" = "קבצים אחרונים"; +"recent_files_empty" = "אין קבצים אחרונים"; +"recent_files_clear" = "נקה רשימה"; +"recent_files_unavailable" = "הקובץ אינו זמין עוד."; + +/* In-app settings */ +"settings_language_title" = "שפה"; +"settings_language_de" = "גרמנית"; +"settings_language_en" = "אנגלית"; +"settings_language_es" = "ספרדית"; +"settings_language_fr" = "צרפתית"; +"settings_language_it" = "איטלקית"; +"settings_language_pl" = "פולנית"; +"settings_language_tr" = "טורקית"; +"settings_language_ko" = "קוריאנית"; +"settings_language_ja" = "יפנית"; +"settings_language_el" = "יוונית"; +"settings_language_uk" = "אוקראינית"; +"settings_language_ar" = "ערבית"; +"settings_language_ru" = "רוסית"; +"settings_language_he" = "עברית"; +"settings_language_zh_hans" = "סינית (מפושטת)"; +"settings_language_zh_hant" = "סינית (מסורתית)"; +"settings_language_ptpt" = "פורטוגזית"; +"settings_language_java" = "Java (מילות מפתח)"; + + +/* Error overlay */ +"error_title" = "שגיאה"; +"error_back_editor" = "חזרה לעורך"; + +/* Toolbar */ +"toolbar_undo" = "בטל"; +"toolbar_redo" = "בצע שוב"; +"toolbar_new" = "חדש"; +"menu_open" = "פתח…"; +"menu_save" = "שמור"; +"menu_save_as" = "שמור בשם…"; +"menu_print" = "הדפס…"; +"menu_file" = "קובץ"; +"menu_new" = "חדש"; +"menu_close" = "סגור"; + +/* Accessibility */ +"a11y_generate_code" = "יצירת קוד מהתרשים"; +"a11y_generate_code_locked" = "יצירת קוד, זמין לאחר רכישה"; +"a11y_unsaved_changes" = "שינויים שלא נשמרו"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "יצירת קוד"; +"codegen_gate_body" = "קוד Java, Python ו‑JavaScript מהתרשים ייפתח באמצעות רכישה בתוך האפליקציה (בקרוב)."; +"codegen_gate_ok" = "אישור"; +"codegen_placeholder_title" = "מחולל קוד"; +"codegen_placeholder_body" = "הקוד שייווצר יופיע כאן."; +"codegen_placeholder_compare" = "עברו בין Java, Python ו‑JavaScript להשוואת תחביר (דוגמה למטה)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (condition) {\\n statement();\\n} else {\\n alternative();\\n}"; +"codegen_preview_python" = "if condition:\\n statement()\\nelse:\\n alternative()"; +"codegen_copy" = "העתק"; +"codegen_run_in_browser" = "בדיקה בדפדפן"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "כרטיסיית תרשים חדשה"; +"a11y_close_tab" = "סגור כרטיסייה"; + +"close_unsaved_title" = "שינויים שלא נשמרו"; +"close_unsaved_message" = "בתרשים זה יש שינויים שלא נשמרו. לשמור אותם לפני הסגירה?"; +"close_unsaved_discard" = "התעלם"; +"close_unsaved_cancel" = "ביטול"; +"a11y_placeholder_drop" = "שחררו רכיב כאן כדי להחליף את מציין המקום. לחצו והחזיקו כדי לגרור ולהזיז."; +"a11y_node_drop" = "לחצו והחזיקו בלוק ואז גררו: שחררו על הקצה העליון או התחתון כדי להוסיף לפני או אחרי. שחרור במרכז רק על מציין מקום ø."; +"a11y_codegen_panel_drag" = "גרור כדי להזיז את לוח מחולל הקוד"; + +/* Diagram */ +"diagram_title_label" = "כותרת"; +"diagram_title_placeholder" = "ללא כותרת"; + +/* Inspector */ +"inspector_no_selection" = "לא נבחר רכיב — הקישו על אריח."; +"inspector_apply_text" = "החל טקסט"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "סוג"; +"inspector_io_mode_statement" = "הוראה"; +"inspector_io_mode_input" = "קלט"; +"inspector_io_mode_output" = "פלט"; +"inspector_io_mode_help_java_like" = "קלט: input: … | פלט: output: …"; +"inspector_add_case" = "הוסף מקרה"; +"inspector_remove_case" = "הסר מקרה"; +"inspector_group_element" = "טקסט רכיב"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "הוסף condition…"; +"inspector_placeholder_selector" = "הוסף selector…"; +"inspector_placeholder_call" = "הוסף call…"; +"inspector_placeholder_break" = "הערה (רשות)"; + +/* Element types — keep Java-like (LTR) to reduce RTL confusion */ +"element_anweisung" = "Statement"; +"element_verzweigung" = "if"; +"element_fallauswahl" = "switch"; +"element_forSchleife" = "for"; +"element_whileSchleife" = "while"; +"element_doUntilSchleife" = "do"; +"element_endlosschleife" = "while(true)"; +"element_aussprung" = "break"; +"element_aufruf" = "קריאה"; +"element_leerElement" = "ø"; + +/* Tabs */ +"tab_title_format" = "תרשים %d"; + +/* Empty canvas */ +"canvas_empty_title" = "תרשים ריק"; +"canvas_empty_hint" = "גררו בלוק מתוך „רכיבים“ לכאן."; + +/* Diagram: new element stubs & column headers — keep Java-like */ +"canvas_stub_anweisung" = "Statement"; +"canvas_stub_condition" = "condition"; +"canvas_stub_fallauswahl" = "selector"; +"canvas_stub_for" = "i = 0; i < n; i++"; +"canvas_stub_while" = "condition"; +"canvas_stub_until" = "condition"; +"canvas_stub_endless" = "∞"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "קריאה()"; + +/* About */ +"about_version_fmt" = "גרסה %@ (%@)"; +"about_nav_title" = "אודות VisuStruct"; +"about_features_heading" = "תכונות"; +"about_bullet_palette" = "הוספת בלוקים מהפלטה או גרירה אל התרשים"; +"about_bullet_edit" = "עריכת התרשים: שינוי טקסט, בחירת רכיבים ומחיקה לפי הצורך"; +"about_bullet_tabs" = "כמה תרשימים בכרטיסיות — לכל אחד כותרת משלו"; +"about_bullet_file" = "שמירה ופתיחה של תרשימים כקבצי ‎.visustruct"; +"about_bullet_share" = "שיתוף התרשים כתמונה (PNG)"; +"about_dateiformat_heading" = "פורמט קובץ"; +"about_dateiformat_part1" = "הפורמט המקורי של VisuStruct משתמש בסיומת "; +"about_dateiformat_part2" = ". ניתן לשמור תרשימים ולהחליף אותם עם אפליקציות אחרות שתומכות באותו פורמט."; +"about_dateiformat_strk" = "ניתן לפתוח גם קבצים עם הסיומת .strk."; +"about_project_github_label" = "אפליקציית Java (מקור וגרסאות):"; +"about_web_label" = "אתר:"; +"about_developer_label" = "מפתח:"; +"about_lineage_heading" = "מקור"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "סיום"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "בטל הוספה"; +"phone_show_text_editor" = "עריכת טקסט"; +"phone_hide_text_editor" = "כיווץ"; +"phone_title_done" = "סיום"; + +/* Alerts */ +"err_save_failed_fmt" = "לא ניתן לשמור: %@"; +"err_share_prepare_failed_fmt" = "לא ניתן להכין שיתוף: %@"; +"err_diagram_too_small_export" = "התרשים קטן מדי — אין מה לייצא."; +"err_image_render_failed" = "לא ניתן ליצור תמונה."; +"err_diagram_too_small_print" = "התרשים קטן מדי — אין מה להדפיס."; +"err_print_unavailable" = "הדפסה אינה זמינה במכשיר זה."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "הצעת שם קובץ"; +"settings_export_filename_picker" = "פורמט"; +"settings_export_filename_date_title" = "עם תאריך"; +"settings_export_filename_title_only" = "בלי תאריך"; +"settings_export_filename_footer_with_date" = "עם תאריך: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "בלי תאריך: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "הסימולציה הסתיימה."; +"sim_notice_infinite_loop_empty" = "ללולאה האינסופית אין גוף."; +"sim_notice_unsupported_statement_fmt" = "הוראה לא נתמכת: %@"; +"sim_notice_invalid_expression_fmt" = "ביטוי לא חוקי: %@"; +"sim_notice_unknown_variable_fmt" = "משתנה לא ידוע: %@"; +"sim_notice_division_by_zero" = "חלוקה באפס."; +"sim_notice_whole_number_expected" = "יש להזין מספר שלם."; +"sim_notice_number_expected" = "יש להזין מספר."; +"sim_notice_boolean_expected" = "הזן true או false."; +"sim_notice_subprogram_not_found_fmt" = "אין תרשים פתוח בשם %@. הקריאה דולגה."; +"sim_notice_call_too_deep" = "יותר מדי קריאות מקוננות. האם תת־תוכנית קוראת לעצמה?"; + +"codegen_pseudocode_toggle" = "פסאודו-קוד (קוד שאינו ניתן להרצה)"; +"codegen_pseudocode_note" = "פסאודו-קוד – לא תוכנית שניתן להריץ"; +"codegen_pseudocode_hint" = "תרשים זה מסומן כפסאודו-קוד. הקוד הוא רק טיוטה ולא ניתן להריץ אותו."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-UGog_aku.js b/website/app/assets/Localizable-UGog_aku.js new file mode 100644 index 00000000..0caa0638 --- /dev/null +++ b/website/app/assets/Localizable-UGog_aku.js @@ -0,0 +1,238 @@ +const e=`/* Palette */ +"palette_header" = "Елементи"; +"inspector_header" = "Інспектор об’єктів"; + +/* Actions */ +"action_share_png" = "Поділитися зображенням…"; +"action_share_document" = "Поділитися файлом…"; +"action_export_pdf" = "Перегляд PDF…"; +"action_generate_code" = "Згенерувати код…"; +"action_simulation" = "Симуляція"; +"action_diagram" = "Діаграма"; +"simulation_placeholder_body" = "Режим симуляції виконує діаграму крок за кроком, підсвічує поточний елемент і показує значення змінних та вивід."; +"simulation_controls" = "Керування"; +"simulation_highlight_label" = "Підсвічування"; +"simulation_highlight_last" = "Останній крок"; +"simulation_highlight_next" = "Наступний крок"; +"simulation_not_available" = "Play автоматично виконує симуляцію з паузою 0,5 секунди на крок."; +"simulation_play" = "Відтворити"; +"simulation_pause" = "Пауза"; +"simulation_step" = "Крок"; +"simulation_stop" = "Стоп"; +"simulation_input" = "Ввід"; +"simulation_input_placeholder" = "Ввід не потрібен."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Введіть ціле число."; +"simulation_trace" = "Останній крок"; +"simulation_trace_placeholder" = "Ще не виконано жодного кроку."; +"simulation_variables" = "Змінні"; +"simulation_variables_placeholder" = "Змінних поки немає."; +"simulation_output" = "Вивід"; +"simulation_output_placeholder" = "Виведення поки немає."; +"action_delete_selection" = "Видалити вибране"; +"ctx_copy" = "Копіювати"; +"ctx_cut" = "Вирізати"; +"ctx_paste" = "Вставити"; +"action_settings" = "Налаштування"; +"action_about" = "Про VisuStruct"; +"recent_files_menu" = "Останні файли"; +"recent_files_empty" = "Немає останніх файлів"; +"recent_files_clear" = "Очистити список"; +"recent_files_unavailable" = "Файл більше недоступний."; + +/* In-app settings */ +"settings_language_title" = "Мова"; +"settings_language_de" = "Німецька"; +"settings_language_en" = "Англійська"; +"settings_language_es" = "Іспанська"; +"settings_language_fr" = "Французька"; +"settings_language_it" = "Італійська"; +"settings_language_pl" = "Польська"; +"settings_language_tr" = "Турецька"; +"settings_language_ko" = "Корейська"; +"settings_language_ja" = "Японська"; +"settings_language_el" = "Грецька"; +"settings_language_uk" = "Українська"; +"settings_language_zh_hans" = "Китайська (спрощена)"; +"settings_language_zh_hant" = "Китайська (традиційна)"; +"settings_language_ptpt" = "Португальська"; +"settings_language_java" = "Java (ключові слова)"; + + +/* Error overlay */ +"error_title" = "Помилка"; +"error_back_editor" = "Назад до редактора"; + +/* Toolbar */ +"toolbar_undo" = "Скасувати"; +"toolbar_redo" = "Повторити"; +"toolbar_new" = "Нове"; +"menu_open" = "Відкрити…"; +"menu_save" = "Зберегти"; +"menu_save_as" = "Зберегти як…"; +"menu_print" = "Друк…"; +"menu_file" = "Файл"; +"menu_new" = "Створити"; +"menu_close" = "Закрити"; + +/* Accessibility */ +"a11y_generate_code" = "Згенерувати код зі структурної схеми"; +"a11y_generate_code_locked" = "Згенерувати код, доступно після покупки"; +"a11y_unsaved_changes" = "Незбережені зміни"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Згенерувати код"; +"codegen_gate_body" = "Код Java, Python і JavaScript з вашої схеми буде розблоковано через покупку в застосунку (незабаром)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Генератор коду"; +"codegen_placeholder_body" = "Згенерований код з’явиться тут."; +"codegen_placeholder_compare" = "Перемикайтеся між Java, Python і JavaScript, щоб порівняти синтаксис (приклад нижче)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (умова) {\\n інструкція();\\n} else {\\n альтернатива();\\n}"; +"codegen_preview_python" = "if умова:\\n інструкція()\\nelse:\\n альтернатива()"; +"codegen_copy" = "Копіювати"; +"codegen_run_in_browser" = "Перевірити в браузері"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "Нова вкладка схеми"; +"a11y_close_tab" = "Закрити вкладку"; + +"close_unsaved_title" = "Незбережені зміни"; +"close_unsaved_message" = "Ця діаграма містить незбережені зміни. Зберегти їх перед закриттям?"; +"close_unsaved_discard" = "Відхилити"; +"close_unsaved_cancel" = "Скасувати"; +"a11y_placeholder_drop" = "Перетягніть елемент сюди, щоб замінити заповнювач. Натисніть і утримуйте, щоб перемістити."; +"a11y_node_drop" = "Натисніть і утримуйте блок, потім перетягніть: скиньте на верхній або нижній край цілі, щоб вставити до або після. Скидання в центрі лише на заповнювач ø."; +"a11y_codegen_panel_drag" = "Перетягніть панель генератора коду"; + +/* Diagram */ +"diagram_title_label" = "Назва"; +"diagram_title_placeholder" = "Без назви"; + +/* Inspector */ +"inspector_no_selection" = "Елемент не вибрано — торкніться плитки."; +"inspector_apply_text" = "Застосувати текст"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Вид"; +"inspector_io_mode_statement" = "Інструкція"; +"inspector_io_mode_input" = "Введення"; +"inspector_io_mode_output" = "Виведення"; +"inspector_io_mode_help_java_like" = "Java: input: int zahl | output: number"; +"inspector_add_case" = "Додати випадок"; +"inspector_remove_case" = "Видалити випадок"; +"inspector_group_element" = "Текст елемента"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Вставити умову…"; +"inspector_placeholder_selector" = "Вставити selector…"; +"inspector_placeholder_call" = "Вставити виклик…"; +"inspector_placeholder_break" = "Коментар (необов'язково)"; + +/* Element types (Ukrainian + keyword hint) */ +"element_anweisung" = "Інструкція (statement)"; +"element_verzweigung" = "Умова (if/else)"; +"element_fallauswahl" = "Вибір (switch)"; +"element_forSchleife" = "Цикл (for)"; +"element_whileSchleife" = "Цикл (while)"; +"element_doUntilSchleife" = "Цикл (do-while)"; +"element_endlosschleife" = "Нескінченний цикл (while true)"; +"element_aussprung" = "Вихід (break)"; +"element_aufruf" = "Виклик (call)"; +"element_leerElement" = "Порожній елемент"; + +/* Tabs */ +"tab_title_format" = "Схема %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Порожня структурна схема"; +"canvas_empty_hint" = "Перетягніть елемент з «Елементи» сюди."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "Вибір (switch)"; +"canvas_stub_anweisung" = "Інструкція (statement)"; +"canvas_stub_condition" = "Умова"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "нескінченний"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Виклик()"; + +/* About */ +"about_version_fmt" = "Версія %@ (%@)"; +"about_nav_title" = "Про VisuStruct"; +"about_features_heading" = "Можливості"; +"about_bullet_palette" = "Вставляйте блоки з палітри або перетягуйте їх у схему"; +"about_bullet_edit" = "Редагуйте схему: змінюйте текст, вибирайте елементи та видаляйте за потреби"; +"about_bullet_tabs" = "Кілька схем у вкладках — кожна з власною назвою"; +"about_bullet_file" = "Зберігайте та відкривайте схеми як файли .visustruct"; +"about_bullet_share" = "Поділіться схемою як зображенням (PNG)"; +"about_dateiformat_heading" = "Формат файлу"; +"about_dateiformat_part1" = "Рідний формат VisuStruct використовує розширення "; +"about_dateiformat_part2" = ". Ви можете зберігати схеми та обмінюватися ними з іншими застосунками, що підтримують цей формат."; +"about_dateiformat_strk" = "Файли з розширенням .strk також можна відкривати."; +"about_project_github_label" = "Java застосунок (код і релізи):"; +"about_web_label" = "Веб:"; +"about_developer_label" = "Розробник:"; +"about_lineage_heading" = "Походження"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "Готово"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Скасувати вставку"; +"phone_show_text_editor" = "Редагувати текст"; +"phone_hide_text_editor" = "Згорнути"; +"phone_title_done" = "Готово"; + +/* Alerts */ +"err_save_failed_fmt" = "Не вдалося зберегти: %@"; +"err_share_prepare_failed_fmt" = "Не вдалося підготувати поширення: %@"; +"err_diagram_too_small_export" = "Схема занадто мала — нічого експортувати."; +"err_image_render_failed" = "Не вдалося створити зображення."; +"err_diagram_too_small_print" = "Схема занадто мала — нічого друкувати."; +"err_print_unavailable" = "Друк недоступний на цьому пристрої."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Запропонована назва файлу"; +"settings_export_filename_picker" = "Формат"; +"settings_export_filename_date_title" = "З датою"; +"settings_export_filename_title_only" = "Без дати"; +"settings_export_filename_footer_with_date" = "З датою: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Без дати: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Симуляцію завершено."; +"sim_notice_infinite_loop_empty" = "Нескінченний цикл не має тіла."; +"sim_notice_unsupported_statement_fmt" = "Непідтримувана інструкція: %@"; +"sim_notice_invalid_expression_fmt" = "Неприпустимий вираз: %@"; +"sim_notice_unknown_variable_fmt" = "Невідома змінна: %@"; +"sim_notice_division_by_zero" = "Ділення на нуль."; +"sim_notice_whole_number_expected" = "Введіть ціле число."; +"sim_notice_number_expected" = "Введіть число."; +"sim_notice_boolean_expected" = "Введіть true або false."; +"sim_notice_subprogram_not_found_fmt" = "Немає відкритої діаграми з назвою %@. Виклик пропущено."; +"sim_notice_call_too_deep" = "Забагато вкладених викликів. Підпрограма викликає сама себе?"; + +"codegen_pseudocode_toggle" = "Псевдокод (не виконуваний код)"; +"codegen_pseudocode_note" = "Псевдокод – не виконувана програма"; +"codegen_pseudocode_hint" = "Цю діаграму позначено як псевдокод. Код — лише ескіз, його не можна запустити."; +`;export{e as default}; diff --git a/website/app/assets/Localizable-rqA-20hM.js b/website/app/assets/Localizable-rqA-20hM.js new file mode 100644 index 00000000..71a0cbb2 --- /dev/null +++ b/website/app/assets/Localizable-rqA-20hM.js @@ -0,0 +1,238 @@ +const e=`/* Palette */ +"palette_header" = "Στοιχεία"; +"inspector_header" = "Επιθεωρητής αντικειμένων"; + +/* Actions */ +"action_share_png" = "Κοινή χρήση εικόνας…"; +"action_share_document" = "Κοινή χρήση αρχείου…"; +"action_export_pdf" = "Προεπισκόπηση PDF…"; +"action_generate_code" = "Δημιουργία κώδικα…"; +"action_simulation" = "Προσομοίωση"; +"action_diagram" = "Διάγραμμα"; +"simulation_placeholder_body" = "Η λειτουργία προσομοίωσης εκτελεί το διάγραμμα βήμα προς βήμα, επισημαίνει το τρέχον στοιχείο και εμφανίζει τις τιμές των μεταβλητών και την έξοδο."; +"simulation_controls" = "Έλεγχος"; +"simulation_highlight_label" = "Επισήμανση"; +"simulation_highlight_last" = "Τελευταίο βήμα"; +"simulation_highlight_next" = "Επόμενο βήμα"; +"simulation_not_available" = "Το Play εκτελεί αυτόματα την προσομοίωση με παύση 0,5 δευτερολέπτων ανά βήμα."; +"simulation_play" = "Αναπαραγωγή"; +"simulation_pause" = "Παύση"; +"simulation_step" = "Βήμα"; +"simulation_stop" = "Διακοπή"; +"simulation_input" = "Είσοδος"; +"simulation_input_placeholder" = "Δεν απαιτείται είσοδος."; +"simulation_input_submit" = "OK"; +"simulation_input_invalid_int" = "Πληκτρολογήστε έναν ακέραιο αριθμό."; +"simulation_trace" = "Τελευταίο βήμα"; +"simulation_trace_placeholder" = "Δεν έχει εκτελεστεί ακόμη κανένα βήμα."; +"simulation_variables" = "Μεταβλητές"; +"simulation_variables_placeholder" = "Δεν υπάρχουν ακόμη μεταβλητές."; +"simulation_output" = "Έξοδος"; +"simulation_output_placeholder" = "Δεν υπάρχει ακόμη έξοδος."; +"action_delete_selection" = "Διαγραφή επιλογής"; +"ctx_copy" = "Αντιγραφή"; +"ctx_cut" = "Αποκοπή"; +"ctx_paste" = "Επικόλληση"; +"action_settings" = "Ρυθμίσεις"; +"action_about" = "Σχετικά με το VisuStruct"; +"recent_files_menu" = "Πρόσφατα αρχεία"; +"recent_files_empty" = "Δεν υπάρχουν πρόσφατα αρχεία"; +"recent_files_clear" = "Εκκαθάριση λίστας"; +"recent_files_unavailable" = "Το αρχείο δεν είναι πλέον διαθέσιμο."; + +/* In-app settings */ +"settings_language_title" = "Γλώσσα"; +"settings_language_de" = "Γερμανικά"; +"settings_language_en" = "Αγγλικά"; +"settings_language_es" = "Ισπανικά"; +"settings_language_fr" = "Γαλλικά"; +"settings_language_it" = "Ιταλικά"; +"settings_language_pl" = "Πολωνικά"; +"settings_language_tr" = "Τουρκικά"; +"settings_language_ko" = "Κορεατικά"; +"settings_language_ja" = "Ιαπωνικά"; +"settings_language_el" = "Ελληνικά"; +"settings_language_uk" = "Ουκρανικά"; +"settings_language_zh_hans" = "Κινέζικα (Απλοποιημένα)"; +"settings_language_zh_hant" = "Κινέζικα (Παραδοσιακά)"; +"settings_language_ptpt" = "Πορτογαλικά"; +"settings_language_java" = "Java (λέξεις-κλειδιά)"; + + +/* Error overlay */ +"error_title" = "Σφάλμα"; +"error_back_editor" = "Πίσω στον επεξεργαστή"; + +/* Toolbar */ +"toolbar_undo" = "Αναίρεση"; +"toolbar_redo" = "Επανάληψη"; +"toolbar_new" = "Νέο"; +"menu_open" = "Άνοιγμα…"; +"menu_save" = "Αποθήκευση"; +"menu_save_as" = "Αποθήκευση ως…"; +"menu_print" = "Εκτύπωση…"; +"menu_file" = "Αρχείο"; +"menu_new" = "Νέο"; +"menu_close" = "Κλείσιμο"; + +/* Accessibility */ +"a11y_generate_code" = "Δημιουργία κώδικα από το διάγραμμα"; +"a11y_generate_code_locked" = "Δημιουργία κώδικα, διαθέσιμο μετά την αγορά"; +"a11y_unsaved_changes" = "Μη αποθηκευμένες αλλαγές"; + +/* Code generator (IAP to follow) */ +"codegen_gate_title" = "Δημιουργία κώδικα"; +"codegen_gate_body" = "Ο κώδικας Java, Python και JavaScript από το διάγραμμά σας θα ξεκλειδωθεί μέσω αγοράς εντός εφαρμογής (σύντομα)."; +"codegen_gate_ok" = "OK"; +"codegen_placeholder_title" = "Γεννήτρια κώδικα"; +"codegen_placeholder_body" = "Ο παραγόμενος κώδικας θα εμφανίζεται εδώ."; +"codegen_placeholder_compare" = "Εναλλαγή μεταξύ Java, Python και JavaScript για σύγκριση σύνταξης (παράδειγμα παρακάτω)."; +"codegen_target_java" = "Java"; +"codegen_target_python" = "Python"; +"codegen_target_javascript" = "JavaScript"; +"codegen_preview_java" = "if (συνθήκη) {\\n εντολή();\\n} else {\\n εναλλακτική();\\n}"; +"codegen_preview_python" = "if συνθήκη:\\n εντολή()\\nelse:\\n εναλλακτική()"; +"codegen_copy" = "Αντιγραφή"; +"codegen_run_in_browser" = "Δοκιμή στο πρόγραμμα περιήγησης"; +"codegen_save_java" = "Save Java…"; +"codegen_java_output_mode" = "Java output"; +"codegen_java_output_snippet" = "Snippet"; +"codegen_java_output_class" = "Class"; +"a11y_new_diagram_tab" = "Νέα καρτέλα διαγράμματος"; +"a11y_close_tab" = "Κλείσιμο καρτέλας"; + +"close_unsaved_title" = "Μη αποθηκευμένες αλλαγές"; +"close_unsaved_message" = "Αυτό το διάγραμμα περιέχει μη αποθηκευμένες αλλαγές. Θέλετε να τις αποθηκεύσετε πριν το κλείσιμο;"; +"close_unsaved_discard" = "Απόρριψη"; +"close_unsaved_cancel" = "Άκυρο"; +"a11y_placeholder_drop" = "Αποθέστε ένα στοιχείο εδώ για να αντικαταστήσετε το σύμβολο κράτησης. Πατήστε παρατεταμένα για μετακίνηση."; +"a11y_node_drop" = "Πατήστε παρατεταμένα ένα μπλοκ και σύρετε: αποθέστε στην πάνω/κάτω ακμή για εισαγωγή πριν/μετά. Κεντρική απόθεση μόνο σε ø."; +"a11y_codegen_panel_drag" = "Σύρετε για να μετακινήσετε το πλαίσιο δημιουργίας κώδικα"; + +/* Diagram */ +"diagram_title_label" = "Τίτλος"; +"diagram_title_placeholder" = "Χωρίς τίτλο"; + +/* Inspector */ +"inspector_no_selection" = "Δεν έχει επιλεγεί στοιχείο — πατήστε ένα πλακίδιο."; +"inspector_apply_text" = "Εφαρμογή κειμένου"; +"inspector_for_init" = "Init"; +"inspector_for_condition" = "Condition"; +"inspector_for_step" = "Step"; +"inspector_for_placeholder_init" = "int i = 0"; +"inspector_for_placeholder_condition" = "i < 5"; +"inspector_for_placeholder_step" = "i++"; + +"inspector_io_mode_title" = "Είδος"; +"inspector_io_mode_statement" = "Εντολή"; +"inspector_io_mode_input" = "Είσοδος"; +"inspector_io_mode_output" = "Έξοδος"; +"inspector_io_mode_help_java_like" = "Java: input: int zahl | output: number"; +"inspector_add_case" = "Προσθήκη περίπτωσης"; +"inspector_remove_case" = "Αφαίρεση περίπτωσης"; +"inspector_group_element" = "Κείμενο στοιχείου"; +"inspector_placeholder_statement" = "int sum = number1 + number2"; +"inspector_placeholder_condition" = "Εισαγωγή συνθήκης…"; +"inspector_placeholder_selector" = "Εισαγωγή selector…"; +"inspector_placeholder_call" = "Εισαγωγή κλήσης…"; +"inspector_placeholder_break" = "Σχόλιο (προαιρετικό)"; + +/* Element types (Greek + keyword hint) */ +"element_anweisung" = "Εντολή (statement)"; +"element_verzweigung" = "Συνθήκη (if/else)"; +"element_fallauswahl" = "Επιλογή (switch)"; +"element_forSchleife" = "Επανάληψη (for)"; +"element_whileSchleife" = "Επανάληψη (while)"; +"element_doUntilSchleife" = "Επανάληψη (do-while)"; +"element_endlosschleife" = "Ατέρμονος βρόχος (while true)"; +"element_aussprung" = "Έξοδος (break)"; +"element_aufruf" = "Κλήση (call)"; +"element_leerElement" = "Κενό στοιχείο"; + +/* Tabs */ +"tab_title_format" = "Διάγραμμα %d"; + +/* Empty canvas */ +"canvas_empty_title" = "Κενό διάγραμμα"; +"canvas_empty_hint" = "Σύρετε ένα στοιχείο από τα «Στοιχεία» εδώ."; + +/* Diagram: new element stubs & column headers (display) */ +"canvas_stub_fallauswahl" = "Επιλογή (switch)"; +"canvas_stub_anweisung" = "Εντολή (statement)"; +"canvas_stub_condition" = "Συνθήκη"; +"canvas_stub_for" = "for 0 < i < n"; +"canvas_stub_while" = "while …"; +"canvas_stub_until" = "until …"; +"canvas_stub_endless" = "ατέρμονο"; +"canvas_stub_break" = "break"; +"canvas_stub_call" = "Κλήση()"; + +/* About */ +"about_version_fmt" = "Έκδοση %@ (%@)"; +"about_nav_title" = "Σχετικά με το VisuStruct"; +"about_features_heading" = "Δυνατότητες"; +"about_bullet_palette" = "Εισαγωγή μπλοκ από την παλέτα ή μεταφορά τους στο διάγραμμα"; +"about_bullet_edit" = "Επεξεργασία διαγράμματος: αλλαγή κειμένου, επιλογή στοιχείων και διαγραφή αν χρειάζεται"; +"about_bullet_tabs" = "Πολλά διαγράμματα σε καρτέλες — το καθένα με τίτλο"; +"about_bullet_file" = "Αποθήκευση και άνοιγμα διαγραμμάτων ως αρχεία .visustruct"; +"about_bullet_share" = "Κοινή χρήση διαγράμματος ως εικόνα (PNG)"; +"about_dateiformat_heading" = "Μορφή αρχείου"; +"about_dateiformat_part1" = "Η εγγενής μορφή του VisuStruct χρησιμοποιεί την επέκταση "; +"about_dateiformat_part2" = ". Μπορείτε να αποθηκεύετε και να ανταλλάσσετε διαγράμματα με άλλες εφαρμογές που υποστηρίζουν την ίδια μορφή."; +"about_dateiformat_strk" = "Μπορούν να ανοίξουν και αρχεία με επέκταση .strk."; +"about_project_github_label" = "Εφαρμογή Java (πηγαίος κώδικας & εκδόσεις):"; +"about_web_label" = "Ιστός:"; +"about_developer_label" = "Προγραμματιστής:"; +"about_lineage_heading" = "Καταγωγή"; +"about_lineage_body" = "VisuStruct originally began as a Java desktop app and remains available across platforms for use in schools. The current Swift/SwiftUI version is the modern native app for Mac, iPad, and iPhone and remains compatible with the .visustruct file format. It builds on the original open-source work by Kevin Krummenauer (MIT)."; +"about_lineage_upstream_label" = "Java upstream:"; +"about_done" = "Τέλος"; +"about_copyright" = "Copyright © 2026 Holger Sebastiao"; + +/* iPhone: tap-to-insert */ +"phone_insert_cancel" = "Ακύρωση εισαγωγής"; +"phone_show_text_editor" = "Επεξεργασία κειμένου"; +"phone_hide_text_editor" = "Σύμπτυξη"; +"phone_title_done" = "Τέλος"; + +/* Alerts */ +"err_save_failed_fmt" = "Δεν ήταν δυνατή η αποθήκευση: %@"; +"err_share_prepare_failed_fmt" = "Δεν ήταν δυνατή η προετοιμασία κοινής χρήσης: %@"; +"err_diagram_too_small_export" = "Το διάγραμμα είναι πολύ μικρό — δεν υπάρχει τίποτα για εξαγωγή."; +"err_image_render_failed" = "Δεν ήταν δυνατή η δημιουργία εικόνας."; +"err_diagram_too_small_print" = "Το διάγραμμα είναι πολύ μικρό — δεν υπάρχει τίποτα για εκτύπωση."; +"err_print_unavailable" = "Η εκτύπωση δεν είναι διαθέσιμη σε αυτή τη συσκευή."; + +"settings_ui_scale_section" = "Text size"; +"settings_ui_scale_canvas" = "Structure chart"; +"settings_ui_scale_inspector" = "Text entry below"; +"settings_ui_scale_small" = "Small"; +"settings_ui_scale_medium" = "Medium"; +"settings_ui_scale_large" = "Large"; +"settings_ui_scale_extra_large" = "Extra large"; + +"settings_export_filename_section" = "Πρόταση ονόματος αρχείου"; +"settings_export_filename_picker" = "Μορφή"; +"settings_export_filename_date_title" = "Με ημερομηνία"; +"settings_export_filename_title_only" = "Χωρίς ημερομηνία"; +"settings_export_filename_footer_with_date" = "Με ημερομηνία: yyyy-mm-dd-Filename.visustruct"; +"settings_export_filename_footer_without_date" = "Χωρίς ημερομηνία: Filename.visustruct"; + + +/* Simulation: Meldungen */ +"sim_notice_finished" = "Η προσομοίωση ολοκληρώθηκε."; +"sim_notice_infinite_loop_empty" = "Ο ατέρμονος βρόχος δεν έχει σώμα."; +"sim_notice_unsupported_statement_fmt" = "Μη υποστηριζόμενη εντολή: %@"; +"sim_notice_invalid_expression_fmt" = "Μη έγκυρη έκφραση: %@"; +"sim_notice_unknown_variable_fmt" = "Άγνωστη μεταβλητή: %@"; +"sim_notice_division_by_zero" = "Διαίρεση με το μηδέν."; +"sim_notice_whole_number_expected" = "Εισαγάγετε έναν ακέραιο αριθμό."; +"sim_notice_number_expected" = "Εισαγάγετε έναν αριθμό."; +"sim_notice_boolean_expected" = "Πληκτρολογήστε true ή false."; +"sim_notice_subprogram_not_found_fmt" = "Κανένα ανοιχτό διάγραμμα δεν ονομάζεται %@. Η κλήση παραλείφθηκε."; +"sim_notice_call_too_deep" = "Πάρα πολλές ένθετες κλήσεις. Καλεί ένα υποπρόγραμμα τον εαυτό του;"; + +"codegen_pseudocode_toggle" = "Ψευδοκώδικας (μη εκτελέσιμος κώδικας)"; +"codegen_pseudocode_note" = "Ψευδοκώδικας – όχι εκτελέσιμο πρόγραμμα"; +"codegen_pseudocode_hint" = "Αυτό το διάγραμμα έχει επισημανθεί ως ψευδοκώδικας. Ο κώδικας είναι μόνο ένα σχέδιο και δεν μπορεί να εκτελεστεί."; +`;export{e as default}; diff --git a/website/app/assets/ar-DeE-RHam.js b/website/app/assets/ar-DeE-RHam.js new file mode 100644 index 00000000..5352e2b8 --- /dev/null +++ b/website/app/assets/ar-DeE-RHam.js @@ -0,0 +1,180 @@ +const e=`/* نصوص موجودة في نسخة الويب فقط. أما بقية النصوص فتأتي من ملف Localizable.strings الخاص بالتطبيق. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "مخطط VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "تصدير…"; +"web_export_title" = "حفظ كصورة أو PDF، أو طباعة"; +"web_export_png" = "صورة (PNG)"; +"web_export_svg" = "رسم متجهي (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "ملف VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "فشل التصدير: %@"; +"web_print_hint" = "استخدم «تصدير… → PDF» لحفظ المخطط ثم طباعته من هناك."; +"web_delete" = "حذف"; +"web_language_title" = "لغة الواجهة"; +"web_simulation_start" = "بدء المحاكاة"; +"web_simulation_end" = "إنهاء المحاكاة"; +"web_simulation_start_title" = "تشغيل المخطط خطوة بخطوة"; +"web_simulation_end_title" = "إنهاء المحاكاة ومتابعة التحرير"; +"web_palette_hint" = "اسحب إلى المخطط"; +"web_tabs_label" = "المخططات"; +"web_status_modified" = "معدَّل"; +"web_inspector_title" = "الخصائص"; +"web_inspector_help_drop" = "اسحب العناصر من اللوحة إلى كتلة: أعلى = قبل، أسفل = بعد، على «ø» = استبدال. يمكن نقل العناصر الموجودة بالفأرة."; +"web_inspector_help_files" = "يمكنك أيضًا إفلات الملفات في النافذة."; +"web_case_name" = "اسم الحالة"; +"web_case_name_placeholder" = "مثلًا 1، ok، default"; +"web_copied" = "تم نسخ العنصر."; +"web_discard_message_fmt" = "ستُفقد التغييرات على «%@»."; +"web_err_unreadable_fmt" = "«%@» ليس ملف VisuStruct قابلًا للقراءة (%@)."; +"web_saved_fmt" = "تم حفظ «%@»."; +"web_saved_txt_fmt" = "تم الحفظ باسم «%@». احذف الامتداد .txt لاستخدامه."; +"web_drop_impossible" = "لا يمكن الإفلات هنا"; +"web_sim_delay" = "التوقف لكل خطوة"; +"web_sim_delay_value_fmt" = "%@ ث"; +"web_codegen_language" = "اللغة"; +"web_codegen_comments" = "نص المخطط كتعليقات"; +"web_codegen_empty_else" = "إخراج فرع else فارغ في الشفرة"; +"web_copied_check" = "تم النسخ ✓"; +"web_copy_manual" = "تم التحديد، اضغط Ctrl+C للنسخ"; +"web_run_stopped_loop" = "توقف التنفيذ: حلقة لا نهائية محتملة."; +"web_run_cancelled" = "تم إلغاء التنفيذ."; +"web_run_error" = "خطأ أثناء التشغيل."; +"web_run_dropped_fmt" = "… تم إخفاء %d من الأسطر السابقة"; +"web_sim_call_arguments_fmt" = "الاستدعاء لا يطابق ترويسة %@. تحقق من القيم بين القوسين."; +"web_sim_missing_return_fmt" = "انتهى %@ دون إرجاع قيمة باستخدام return."; +"web_sim_file_not_found_fmt" = "لا يوجد ملف باسم %@."; +"web_sim_end_of_file_fmt" = "لا يوجد سطر آخر في الملف %@."; +"web_sim_null_value_fmt" = "القيمة في %@ هي null."; +"web_sim_written_file_fmt" = "%@ (محفوظ)"; +"web_site_home" = "الصفحة الرئيسية"; +"web_site_imprint" = "بيانات الناشر"; +"web_site_privacy" = "الخصوصية"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "البرمجة"; +"web_live_hide" = "إخفاء البرمجة"; +"web_scale_canvas" = "حجم النص: المخطط"; +"web_scale_code" = "حجم النص: البرمجة"; +"web_live_indent" = "إزاحة"; +"web_live_indent_title" = "إزاحة الشيفرة: أربع مسافات لكل مستوى (الأسطر المحددة، وإلا فالكل)"; +"web_live_show" = "إظهار البرمجة"; +"web_live_resize" = "تغيير عرض منطقة الشيفرة (نقر مزدوج: إعادة تعيين)"; +"web_live_hint" = "تنمو الشيفرة مع مخططك. الرمادي = عنصر نائب: اكتب في المفتش ليظهر نصك هنا. انقر على سطر لتحديد عنصره."; +"web_live_ph_selector" = "المتغير"; +"web_live_ph_code" = "شيفرتك"; +"web_live_ph_end" = "النهاية"; +"web_live_language" = "لغة البرمجة"; +"web_live_java_class" = "كصنف"; +"web_live_java_class_hint" = "اسم الصنف = عنوان المخطط"; +"web_live_java_main" = "مع الطريقة main"; +"web_settings_display" = "العرض"; +"web_live_swing" = "جافا حقيقية (مع Swing)"; +"web_live_swing_hint" = "جافا حقيقية مع نوافذ (CheerpJ). تُنزّل نحو 40 ميغابايت مرة واحدة عند أول تشغيل."; +"web_live_swing_windows" = "نوافذ جافا"; +"web_live_swing_hide" = "إغلاق نوافذ جافا"; +"web_live_swing_loading" = "جارٍ تحميل جافا (نحو 40 ميغابايت في المرة الأولى) …"; +"web_live_swing_compiling" = "جارٍ الترجمة …"; +"web_live_swing_running" = "البرنامج قيد التشغيل."; +"web_live_swing_compile_failed" = "خطأ في الترجمة، انظر أعلاه."; +"web_live_swing_failed" = "تعذّر تحميل جافا. تحقّق من الاتصال بالإنترنت."; +"web_live_hint_edit" = "اكتب هنا شيفرة Java وسيُبنى المخطط تلقائيًا. أو اعمل في المخطط وستنمو الشيفرة معه. الرمادي = عنصر نائب، اكتب فوقه مباشرة."; +"web_live_edit_label" = "شيفرة Java"; +"web_parse_line_fmt" = "السطر %d: %@"; +"web_parse_missing" = "ما زال ينقص هنا: %@"; +"web_parse_extra" = "زائد: %@"; +"web_parse_unclosed_string" = "ينقص %@ الإغلاق هنا."; +"web_parse_else_without_if" = "لا يوجد «if» لهذا «else»."; +"web_parse_case_outside_switch" = "«case» و«default» مكانهما داخل «switch»."; +"web_parse_missing_do_while" = "بعد «do { … }» ينقص «while (الشرط);»."; +"web_parse_more_methods" = "حاليًا تُحتسب طريقة واحدة فقط هنا. أنشئ البرامج الفرعية الأخرى في علامات تبويب منفصلة."; +"web_parse_missing_import" = "ينقص في الأعلى %@ بدون هذا السطر لا تعرف Java الصنف Scanner."; +"web_parse_missing_scanner" = "ينقص قبل ذلك %@ بدون هذا السطر لا يوجد Scanner."; +"web_parse_unknown_type" = "لا تعرف Java نوع البيانات هذا. هل تقصد %@؟"; +"web_editor_title" = "المخطط"; +"web_editor_show" = "إظهار المخطط"; +"web_editor_hide" = "إخفاء المخطط"; +"web_keywords_title" = "كلمات الشيفرة المفتاحية"; +"web_keywords_hint" = "if و while و for بدلًا من أسماء العناصر"; +"web_palette_compact" = "العناصر مضغوطة دائمًا"; +"web_palette_compact_hint" = "رمز مع اسم صغير تحته، وإلا فقط عندما يكون العمود ضيقًا"; +"web_about_version_fmt" = "الإصدار %@"; +"web_about_software" = "البرمجيات المستخدمة"; +"web_about_software_text" = "يستخدم محرر الشيفرة CodeMirror و Lezer (ترخيص MIT). مع دعم Swing يحمّل VisuStruct برنامج CheerpJ من Leaning Technologies (ترخيص Community) و javac من OpenJDK."; +"web_about_licenses" = "نصوص التراخيص"; +"web_live_run" = "تشغيل"; +"web_live_run_title" = "تشغيل البرنامج: تظهر المخرجات والمدخلات بالأسفل"; +"web_live_run_finished" = "انتهى البرنامج."; +"web_live_run_stopped" = "تم الإيقاف."; +"web_console" = "وحدة التحكم"; +"web_console_hide" = "إخفاء وحدة التحكم"; +"web_console_resize" = "تغيير ارتفاع وحدة التحكم"; +"web_diagram_tools" = "أدوات المخطط"; +"web_files_title" = "الملفات"; +"web_files_show" = "إظهار الملفات"; +"web_files_hide" = "إخفاء الملفات"; +"web_files_resize" = "تغيير عرض الملفات"; +"web_files_new_folder" = "مجلد جديد"; +"web_files_switch" = "اختيار مجلد آخر"; +"web_files_delete" = "حذف"; +"web_files_in_browser" = "في تخزين هذا المتصفح"; +"web_files_save_hint_fmt" = "الحفظ يضع البرنامج في %@."; +"web_files_empty" = "لم يُحفظ شيء بعد. عند الحفظ ينشئ VisuStruct هنا مجلداً بتاريخ اليوم."; +"web_files_reconnect_hint" = "بعد إعادة التحميل يسأل المتصفح مرة أخرى إن كان يمكن لـ VisuStruct استخدام مجلدك."; +"web_files_reconnect_fmt" = "فتح المجلد «%@»"; +"web_files_connect_hint" = "اختر مجلداً كمساحة عمل. ينشئ VisuStruct فيه مجلداً لكل يوم ويحفظ المخطط والشيفرة."; +"web_files_connect" = "اختيار مجلد"; +"web_files_browser_hint" = "لا يستطيع هذا المتصفح فتح مجلدات الجهاز (مثلاً على iPad). تبقى ملفاتك في تخزين هذا المتصفح."; +"web_files_browser" = "الحفظ في المتصفح"; +"web_files_delete_confirm_fmt" = "هل تريد حذف «%@» فعلاً؟"; +"web_files_folder_prompt" = "اسم المجلد الجديد:"; +"web_files_default_name" = "برنامج"; +"web_files_saved_fmt" = "تم الحفظ: %@"; +"web_files_create" = "إنشاء"; +"web_learn_ludwig_tip" = "نصيحة لودفيغ"; +"web_game_title" = "لعبة: صحيح أم خطأ؟"; +"web_game_intro" = "يعرض لك لودفيغ قيماً وشرطاً. هل الشرط صحيح (true) أم خطأ (false)؟ عشر جولات تزداد صعوبة."; +"web_game_start" = "ابدأ اللعبة"; +"web_game_round_fmt" = "الجولة %@ من %@"; +"web_game_score_fmt" = "النقاط: %@"; +"web_game_true" = "صحيح (true)"; +"web_game_false" = "خطأ (false)"; +"web_game_right" = "صحيح!"; +"web_game_wrong" = "ليس تماماً. هكذا يُحسب:"; +"web_game_next" = "التالي"; +"web_game_finish" = "النتيجة"; +"web_game_done_fmt" = "%@ من %@ صحيحة."; +"web_game_perfect" = "كلها صحيحة – لودفيغ معجب جداً!"; +"web_game_good" = "رائع! راجع أخطاءك وحاول مرة أخرى."; +"web_game_practice" = "التمرين يصنع الإتقان. اقرأ جدول الحقيقة مرة أخرى والعب جولة أخرى."; +"web_game_again" = "العب مرة أخرى"; +"web_game_wrong_short" = "للأسف خطأ."; +"web_game_practice_short" = "التمرين يصنع الإتقان. اقرأ الشروح مرة أخرى والعب جولة أخرى."; +"web_game_clicks" = "النقرات:"; +"web_game_nobody" = "لا أحد يستمع – لا يحدث شيء."; +"web_game_event_fmt" = "نقرة على «%@»: المستمع يسمعها وينفّذ شيفرته."; +"web_game_try" = "جرّب الآن أزرار النافذة بنفسك."; +"web_game_time_fmt" = "متبقٍ %@ ث"; +"web_game_defused" = "✂️ تم تعطيلها! وجدت الخطأ."; +"web_game_boom_time" = "💥 بوم! انتهى الوقت."; +"web_game_boom_wrong" = "💥 بوم! كان ذلك السطر الخطأ."; +"web_game_fix" = "السطر الصحيح:"; +"web_game_order_hint" = "اضغط على الخطوات بالترتيب الصحيح."; +"web_debug_step" = "خطوة"; +"web_debug_step_title" = "خطوة: تنفيذ تعليمة واحدة ثم التوقف مجدداً"; +"web_debug_continue" = "متابعة حتى نقطة التوقف التالية"; +"web_debug_paused_fmt" = "متوقف قبل السطر %d."; +"web_debug_gutter_title" = "انقر على رقم السطر لوضع نقطة توقف أو إزالتها"; +"web_swap_to_code" = "البرمجة كبيرة"; +"web_swap_to_editor" = "المخطط كبير"; +"web_editor_resize" = "تغيير عرض المخطط"; +"web_palette_resize" = "تغيير عرض العناصر"; +"web_palette_hide" = "إخفاء العناصر"; +"web_palette_show" = "إظهار العناصر"; +"web_code_scopes" = "كتل الشيفرة ملوّنة"; +"web_code_scopes_hint" = "الصنف والدالة والحلقة والتفرّع في مربعات خاصة"; +"web_pseudocode" = "شبه كود"; +`;export{e as default}; diff --git a/website/app/assets/aufgabe-mehrwertsteuer-C-TFTrWz.svg b/website/app/assets/aufgabe-mehrwertsteuer-C-TFTrWz.svg new file mode 100644 index 00000000..57094a66 --- /dev/null +++ b/website/app/assets/aufgabe-mehrwertsteuer-C-TFTrWz.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + 12:34 + + + zu: Handy + + + + aufklappen + + + + + + + + + + + + + + + NEU + + auf: Tablet + + + + + KASSENBON + Falt-Handy + netto1000,00 € + +19% MwSt190,00 € + + SUMME1190,00 € + + + + So setzt sich der Preis zusammen: + + netto 1000 € + + 190 € + + + + + + + + + + + Finanzamt + + + + + + brutto 1190 € + Das zahlst du an der Kasse. + diff --git a/website/app/assets/aufgabe-mehrwertsteuer-CnrZ00ny.svg b/website/app/assets/aufgabe-mehrwertsteuer-CnrZ00ny.svg new file mode 100644 index 00000000..920b4411 --- /dev/null +++ b/website/app/assets/aufgabe-mehrwertsteuer-CnrZ00ny.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + 12:34 + + + phone + + + + unfold + + + + + + + + + + + + + + + NEW + + tablet + + + + + RECEIPT + Folding phone + net€1,000.00 + +19% VAT€190.00 + + TOTAL€1,190.00 + + + + This is how the price is made up: + + net €1,000 + + €190 + + + + + + + + + + + Tax office + + + + + + gross €1,190 + You pay this at the till. + diff --git a/website/app/assets/aufgabe-mehrwertsteuer-KUkerRBd.svg b/website/app/assets/aufgabe-mehrwertsteuer-KUkerRBd.svg new file mode 100644 index 00000000..70b4b6bb --- /dev/null +++ b/website/app/assets/aufgabe-mehrwertsteuer-KUkerRBd.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + 12:34 + + + telemóvel + + + + abrir + + + + + + + + + + + + + + + NOVO + + tablet + + + + + TALÃO + Telem. dobrável + s/ IVA1000,00 € + +23% IVA230,00 € + + TOTAL1230,00 € + + + + Assim se forma o preço: + + sem IVA 1000 € + + 230 € + + + + + + + + + + + Finanças + + + + + + com IVA 1230 € + É isto que pagas na caixa. + diff --git a/website/app/assets/ben-shneiderman-Cev5hrqS.jpg b/website/app/assets/ben-shneiderman-Cev5hrqS.jpg new file mode 100644 index 0000000000000000000000000000000000000000..369a8ef07074183e428aa69f946f13fe0940d2ce GIT binary patch literal 19298 zcmbSyWmFtN*XH07+#P~@&;)mP7~B#VoFId12oP+r0D%C(-Q6wt;BLWvaCcqa@7uF` z&i>ln>eKb7tGnwteQ(vh&wcuJ;dLE=qa>#&2Y`bE0N~yZ!0Qq~8i0(5h=hoUjD&=Q zjEszehJ}WPii(DZiHVLyh(|<3h(|y`O!l6Fn1q^?fPj*TlA4x|fq{XDf`y%#p6xw7 z1O0y<0{3<+8Y&tt8X7J=2>}WH|8slo1mL2={e)vjfTIP#w4?agp%eb4w!QYnq|Zf(dv6 zggL8 zf-EeptZi)VT;1F~JiWYqf`5dBhJ{B!;uC%)CjCxMNzKX4%P%M_DlVz1t*dWnY-(=l z?&(+TPiP?d>0&UtC^Y-`w8aKl}$5901|JVZHVL4ebBG zh5LpJ9uW}%5#>L);NU&qP6S*;r1#v&c#@hZW?+0;olAbdHFeQlYkrua}~)$(V;$B z7%th`tWRp!Ou$Sk^qA^}_>PI2c_jL}AW$vgG}XbKbU{;D3Sua&pv0U{lE=-$YD0^6 zAJT{ut`E0-MLkwumx*dmRyWk};6D=4wQA0qEPhOZZj&^%+>_Vm!x7uHhChzWy<`{! zrLP;(_o+aZC?CfD-V)Mf@FB0Rao|2D&2RN@fACsNRYeuz=Kn- zA1i`>RHc$8_v5dSP=+LSMrsa(7l9@I+pd|k=Sd82}6@hZolj~N_|4&M(eg&$^P#@=$nnV`jDJ#D(6Z4&Z7~T#li#JXFlWKXFy~%m$v02RB3FxK zk$WlNtdJqDWT({1rUMg@?FmyWgYKemuDi>(p0O5Z( z_U(MUk}f^$A#m9)|GmwD}Bk58BiCNq@GIRP}|g!z?YMR zIdaE>fRQfE-Il&l+UBZd3K4qKqOSmSnERS*zS(bcmV&rkL1Iqfr_#o&vUjI^mUHvY z+uPR_F}AxF{j-+9&VI1AV_F(ADaR7zH?SI<>oCT7p&X>BL*oOGENd`23_~Z=aP6c& zH<@YiZc^D$6SgKK-^UtA#*kQ7%EbtqY;W(=YHL7q>2Xa^#j~|$qc1w7M%>;}|LYU) zgdHhGNv~z>@`-Teh@9jJ({_1DrE(Wav=4$N6E|HG9EOH^(Q)(AfP*nQzhp}Ie!47; zg77R z`2CM#+~QafK@zsB!jZvhsMqfv-I$SkeGA}3aNxZjVd=iroYp{Bm=xS8T;@3m# z1eNmQAMh%aZf+c@`pq(KHT9)(BMzY{IaftFbIXXv*2(p45Sr6%DA2(50u6eqQmRLT8Xo ztF8mX)u$Sr0_Jq78W!HH6zQB=R{D;4+vt?cPqVH97g;|IPDR|O^)vjQD%hWJMEB6; zyaT;y{o`^FZ&w#>ix&5i&unt0ASxTDrexnuEp04^)y{;_pPG zqCHVpNVnH1K=ZGFa$|@CT;MPmT42AjLf6c*w4Br6Wl7uix8IapNOf2p5j5bpWxGzT zq9;RtW3I}ZK%bB>Gi|F%SoI^1uONY-w>KwP79J16EyoPV<+FkSZhe&88LYgew5USU zRh?RF5Xc^%EzRxiOhrr3n6fAj9j~km`{oiGERAd_PR6)T^`CS1m;=yA$gC2<0X&Ju z@_)_Dg&*|Vo&?UW>(k3zTfHLy|Jr{eHa(7Jsyo@8I|zY%-JKjWG#AA@-UlAWdu_I# z_Vm`L7i4~o?$FnEU_xPcaowLuFhRQ(v^V)jnUS%!SQCslP?bf^O#{BF2qM=BKkqE! z8xgCC*WLbs>o8m!dJIpmx9j0?irvtonc&Ev{ zr{(jD^qXVwYRQ1}YHk6hK7IHt{5yofQR$E9J1ukU6Ea9xa4^B_;ih{RD&A)B?f27I zV{o4yUh?)jEHy(=1d1f7MNWFP*^t{j9v%~XjkeX+fbBArAm2SwXhSE0aH=1#ru_%p zlTFXEB`AtyXV=d!C$C|aOlW!a3b^KX(K2}j<36Rnk7_(hO{+>On;H8IVvDyJMl*xLt3&&C29!JvJ3%X z*}D3HidE18|HDt50Z;!`S4e5Aoor?G=(57Ov0ow6Hz?B;KT)fBvGWmBI@z_c8*ubme zvY(6P7yE!rvZ#;v9oa^n06hROZa0V5@{z>0?!dMjmtBeZRF0Wm$&fhJ>l+ z`;2>~{R;R2F~x3-S>09slU7=R3%8dtW)fzKBDws`wx=GVJLrkOMwurkQil-Ve0|$V zo$hyAV0VB=QYeFLD_z^4DF9f{94?&eNV*fXFgp{=q;}_Y~AH_Ibk%8&C1{D)I=gtdZ9HH2ure=c;#WETt=(WZwvhGlQap~qy%*wH$?s6Shc`X6oY^H|2H-HJ4B=H_mSw1np?5g)mK1yU?S=>B$OmMDKLETk_Ty!Vss84PW2g)rMO-8}$uf zrjq8GR^B6V_IY1JzAs^VT9k#=I>38e)8yc@eD1$eoNmnm!M|<4?RB@4|H$A zosfZ#c*I%P<*g{hjq^N0_+)>76;>g<0xE&b#jTXdo`Y1@O}legS$>hNUa5>Ebb_5_ zCQ74q&3Uolj~CIC)z_4zg)>+FN!CjIH zE^=CUiVLR0^Z2uRb093?N~k#yLk_zxnAJFKv`+1A}FrkrNqVmFhf&imB(L6O3E^koE}GAw786ZDd-*1I)hf=Qlo$W3gIMt$IVUwViK8cTEFCwifuu0+^rf*=ZGHetHSIZ$gLjN)FdtBFo{{{ zS*a1WFD>3jTb#2)9aShZS_ zozIiMkl3C|ZCQ1?Z$1FZL)X3BGrD)m>>t+Ot#m%I9gQO?QbI%A8h@Dc zI%b3S1S+H0cZe?02AIs&eNrDzH|STbzq`e?di1hnnyTN;wPUb;@aC=2++QrvoX+ge z(LyoJ94o-X&}ML{ppn4Zn9&+=1`HC+$EoSX_36Z4t9T2n3QgC4PwcK7dj%v~uO2j< zDaP^}N`V9C#S)`8)$!yDB}~%wM6jBl*v59xIbMq0&h?G9K`A6pqlfWA*k*S#4WS7> z8GrmYm+alSbDa`M7qQhV^Ie60hnpIUcrvHJ>?%KxC*14GCPjmNM3$D)i^K!J>3kk8 zw^1yx)h$Broab>DGjtr^w4=(^Y}gfE8|4^Jo*tWYj~AF!Zmfv`JlX!{T&2rU)^|*C zE4V1Ml+xU^eC$g5QpMyI^F7i|wn2-D9F$P&Ml69ijbq?OGLMMc`;=Wq{pkB#$6R(^S z;HEN_*|u1Pxi1FU3>UZLLY6L#>fURGy?m47{5cRd-uW ztFZo_6t07{k2d_p`nu%I6!8x`PvE1+!*qeHN@&Vb1|*BQq>}c#lttW_y3ZI-Ek9V* z&dIn%8KDMu94#Y7WP6TbLZOUGlK(3`Jkk~gh)}ur#eDyKS*|IOUhA*Q1*;A9S9H6vZ1@8ra96ACI&7+D zvcRqDqHe&!^3kMV!FEh$Pcz31#LSNxO9_Xbomj2AggZHV@tXl{{ zHoG0W)k!T>pU+KqvS;H!V_V1q5A(l1D@==Bz5?K>u2=n}=gel>G+p98`i0*(`_y}1 zh1|wNQxEdWVui{o1@*(HfYA(Jtv*5wRWxXFk|5@If7JRInGsg26(L}PCl+ zs}d-N*;0N});tT}*gEptEmi#@?kHG{;}u{K>(jrODUEWH`)8b_viKX)=lcu-BCG&! zM`@5K9O1>Rul3PsSzMX1p>X3k6_*cw>ZH4zPEtgsR3SY)OYP8mlwE$Lv24s1ZWMN* zN4@uDUiq^_{pT{gQR6fy7l#_Dv@l!3A!7jV;QB0w9A{ZnSG&B=y4ktqNv5acD4bhL z!zt#4;MF+D#3Q8)8{ep{#juspnUle!I_^NYaU<|ld2?Y>3^>+i=g2U#D!8NZlZF-0 zB^(;?uohx<2hwe5Xl%yn{xs%&AZvH`sMIlCiMMIgm=3d4J%P``R)K@gi|BFZ5;k;z zM3`$!Yue=RED$EHwzBu^Ne-K5rfTG_$hK?vej^j7N`R4SqOfoOOx48%mV1>GKicgd zUClxtIGUL&kJN#8v*~14qc}0Et0XA_KbXXUM#Fh_o*R0{@B)t~JFy#!4U>M1c#(hG zvvn8Q{5ehlE`o7V5tsWyH1jo;MWn}Ybl4$l07QvPMOae211($oBU z#-2z&>s{<$w63R8tj8he@ezo?wu^YVQ3iR)&Q4DNUTmv21)4z&dd>O#TXa-rNp#D} z!4X9%r46%7$bePY6B+!W|1L>spV!_99234OvoGodMft{DCzd%8yNafRFEY}mC0E8Z zrD-t0-?7D&^h2pB!Foi3v^HxwnfbQ1cb50DYzFZ`Itt>SjDdy^M#{DYQI2sMi73s4 zg(y&(8A_NB5Z7#P{jy80;j4olv?%$zsgPGG`wzh)X>NNSHL1RW5UMWPI4CdB{L26*9TowDaf?6 zym3bFlB&gpBJFWcI7z5_E>_ri=^BbVOQY$&mLmCcI_^wmfdVPDL}83z8JiQl@rpy! zIp*a%X9R}4&$QH)MHQ7@9~+WPX<9$p;IVMfk!yc}uaLj!v)Rm@*JRvzdqF>$kDYUy z77epJaIS5^R=r@k_8!@5;B7|tHl_O~qNVfhKM|2`9HD2GJ}|mQgQb)2M)CH6jika< zdjfUAEyh{Sab!-a(*-; z?zjj8fpi%@*8J>0U^JkNSsVdU`WL=tRZit50nF)%)F5{%2&Wwf$%&7ECp+)=#usS2`7P?4=JHmBCQK&_S6lVUe-;Ek6bDwwW1PZ| zV(q2haA5|=f)0(DBCbA8Tz{a)J5%ZS${7%$eoeTxx#OquEH0fXh~ z?U_1uzG_0M%*Q1aZ#+a%2tV@e%KESl)Vi+Ne(Q$aC8erlc-^v2UYBP68w&{63a}bJ zsB@{hi97L4V&PWH%R2AvV-&M<2Uvz+w0tI`ru}yG%r+|Wmg7@<-BxP2i)lXSC42R} zh_m7EX$HdgPnC=)NY7JzYcDOIsc-eHZs?dU%Z{;p?ya?`g$JNx`9$Xew$jM94sQMw z*N3MPM_4s9!C6Iz(IfoSzM-27t-ummzE%%2e6Z8#NMtJ+c5c4JCRhK0(p0HE>89_N zPDRjIe`(0)FopCkEp2{$6?b|!^7Ax99mo|VI-_K%R=v|ACbs`@W`A&~zaBI_lH4EH zuQ>dZFaY16PWI?2M%1m`TE9sy5metOu=8RCEfD=yUzy9$au<3cK+WQS;gL(R6Ue^( z!XUry&)T=Lvs)I874ajY$^Q0pqI>{5b=&GQO1tTF-J>YgA~~DRyT&A@B+zoga=fcl zB)^Nww}Pkv91taTQH9IBY7RGWK5(&>Lu$n@j^~Olb^BVsH(9FF720lQ`bQ0>OJ%3j z&rlG)I82l(N7@hIXUxwxusI_N)y2p9o?7cr1kGPkY=x`ttibN2qEFCh^~x6BJ}F%~ z+&7R_Gn6?Fnr;5-Ziw7*8^_IC!&9x5w{5*x_n}@8B*%{N-Bay)U{B-TBLZ(DnX>n4 zx2_^DUR!6p-oxg~ntt z#)k72gYKYLqulx11t+wk%r$(-C3l7NHTiwggdVEqOixJ3Q#JP~RQ%hH(vfp6pD(Oe z#m9?&+EWM}IXsVhKTa9VzBA_QN$JT2U>p&p8=Q;<5WTK?%=HNBysKK2PPp+s$4b;wfMue@cC0R-69c4UZ^q0t@F zs7xgpB-q(qPqw5pkjacK_7aL5=h8q3EJ4G&O@15YUY8M+@yxnCPogXKQr~?bls4zH zY0}%{W{pVog9^25xn5p})p&5JdVlJ3_ym&=pvDvsXd z#q<}pwf_bKiu0!E!p#PaqZ~nNdq@uZ2NO&p*7FdS3T-D{hq|~*(AR31IJ2?EjOQ)5 zUvAkE0TGt3*)g|X8?~!CzQ4pjx@Nj+D$}S{v$*j4c{}d{UnDgt!3Sqa>C!5+bW_;Z zPsW;2{=HO;{%ktZ$!_`uSKQy#PfTg%-9!_9)6&|2klE^F zzX@32gbt+~XD|)c-{>zBGi66s#+-W#R9^eWJBQz&Kos-ptV!YLvA+c?^mJ5z_@=57 zk7g6F8VSB|vOd>5wQV`&1Lc@=o9Xh6>Je%B{cRV14S5bjJC0m+cBBS0!;!MWLAF#(|mjID@T&C5Eq9gD6j*om8WUY2hU)NoAa*g8*aTx8w zWypS!Mp#k&5_x770DS#&K37l1aZY$7hiNHM@Gi9B8w-iln;kB}cHPvEIwS37nUTB%p%>Q*HZhvESx=XJ2 zS(y&V{WR4U*86mzZjkY?Jb?TQ=sOh*k$wNKJQM9MG~nIgTxuC9Bhmfzz~ z2-Pfu;RCgi(LuFcs^6!i8niFz2)V&CxW*0DZ2 zWD@UI&wj@A)qX3>#w9HZ?$&}?qaEd~ti81E9EdK`iuW_Fr-p59vcn;WC`}q{iBkrqCP|Q=iTpl!C>jzp<{8!LW!noALc)W`DW1hy*DE>sPw|I~ zx-4z^$mnYBzqv_$T#E5NBCimdw=E6mmflh|pw_I9RGlhc@~U=ihM7$a#*R~p)lVAi z-G1UGkBHlZ7(2?5V8_}in}%q$#{WuR+XhpSpVg5W{;A2^khpKzZD|){TxqUO7*#ET zQfQUez(GZ@3JPlj{rX^za%@a&wGH{X8g*Zc|D*M9Z;KFmh?h%b?7D}o z6xWw%=B)A2#pCL>oK54~c-p1@nc@$+Shd7j>_Gq&rc(4%Whu|atIs`yw1G%SpxOO- zrxOqKoZ0?Rg8g{XY)>iV0Ma0ei$}mAZHJ?=zOL9k(Lpao4~c@S_9u?cy}%7vldH?c zt|NrqXvX;+LCpk3$N#Fs#VKC)ou;H+6Qb0c4bm@hxNN zp89Y~w*0TLLY4gkxu#&qU&oYw-&vcV$a`#3s1MfdT5_J%X82LMR^=8-Xj{}Ge$TRw zP%6EAxyj&WrQpn|I`Bl~uexTWUZtKr`Fy*Ob$9-8`EZ(T>C;5g3s{(1iT^S9Zfn2FWS zc%zy&7eLoc5b8B@7*)}r+UijRA?-}vO13hN*#5D;k6y^;RE70#wSQKQf86p3{6?n* z_Ani7WgU`(ut(HT>J8fKXoyvgMa~y1czl0Y{ch%n$ZnV}(;IKGY)%fmt&VzF2kSqq zwlb{uddcj;KWMeLCea|HJEI-g(G>!c!A-?uX#FfhF7egn;?|hDWdq9A=@}m8+!L_& zulpZ4n3B-1ozzzAJ;qfo&zk`##pS-_W*B|nyE!G8+RbMnzwQ%QKX>g2pv(D!jpZXa zP3JZk#-)GyAJ)!%Aao@4x|bI`Hg(@@?H(EOLFkjVkhQZpxD7p+5L+j9(lnMUSm2oP zU~DwquK%tfKP1O(ys{l?6rCHFVH*^k7*anH6B#(4x(sUIryi>=195PVOZK@vF#dcP zJ&TM({6b3cm(BmO&e?RzPHvxnfl z>-=-3Q;)zapuwGgc1ZO-cj1Wy9Dd;t0R1oIi27z`7Sw&A{E&GX@NoYM_?y$(tfebY z{+st}*>aM=eY@!W+np031`z`2g}Wl~0RU`R)s#FIDy6=gSmFF7dce94D{azZVem!p z^*Z&F7j<`*b@Y>JpkALApNerCcP+~cZtSmsHJWekeS_G7hpDF>jQ8?=^u5U-biPdB z0CmtY;h+eW*>Wz*{k#LeSMG4dv1W<`!iSN1ml5kzaLmk2sGPW4l*e^3ZEzC_zakH3 zE&lEpOLQM?zh~}Q zK0>Oo7Rj=COC{3XE5PWieMs7tY0-hS!`?uV?fUacX1+_WubzC?z7%uEH0{pY>RIm~ zhviZ|8c|Flb@V{p-N7~OCsjoIJUT&YL-Ex4=mR-2(@EkS!4|0ey^*18tE->B6^ErW zvmShG+Ilt*ZS*OJ-nd^OE8_9I_(Wmm7Mm>{n&@y<2=!jFY&NIoH?Jw1Ai3nfC^!Qxouli?2tY1zW(5Wo75*=YWLF6)SX~>((0}XCWF>buBbgOMobGjDVD>6 z%i0tP34NAEv308{s1CUyDARK__0g++j}hHQQD+imCcC=U;`uhF4U;=t2@g67<}e#V zMO^cj6rx^I4gEC8mHj)oygg0HPbaW+zr!Guk?dbT#Y%|+NM(U%#9_2Xy0g~+v9a$z z5Iq1%P6K3(MW&;!Yy*!nQU73B4xKMXH?et)Ew<3#x~?;+-ws%Xi9Fb)T$H)?3Yo;? zR=>q@$X%?joAaJNQNQHIK3>_?&D%u&(2^(DX%_%c_k0mQ6$O4WIBoK2eq4neu06x9 z%99EhteHR(B(Rns{-WgsBj?EuOo_(1*p1;Kc6U3WfG`(y6A%jQkt z*d|eN?90{a7KCx1!=Re#UA?=1ta3F$s3LB8OFL(W(A)3(*TrT7;vp&;g!GqtY}#M? zb3&q!-Um|3YNuM%h8h$IYw>d==o&Icg+_%i6(I!Q=`umSbj&zt%}p%?rVY7p`EyI# z(&#luWGyL{A6$H1#;7>@9w2ElR51&17ORiTGK3Z^oT-y>YuM$*}r2_Y^6iLz19q7{bi3gjOZzbcaOuA)a_k$_R zBzK^m&{x3c>vFd7B#bCZexb+#ryvoJ8=~R@dwfz5bWjjxCf@DeepsEU-^le_UQdn` zBRcLuFS2qtPQ%1b>)(5BReGD{wnubT`W5aH=aP)aafJ_q;CZTG5$h{{Y3(`s z8Pg9UBo5}}?;C=@2T%Ck(!*x9wnD&hw%@5 zUIF#Wd8VTMY38gNiybqAf(!pdpRodXO;j0O=qC#q{<*j)iakHP0wP`k9mzgg-q2#f zTXERa3uEb7AyceUp}TKw2p-IAO`Z9@F2=b; zaIoT!^b~Eq*KS*Hd_0)2mi?Bf=( z^L?0lKL{Pl)cwqiC;vfmwL&DGntFMWY-U1mEuRuG1^S64P zkprjBG4Foy?xdKK%jL*4)SRK1DuRhzm&jCq1PBV|amy&)6Fkc*Nt^~M{-UhC16EZS zwx@# zd=Cuc_m$JgK&GH}bG{QaLB5@qaiG@vq@7i%iPIK8sf!?T5!!*IIK{MrU^J?e2{!#) zefxSGvZ^bsaYnt%BFvUz%DIU(w6E8miME!r{4FSx1-H4_PBXg?RCvqgR-~)_Xpspi z2Z(or^%Mp=DRjU6;+kTrIlj%ZhUvsE!jkJ+{$BiR~x_3*81U=R}@-=-y3Y*Q<8_G?3?(?F~kz4 z=}bmdq->jt*EZG8loKeBVvvksQ*-aX>CGs3(7p@ON8x#+i$1G2DqV>~ln`vs8zjk> z=%Qi-9`x|x2Tl|=Toj*1-DFqDr|*=e4DZ*gDd1)7!la8h4p00Rc*mh6~fbm6J|S8{$!v22(d;P=~qq zvMgXvuYio}#!}mco12PgUhhAiypHQQyaQKd;}{DohZr@By{G*=a=7xwu&3)iRyr{& z>ruDQQ{~_KyX7<)rm-u8&hG>7=RfD!%%=uFg&W0YQA!NHd8pl73s0jQBIkIKY{|_XQeDVS0hL1++WCY zT7rV)2jie?Z^Ev)%AX)n@Ubebkr2KkHoxxi4<%onQ+}oEG86N4BpR~I1Ab6Pszb6* z$e^dloIQ;oV?p9DH$P&91b@8Mg-X6NU=--lb*O8(d|wjJ$g;xwF_j_4__nz5TwCW{ zi@lko(9D(SN85EN*WgrbqpNQDVrq0x@=U0oXKB@NQ()?#N<6orZn%yl|EP}sem>iQ z{l6vV`^))ygLp3FSwgvY<-w$-RYUZrbEVjye@od{QjdI@X-?zxf{zioI3vSkJFUxPBd2vu zF6UL0lH)r@o4Gl^lsk1=oqf~t&UU+ARby%xmT>)&@52DBg^w8UulCWOq&_KtuiF ztKxlEgds|Lp0Ys4IkqQ7dv92c)YeD{X_^nb9Pd5Zr795E$z}8e;cX5B_Iyjzt!OS@ zSsR)sMq0_ECayX^DQ@qN0qE3NSJB35jq5)6)R4AUQmp6y)@HZDgG0Ls^kr#W(gQuRj7Mg<2#O?Oij0Nc2C zI(S2JNXa!s->_XXVQNN*k|8nd?t@XT%1z$EDAXaw*nu-I+A>;F&yDZqYAPK?=0tXL zcry)uREeaX?=X&A;Z*ftU8?$u%q9=;JK*rlGz?AjCXL(d8#Fp^@lTnshVVzY1}Wr| za`UBx(DJ0(xUeZHAXvkfD1McfH0t-{O610^)hpMD*vzi0u@;$YBl-i_tZ$E+ac5`@ zBjI;$iUQ@!(Z6?>Wbt2cce2EoH#bKy%M%N^LOqFao_{hR%-W|Q;I0dSkp6}-Ijq02sHj2*I zm(Q!7L2LA@w*XW}6smM6!o3mU^gTnC6~Wq@{7oeQrml7GPbZFa>Kl|4?rGpyxP}p4 zb;|-sWhAfQD;N4&bFPM-_Qi~keDp9-iTfEx5!$ntxUx4`viGrLxb48!~WMP>EGeFc6tRmnaW$7E+8DhI$dh;ma zBO>k=Jxm|I{YY{1Rz>_&>(<0?as6a*4 zCs~?9isUU33fy^=Y{D>#Qa-x_7t}4}j>x;e`Oxw^Y`v=ZdAp^>w*3!qGI2YhD8}ax z^TQ8>(3C>CfBgT#iWX}H5BeM-f1(+;bd%P+`xL%9^FlThZs^N&BbrOks*kk|L~4PO z?}0#iE1^5fw{Y0ym!I#vvWql>t0Ba4jMc0uzv`y~RXIEQN+~B1>ue!nN}sJo2(im? zc~d!Ih>jdmN?$)5;cr(qag~`mQJLq4_s^1Niemb@1mR3W%gtLbPj}jMK*J|mxqWhflXeXX@ zvXL#j3%R58PIME~+T?6XwG@8({USvaF;)G>D)QNtPk$-iP-_k_sj`3%HM_Px29-`* z763qIEBTS$7M_MTvkYuQcUH}U<rQ>Ktg7d6*`?>We#=}<>$XfvW3C`c+nyu}tI~^E_4WF{s;Px3 zdmm;aM?NKzzAz3_^`yoqN^!a_q#{iiq|s(Nor!N4+8wqKrOuF@p;puq=$OS~}hmJ4{ z9`wGn{_U?|MckiBdntU&S?^~W&6D!%9diXwpx1Bewmx9QX>7oDz+H)+S&Wa*H|mY2 z;xgVYk*g=y7lEfk;Uqbzqu~D9Th#?%j{x;hExwc1sh5!&bsTAZV9_uV*C70>wBkY% zIH|seC7w$?RAM4axUK3S&OKHji0l*E>9l(_ja*UYm&js8x+q`BzqeNV+?R8=bL>QJ zw`|x_I2t{I`W3?;d&d~_%ATTzd9SSVo1eC!Sh;J?LBnE5ZppX&Y?p1n6) zDV4{_Lu7A@S}wQ9yn^wGptRtRK3XHV3k2WiWbd6 zy$&ya87p=NX5%6hYwB<3|88?U%nxL1+u_Cc*wlHM757w#LW$cn^vq^tc%B*ZB<^@i zoSK+zgGQ&0XXo{aJV8}@a?Ok7+gRdhI%lm0|7l-m~L33y<_nWK<3hk9qBgGiOkNqT|DT1)wal8`bMMbNF3j4saPIS3ulCIL_!4yv-Uo_g{CRTf0Z#d-I9r)Z|e!a8~_4JBVvaPhCY~FUr z==vp`nh@+*ny2pSiG~s_bBXPp8l?VcUEtmm?|X}jnt@+GW`LEEYDUHSNljhf7=;jf zSB7RkDLOcb4LLv|T%XdGU;%bJL?H>-^6Oo^cvCKQ1fj%`^_#Hbdg;wxwei=yQ%8^9 z zi<>2a>PfK)11Qwr#h(-kKa8w+(Z}|%i{F^(@Lap{mQGm0rhpS78%bL*nC4=v%oG1=8RZGNt>Fv8 z+m8!U|9HoW%0EV|fAKQQ*fuZEmPMou8FvPh?G1GCJ5VQl7Z+-(VZiH&%BCZQmdoT- z$W!{WOr{UU1Fj1zxTh}&eN&D=z5Rvn`c(^jSeMW6)CQNxY-a<}eJTxmzv%FV7i46X@=yycpS@*+9{Jc2{zjH+Be zXKqdFaZGJpB9r~T1b0mH2nyQoOkS(S6hDLNzLZ`$3AA#P*ZGQeO37m3Nm{$7*t$ z-vz~$a52`)7Dl%)?NN5{X}_83xXKbXT5FBJ6FugcVPyfwbEZc*3Pdvy{-Exbi+Gu#N`b2 zd6A=q#_+(R(B;YBiBCJaAS9g&pEuU5Udgq&IwlW$c2IKLQX6 z@AY57PJiGPPUh)~wh@;gCuf^xK((M=9%+cK-m! zXFt}Fq2@msq5E7mSIxLQZqS81WHURGKA$h+X&ps48 zt{3ZG@8JMh6a$lh4G}tC$8~ItC~RZpUB;D7XRiNCobu!;)`g&;C9B71OHz6@{QiB)ZgOQSzI)G58i0zHqrGwJ7XuJ;q$V z$XNYPZn*Qb^?r9CX|K$NvBmPEry) z{{VG=kRSX_Hs}QobN5vKf?x2YUsAICts3$7qaXP61OEVJH9)rOVd`NYtV{m@$145K zBbX767$3=;{{ZZQs>Z9BW8?S~{&ve!XpGHn&MjKf>e6ADrw@_zdzT0EP;2Jfv|@m< zB;X&$zLp%txbv8IesIWtoR#37H?WIM@iwn%ZlFU2+=zqF1Jbvn)f{-WvpJ5S)8ZVl z&w7Zq3k(XH79<`3$9z_a9F6Eq7Xt+6+Jm%pJpE~LoOH!T#|Ib{b|mNDIjN#TMKmVn zt7#V1uO50H#9hia0~J|$HFD@xc;oLxb`#udjwz~sYMMl-f*jQ%SvsC63t-Zy!0S=S zaau&qMVMsCsTxhEtx}3i8hny*SIlQ)LK*YHrd@R6soThNR%C6p6&ewC>;-DzFV1RvuGue*-iie${D ziqSAg+(&;!QB|F@K79s%U;f6evBVJ$0Qvs_oFps`znL|VD2|y55y1tIY_jGznVldA2E*5$MO@O=qk8*7UK;gaVTHF zN`wCZWHh&r=0z)ic^Lj^-~3%yx|jEoI6WPY{y%Vk_F9%&ML1=Z<3L>F%2CK1pDG{z zF1(xK<(x_4B%KG%bpe^rOt+gL{y0i6D{>#zahp@^QCKb3TKJnn{&AgKCOZ-9FC zsNs_*sp;HQtj(U4q9MB&mg~@(w9EqHoVNQ@II6b}SBml{8?)7ntXH@@k6Kulij1Ac zrB=Y9M?iA8*;fLhP%3Bng+km?uv|uLR8ltTNf_puIjt6iJx3|#p8Y8maZ)h(Xj_O# zKJcrD?$s#xYO-JCt>BDi#xms8PMD=K^G$c+teXrVftpp5)}Ets^r&TBrjQ}!w^Wdm z(x5_3Scr2`BI0&F5QM$L5Ifhucs&Z+{y)%Hhxi6P)2Jhi*S~mT5Ro6KKcJ^g8@-OU z1M+7y-9}}K#iVb#tc0KV64J-_aqU$6LZ(j-YGHC4?Cw*k2m;LVlyH4 zKh^&L#-!X?Ey@1?oJdyy23H=VANc90Gr0BY!}VeR0L4`7c^`-PRao1V`ls`c z{Ago{v9?(ct0(h|{AwtO#3R(l{{XZp(PwOV>|_4`+BF_6{|hW`NBgiIJQItzKjnour zLXbyM=GzKuM{-`O$IMrQa3db|MIR522Nl2KJvL1s^msQRB638EO|Gj)c{bhUAk}VK^g_4Ov$h=QUB>h7(Au9~F-~Z*x}eTD6uIC1+i5`>i_8{^jSG{NhXvg~i{-(Zr_Wf|ye z=noIe<}7XMxc;?p*x8*j9-MU*4yX(17we9;@_*AlZ=n^({49{430mi>k`Lf(t&s3X)}lKjTAvduyq_`0sr?K8 z0EJH9EN~9uH6N>0GJbZ)ss8}k{{Y6WO~H(Rus`%Brb`%4%sX;FomWH3H7 zKI8e+35=olU*`=bR7B{2`e6Qx{uK#qI`hzv=0EtFkdk7?IotmLvWkL21LxmAsi|g& zVjZ$TJMN4B07JK`K>q-t1M3L?0MRQ}Nj`i(@5lcDqb=&I5Vlc|NJsvPN|QuMaCnrT zSN?ZZ0e!bI=l*)B{{YC=^y}F+mr>oD`Q24BC^t&ow}YSiX=;D1G#yVU__wFZx3(I9 zQX-Ph7067)aPgtI2 hCOotCAX0J(CZ-&YnfjWooF01T)~8(KwOP!6|Jf=Iu<`%^ literal 0 HcmV?d00001 diff --git a/website/app/assets/caesar-ascii-Bix93F5i.svg b/website/app/assets/caesar-ascii-Bix93F5i.svg new file mode 100644 index 00000000..d6beace8 --- /dev/null +++ b/website/app/assets/caesar-ascii-Bix93F5i.svg @@ -0,0 +1,98 @@ + + +A +65 + +B +66 + +C +67 + +D +68 + +E +69 + +F +70 + +G +71 + +H +72 + +I +73 + +J +74 + +K +75 + +L +76 + +M +77 + +N +78 + +O +79 + +P +80 + +Q +81 + +R +82 + +S +83 + +T +84 + +U +85 + +V +86 + +W +87 + +X +88 + +Y +89 + +Z +90 +(int) 'X' +→ +88 +88 - 65 +→ +23 +23 + 3 +→ +26 +26 % 26 +→ +0 +0 + 65 +→ +65 +(char) 65 +→ +'A' + \ No newline at end of file diff --git a/website/app/assets/caesar-scheibe-CMRPZI6Y.svg b/website/app/assets/caesar-scheibe-CMRPZI6Y.svg new file mode 100644 index 00000000..8d8484de --- /dev/null +++ b/website/app/assets/caesar-scheibe-CMRPZI6Y.svg @@ -0,0 +1,62 @@ + + + + + +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y +Z + +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y +Z + + + + \ No newline at end of file diff --git a/website/app/assets/caesar-verschiebung-DIR-lDbs.svg b/website/app/assets/caesar-verschiebung-DIR-lDbs.svg new file mode 100644 index 00000000..81035fc3 --- /dev/null +++ b/website/app/assets/caesar-verschiebung-DIR-lDbs.svg @@ -0,0 +1,133 @@ + + + +A + +B + +C + +D + +E + +F + +G + +H + +I + +J + +K + +L + +M + +D + +E + +F + +G + +H + +I + +J + +K + +L + +M + +N + +O + +P + + + + + + + + + + + + + + +N + +O + +P + +Q + +R + +S + +T + +U + +V + +W + +X + +Y + +Z + +Q + +R + +S + +T + +U + +V + +W + +X + +Y + +Z + +A + +B + +C + + + + + + + + + + + + + + \ No newline at end of file diff --git a/website/app/assets/da-D4INXE4p.js b/website/app/assets/da-D4INXE4p.js new file mode 100644 index 00000000..635f9b95 --- /dev/null +++ b/website/app/assets/da-D4INXE4p.js @@ -0,0 +1,180 @@ +const e=`/* Tekster, der kun findes i webversionen. Alt andet kommer fra appens Localizable.strings. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct-struktogram"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Eksportér…"; +"web_export_title" = "Gem som billede eller PDF, eller udskriv"; +"web_export_png" = "Billede (PNG)"; +"web_export_svg" = "Vektorgrafik (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "VisuStruct-fil (.visustruct)"; +"web_export_failed_fmt" = "Eksport mislykkedes: %@"; +"web_print_hint" = "Brug »Eksportér… → PDF« til at gemme diagrammet og udskrive det derfra."; +"web_delete" = "Slet"; +"web_language_title" = "Sprog i brugerfladen"; +"web_simulation_start" = "Start simulering"; +"web_simulation_end" = "Afslut simulering"; +"web_simulation_start_title" = "Kør struktogrammet trin for trin"; +"web_simulation_end_title" = "Afslut simuleringen og fortsæt redigeringen"; +"web_palette_hint" = "Træk ind i struktogrammet"; +"web_tabs_label" = "Diagrammer"; +"web_status_modified" = "ændret"; +"web_inspector_title" = "Egenskaber"; +"web_inspector_help_drop" = "Træk elementer fra paletten over på en flise: øverst = før, nederst = efter, på »ø« = erstat. Eksisterende elementer kan flyttes med musen."; +"web_inspector_help_files" = "Du kan også slippe filer i vinduet."; +"web_case_name" = "Navn på case"; +"web_case_name_placeholder" = "f.eks. 1, ok, default"; +"web_copied" = "Element kopieret."; +"web_discard_message_fmt" = "Ændringerne i »%@« går tabt."; +"web_err_unreadable_fmt" = "»%@« er ikke en læsbar VisuStruct-fil (%@)."; +"web_saved_fmt" = "»%@« gemt."; +"web_saved_txt_fmt" = "Gemt som »%@«. Fjern filtypenavnet .txt for at bruge den."; +"web_drop_impossible" = "Kan ikke slippes her"; +"web_sim_delay" = "Pause pr. trin"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Sprog"; +"web_codegen_comments" = "Diagramtekst som kommentarer"; +"web_codegen_empty_else" = "Skriv tom else-gren i koden"; +"web_copied_check" = "Kopieret ✓"; +"web_copy_manual" = "Markeret, tryk Ctrl+C for at kopiere"; +"web_run_stopped_loop" = "Kørslen stoppet: mulig uendelig løkke."; +"web_run_cancelled" = "Kørslen annulleret."; +"web_run_error" = "Fejl under kørsel."; +"web_run_dropped_fmt" = "… %d tidligere linjer skjult"; +"web_sim_call_arguments_fmt" = "Kaldet passer ikke til hovedet i %@. Tjek værdierne i parenteserne."; +"web_sim_missing_return_fmt" = "%@ sluttede uden at returnere en værdi med return."; +"web_sim_file_not_found_fmt" = "Der findes ingen fil med navnet %@."; +"web_sim_end_of_file_fmt" = "Filen %@ har ikke flere linjer."; +"web_sim_null_value_fmt" = "%@ er null."; +"web_sim_written_file_fmt" = "%@ (gemt)"; +"web_site_home" = "Forside"; +"web_site_imprint" = "Kolofon"; +"web_site_privacy" = "Privatliv"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Programmering"; +"web_live_hide" = "Skjul programmering"; +"web_scale_canvas" = "Tekststørrelse: struktogram"; +"web_scale_code" = "Tekststørrelse: programmering"; +"web_live_indent" = "Indryk"; +"web_live_indent_title" = "Indryk koden: fire mellemrum pr. niveau (markerede linjer, ellers alt)"; +"web_live_show" = "Vis programmering"; +"web_live_resize" = "Skift kodeområdets bredde (dobbeltklik: nulstil)"; +"web_live_hint" = "Koden vokser med dit diagram. Gråt = pladsholder: skriv i inspektøren, så vises teksten her. Klik på en linje for at vælge elementet."; +"web_live_ph_selector" = "variabel"; +"web_live_ph_code" = "Din kode"; +"web_live_ph_end" = "slut"; +"web_live_language" = "Programmeringssprog"; +"web_live_java_class" = "Som klasse"; +"web_live_java_class_hint" = "Klassenavn = diagrammets titel"; +"web_live_java_main" = "Med main-metode"; +"web_settings_display" = "Visning"; +"web_live_swing" = "Ægte Java (med Swing)"; +"web_live_swing_hint" = "Rigtig Java med vinduer (CheerpJ). Henter ca. 40 MB én gang ved første kørsel."; +"web_live_swing_windows" = "Java-vinduer"; +"web_live_swing_hide" = "Luk Java-vinduer"; +"web_live_swing_loading" = "Java indlæses (første gang ca. 40 MB) …"; +"web_live_swing_compiling" = "Kompilerer …"; +"web_live_swing_running" = "Programmet kører."; +"web_live_swing_compile_failed" = "Kompileringsfejl, se ovenfor."; +"web_live_swing_failed" = "Java kunne ikke indlæses. Tjek internetforbindelsen."; +"web_live_hint_edit" = "Skriv Java-kode her, så bygger diagrammet sig selv. Eller arbejd i diagrammet, så vokser koden med. Gråt = pladsholder, skriv bare ovenpå."; +"web_live_edit_label" = "Java-kode"; +"web_parse_line_fmt" = "Linje %d: %@"; +"web_parse_missing" = "Her mangler stadig: %@"; +"web_parse_extra" = "For meget: %@"; +"web_parse_unclosed_string" = "Det afsluttende %@ mangler."; +"web_parse_else_without_if" = "Denne “else” har ingen “if”."; +"web_parse_case_outside_switch" = "“case” og “default” hører til i en “switch”."; +"web_parse_missing_do_while" = "Efter “do { … }” mangler “while (betingelse);”."; +"web_parse_more_methods" = "Indtil videre tæller kun én metode her. Opret andre underprogrammer i egne faner."; +"web_parse_missing_import" = "Øverst mangler %@ Uden denne linje kender Java ikke Scanner."; +"web_parse_missing_scanner" = "Før mangler %@ Uden den linje findes Scanneren ikke."; +"web_parse_unknown_type" = "Java kender ikke denne datatype. Mente du %@?"; +"web_editor_title" = "Strukturdiagram"; +"web_editor_show" = "Vis strukturdiagram"; +"web_editor_hide" = "Skjul strukturdiagram"; +"web_keywords_title" = "Kode-nøgleord"; +"web_keywords_hint" = "if, while, for i stedet for elementnavne"; +"web_palette_compact" = "Elementer altid kompakte"; +"web_palette_compact_hint" = "Symbol med lille navn nedenunder, ellers kun når kolonnen er smal"; +"web_about_version_fmt" = "Version %@"; +"web_about_software" = "Anvendt software"; +"web_about_software_text" = "Kodeeditoren bruger CodeMirror og Lezer (MIT-licens). Med Swing-understøttelse indlæser VisuStruct CheerpJ fra Leaning Technologies (Community-licens) og javac fra OpenJDK."; +"web_about_licenses" = "Licenstekster"; +"web_live_run" = "Kør"; +"web_live_run_title" = "Kør programmet: output og input vises nedenfor"; +"web_live_run_finished" = "Programmet er færdigt."; +"web_live_run_stopped" = "Stoppet."; +"web_console" = "Konsol"; +"web_console_hide" = "Skjul konsollen"; +"web_console_resize" = "Ændr konsollens højde"; +"web_diagram_tools" = "Diagramværktøjer"; +"web_files_title" = "Filer"; +"web_files_show" = "Vis filer"; +"web_files_hide" = "Skjul filer"; +"web_files_resize" = "Ændr bredden på filer"; +"web_files_new_folder" = "Ny mappe"; +"web_files_switch" = "Vælg en anden mappe"; +"web_files_delete" = "Slet"; +"web_files_in_browser" = "I denne browsers lager"; +"web_files_save_hint_fmt" = "Når du gemmer, lægges programmet i %@."; +"web_files_empty" = "Intet gemt endnu. Når du gemmer, opretter VisuStruct her en mappe med dagens dato."; +"web_files_reconnect_hint" = "Efter genindlæsning spørger browseren igen, om VisuStruct må bruge din mappe."; +"web_files_reconnect_fmt" = "Åbn mappen “%@”"; +"web_files_connect_hint" = "Vælg en mappe som arbejdsområde. VisuStruct opretter en mappe for hver dag og gemmer diagram og kode."; +"web_files_connect" = "Vælg mappe"; +"web_files_browser_hint" = "Denne browser kan ikke åbne mapper på enheden (fx på iPad). Dine filer bliver i browserens lager."; +"web_files_browser" = "Gem i browseren"; +"web_files_delete_confirm_fmt" = "Vil du virkelig slette “%@”?"; +"web_files_folder_prompt" = "Navn på den nye mappe:"; +"web_files_default_name" = "Program"; +"web_files_saved_fmt" = "Gemt: %@"; +"web_files_create" = "Opret"; +"web_learn_ludwig_tip" = "Ludwigs tip"; +"web_game_title" = "Spil: Sandt eller falsk?"; +"web_game_intro" = "Ludwig viser dig værdier og en betingelse. Er betingelsen sand (true) eller falsk (false)? Ti runder, sværere og sværere."; +"web_game_start" = "Start spillet"; +"web_game_round_fmt" = "Runde %@ af %@"; +"web_game_score_fmt" = "Point: %@"; +"web_game_true" = "sand (true)"; +"web_game_false" = "falsk (false)"; +"web_game_right" = "Rigtigt!"; +"web_game_wrong" = "Ikke helt. Sådan regnes det ud:"; +"web_game_next" = "Videre"; +"web_game_finish" = "Resultat"; +"web_game_done_fmt" = "%@ af %@ rigtige."; +"web_game_perfect" = "Alt rigtigt – Ludwig er dybt imponeret!"; +"web_game_good" = "Flot! Se på dine fejl og prøv igen."; +"web_game_practice" = "Øvelse gør mester. Læs sandhedstabellen igen, og spil en runde mere."; +"web_game_again" = "Spil igen"; +"web_game_wrong_short" = "Desværre forkert."; +"web_game_practice_short" = "Øvelse gør mester. Læs forklaringerne igen og spil en runde til."; +"web_game_clicks" = "Klik:"; +"web_game_nobody" = "Ingen lytter – der sker ingenting."; +"web_game_event_fmt" = "Klik på »%@«: lytteren hører det og kører sin kode."; +"web_game_try" = "Prøv nu selv knapperne i vinduet."; +"web_game_time_fmt" = "%@ s tilbage"; +"web_game_defused" = "✂️ Desarmeret! Du fandt fejlen."; +"web_game_boom_time" = "💥 Bum! Tiden er gået."; +"web_game_boom_wrong" = "💥 Bum! Det var den forkerte linje."; +"web_game_fix" = "Den rigtige linje:"; +"web_game_order_hint" = "Tryk på trinnene i den rigtige rækkefølge."; +"web_debug_step" = "Trin"; +"web_debug_step_title" = "Trin: kør én sætning og hold pause igen"; +"web_debug_continue" = "Fortsæt til næste breakpoint"; +"web_debug_paused_fmt" = "Sat på pause før linje %d."; +"web_debug_gutter_title" = "Klik på et linjenummer for at sætte eller fjerne et breakpoint"; +"web_swap_to_code" = "Programmering stor"; +"web_swap_to_editor" = "Struktogram stort"; +"web_editor_resize" = "Skift bredde på struktogrammet"; +"web_palette_resize" = "Skift bredde på elementerne"; +"web_palette_hide" = "Skjul elementerne"; +"web_palette_show" = "Vis elementerne"; +"web_code_scopes" = "Farvede kodeblokke"; +"web_code_scopes_hint" = "Klasse, metode, løkke, forgrening i egne felter"; +"web_pseudocode" = "Pseudokode"; +`;export{e as default}; diff --git a/website/app/assets/de-3XOrIl-I.js b/website/app/assets/de-3XOrIl-I.js new file mode 100644 index 00000000..b512bd6a --- /dev/null +++ b/website/app/assets/de-3XOrIl-I.js @@ -0,0 +1,744 @@ +const e=`/* Texte, die es nur in der Web-Version gibt. Alle anderen kommen aus den Localizable.strings der App. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct-Struktogramm"; +"web_key_ctrl" = "Strg"; +"web_key_delete" = "Entf"; +"web_key_shift" = "Umschalt"; +"web_export" = "Exportieren …"; +"web_export_title" = "Als Bild oder PDF speichern oder drucken"; +"web_export_png" = "Bild (PNG)"; +"web_export_svg" = "Vektorgrafik (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "VisuStruct-Datei (.visustruct)"; +"web_export_failed_fmt" = "Export fehlgeschlagen: %@"; +"web_print_hint" = "Über „Exportieren … → PDF“ lässt sich das Diagramm speichern und dann drucken."; +"web_delete" = "Löschen"; +"web_language_title" = "Sprache der Oberfläche"; +"web_simulation_start" = "Simulation starten"; +"web_simulation_end" = "Simulation beenden"; +"web_simulation_start_title" = "Struktogramm Schritt für Schritt ausführen"; +"web_simulation_end_title" = "Simulation beenden und weiter bearbeiten"; +"web_palette_hint" = "Ins Struktogramm ziehen"; +"web_tabs_label" = "Diagramme"; +"web_status_modified" = "geändert"; +"web_inspector_title" = "Objektinspektor"; +"web_inspector_help_drop" = "Elemente aus dem Bereich „Elemente“ auf eine Kachel ziehen: oben = davor, unten = dahinter, auf „ø“ = ersetzen. Vorhandene Elemente lassen sich mit der Maus verschieben."; +"web_inspector_help_files" = "Dateien können auch einfach ins Fenster gezogen werden."; +"web_case_name" = "Fallname"; +"web_case_name_placeholder" = "z. B. 1, ok, default"; +"web_copied" = "Element kopiert."; +"web_discard_message_fmt" = "Die Änderungen an „%@“ gehen verloren."; +"web_err_unreadable_fmt" = "„%@“ ist keine lesbare VisuStruct-Datei (%@)."; +"web_saved_fmt" = "„%@“ gespeichert."; +"web_saved_txt_fmt" = "Gespeichert als „%@“. Zum Verwenden die Endung .txt entfernen."; +"web_drop_impossible" = "Ablegen nicht möglich"; +"web_sim_delay" = "Pause pro Schritt"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Sprache"; +"web_codegen_comments" = "Diagramm-Text als Kommentare"; +"web_codegen_empty_else" = "Leeren else-Zweig im Code ausgeben"; +"web_copied_check" = "Kopiert ✓"; +"web_copy_manual" = "Markiert, mit Strg+C kopieren"; +"web_run_stopped_loop" = "Ausführung gestoppt: mögliche Endlosschleife."; +"web_run_cancelled" = "Ausführung abgebrochen."; +"web_run_error" = "Fehler beim Ausführen."; +"web_run_dropped_fmt" = "… %d frühere Zeilen ausgeblendet"; + +/* Lernbereich (Lektionen gibt es vorerst nur auf Deutsch) */ +"web_learn_title" = "Lernen"; +"web_learn_hide" = "Lernbereich einklappen"; +"web_learn_show" = "Lernbereich aufklappen: Lektionen, Aufgaben und Nachschlagen"; +"web_learn_lessons" = "Lektionen"; +"web_learn_tasks" = "Aufgaben"; +"web_learn_reference" = "Nachschlagen"; +"web_learn_intro" = "Schritt für Schritt lernen, mit Übungen. Dein Fortschritt wird in diesem Browser gemerkt."; +"web_learn_tasks_intro" = "Kleine Projekte ohne Anleitung. Jede Aufgabe nennt die Lektion, die du vorher abgeschlossen haben solltest."; +"web_learn_step_of_fmt" = "Schritt %d von %d"; +"web_learn_lesson_fmt" = "Lektion %d"; +"web_learn_all_lessons" = "Alle Lektionen"; +"web_learn_all_tasks" = "Alle Aufgaben"; +"web_learn_back" = "Zurück"; +"web_learn_next" = "Weiter"; +"web_learn_finish" = "Lektion abschließen"; +"web_learn_done" = "Abgeschlossen"; +"web_learn_after_fmt" = "Nach Lektion %d: %@"; +"web_learn_level_fmt" = "Schwierigkeit %d von 3"; +"web_learn_exercise" = "Übung"; +"web_learn_brag" = "Angeberwissen mit Ludwig"; +"web_learn_solved" = "geschafft"; +"web_learn_open_exercise" = "Im Editor öffnen"; +"web_learn_solve_in_editor" = "Löse diese Übung im %@."; +"web_learn_solve_in_code" = "Löse diese Übung im %@."; +"web_learn_solve_in_both" = "Löse diese Übung im %1$@ und im %2$@."; +"web_learn_open_in_editor" = "Im Editor öffnen"; +"web_learn_graphic_labels" = "👆 Klick aufs Bild: Beschriftung ein oder aus"; +"web_learn_check" = "Prüfen"; +"web_learn_hint" = "Tipp"; +"web_learn_reset" = "Von vorn"; +"web_learn_reset_confirm" = "Wirklich von vorn?"; +"web_learn_solution" = "Musterlösung ansehen"; +"web_learn_hint_more" = "Noch ein Tipp"; +"web_learn_hint_fmt" = "Tipp %d von %d"; +"web_learn_teacher" = "Für Lehrkräfte"; +"web_learn_teacher_intro" = "Mit dem Lehrercode werden bei allen Übungen die Musterlösungen sichtbar. Der Browser merkt sich das."; +"web_learn_teacher_code" = "Lehrercode"; +"web_learn_teacher_unlock" = "Freischalten"; +"web_learn_teacher_wrong" = "Der Code stimmt nicht."; +"web_learn_teacher_on" = "Lehrermodus ist an: Bei allen Übungen sind die Musterlösungen sichtbar."; +"web_learn_teacher_off" = "Lehrermodus beenden"; +"web_learn_open_first" = "Öffne die Übung zuerst im Editor und baue dort dein Struktogramm."; +"web_learn_empty" = "Dein Struktogramm ist noch leer. Ziehe zuerst Elemente aus dem Bereich „Elemente“ hinein."; +"web_learn_passed" = "Geschafft! Dein Struktogramm macht genau, was es soll."; +"web_learn_failed" = "Noch nicht ganz. Vergleiche die erwartete mit deiner Ausgabe:"; +"web_learn_missing_fmt" = "Dein Struktogramm braucht noch: %@"; +"web_learn_input_fmt" = "Eingabe: %@"; +"web_learn_no_input" = "Ohne Eingabe"; +"web_learn_expected" = "Erwartet"; +"web_learn_actual" = "Deine Ausgabe"; +"web_learn_missing_input" = "Dein Struktogramm fragt nach mehr Eingaben als vorgesehen."; +"web_learn_unused_input" = "Dein Struktogramm fragt nicht alle Eingaben ab."; +"web_learn_too_many_steps" = "Abbruch nach 100 000 Schritten. Läuft eine Schleife endlos?"; +"web_learn_score_fmt" = "%d von %d richtig"; +"web_learn_cloze_hint" = "Tippe die fehlenden Wörter in die Lücken und drücke „Prüfen“."; +"web_learn_cloze_score_fmt" = "%d von %d Lücken richtig"; +"web_learn_cloze_all_right" = "Alle Lücken richtig!"; +"web_learn_cloze_solution" = "Lösung zeigen"; +"web_learn_cloze_again" = "Nochmal"; +"web_learn_pap_hint" = "Tippe ein Element rechts an und dann seinen Platz im Plan. Du kannst es auch hinziehen. Ein belegter Platz gibt sein Element beim Antippen zurück."; +"web_learn_pap_score_fmt" = "%d von %d Elementen richtig"; +"web_learn_pap_all_right" = "Alles richtig! Dein PAP ist fertig."; +"web_learn_pap_missing_fmt" = "Es fehlen noch %d Elemente."; +"web_learn_pap_empty" = "Leerer Platz"; +"web_learn_pap_yes" = "ja"; +"web_learn_pap_no" = "nein"; +"web_learn_pap_legend_oval" = "Start oder Ende"; +"web_learn_pap_legend_rect" = "Anweisung"; +"web_learn_pap_legend_diamond" = "Verzweigung: Frage mit ja und nein"; +"web_learn_pap_legend_para" = "Ein- oder Ausgabe"; +"web_learn_review" = "Nachlesen"; +"web_learn_terms" = "Fachbegriffe"; +"web_learn_resize" = "Breite des Lernbereichs ändern (Doppelklick: zurücksetzen)"; +"web_learn_competences_intro" = "Am Ende dieser Lektion kann ich …"; +"web_learn_rating_sun" = "kann ich sicher"; +"web_learn_rating_cloud" = "teilweise"; +"web_learn_rating_umbrella" = "noch nicht"; +"web_learn_review_title" = "Deine Checkliste im Vergleich"; +"web_learn_review_hint" = "Hier weichen deine Einschätzung und der Test voneinander ab. Lies den Schritt noch einmal nach und schätze dich in der Checkliste neu ein."; +"web_learn_review_match" = "Deine Einschätzung passt zu deinem Test. Gut gemacht!"; +"web_learn_review_overrated_fmt" = "Du hast ☀️ gewählt, aber Frage %@ war falsch."; +"web_learn_review_underrated" = "Alle Fragen dazu waren richtig. Du kannst mehr, als du denkst!"; +"web_learn_review_unrated" = "noch nicht eingeschätzt"; +"web_learn_back_to_checklist" = "Zurück zur Checkliste"; +"web_learn_step_fmt" = "Schritt %d: %@"; +"web_sim_call_arguments_fmt" = "Der Aufruf passt nicht zur Kopfzeile von %@. Prüfe die Werte in den Klammern."; +"web_sim_missing_return_fmt" = "%@ hat keinen Wert mit return zurückgegeben."; +"web_sim_file_not_found_fmt" = "Es gibt keine Datei %@."; +"web_sim_end_of_file_fmt" = "Die Datei %@ hat keine Zeile mehr."; +"web_sim_null_value_fmt" = "%@ ist null."; +"web_sim_written_file_fmt" = "%@ (gespeichert)"; +"web_site_home" = "Startseite"; +"web_site_imprint" = "Impressum"; +"web_site_privacy" = "Datenschutz"; + +/* Code (früher „Code live“, dann „Programmieren“) */ +"web_live_title" = "Code"; +"web_live_hide" = "Code ausblenden"; +"web_scale_canvas" = "Textgröße Struktogramm"; +"web_scale_code" = "Textgröße Code"; +"web_live_indent" = "Einrücken"; +"web_live_indent_title" = "Code einrücken: jede Ebene vier Leerzeichen tiefer (markierte Zeilen, sonst alles)"; +"web_live_show" = "Code aufklappen"; +"web_live_resize" = "Breite des Codebereichs ändern (Doppelklick: zurücksetzen)"; +"web_live_hint" = "Der Code wächst mit deinem Struktogramm. Grau = Platzhalter: Schreib im Objektinspektor, dann steht dort dein Text. Klick auf eine Zeile markiert das Element."; +"web_live_ph_selector" = "Variable"; +"web_live_ph_code" = "Dein Code"; +"web_live_ph_end" = "Ende"; +"web_live_language" = "Programmiersprache"; +"web_live_java_class" = "Als Klasse"; +"web_live_java_class_hint" = "Klassenname = Titel des Struktogramms"; +"web_live_java_main" = "Mit main-Methode"; +"web_settings_display" = "Darstellung"; +"web_live_swing" = "Echtes Java (mit Swing)"; +"web_live_swing_hint" = "Echtes Java mit Fenstern (CheerpJ). Lädt beim ersten Ausführen einmalig ca. 40 MB."; +"web_live_swing_windows" = "Java-Fenster"; +"web_live_swing_hide" = "Java-Fenster schließen"; +"web_live_swing_loading" = "Java wird geladen (beim ersten Mal ca. 40 MB) …"; +"web_live_swing_compiling" = "Kompiliere …"; +"web_live_swing_running" = "Programm läuft."; +"web_live_swing_compile_failed" = "Fehler beim Kompilieren, siehe oben."; +"web_live_swing_failed" = "Java konnte nicht geladen werden. Prüfe die Internetverbindung."; +"web_live_hint_edit" = "Tippe hier Java-Code, dann baut sich das Struktogramm mit. Oder arbeite im Struktogramm, dann wächst der Code mit. Grau = Platzhalter, einfach drüberschreiben."; +"web_live_edit_label" = "Java-Code"; +"web_parse_line_fmt" = "Zeile %d: %@"; +"web_parse_missing" = "Hier fehlt noch: %@"; +"web_parse_extra" = "Das ist zu viel: %@"; +"web_parse_unclosed_string" = "Hier fehlt das schließende %@."; +"web_parse_else_without_if" = "Zu diesem „else“ gehört kein „if“."; +"web_parse_case_outside_switch" = "„case“ und „default“ gehören in ein „switch“."; +"web_parse_missing_do_while" = "Nach „do { … }“ fehlt noch „while (Bedingung);“."; +"web_parse_more_methods" = "Hier zählt im Moment nur eine Methode. Lege weitere Unterprogramme als eigene Reiter an."; +"web_parse_missing_import" = "Ganz oben fehlt %@ Ohne diese Zeile kennt Java den Scanner nicht."; +"web_parse_missing_scanner" = "Vorher fehlt %@ Ohne diese Zeile gibt es den Scanner nicht."; +"web_parse_unknown_type" = "Diesen Datentyp kennt Java nicht. Meintest du %@?"; +"web_editor_title" = "Struktogramm"; +"web_editor_show" = "Struktogramm aufklappen"; +"web_editor_hide" = "Struktogramm einklappen"; +"web_keywords_title" = "Code-Keywords"; +"web_keywords_hint" = "if, while, for statt Verzweigung, For-Schleife …"; +"web_palette_compact" = "Elemente immer kompakt"; +"web_palette_compact_hint" = "Symbol mit kleinem Namen darunter, sonst nur bei schmaler Spalte"; +"web_about_version_fmt" = "Version %@"; +"web_about_software" = "Verwendete Software"; +"web_about_software_text" = "Der Code-Editor nutzt CodeMirror und Lezer (MIT-Lizenz). Mit Swing-Unterstützung lädt VisuStruct CheerpJ von Leaning Technologies (Community-Lizenz) und javac aus OpenJDK."; +"web_about_licenses" = "Lizenztexte"; +"web_live_run" = "Ausführen"; +"web_live_run_title" = "Programm ausführen: Ausgaben und Eingaben erscheinen darunter"; +"web_live_run_finished" = "Programm beendet."; +"web_live_run_stopped" = "Gestoppt."; +"web_console" = "Konsole"; +"web_console_hide" = "Konsole ausblenden"; +"web_console_resize" = "Höhe der Konsole ändern"; +"web_diagram_tools" = "Werkzeuge für das Struktogramm"; +"web_files_title" = "Dateien"; +"web_files_show" = "Dateien einblenden"; +"web_files_hide" = "Dateien ausblenden"; +"web_files_resize" = "Breite der Dateien ändern"; +"web_files_new_folder" = "Neuer Ordner"; +"web_files_switch" = "Anderen Ordner wählen"; +"web_files_delete" = "Löschen"; +"web_files_in_browser" = "Im Speicher dieses Browsers"; +"web_files_save_hint_fmt" = "Speichern legt das Programm in %@ ab."; +"web_files_empty" = "Noch nichts gespeichert. Beim Speichern legt VisuStruct hier einen Ordner mit dem heutigen Datum an."; +"web_files_reconnect_hint" = "Der Browser fragt nach dem Neuladen noch einmal, ob VisuStruct deinen Ordner benutzen darf."; +"web_files_reconnect_fmt" = "Ordner „%@“ öffnen"; +"web_files_connect_hint" = "Wähle einen Ordner als Arbeitsbereich, am besten einen neuen Ordner „VisuStruct-Dateien“ in deinen Dokumenten. VisuStruct legt darin für jeden Tag einen Ordner an und speichert Struktogramm und Code."; +"web_files_connect" = "Ordner wählen"; +"web_files_browser_hint" = "Dieser Browser kann keine Ordner auf dem Gerät öffnen (z. B. auf dem iPad). Deine Dateien bleiben dann im Speicher dieses Browsers."; +"web_files_browser" = "Im Browser speichern"; +"web_files_delete_confirm_fmt" = "„%@“ wirklich löschen?"; +"web_files_folder_prompt" = "Name des neuen Ordners:"; +"web_files_default_name" = "Programm"; +"web_files_saved_fmt" = "Gespeichert: %@"; +"web_files_create" = "Anlegen"; +"web_learn_ludwig_tip" = "Ludwigs Tipp"; +"web_game_title" = "Spiel: Wahr oder falsch?"; +"web_game_intro" = "Ludwig zeigt dir Werte und eine Bedingung. Ist die Bedingung wahr (true) oder falsch (false)? Zehn Runden, es wird von Runde zu Runde kniffliger."; +"web_game_start" = "Spiel starten"; +"web_game_round_fmt" = "Runde %@ von %@"; +"web_game_score_fmt" = "Punkte: %@"; +"web_game_true" = "wahr (true)"; +"web_game_false" = "falsch (false)"; +"web_game_right" = "Richtig!"; +"web_game_wrong" = "Leider falsch. So wird gerechnet:"; +"web_game_next" = "Weiter"; +"web_game_finish" = "Ergebnis"; +"web_game_done_fmt" = "%@ von %@ richtig."; +"web_game_perfect" = "Alles richtig – Ludwig ist schwer beeindruckt!"; +"web_game_good" = "Stark! Schau dir die Fehler noch einmal an und versuch es nochmal."; +"web_game_practice" = "Übung macht den Meister. Lies dir die Wahrheitstabelle oben noch einmal durch und spiel noch eine Runde."; +"web_game_again" = "Noch einmal"; +"web_game_wrong_short" = "Leider falsch."; +"web_game_practice_short" = "Übung macht den Meister. Lies dir die Erklärungen noch einmal durch und spiel noch eine Runde."; +"web_game_clicks" = "Klicks:"; +"web_game_nobody" = "Niemand hört zu – nichts passiert."; +"web_game_event_fmt" = "Klick auf „%@“: Der Zuhörer hört es und führt seinen Code aus."; +"web_game_try" = "Probier die Knöpfe im Fenster jetzt selbst aus."; +"web_game_time_fmt" = "Noch %@ s"; +"web_game_defused" = "✂️ Entschärft! Du hast den Fehler gefunden."; +"web_game_boom_time" = "💥 Bumm! Die Zeit ist abgelaufen."; +"web_game_boom_wrong" = "💥 Bumm! Das war die falsche Zeile."; +"web_game_fix" = "So stimmt die Zeile:"; +"web_game_order_hint" = "Tippe die Schritte in der richtigen Reihenfolge an."; +"web_debug_step" = "Einzelschritt"; +"web_debug_step_title" = "Einzelschritt: eine Anweisung ausführen und wieder anhalten"; +"web_debug_continue" = "Weiter bis zum nächsten Haltepunkt"; +"web_debug_paused_fmt" = "Angehalten vor Zeile %d."; +"web_debug_gutter_title" = "Auf die Zeilennummer klicken: Haltepunkt setzen oder entfernen"; + +/* Lernbereich: Caesar-Scheibe */ +"web_learn_caesar_title" = "Caesar-Scheibe"; +"web_learn_caesar_hint" = "Drehe die innere Scheibe oder tippe auf −1 und +1. Außen steht der Klartext, innen der Geheimtext."; +"web_learn_caesar_key_fmt" = "Schlüssel %d"; +"web_learn_caesar_plain" = "Klartext"; +"web_learn_caesar_secret" = "Geheimtext"; +"web_learn_caesar_encrypt" = "Verschlüsseln"; +"web_learn_caesar_decrypt" = "Entschlüsseln"; +"web_learn_caesar_back" = "Scheibe eins zurück"; +"web_learn_caesar_forward" = "Scheibe eins weiter"; +"web_learn_rescue_station_fmt" = "Station %@ von %@: %@"; +"web_learn_rescue_number" = "Deine Zahl"; +"web_learn_rescue_not_number" = "Gib eine ganze Zahl ein."; +"web_learn_rescue_wrong" = "Noch nicht. Lies den Code noch einmal Zeichen für Zeichen."; +"web_learn_rescue_letter_moved" = "Der Buchstabe wandert ins Kreuzworträtsel."; +"web_learn_rescue_alphabet" = "Aus deiner Zahl wird ein Buchstabe:"; +"web_learn_rescue_to_crossword" = "Zum Kreuzworträtsel"; +"web_learn_rescue_crossword" = "Das Kreuzworträtsel"; +"web_learn_rescue_across" = "→ Waagrecht"; +"web_learn_rescue_down" = "↓ Senkrecht"; +"web_learn_rescue_cell_fmt" = "Feld Zeile %@, Spalte %@"; +"web_learn_rescue_keyword" = "Geheimes Wort:"; +"web_learn_rescue_cw_wrong" = "Die rot markierten Felder stimmen noch nicht."; +"web_learn_rescue_cw_done" = "Gelöst! Die gelben Felder ergeben das geheime Wort."; +"web_learn_rescue_to_gate" = "Zum Tor"; +"web_learn_rescue_gate" = "Das Tor"; +"web_learn_rescue_word" = "Geheimes Wort"; +"web_learn_rescue_open" = "Tor öffnen"; +"web_learn_rescue_gate_case" = "Fast! equals unterscheidet Groß- und Kleinbuchstaben. Schreib das Wort genau so wie im Rätsel."; +"web_learn_rescue_gate_wrong" = "Das Tor bleibt zu. Schau noch einmal auf die gelben Felder."; +"web_learn_rescue_freed" = "🎉 Das Tor ist offen!"; + +/* VisuBot (mBot2-Modus), nur de/en/pt */ +"web_visubot_world_title" = "Womit möchtest du arbeiten?"; +"web_visubot_world_visustruct_hint" = "VisuStruct: Struktogramme und Java mit dem ganzen Kurs. Wechseln geht jederzeit im Zahnrad."; +"web_visubot_world_visubot_hint" = "VisuBot: den Roboter mBot2 programmieren, mit eigenen Lektionen und Aufgaben. Wechseln geht jederzeit im Zahnrad."; +"web_visubot_connect" = "Mit echtem mBot2 verbinden"; +"web_visubot_upload_button" = "Übertragen"; +"web_visubot_upload_title" = "Programm auf den mBot2 übertragen"; +"web_visubot_upload_step1" = "Schließe den mBot2 mit dem USB-Kabel an und schalte ihn ein. Das geht nur in Chrome oder Edge."; +"web_visubot_upload_step2" = "Klicke auf „Jetzt übertragen“ und wähle „USB Serial“. Der mBot2 speichert dein Programm und startet neu."; +"web_visubot_upload_step3" = "Zieh das Kabel ab und setze den mBot2 an den Start. Drückst du Taste A, fährt dein Programm los. Es bleibt gespeichert, auch nach dem Ausschalten."; +"web_visubot_upload_start" = "Jetzt übertragen"; +"web_visubot_upload_busy" = "Wird übertragen … Kabel nicht abziehen."; +"web_visubot_upload_done" = "Fertig! Kabel ab, mBot2 an den Start, Taste A drücken."; +"web_visubot_upload_failed" = "Das Übertragen hat nicht geklappt. Starte den mBot2 neu und versuche es noch einmal."; +"web_visubot_upload_label" = "A = Start"; +"web_visubot_upload_error_input" = "Dein Programm fragt nach einer Eingabe. Am mBot2 gibt es keine Tastatur, deshalb geht das nicht."; +"web_visubot_upload_error_files" = "Dein Programm arbeitet mit Dateien. Das geht am mBot2 nicht."; +"web_visubot_upload_error_empty" = "Dein Programm ist noch leer."; +"web_visubot_disconnect" = "Trennen"; +"web_visubot_connecting" = "Verbinde … (der CyberPi startet kurz neu)"; +"web_visubot_connected" = "Echter mBot2 fährt mit"; +"web_visubot_no_serial" = "Echter mBot2: nur in Chrome oder Edge am Computer."; +"web_visubot_link_error" = "Verbindung getrennt"; +"web_visubot_world" = "VisuBot-Welt"; +"web_visubot_no_3d" = "Die 3D-Ansicht kann in diesem Browser nicht starten."; +"web_visubot_distance" = "Abstand"; +"web_visubot_line" = "Linie"; +"web_visubot_bumps" = "an die Wand gestoßen"; +"web_visubot_el_forward" = "fahre vor"; +"web_visubot_el_backward" = "fahre zurück"; +"web_visubot_el_right" = "drehe rechts"; +"web_visubot_el_left" = "drehe links"; +"web_visubot_el_led" = "LEDs an"; +"web_visubot_el_tone" = "Ton spielen"; +"web_visubot_drive" = "Fahrt"; +"web_visubot_depth_fmt" = "Die Schleifen müssen %d-fach ineinander stecken."; +"web_visubot_tap_part" = "Dreh den mBot2 mit der Maus oder dem Finger. Tippst du ein Teil an, siehst du seinen Namen."; +"web_visubot_quiz_right" = "Richtig!"; +"web_visubot_quiz_wrong_fmt" = "Das ist: %@. Versuch es noch einmal."; +"web_visubot_part_cyberpi" = "CyberPi"; +"web_visubot_part_screen" = "Bildschirm"; +"web_visubot_part_joystick" = "Joystick"; +"web_visubot_part_buttons" = "Tasten A, B und Home"; +"web_visubot_part_leds" = "RGB-LEDs"; +"web_visubot_part_lightSensor" = "Lichtsensor"; +"web_visubot_part_microphone" = "Mikrofon"; +"web_visubot_part_shield" = "mBot2-Shield mit Akku"; +"web_visubot_part_powerSwitch" = "Ein-Aus-Schalter"; +"web_visubot_part_motors" = "Encoder-Motoren"; +"web_visubot_part_wheels" = "Räder"; +"web_visubot_part_ultrasonic" = "Ultraschallsensor"; +"web_visubot_part_lineSensor" = "Liniensensor (Quad-RGB)"; +"web_visubot_part_caster" = "Kugelrolle"; +"web_visubot_part_chassis" = "Chassis"; +"web_visubot_world_fmt" = "Welt %d"; +"web_visubot_goal_reached" = "Ziel erreicht"; +"web_visubot_goal_missed" = "Ziel nicht erreicht"; +"web_visubot_commands" = "mBot2-Befehle"; +"web_visubot_sensors" = "mBot2-Sensoren"; +"web_visubot_sensor_distance" = "Abstand"; +"web_visubot_sensor_line" = "Linie"; +"web_visubot_el_led_off" = "LEDs aus"; +"web_visubot_el_led_color" = "LED-Farbe setzen"; +"web_visubot_el_wait" = "kurz warten"; +"web_visubot_el_emotion" = "Gefühl zeigen"; +"web_visubot_el_text" = "Text anzeigen"; +"web_visubot_sensor_color" = "Farbe ist rot?"; +"web_visubot_sensor_button_a" = "Taste A gedrückt?"; +"web_visubot_sensor_button_b" = "Taste B gedrückt?"; +"web_visubot_sensor_joy_up" = "Joystick oben?"; +"web_visubot_sensor_joy_down" = "Joystick unten?"; +"web_visubot_sensor_joy_left" = "Joystick links?"; +"web_visubot_sensor_joy_right" = "Joystick rechts?"; +"web_visubot_sensor_brightness" = "Helligkeit"; +"web_visubot_sensor_loudness" = "Lautstärke"; +"web_visubot_sensor_pitch" = "Neigung vorn/hinten"; +"web_visubot_sensor_roll" = "Neigung seitlich"; +"web_visubot_sensor_shake" = "geschüttelt?"; +"web_visubot_el_drive" = "Räder einzeln"; +"web_visubot_el_stop" = "anhalten"; +"web_visubot_el_timer" = "Stoppuhr auf 0"; +"web_visubot_sensor_line_left" = "Linie links?"; +"web_visubot_sensor_line_right" = "Linie rechts?"; +"web_visubot_sensor_timer" = "Stoppuhr (s)"; +"web_visubot_sensor_battery" = "Akku (%)"; +"web_visubot_actions" = "Befehle"; +"web_visubot_led_on" = "LEDs an"; +"web_visubot_led_off" = "LEDs aus"; +"web_visubot_tone_yes" = "Ton"; +"web_visubot_tone_no" = "kein Ton"; +"web_visubot_controls" = "Sensoren ausprobieren"; +"web_visubot_controls_hint" = "Ohne echten mBot2: Hier stellst du ein, was die Sensoren messen. Tasten, Joystick und Schütteln gelten eine Sekunde lang."; +"web_visubot_shake" = "schütteln"; +"web_visubot_check" = "mBot2 testen"; +"web_visubot_check_hint" = "Probiere jeden Aktor einmal aus. Die Sensorwerte laufen live mit: Halte die Hand vor den Ultraschall, drück die Tasten, neige oder schüttle den mBot2. Heb ihn für die Räder hoch."; +"web_visubot_check_forward" = "Räder 1 s vorwärts"; +"web_visubot_check_spin" = "1 s auf der Stelle drehen"; + +/* Start: Ordner für Lernstand und Programme */ +"web_learn_start_title" = "Wo speicherst du deine Arbeit?"; +"web_learn_start_hint" = "Lernstand und Programme liegen in einem Ordner auf deinem Gerät. Der Lernstand steht dort in der Datei learnProgress.json."; +"web_learn_start_continue_fmt" = "Weiter mit „%@“"; +"web_learn_start_open" = "Vorhandenen Ordner öffnen"; +"web_learn_start_create_fmt" = "Neuen Ordner „%@“ anlegen"; +"web_learn_start_create_hint" = "Danach wählst du, wo er liegen soll, z. B. in „Dokumente“."; +"web_learn_start_folder" = "VisuStruct-Dateien"; +"web_learn_start_without" = "Ohne Ordner weiter"; +"web_learn_start_without_hint" = "Dann ist dein Lernstand nach dem Schließen weg."; +"web_visubot_preview_title" = "mBot2 live"; +"web_visubot_preview_hint" = "Zeigt sofort, wohin dein Programm den mBot2 fährt."; +"web_visubot_preview_sim_title" = "Simulation"; +"web_visubot_preview_sim_hint" = "Hier fährt der mBot2 mit, während die Simulation läuft."; +"web_visubot_world_in_preview" = "Der mBot2 fährt im Fenster „Simulation“."; +"web_visubot_preview_play" = "Fahrt abspielen"; +"web_visubot_preview_stop" = "Anhalten"; +"web_visubot_preview_hide" = "mBot2 live einklappen"; +"web_visubot_preview_show" = "mBot2 live zeigen"; +"web_visubot_preview_resize" = "Größe von mBot2 live ändern"; +"web_visubot_preview_stack" = "Unter den Code im Bereich Code"; +"web_visubot_preview_side" = "Als eigene Spalte"; +"web_visubot_preview_distance_fmt" = "Strecke: %d cm"; +"web_visubot_preview_input" = "braucht eine Eingabe, dafür die Simulation starten"; +"web_visubot_preview_limit" = "läuft sehr lange (Endlosschleife?), gezeigt ist der Anfang"; +"web_visubot_group_drive" = "Fahren und Drehen"; +"web_visubot_group_wheels" = "Räder einzeln"; +"web_visubot_group_output" = "Licht, Ton und Bildschirm"; +"web_visubot_group_emotion" = "Gefühle"; +"web_visubot_group_wait" = "Warten und Stoppuhr"; +"web_visubot_group_distance" = "Abstand"; +"web_visubot_group_line" = "Linie"; +"web_visubot_group_color" = "Farben"; +"web_visubot_group_buttons" = "Tasten und Joystick"; +"web_visubot_group_light" = "Licht und Lautstärke"; +"web_visubot_group_tilt" = "Neigung und Schütteln"; +"web_visubot_group_timer" = "Stoppuhr und Akku"; +"web_swap_to_code" = "Code groß, Struktogramm schmal"; +"web_swap_to_editor" = "Struktogramm groß, Code schmal"; +"web_editor_resize" = "Breite des Struktogramms ändern"; +"web_palette_resize" = "Breite der Elemente ändern (Doppelklick: zurücksetzen)"; +"web_palette_hide" = "Elemente einklappen"; +"web_palette_show" = "Elemente aufklappen"; + +/* VisuObject */ +"web_visuobject_world_hint" = "VisuObject: Klassen in Java programmieren und als Klassendiagramm sehen oder zeichnen (ab Klasse 12). Wechseln geht jederzeit im Zahnrad."; +"web_visuobject_subtitle" = "Klassendiagramm"; +"web_visuobject_code" = "Java-Code"; +"web_visuobject_diagram" = "Klassendiagramm"; +"web_visuobject_add_interface" = "Interface"; +"web_visuobject_add_interface_tip" = "Neues Interface ins Diagramm und in den Code"; +"web_visuobject_layout" = "Neu anordnen"; +"web_visuobject_layout_tip" = "Alle Klassen automatisch anordnen: Oberklassen oben"; +"web_visuobject_add_field" = "neues Attribut …"; +"web_visuobject_add_method" = "neue Methode …"; +"web_visuobject_delete_class" = "Klasse löschen"; +"web_visuobject_new_class_name" = "NeueKlasse"; +"web_visuobject_new_interface_name" = "NeuesInterface"; +"web_visuobject_example" = "Beispiel"; +"web_visuobject_example_tip" = "Beispielprojekt Zoo laden: Tier und Hund im Package tiere, Besitzer in personen"; +"web_visuobject_new_tip" = "Neu: leeres Projekt (Rückgängig holt das alte zurück)"; +"web_visuobject_empty" = "Noch keine Klasse. Klicke links auf „+ Klasse“ oder tippe zum Beispiel „public class Hund { }“ in eine Datei."; +"web_visuobject_edit_hint" = "Doppelklick ändert. Schreibweise wie in UML: „- name: String“ oder „+ bellen(): void“. Leer lassen löscht."; +"web_visuobject_member_label" = "Attribut oder Methode in UML-Schreibweise"; +"web_visuobject_name_label" = "Name der Klasse"; +"web_visuobject_bad_name" = "„%@“ ist kein gültiger Name oder gibt es schon."; +"web_visuobject_bad_line" = "„%@“ verstehe ich nicht. Beispiel: - name: String oder + bellen(): void"; +"web_visuobject_open_failed" = "Die Datei konnte nicht gelesen werden."; +"web_visuobject_field_ph" = "- name: String"; +"web_visuobject_seq_diagram" = "Sequenzdiagramm"; +"web_visuobject_seq_empty" = "Das Sequenzdiagramm entsteht beim Debuggen: Klicke oben auf „Debuggen“ und gehe Schritt für Schritt durch das Programm."; +"web_visuobject_seq_no_calls" = "Noch keine Aufrufe eigener Methoden."; +"web_visuobject_seq_truncated" = "… gekürzt: Ab hier sind es zu viele Aufrufe."; +"web_visuobject_seq_hint" = "Jeder Pfeil ist ein Aufruf einer eigenen Methode, gestrichelt kommt die Rückgabe zurück. Klick auf einen Pfeil zeigt die Zeile im Code."; +"web_visuobject_dbg" = "Debuggen"; +"web_visuobject_dbg_tip" = "Programm Schritt für Schritt ausführen. Haltepunkt: auf die Zeilennummer klicken. Das Objektdiagramm zeigt dabei die Objekte im Speicher."; +"web_visuobject_dbg_continue" = "Weiter"; +"web_visuobject_dbg_continue_tip" = "Weiter bis zum nächsten Haltepunkt (F8)"; +"web_visuobject_dbg_pause" = "Pause"; +"web_visuobject_dbg_pause_tip" = "Programm anhalten"; +"web_visuobject_dbg_over" = "Schritt"; +"web_visuobject_dbg_over_tip" = "Nächste Zeile; Methoden laufen ganz durch (F6)"; +"web_visuobject_dbg_into" = "Hinein"; +"web_visuobject_dbg_into_tip" = "In die aufgerufene Methode hineingehen (F5)"; +"web_visuobject_dbg_out" = "Heraus"; +"web_visuobject_dbg_out_tip" = "Methode zu Ende ausführen und zurück zum Aufrufer (F7)"; +"web_visuobject_dbg_input" = "Eingabe für den Scanner, dann Enter"; +"web_visuobject_dbg_running" = "Debugger: Programm läuft …"; +"web_visuobject_dbg_waiting" = "Debugger: Das Programm wartet auf deine Eingabe."; +"web_visuobject_dbg_paused_fmt" = "Debugger: angehalten in %1$@, Zeile %2$@"; +"web_visuobject_dbg_exception" = "Programm mit einer Exception abgebrochen."; +"web_visuobject_dbg_code_changed" = "Code geändert: Debugger beendet."; +"web_visuobject_dbg_line_fmt" = "%1$@:%2$@"; +"web_visuobject_dbg_stack" = "Aufrufstapel"; +"web_visuobject_dbg_vars" = "Variablen"; +"web_visuobject_dbg_var_name" = "Name"; +"web_visuobject_dbg_var_type" = "Typ"; +"web_visuobject_dbg_no_vars" = "Keine Variablen"; +"web_visuobject_dbg_err_syntax" = "%1$@, Zeile %2$@: Das versteht der Debugger nicht (%3$@). Mit ▶ Start siehst du die Meldung von Java."; +"web_visuobject_dbg_err_symbol" = "%1$@, Zeile %2$@: %3$@ ist unbekannt."; +"web_visuobject_dbg_err_import" = "%1$@, Zeile %2$@: Ganz oben fehlt %3$@ Ohne diese Zeile kennt Java die Klasse nicht."; +"web_visuobject_dbg_err_typename" = "%1$@, Zeile %2$@: Diesen Datentyp kennt Java nicht. Meintest du %3$@?"; +"web_visuobject_dbg_err_unsupported" = "%1$@, Zeile %2$@: %3$@ kann der Debugger noch nicht. Mit ▶ Start läuft das Programm in echtem Java."; +"web_visuobject_dbg_err_type" = "%1$@, Zeile %2$@: Hier passt etwas nicht zusammen (%3$@)."; +"web_visuobject_obj_diagram" = "Objektdiagramm"; +"web_visuobject_obj_new" = "Neues Objekt der Klasse"; +"web_visuobject_obj_add" = "Objekt"; +"web_visuobject_obj_empty" = "Noch keine Objekte. Wähle oben eine Klasse und klicke auf „+ Objekt“."; +"web_visuobject_obj_no_classes" = "Lege zuerst im Klassendiagramm eine Klasse an (nicht abstract)."; +"web_visuobject_obj_hint" = "Klicke auf ein Objekt, dann kannst du hier Name, Klasse und Werte ändern. Vom Griff am Objekt zu einem anderen ziehen verbindet sie über ein Referenzattribut."; +"web_visuobject_obj_live_hint" = "Live aus dem Debugger: So sehen die Objekte gerade im Speicher aus."; +"web_visuobject_obj_link" = "Zu einem anderen Objekt ziehen: Referenz setzen"; +"web_visuobject_obj_name" = "Name"; +"web_visuobject_obj_class" = "Klasse"; +"web_visuobject_obj_attribute" = "Attribut"; +"web_visuobject_obj_value" = "Wert"; +"web_visuobject_obj_delete" = "Objekt löschen"; +"web_visuobject_obj_bad_name" = "„%@“ ist kein gültiger Name für ein Objekt."; +"web_visuobject_obj_name_taken" = "Ein Objekt „%@“ gibt es schon."; +"web_visuobject_obj_no_ref" = "%1$@ hat kein Attribut, das auf %2$@ zeigen kann."; +"web_visuobject_tool_note" = "Notiz"; +"web_visuobject_tool_note_tip" = "Notiz: Klicke ins Klassendiagramm, dann tippe den Text. Mit dem Griff ziehst du eine gestrichelte Linie zu einer Klasse."; +"web_visuobject_note_ph" = "Notiz …"; +"web_visuobject_note_text" = "Text"; +"web_visuobject_note_attached" = "Verbunden mit"; +"web_visuobject_note_attach" = "Zu einer Klasse ziehen: gestrichelte Linie"; +"web_visuobject_note_delete" = "Notiz löschen"; +"web_visuobject_run" = "Start"; +"web_visuobject_run_tip" = "Programm mit echtem Java starten: alle Klassen werden übersetzt, gestartet wird die Klasse mit main (bevorzugt die offene)."; +"web_visuobject_stop" = "Stop"; +"web_visuobject_stop_tip" = "Programm beenden und seine Fenster schließen"; +"web_visuobject_stopped" = "Programm beendet."; +"web_visuobject_no_main" = "Keine Klasse mit public static void main(String[] args) gefunden."; +"web_visuobject_running_fmt" = "%@ läuft …"; +"web_visuobject_console_clear" = "Leeren"; +"web_visuobject_section_fields" = "Attribute"; +"web_visuobject_section_refs" = "Referenzattribute"; +"web_visuobject_section_ctors" = "Konstruktor"; +"web_visuobject_section_methods" = "Methoden"; +"web_visuobject_insp_sections" = "Abschnitts-Kommentare einfügen"; +"web_visuobject_insp_sort" = "Einsortieren"; +"web_visuobject_insp_sections_tip" = "Schreibt // Attribute, // Referenzattribute, // Konstruktor und // Methoden in die Klasse und sortiert alles darunter. Neues aus dem Klassendiagramm kommt dann gleich an die richtige Stelle."; +"web_visuobject_insp_doc" = "Beschreibung (Javadoc)"; +"web_visuobject_insp_doc_ph" = "Wofür ist die Klasse da? Steht im Code als Javadoc-Kommentar über der Klasse."; +"web_visuobject_insp_visibility" = "Sichtbarkeit"; +"web_visuobject_insp_type" = "Typ"; +"web_visuobject_insp_init" = "Startwert"; +"web_visuobject_insp_no_fields" = "Noch keine Attribute."; +"web_visuobject_insp_add_field" = "Attribut"; +"web_visuobject_insp_params" = "Parameter"; +"web_visuobject_insp_return" = "Rückgabetyp"; +"web_visuobject_insp_constructor" = "Konstruktor"; +"web_visuobject_insp_no_methods" = "Noch keine Methoden."; +"web_visuobject_insp_add_method" = "Methode"; +"web_visuobject_insp_generate" = "Erzeugen:"; +"web_visuobject_insp_gen_constructor" = "Konstruktor aus Attributen"; +"web_visuobject_insp_gen_constructor_tip" = "Wie in Eclipse „Generate Constructor using Fields“: ein Konstruktor, der alle Attribute (ohne static) setzt."; +"web_visuobject_insp_gen_accessors" = "Getter und Setter"; +"web_visuobject_insp_gen_accessors_tip" = "Wie in Eclipse „Generate Getters and Setters“: für jedes Attribut get…/set… (final-Attribute nur Getter)."; +"web_visuobject_insp_bad_params" = "Parameter so schreiben: name: Typ, zweiter: int (gelesen wurde „%@“)."; +"web_visuobject_insp_fields" = "Attribute"; +"web_visuobject_insp_methods" = "Methoden"; +"web_visuobject_inspector_resize" = "Größe ändern: Grenze zwischen Klassendiagramm und Objektinspektor nach oben oder unten ziehen (Doppelklick = Standard)"; +"web_visuobject_dep_title" = "Abhängigkeit «%@»"; +"web_visuobject_dep_create_text" = "%1$@ erzeugt in %3$@ ein Objekt der Klasse %2$@ (new)."; +"web_visuobject_dep_use_text" = "%1$@ benutzt die Klasse %2$@ in %3$@."; +"web_visuobject_dep_hint" = "Das ist keine Assoziation: %@ merkt sich das %@-Objekt nicht in einem Attribut, es lebt nur in der Methode. Darum gestrichelt."; +"web_visuobject_dep_to_assoc" = "Als Attribut merken (Assoziation zu %@)"; +"web_visuobject_end_mult_ph" = "Mult."; +"web_visuobject_end_tip" = "Klick (Linie markiert) oder Rechtsklick: Rolle, Multiplizität und Navigierbarkeit an diesem Ende"; +"web_visuobject_end_role_ph" = "z. B. meineKatzen"; +"web_visuobject_new_menu" = "Neu"; +"web_visuobject_new_menu_tip" = "Neues Projekt, Source Folder, Package, Klasse oder Interface anlegen"; +"web_visuobject_new_project" = "Java-Projekt"; +"web_visuobject_new_folder" = "Source Folder"; +"web_visuobject_new_package" = "Package"; +"web_visuobject_new_class" = "Klasse"; +"web_visuobject_new_interface" = "Interface"; +"web_visuobject_new_project_title" = "Neues Java-Projekt"; +"web_visuobject_new_project_hint" = "Im Workspace bekommt jedes Projekt einen eigenen Ordner mit src."; +"web_visuobject_new_folder_title" = "Neuer Source Folder"; +"web_visuobject_new_folder_hint" = "Ein weiterer Ordner für Quellcode neben src, z. B. test für Testklassen."; +"web_visuobject_new_package_title" = "Neues Package"; +"web_visuobject_new_package_hint" = "Package-Namen schreibt man klein, Teile mit Punkt: tiere oder schule.verwaltung."; +"web_visuobject_new_class_title" = "Neue Java-Klasse"; +"web_visuobject_new_class_hint" = "Klassennamen beginnen mit einem Großbuchstaben, z. B. Hund oder Bankkonto."; +"web_visuobject_new_interface_title" = "Neues Java-Interface"; +"web_visuobject_new_interface_hint" = "Ein Interface legt Methoden fest, die Klassen später implementieren."; +"web_visuobject_new_root" = "Source Folder"; +"web_visuobject_new_name" = "Name"; +"web_visuobject_new_modifiers" = "Modifier"; +"web_visuobject_new_package_private" = "package (ohne Modifier)"; +"web_visuobject_new_superclass" = "Oberklasse"; +"web_visuobject_new_interfaces" = "Interfaces (implements)"; +"web_visuobject_new_extends_interfaces" = "Erweitert Interfaces (extends)"; +"web_visuobject_new_stubs" = "Welche Methoden-Rümpfe sollen entstehen?"; +"web_visuobject_new_stub_constructors" = "Konstruktoren der Oberklasse"; +"web_visuobject_new_stub_inherited" = "Geerbte abstrakte Methoden"; +"web_visuobject_new_comment_legend" = "Kommentar"; +"web_visuobject_new_comment" = "Javadoc-Kommentar mit @author"; +"web_visuobject_new_author" = "Dein Name"; +"web_visuobject_new_finish" = "Fertigstellen"; +"web_visuobject_new_name_missing" = "Bitte gib einen Namen ein."; +"web_visuobject_new_exists" = "„%@“ gibt es im Projekt schon."; +"web_visuobject_new_upper" = "Klassennamen beginnen in Java mit einem Großbuchstaben."; +"web_visuobject_bad_folder" = "„%@“ ist kein gültiger Ordnername oder gibt es schon."; +"web_visuobject_inspector_hide" = "Objektinspektor einklappen"; +"web_visuobject_inspector_show" = "Objektinspektor aufklappen"; +"web_visuobject_inspector_empty" = "Klicke im Diagramm auf eine Beziehung (Linie), dann kannst du sie hier bearbeiten."; +"web_visuobject_rel_end_a" = "Ende A: %@ (Linie beginnt hier)"; +"web_visuobject_rel_end_b" = "Ende B: %@ (Linie endet hier)"; +"web_visuobject_ws_title" = "Workspace-Ordner auf deinem Rechner"; +"web_visuobject_ws_question" = "Wo speicherst du deine Projekte?"; +"web_visuobject_ws_hint" = "Wie in Eclipse: ein Workspace-Ordner auf deinem Rechner, darin ein Ordner je Projekt mit src und den .java-Dateien."; +"web_visuobject_ws_create" = "Ordner „%@“ anlegen"; +"web_visuobject_ws_open" = "Vorhandenen Workspace öffnen"; +"web_visuobject_ws_skip" = "Ohne Ordner (nur im Browser)"; +"web_visuobject_ws_choose" = "Workspace wählen"; +"web_visuobject_ws_reopen" = "Workspace „%@“ öffnen"; +"web_visuobject_ws_switch" = "Wechseln"; +"web_visuobject_ws_zip" = "ZIP"; +"web_visuobject_ws_zip_tip" = "Projekt als .zip herunterladen, z. B. zum Abgeben"; +"web_visuobject_ws_saved" = "Gespeichert in %@/%@"; +"web_visuobject_ws_created" = "Neues Projekt „%@“ im Workspace"; +"web_visuobject_ws_failed" = "Speichern im Workspace hat nicht geklappt: %@"; +"web_visuobject_ws_taken" = "Im Workspace gibt es schon ein Projekt „%@“."; +"web_visuobject_ws_open_project" = "Projekt %@ öffnen"; +"web_visuobject_save_ws_tip" = "Im Workspace speichern (Strg+S)"; +"web_visuobject_unsaved" = "nicht gespeichert"; +"web_visuobject_rel_nav_navigable" = "navigierbar (Pfeil)"; +"web_visuobject_rel_nav_non-navigable" = "nicht navigierbar (Kreuz ×)"; +"web_visuobject_rel_nav_unspecified" = "nicht spezifiziert (offen)"; +"web_visuobject_rel_reading_flip" = "umdrehen"; +"web_visuobject_rel_reading_auto" = "Mit einem Namen liest sich die Beziehung in Zugrichtung."; +"web_visuobject_tools" = "Werkzeuge"; +"web_visuobject_tool_select" = "Auswahl"; +"web_visuobject_tool_select_tip" = "Auswählen und verschieben"; +"web_visuobject_tool_class" = "Klasse"; +"web_visuobject_tool_class_tip" = "Klasse: auf die Fläche ziehen oder wählen und auf die Fläche klicken"; +"web_visuobject_tool_interface" = "Interface"; +"web_visuobject_tool_interface_tip" = "Interface: auf die Fläche ziehen oder wählen und auf die Fläche klicken"; +"web_visuobject_tool_link" = "Assoziation"; +"web_visuobject_tool_link_tip" = "Assoziation ohne Navigation: einfache Linie zwischen zwei Klassen ziehen"; +"web_visuobject_rel_link" = "Assoziation (ohne Navigation)"; +"web_visuobject_tool_not_link" = "%@ ist ein Interface und kann keine Attribute haben. Zieh die Beziehung von einer Klasse aus."; +"web_visuobject_tool_association" = "Gerichtet"; +"web_visuobject_tool_association_tip" = "Gerichtete Assoziation: von der Klasse, die die andere kennt, zur anderen ziehen (Pfeil)"; +"web_visuobject_tool_aggregation" = "Aggregation"; +"web_visuobject_tool_aggregation_tip" = "Aggregation: vom Ganzen zum Teil ziehen (hat, Teile leben weiter)"; +"web_visuobject_tool_composition" = "Komposition"; +"web_visuobject_tool_composition_tip" = "Komposition: vom Ganzen zum Teil ziehen (besteht aus, Teile gehören fest dazu)"; +"web_visuobject_tool_extends" = "Vererbung"; +"web_visuobject_tool_extends_tip" = "Vererbung: von der Unterklasse zur Oberklasse ziehen (erbt von)"; +"web_visuobject_tool_implements" = "Realisierung"; +"web_visuobject_tool_implements_tip" = "Realisierung: von der Klasse zum Interface ziehen (implementiert)"; +"web_visuobject_tool_pick_second" = "Jetzt die zweite Klasse anklicken (von %@ aus). Esc bricht ab."; +"web_visuobject_tool_not_association" = "%@ ist ein Interface und kann keine Attribute haben. Zieh die Beziehung von einer Klasse aus."; +"web_visuobject_tool_not_aggregation" = "%@ ist ein Interface und kann keine Attribute haben. Zieh die Beziehung von einer Klasse aus."; +"web_visuobject_tool_not_composition" = "%@ ist ein Interface und kann keine Attribute haben. Zieh die Beziehung von einer Klasse aus."; +"web_visuobject_tool_not_extends" = "%@ kann nicht von %@ erben: Klassen erben von Klassen, Interfaces von Interfaces. Für ein Interface nimm Realisierung."; +"web_visuobject_tool_not_implements" = "%@ kann %@ nicht implementieren: Nur eine Klasse implementiert ein Interface."; +"web_visuobject_inspector" = "Objektinspektor"; +"web_visuobject_connect" = "Ziehen: Beziehung zu einer anderen Klasse"; +"web_visuobject_rel_association" = "Assoziation"; +"web_visuobject_rel_directed" = "Gerichtete Assoziation"; +"web_visuobject_rel_aggregation" = "Aggregation (hat, Teile leben weiter)"; +"web_visuobject_rel_composition" = "Komposition (besteht aus, Teile gehören fest dazu)"; +"web_visuobject_rel_extends" = "Vererbung (erbt von)"; +"web_visuobject_rel_implements" = "Realisierung (implementiert)"; +"web_visuobject_rel_extends_text" = "%@ erbt von %@ (extends im Code)."; +"web_visuobject_rel_implements_text" = "%@ implementiert das Interface %@ (implements im Code)."; +"web_visuobject_rel_kind" = "Art"; +"web_visuobject_rel_name" = "Name der Beziehung"; +"web_visuobject_rel_name_ph" = "z. B. besitzt"; +"web_visuobject_rel_reading" = "Leserichtung"; +"web_visuobject_rel_navigable" = "Navigierbarkeit"; +"web_visuobject_rel_role" = "Rolle"; +"web_visuobject_rel_multiplicity" = "Multiplizität"; +"web_visuobject_rel_role_field" = "= Attribut %@.%@ im Code"; +"web_visuobject_rel_role_only_uml" = "nur im Diagramm (kein Attribut, solange der Pfeil nur in eine Richtung zeigt)"; +"web_visuobject_rel_delete" = "Beziehung löschen"; +"web_visuobject_rel_impossible" = "Von %@ zu %@ gibt es keine passende Beziehung."; +"web_visuobject_rel_menu" = "%@ → %@"; +"web_visuobject_resize" = "Breite ziehen (Doppelklick: Standard)"; +"web_visuobject_pane_show" = "Bereich aufklappen"; +"web_visuobject_pane_hide" = "Bereich einklappen"; +"web_visuobject_close_tab" = "%@ schließen"; +"web_visuobject_collapse" = "Einklappen"; +"web_visuobject_expand" = "Aufklappen"; +"web_visuobject_tree_empty" = "Noch leer. Lege mit „+ Neu“ ein Package oder eine Klasse an."; +"web_visuobject_delete" = "Löschen"; +"web_visuobject_default_package" = "(Standard-Package)"; +"web_visuobject_bad_package" = "„%@“ ist kein gültiger Package-Name oder gibt es schon. Package-Namen schreibt man klein, z. B. tiere."; +"web_visuobject_new_package_name" = "neuespackage"; +"web_visuobject_no_file" = "Keine Datei offen"; +"web_visuobject_project_name" = "MeinProjekt"; +"web_visuobject_explorer_show" = "Package Explorer zeigen"; +"web_visuobject_explorer_hide" = "Package Explorer einklappen"; +"web_visuobject_explorer" = "Package Explorer"; +"web_visuobject_save_tip" = "Projekt als .zip speichern: Projektname/src/package/Klasse.java"; +"web_visuobject_open_tip" = "Projekt öffnen (.zip wie aus Eclipse oder BlueJ) oder .java-Dateien ins Projekt holen"; +"web_visuobject_method_ph" = "+ bellen(): void"; +"web_code_scopes" = "Blöcke farbig"; +"web_code_scopes_hint" = "Code und Struktogramm: Schleife rosa, Verzweigung blau, Methode gelb, Klasse grün"; +"web_pseudocode" = "Pseudocode"; + +/* VisuFlow (PAP zeichnen) */ +"web_visuflow_subtitle" = "PAP zeichnen"; +"web_visuflow_world_hint" = "VisuFlow: einen Programmablaufplan (PAP, englisch flowchart) frei zeichnen und als Bild oder PDF exportieren. Wechseln geht jederzeit im Zahnrad."; +"web_visuflow_palette" = "Symbole"; +"web_visuflow_palette_hint" = "Antippen hängt das Symbol unter das gewählte an und verbindet es mit einem Pfeil. Du kannst es auch auf die Fläche ziehen."; +"web_visuflow_shape_start" = "Start"; +"web_visuflow_shape_ende" = "Ende"; +"web_visuflow_shape_anweisung" = "Anweisung"; +"web_visuflow_shape_ein" = "Ein-/Ausgabe"; +"web_visuflow_shape_verzweigung" = "Verzweigung"; +"web_visuflow_shape_unterprogramm" = "Unterprogramm"; +"web_visuflow_shape_start_tip" = "Oval: Hier beginnt der Ablauf"; +"web_visuflow_shape_ende_tip" = "Oval: Hier endet der Ablauf"; +"web_visuflow_shape_anweisung_tip" = "Rechteck: eine Anweisung, zum Beispiel „Wasser kochen“"; +"web_visuflow_shape_ein_tip" = "Parallelogramm: Eingabe oder Ausgabe, zum Beispiel „Eingabe: Zahl“"; +"web_visuflow_shape_verzweigung_tip" = "Raute: eine Frage mit den Ausgängen ja und nein"; +"web_visuflow_shape_unterprogramm_tip" = "Rechteck mit zwei Strichen: ruft ein Unterprogramm auf"; +"web_visuflow_text_start" = "Start"; +"web_visuflow_text_ende" = "Ende"; +"web_visuflow_text_anweisung" = "Anweisung"; +"web_visuflow_text_ein" = "Eingabe: Zahl"; +"web_visuflow_text_verzweigung" = "Bedingung?"; +"web_visuflow_text_unterprogramm" = "Unterprogramm"; +"web_visuflow_new_tip" = "Neu: leerer PAP mit Start (Rückgängig holt den alten zurück)"; +"web_visuflow_open_tip" = "PAP-Datei (.visuflow) öffnen"; +"web_visuflow_save_tip" = "PAP als Datei (.visuflow) speichern"; +"web_visuflow_delete" = "Löschen"; +"web_visuflow_delete_tip" = "Gewähltes Symbol oder gewählten Pfeil löschen (Entf)"; +"web_visuflow_swap" = "ja/nein tauschen"; +"web_visuflow_swap_tip" = "Raute: „ja“ und „nein“ tauschen die Seiten"; +"web_visuflow_example" = "Beispiel"; +"web_visuflow_example_tip" = "Beispiel „Tee kochen“ aus Lektion 1 laden (Rückgängig holt den alten PAP zurück)"; +"web_visuflow_example_title" = "Tee kochen"; +"web_visuflow_example_water" = "Wasser kochen"; +"web_visuflow_example_bag" = "Teebeutel in die Tasse"; +"web_visuflow_example_hot" = "Tee noch zu heiß?"; +"web_visuflow_example_wait" = "Warten"; +"web_visuflow_example_drink" = "Tee trinken"; +"web_visuflow_title_label" = "Titel des PAP"; +"web_visuflow_title_ph" = "Titel des PAP"; +"web_visuflow_canvas_label" = "Zeichenfläche des PAP"; +"web_visuflow_open_error" = "Die Datei ist kein VisuFlow-PAP."; +"web_visuflow_saved" = "Gespeichert als %@"; +"web_visuflow_status_empty" = "Zieh ein Symbol aus der Leiste auf die Fläche oder tippe es an."; +"web_visuflow_status_idle" = "Symbol antippen wählt es aus. Vom Punkt am Ausgang ziehst du einen Pfeil zum nächsten Symbol."; +"web_visuflow_status_node" = "Ziehen verschiebt das Symbol, nochmal antippen ändert den Text. Vom Punkt am Ausgang einen Pfeil ziehen."; +"web_visuflow_status_edge" = "Pfeil gewählt. Löschen entfernt ihn."; +"web_visuflow_status_connect" = "Loslassen über dem Symbol, zu dem der Pfeil führt."; +"web_visuflow_edit_label" = "Text im Symbol"; +`;export{e as default}; diff --git a/website/app/assets/el-CtIZyj0I.js b/website/app/assets/el-CtIZyj0I.js new file mode 100644 index 00000000..0c996c1b --- /dev/null +++ b/website/app/assets/el-CtIZyj0I.js @@ -0,0 +1,180 @@ +const e=`/* Κείμενα που υπάρχουν μόνο στην έκδοση web. Όλα τα άλλα προέρχονται από το Localizable.strings της εφαρμογής. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "Διάγραμμα VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Εξαγωγή…"; +"web_export_title" = "Αποθήκευση ως εικόνα ή PDF ή εκτύπωση"; +"web_export_png" = "Εικόνα (PNG)"; +"web_export_svg" = "Διανυσματικό γραφικό (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "Αρχείο VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "Η εξαγωγή απέτυχε: %@"; +"web_print_hint" = "Με «Εξαγωγή… → PDF» μπορείτε να αποθηκεύσετε το διάγραμμα και να το εκτυπώσετε από εκεί."; +"web_delete" = "Διαγραφή"; +"web_language_title" = "Γλώσσα περιβάλλοντος"; +"web_simulation_start" = "Έναρξη προσομοίωσης"; +"web_simulation_end" = "Τέλος προσομοίωσης"; +"web_simulation_start_title" = "Εκτέλεση του διαγράμματος βήμα προς βήμα"; +"web_simulation_end_title" = "Τέλος προσομοίωσης και συνέχεια επεξεργασίας"; +"web_palette_hint" = "Σύρετε στο διάγραμμα"; +"web_tabs_label" = "Διαγράμματα"; +"web_status_modified" = "τροποποιήθηκε"; +"web_inspector_title" = "Ιδιότητες"; +"web_inspector_help_drop" = "Σύρετε στοιχεία από την παλέτα σε ένα πλακίδιο: πάνω = πριν, κάτω = μετά, πάνω στο «ø» = αντικατάσταση. Τα υπάρχοντα στοιχεία μετακινούνται με το ποντίκι."; +"web_inspector_help_files" = "Μπορείτε επίσης να σύρετε αρχεία στο παράθυρο."; +"web_case_name" = "Όνομα περίπτωσης"; +"web_case_name_placeholder" = "π.χ. 1, ok, default"; +"web_copied" = "Το στοιχείο αντιγράφηκε."; +"web_discard_message_fmt" = "Οι αλλαγές στο «%@» θα χαθούν."; +"web_err_unreadable_fmt" = "Το «%@» δεν είναι αναγνώσιμο αρχείο VisuStruct (%@)."; +"web_saved_fmt" = "Το «%@» αποθηκεύτηκε."; +"web_saved_txt_fmt" = "Αποθηκεύτηκε ως «%@». Αφαιρέστε την κατάληξη .txt για να το χρησιμοποιήσετε."; +"web_drop_impossible" = "Δεν είναι δυνατή η απόθεση εδώ"; +"web_sim_delay" = "Παύση ανά βήμα"; +"web_sim_delay_value_fmt" = "%@ δευτ."; +"web_codegen_language" = "Γλώσσα"; +"web_codegen_comments" = "Κείμενο διαγράμματος ως σχόλια"; +"web_codegen_empty_else" = "Εμφάνιση κενού κλάδου else στον κώδικα"; +"web_copied_check" = "Αντιγράφηκε ✓"; +"web_copy_manual" = "Επιλέχθηκε, πατήστε Ctrl+C για αντιγραφή"; +"web_run_stopped_loop" = "Η εκτέλεση διακόπηκε: πιθανός ατέρμονος βρόχος."; +"web_run_cancelled" = "Η εκτέλεση ακυρώθηκε."; +"web_run_error" = "Σφάλμα κατά την εκτέλεση."; +"web_run_dropped_fmt" = "… %d προηγούμενες γραμμές κρυμμένες"; +"web_sim_call_arguments_fmt" = "Η κλήση δεν ταιριάζει με την κεφαλίδα του %@. Έλεγξε τις τιμές μέσα στις παρενθέσεις."; +"web_sim_missing_return_fmt" = "Το %@ τελείωσε χωρίς να επιστρέψει τιμή με return."; +"web_sim_file_not_found_fmt" = "Δεν υπάρχει αρχείο με όνομα %@."; +"web_sim_end_of_file_fmt" = "Το αρχείο %@ δεν έχει άλλες γραμμές."; +"web_sim_null_value_fmt" = "Το %@ είναι null."; +"web_sim_written_file_fmt" = "%@ (αποθηκεύτηκε)"; +"web_site_home" = "Αρχική σελίδα"; +"web_site_imprint" = "Στοιχεία εκδότη"; +"web_site_privacy" = "Απόρρητο"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Προγραμματισμός"; +"web_live_hide" = "Απόκρυψη προγραμματισμού"; +"web_scale_canvas" = "Μέγεθος κειμένου: διάγραμμα"; +"web_scale_code" = "Μέγεθος κειμένου: προγραμματισμός"; +"web_live_indent" = "Εσοχή"; +"web_live_indent_title" = "Εσοχή κώδικα: τέσσερα κενά ανά επίπεδο (επιλεγμένες γραμμές, αλλιώς όλα)"; +"web_live_show" = "Εμφάνιση προγραμματισμού"; +"web_live_resize" = "Αλλαγή πλάτους περιοχής κώδικα (διπλό κλικ: επαναφορά)"; +"web_live_hint" = "Ο κώδικας μεγαλώνει μαζί με το διάγραμμα. Γκρι = σύμβολο κράτησης: γράψε στον επιθεωρητή και το κείμενό σου εμφανίζεται εδώ. Κάνε κλικ σε μια γραμμή για να επιλέξεις το στοιχείο."; +"web_live_ph_selector" = "μεταβλητή"; +"web_live_ph_code" = "Ο κώδικάς σου"; +"web_live_ph_end" = "τέλος"; +"web_live_language" = "Γλώσσα προγραμματισμού"; +"web_live_java_class" = "Ως κλάση"; +"web_live_java_class_hint" = "Όνομα κλάσης = τίτλος διαγράμματος"; +"web_live_java_main" = "Με μέθοδο main"; +"web_settings_display" = "Εμφάνιση"; +"web_live_swing" = "Πραγματική Java (με Swing)"; +"web_live_swing_hint" = "Πραγματική Java με παράθυρα (CheerpJ). Κατεβάζει μία φορά περίπου 40 MB στην πρώτη εκτέλεση."; +"web_live_swing_windows" = "Παράθυρα Java"; +"web_live_swing_hide" = "Κλείσιμο παραθύρων Java"; +"web_live_swing_loading" = "Φόρτωση Java (την πρώτη φορά περίπου 40 MB) …"; +"web_live_swing_compiling" = "Μεταγλώττιση …"; +"web_live_swing_running" = "Το πρόγραμμα εκτελείται."; +"web_live_swing_compile_failed" = "Σφάλμα μεταγλώττισης, δες παραπάνω."; +"web_live_swing_failed" = "Δεν ήταν δυνατή η φόρτωση της Java. Έλεγξε τη σύνδεση στο διαδίκτυο."; +"web_live_hint_edit" = "Γράψε εδώ κώδικα Java και το διάγραμμα φτιάχνεται μόνο του. Ή δούλεψε στο διάγραμμα και ο κώδικας μεγαλώνει μαζί. Γκρι = σύμβολο κράτησης θέσης, απλώς γράψε από πάνω."; +"web_live_edit_label" = "Κώδικας Java"; +"web_parse_line_fmt" = "Γραμμή %d: %@"; +"web_parse_missing" = "Λείπει ακόμα εδώ: %@"; +"web_parse_extra" = "Περισσεύει: %@"; +"web_parse_unclosed_string" = "Λείπει το %@ που κλείνει."; +"web_parse_else_without_if" = "Αυτό το «else» δεν έχει «if»."; +"web_parse_case_outside_switch" = "Τα «case» και «default» ανήκουν μέσα σε «switch»."; +"web_parse_missing_do_while" = "Μετά το «do { … }» λείπει το «while (συνθήκη);»."; +"web_parse_more_methods" = "Προς το παρόν μετράει μόνο μία μέθοδος. Δημιούργησε τα άλλα υποπρογράμματα σε ξεχωριστές καρτέλες."; +"web_parse_missing_import" = "Λείπει στην αρχή το %@ Χωρίς αυτή τη γραμμή η Java δεν γνωρίζει το Scanner."; +"web_parse_missing_scanner" = "Λείπει πρώτα %@ Χωρίς αυτή τη γραμμή ο Scanner δεν υπάρχει."; +"web_parse_unknown_type" = "Η Java δεν γνωρίζει αυτόν τον τύπο δεδομένων. Μήπως εννοείς %@;"; +"web_editor_title" = "Διάγραμμα"; +"web_editor_show" = "Εμφάνιση διαγράμματος"; +"web_editor_hide" = "Απόκρυψη διαγράμματος"; +"web_keywords_title" = "Λέξεις-κλειδιά κώδικα"; +"web_keywords_hint" = "if, while, for αντί για ονόματα στοιχείων"; +"web_palette_compact" = "Στοιχεία πάντα συμπαγή"; +"web_palette_compact_hint" = "Σύμβολο με μικρό όνομα από κάτω, αλλιώς μόνο όταν η στήλη είναι στενή"; +"web_about_version_fmt" = "Έκδοση %@"; +"web_about_software" = "Λογισμικό που χρησιμοποιείται"; +"web_about_software_text" = "Ο επεξεργαστής κώδικα χρησιμοποιεί τα CodeMirror και Lezer (άδεια MIT). Με την υποστήριξη Swing, το VisuStruct φορτώνει το CheerpJ της Leaning Technologies (άδεια Community) και το javac από το OpenJDK."; +"web_about_licenses" = "Κείμενα αδειών"; +"web_live_run" = "Εκτέλεση"; +"web_live_run_title" = "Εκτέλεση προγράμματος: η έξοδος και η είσοδος εμφανίζονται παρακάτω"; +"web_live_run_finished" = "Το πρόγραμμα τελείωσε."; +"web_live_run_stopped" = "Διακόπηκε."; +"web_console" = "Κονσόλα"; +"web_console_hide" = "Απόκρυψη κονσόλας"; +"web_console_resize" = "Αλλαγή ύψους κονσόλας"; +"web_diagram_tools" = "Εργαλεία διαγράμματος"; +"web_files_title" = "Αρχεία"; +"web_files_show" = "Εμφάνιση αρχείων"; +"web_files_hide" = "Απόκρυψη αρχείων"; +"web_files_resize" = "Αλλαγή πλάτους αρχείων"; +"web_files_new_folder" = "Νέος φάκελος"; +"web_files_switch" = "Επιλογή άλλου φακέλου"; +"web_files_delete" = "Διαγραφή"; +"web_files_in_browser" = "Στον χώρο αυτού του προγράμματος περιήγησης"; +"web_files_save_hint_fmt" = "Η αποθήκευση βάζει το πρόγραμμα στο %@."; +"web_files_empty" = "Δεν έχει αποθηκευτεί τίποτα ακόμη. Κατά την αποθήκευση το VisuStruct δημιουργεί εδώ έναν φάκελο με τη σημερινή ημερομηνία."; +"web_files_reconnect_hint" = "Μετά την επαναφόρτωση, το πρόγραμμα περιήγησης ρωτά ξανά αν το VisuStruct μπορεί να χρησιμοποιήσει τον φάκελό σου."; +"web_files_reconnect_fmt" = "Άνοιγμα φακέλου «%@»"; +"web_files_connect_hint" = "Επίλεξε έναν φάκελο ως χώρο εργασίας. Το VisuStruct δημιουργεί εκεί έναν φάκελο για κάθε ημέρα και αποθηκεύει διάγραμμα και κώδικα."; +"web_files_connect" = "Επιλογή φακέλου"; +"web_files_browser_hint" = "Αυτό το πρόγραμμα περιήγησης δεν μπορεί να ανοίξει φακέλους της συσκευής (π.χ. στο iPad). Τα αρχεία σου μένουν στον χώρο του."; +"web_files_browser" = "Αποθήκευση στο πρόγραμμα περιήγησης"; +"web_files_delete_confirm_fmt" = "Να διαγραφεί οριστικά το «%@»;"; +"web_files_folder_prompt" = "Όνομα νέου φακέλου:"; +"web_files_default_name" = "Πρόγραμμα"; +"web_files_saved_fmt" = "Αποθηκεύτηκε: %@"; +"web_files_create" = "Δημιουργία"; +"web_learn_ludwig_tip" = "Η συμβουλή του Ludwig"; +"web_game_title" = "Παιχνίδι: Αληθές ή ψευδές;"; +"web_game_intro" = "Ο Ludwig σου δείχνει τιμές και μια συνθήκη. Είναι αληθής (true) ή ψευδής (false); Δέκα γύροι, όλο και δυσκολότεροι."; +"web_game_start" = "Έναρξη παιχνιδιού"; +"web_game_round_fmt" = "Γύρος %@ από %@"; +"web_game_score_fmt" = "Πόντοι: %@"; +"web_game_true" = "αληθές (true)"; +"web_game_false" = "ψευδές (false)"; +"web_game_right" = "Σωστά!"; +"web_game_wrong" = "Όχι ακριβώς. Έτσι υπολογίζεται:"; +"web_game_next" = "Επόμενο"; +"web_game_finish" = "Αποτέλεσμα"; +"web_game_done_fmt" = "%@ από %@ σωστά."; +"web_game_perfect" = "Όλα σωστά – ο Ludwig εντυπωσιάστηκε!"; +"web_game_good" = "Μπράβο! Δες ξανά τα λάθη σου και δοκίμασε πάλι."; +"web_game_practice" = "Η εξάσκηση φέρνει την τελειότητα. Διάβασε ξανά τον πίνακα αλήθειας και παίξε άλλον έναν γύρο."; +"web_game_again" = "Παίξε ξανά"; +"web_game_wrong_short" = "Δυστυχώς λάθος."; +"web_game_practice_short" = "Η εξάσκηση φέρνει την τελειότητα. Διάβασε ξανά τις εξηγήσεις και παίξε άλλον έναν γύρο."; +"web_game_clicks" = "Κλικ:"; +"web_game_nobody" = "Κανείς δεν ακούει – δεν συμβαίνει τίποτα."; +"web_game_event_fmt" = "Κλικ στο «%@»: ο ακροατής το ακούει και εκτελεί τον κώδικά του."; +"web_game_try" = "Δοκίμασε τώρα μόνος σου τα κουμπιά στο παράθυρο."; +"web_game_time_fmt" = "Απομένουν %@ δ"; +"web_game_defused" = "✂️ Εξουδετερώθηκε! Βρήκες το λάθος."; +"web_game_boom_time" = "💥 Μπαμ! Ο χρόνος τελείωσε."; +"web_game_boom_wrong" = "💥 Μπαμ! Ήταν λάθος γραμμή."; +"web_game_fix" = "Η σωστή γραμμή:"; +"web_game_order_hint" = "Πάτησε τα βήματα με τη σωστή σειρά."; +"web_debug_step" = "Βήμα"; +"web_debug_step_title" = "Βήμα: εκτέλεση μίας εντολής και νέα παύση"; +"web_debug_continue" = "Συνέχεια έως το επόμενο σημείο διακοπής"; +"web_debug_paused_fmt" = "Παύση πριν από τη γραμμή %d."; +"web_debug_gutter_title" = "Κάνε κλικ σε αριθμό γραμμής για να βάλεις ή να βγάλεις σημείο διακοπής"; +"web_swap_to_code" = "Μεγάλος προγραμματισμός"; +"web_swap_to_editor" = "Μεγάλο διάγραμμα"; +"web_editor_resize" = "Αλλαγή πλάτους διαγράμματος"; +"web_palette_resize" = "Αλλαγή πλάτους στοιχείων"; +"web_palette_hide" = "Απόκρυψη στοιχείων"; +"web_palette_show" = "Εμφάνιση στοιχείων"; +"web_code_scopes" = "Χρωματιστά μπλοκ κώδικα"; +"web_code_scopes_hint" = "Κλάση, μέθοδος, βρόχος, διακλάδωση σε δικά τους πλαίσια"; +"web_pseudocode" = "Ψευδοκώδικας"; +`;export{e as default}; diff --git a/website/app/assets/en-sZM_O17d.js b/website/app/assets/en-sZM_O17d.js new file mode 100644 index 00000000..92874780 --- /dev/null +++ b/website/app/assets/en-sZM_O17d.js @@ -0,0 +1,744 @@ +const e=`/* Texts that exist only in the web version. Everything else comes from the app's Localizable.strings. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct structure chart"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Export…"; +"web_export_title" = "Save as image or PDF, or print"; +"web_export_png" = "Image (PNG)"; +"web_export_svg" = "Vector graphic (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "VisuStruct file (.visustruct)"; +"web_export_failed_fmt" = "Export failed: %@"; +"web_print_hint" = "Use “Export… → PDF” to save the diagram and print it from there."; +"web_delete" = "Delete"; +"web_language_title" = "Interface language"; +"web_simulation_start" = "Start simulation"; +"web_simulation_end" = "End simulation"; +"web_simulation_start_title" = "Run the structure chart step by step"; +"web_simulation_end_title" = "End the simulation and continue editing"; +"web_palette_hint" = "Drag into the structure chart"; +"web_tabs_label" = "Diagrams"; +"web_status_modified" = "modified"; +"web_inspector_title" = "Object Inspector"; +"web_inspector_help_drop" = "Drag elements from the “Elements” area onto a tile: top = before, bottom = after, onto “ø” = replace. Existing elements can be moved with the mouse."; +"web_inspector_help_files" = "You can also drop files into the window."; +"web_case_name" = "Case name"; +"web_case_name_placeholder" = "e.g. 1, ok, default"; +"web_copied" = "Element copied."; +"web_discard_message_fmt" = "The changes to “%@” will be lost."; +"web_err_unreadable_fmt" = "“%@” is not a readable VisuStruct file (%@)."; +"web_saved_fmt" = "“%@” saved."; +"web_saved_txt_fmt" = "Saved as “%@”. Remove the .txt extension to use it."; +"web_drop_impossible" = "Cannot drop here"; +"web_sim_delay" = "Pause per step"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Language"; +"web_codegen_comments" = "Diagram text as comments"; +"web_codegen_empty_else" = "Emit empty else branch in code"; +"web_copied_check" = "Copied ✓"; +"web_copy_manual" = "Selected, press Ctrl+C to copy"; +"web_run_stopped_loop" = "Execution stopped: possible infinite loop."; +"web_run_cancelled" = "Execution cancelled."; +"web_run_error" = "Error while running."; +"web_run_dropped_fmt" = "… %d earlier lines hidden"; + +/* Learning area (lessons are German only for now) */ +"web_learn_title" = "Learn"; +"web_learn_hide" = "Collapse the learning area"; +"web_learn_show" = "Expand the learning area: lessons, exercises and reference"; +"web_learn_lessons" = "Lessons"; +"web_learn_tasks" = "Exercises"; +"web_learn_reference" = "Reference"; +"web_learn_intro" = "Learn step by step, with exercises. Your progress is remembered in this browser."; +"web_learn_tasks_intro" = "Small projects without instructions. Each one names the lesson you should finish first."; +"web_learn_step_of_fmt" = "Step %d of %d"; +"web_learn_lesson_fmt" = "Lesson %d"; +"web_learn_all_lessons" = "All lessons"; +"web_learn_all_tasks" = "All exercises"; +"web_learn_back" = "Back"; +"web_learn_next" = "Next"; +"web_learn_finish" = "Finish lesson"; +"web_learn_done" = "Finished"; +"web_learn_after_fmt" = "After lesson %d: %@"; +"web_learn_level_fmt" = "Difficulty %d of 3"; +"web_learn_exercise" = "Exercise"; +"web_learn_brag" = "Fun facts with Ludwig"; +"web_learn_solved" = "solved"; +"web_learn_open_exercise" = "Open in editor"; +"web_learn_solve_in_editor" = "Solve this exercise in the %@ area."; +"web_learn_solve_in_code" = "Solve this exercise in the %@ area."; +"web_learn_solve_in_both" = "Solve this exercise in the %1$@ and %2$@ areas."; +"web_learn_open_in_editor" = "Open in editor"; +"web_learn_graphic_labels" = "👆 Click the picture to show or hide the labels"; +"web_learn_check" = "Check"; +"web_learn_hint" = "Hint"; +"web_learn_reset" = "Start over"; +"web_learn_reset_confirm" = "Really start over?"; +"web_learn_solution" = "Show sample solution"; +"web_learn_hint_more" = "Another hint"; +"web_learn_hint_fmt" = "Hint %d of %d"; +"web_learn_teacher" = "For teachers"; +"web_learn_teacher_intro" = "The teacher code shows the sample solutions for all exercises. The browser remembers it."; +"web_learn_teacher_code" = "Teacher code"; +"web_learn_teacher_unlock" = "Unlock"; +"web_learn_teacher_wrong" = "The code is not correct."; +"web_learn_teacher_on" = "Teacher mode is on: sample solutions are visible for all exercises."; +"web_learn_teacher_off" = "Leave teacher mode"; +"web_learn_open_first" = "Open the exercise in the editor first and build your structure chart there."; +"web_learn_empty" = "Your structure chart is still empty. Drag elements from the “Elements” area into it first."; +"web_learn_passed" = "Well done! Your structure chart does exactly what it should."; +"web_learn_failed" = "Not quite yet. Compare the expected output with yours:"; +"web_learn_missing_fmt" = "Your structure chart still needs: %@"; +"web_learn_input_fmt" = "Input: %@"; +"web_learn_no_input" = "No input"; +"web_learn_expected" = "Expected"; +"web_learn_actual" = "Your output"; +"web_learn_missing_input" = "Your structure chart asks for more input than planned."; +"web_learn_unused_input" = "Your structure chart does not ask for all inputs."; +"web_learn_too_many_steps" = "Stopped after 100,000 steps. Is a loop running forever?"; +"web_learn_score_fmt" = "%d of %d correct"; +"web_learn_cloze_hint" = "Type the missing words into the gaps and press “Check”."; +"web_learn_cloze_score_fmt" = "%d of %d gaps correct"; +"web_learn_cloze_all_right" = "All gaps correct!"; +"web_learn_cloze_solution" = "Show solution"; +"web_learn_cloze_again" = "Try again"; +"web_learn_pap_hint" = "Tap an element on the right and then its place in the chart. You can also drag it there. Tapping a filled place gives its element back."; +"web_learn_pap_score_fmt" = "%d of %d elements correct"; +"web_learn_pap_all_right" = "All correct! Your flowchart is finished."; +"web_learn_pap_missing_fmt" = "%d elements are still missing."; +"web_learn_pap_empty" = "Empty place"; +"web_learn_pap_yes" = "yes"; +"web_learn_pap_no" = "no"; +"web_learn_pap_legend_oval" = "Start or end"; +"web_learn_pap_legend_rect" = "Statement"; +"web_learn_pap_legend_diamond" = "Decision: question with yes and no"; +"web_learn_pap_legend_para" = "Input or output"; +"web_learn_review" = "Review"; +"web_learn_terms" = "Technical terms"; +"web_learn_resize" = "Change the width of the learning area (double-click: reset)"; +"web_learn_competences_intro" = "At the end of this lesson I can …"; +"web_learn_rating_sun" = "I can do this confidently"; +"web_learn_rating_cloud" = "partly"; +"web_learn_rating_umbrella" = "not yet"; +"web_learn_review_title" = "Your checklist compared"; +"web_learn_review_hint" = "Here your self-assessment and the quiz do not match. Read the step again and rate yourself again in the checklist."; +"web_learn_review_match" = "Your self-assessment matches your quiz. Well done!"; +"web_learn_review_overrated_fmt" = "You chose ☀️, but question %@ was wrong."; +"web_learn_review_underrated" = "All questions on this were right. You can do more than you think!"; +"web_learn_review_unrated" = "not rated yet"; +"web_learn_back_to_checklist" = "Back to checklist"; +"web_learn_step_fmt" = "Step %d: %@"; +"web_sim_call_arguments_fmt" = "The call does not match the header of %@. Check the values in the parentheses."; +"web_sim_missing_return_fmt" = "%@ ended without returning a value with return."; +"web_sim_file_not_found_fmt" = "There is no file called %@."; +"web_sim_end_of_file_fmt" = "The file %@ has no more lines."; +"web_sim_null_value_fmt" = "%@ is null."; +"web_sim_written_file_fmt" = "%@ (saved)"; +"web_site_home" = "Home page"; +"web_site_imprint" = "Imprint"; +"web_site_privacy" = "Privacy"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Code"; +"web_live_hide" = "Hide code"; +"web_scale_canvas" = "Text size: structure chart"; +"web_scale_code" = "Text size: Code"; +"web_live_indent" = "Indent"; +"web_live_indent_title" = "Indent the code: four spaces per level (selected lines, otherwise everything)"; +"web_live_show" = "Show code"; +"web_live_resize" = "Change width of the code area (double-click: reset)"; +"web_live_hint" = "The code grows with your diagram. Grey = placeholder: type in the object inspector and your text appears there. Click a line to select its element."; +"web_live_ph_selector" = "variable"; +"web_live_ph_code" = "Your code"; +"web_live_ph_end" = "end"; +"web_live_language" = "Programming language"; +"web_live_java_class" = "As a class"; +"web_live_java_class_hint" = "Class name = title of the diagram"; +"web_live_java_main" = "With main method"; +"web_settings_display" = "Display"; +"web_live_swing" = "Real Java (with Swing)"; +"web_live_swing_hint" = "Real Java with windows (CheerpJ). Downloads about 40 MB once, on the first run."; +"web_live_swing_windows" = "Java windows"; +"web_live_swing_hide" = "Close Java windows"; +"web_live_swing_loading" = "Loading Java (about 40 MB the first time) …"; +"web_live_swing_compiling" = "Compiling …"; +"web_live_swing_running" = "Program is running."; +"web_live_swing_compile_failed" = "Compile error, see above."; +"web_live_swing_failed" = "Java could not be loaded. Check your internet connection."; +"web_live_hint_edit" = "Type Java code here and the diagram builds itself. Or work in the diagram and the code grows along. Grey = placeholder, just type over it."; +"web_live_edit_label" = "Java code"; +"web_parse_line_fmt" = "Line %d: %@"; +"web_parse_missing" = "Still missing here: %@"; +"web_parse_extra" = "One too many: %@"; +"web_parse_unclosed_string" = "The closing %@ is missing here."; +"web_parse_else_without_if" = "This “else” has no matching “if”."; +"web_parse_case_outside_switch" = "“case” and “default” belong inside a “switch”."; +"web_parse_missing_do_while" = "After “do { … }” you still need “while (condition);”."; +"web_parse_more_methods" = "Only one method counts here for now. Create further subprograms as separate tabs."; +"web_parse_missing_import" = "%@ is missing at the very top. Without this line Java doesn’t know Scanner."; +"web_parse_missing_scanner" = "%@ is missing before this line. Without it the Scanner doesn’t exist."; +"web_parse_unknown_type" = "Java doesn’t know this data type. Did you mean %@?"; +"web_editor_title" = "Diagram"; +"web_editor_show" = "Show diagram"; +"web_editor_hide" = "Hide diagram"; +"web_keywords_title" = "Code keywords"; +"web_keywords_hint" = "if, while, for instead of Branch, For loop …"; +"web_palette_compact" = "Elements always compact"; +"web_palette_compact_hint" = "Symbol with a small name below, otherwise only when the column is narrow"; +"web_about_version_fmt" = "Version %@"; +"web_about_software" = "Third-party software"; +"web_about_software_text" = "The code editor uses CodeMirror and Lezer (MIT License). With Swing support, VisuStruct loads CheerpJ by Leaning Technologies (Community License) and javac from OpenJDK."; +"web_about_licenses" = "License texts"; +"web_live_run" = "Run"; +"web_live_run_title" = "Run the program: output and input appear below"; +"web_live_run_finished" = "Program finished."; +"web_live_run_stopped" = "Stopped."; +"web_console" = "Console"; +"web_console_hide" = "Hide console"; +"web_console_resize" = "Resize console"; +"web_diagram_tools" = "Diagram tools"; +"web_files_title" = "Files"; +"web_files_show" = "Show files"; +"web_files_hide" = "Hide files"; +"web_files_resize" = "Resize files"; +"web_files_new_folder" = "New folder"; +"web_files_switch" = "Choose another folder"; +"web_files_delete" = "Delete"; +"web_files_in_browser" = "In this browser’s storage"; +"web_files_save_hint_fmt" = "Saving puts the program in %@."; +"web_files_empty" = "Nothing saved yet. When you save, VisuStruct creates a folder with today’s date here."; +"web_files_reconnect_hint" = "After reloading, the browser asks once more whether VisuStruct may use your folder."; +"web_files_reconnect_fmt" = "Open folder “%@”"; +"web_files_connect_hint" = "Choose a folder as your workspace, ideally a new folder “VisuStruct-Files” in your Documents. VisuStruct creates a folder for each day in it and saves both diagram and code."; +"web_files_connect" = "Choose folder"; +"web_files_browser_hint" = "This browser can’t open folders on the device (for example on iPad). Your files then stay in this browser’s storage."; +"web_files_browser" = "Save in the browser"; +"web_files_delete_confirm_fmt" = "Really delete “%@”?"; +"web_files_folder_prompt" = "Name of the new folder:"; +"web_files_default_name" = "Program"; +"web_files_saved_fmt" = "Saved: %@"; +"web_files_create" = "Create"; +"web_learn_ludwig_tip" = "Ludwig’s tip"; +"web_game_title" = "Game: True or false?"; +"web_game_intro" = "Ludwig shows you values and a condition. Is the condition true or false? Ten rounds, getting trickier each time."; +"web_game_start" = "Start game"; +"web_game_round_fmt" = "Round %@ of %@"; +"web_game_score_fmt" = "Points: %@"; +"web_game_true" = "true"; +"web_game_false" = "false"; +"web_game_right" = "Correct!"; +"web_game_wrong" = "Not quite. This is how it works out:"; +"web_game_next" = "Next"; +"web_game_finish" = "Result"; +"web_game_done_fmt" = "%@ of %@ correct."; +"web_game_perfect" = "All correct – Ludwig is seriously impressed!"; +"web_game_good" = "Great! Have another look at your mistakes and try again."; +"web_game_practice" = "Practice makes perfect. Read the truth table above once more and play another round."; +"web_game_again" = "Play again"; +"web_game_wrong_short" = "Sorry, that's wrong."; +"web_game_practice_short" = "Practice makes perfect. Read the explanations again and play another round."; +"web_game_clicks" = "Clicks:"; +"web_game_nobody" = "Nobody is listening – nothing happens."; +"web_game_event_fmt" = "Click on “%@”: the listener hears it and runs its code."; +"web_game_try" = "Now try the buttons in the window yourself."; +"web_game_time_fmt" = "%@ s left"; +"web_game_defused" = "✂️ Defused! You found the mistake."; +"web_game_boom_time" = "💥 Boom! Time is up."; +"web_game_boom_wrong" = "💥 Boom! That was the wrong line."; +"web_game_fix" = "The correct line:"; +"web_game_order_hint" = "Tap the steps in the right order."; +"web_debug_step" = "Step"; +"web_debug_step_title" = "Step: run one statement and pause again"; +"web_debug_continue" = "Continue to the next breakpoint"; +"web_debug_paused_fmt" = "Paused before line %d."; +"web_debug_gutter_title" = "Click a line number to set or remove a breakpoint"; + +/* Lernbereich: Caesar-Scheibe */ +"web_learn_caesar_title" = "Caesar wheel"; +"web_learn_caesar_hint" = "Turn the inner wheel or tap −1 and +1. The outer ring shows the plain text, the inner ring the secret text."; +"web_learn_caesar_key_fmt" = "Key %d"; +"web_learn_caesar_plain" = "Plain text"; +"web_learn_caesar_secret" = "Secret text"; +"web_learn_caesar_encrypt" = "Encrypt"; +"web_learn_caesar_decrypt" = "Decrypt"; +"web_learn_caesar_back" = "Turn wheel back one"; +"web_learn_caesar_forward" = "Turn wheel forward one"; +"web_learn_rescue_station_fmt" = "Station %@ of %@: %@"; +"web_learn_rescue_number" = "Your number"; +"web_learn_rescue_not_number" = "Enter a whole number."; +"web_learn_rescue_wrong" = "Not yet. Read the code again, character by character."; +"web_learn_rescue_letter_moved" = "The letter goes into the crossword."; +"web_learn_rescue_alphabet" = "Your number turns into a letter:"; +"web_learn_rescue_to_crossword" = "To the crossword"; +"web_learn_rescue_crossword" = "The crossword"; +"web_learn_rescue_across" = "→ Across"; +"web_learn_rescue_down" = "↓ Down"; +"web_learn_rescue_cell_fmt" = "Square row %@, column %@"; +"web_learn_rescue_keyword" = "Secret word:"; +"web_learn_rescue_cw_wrong" = "The squares marked red are not right yet."; +"web_learn_rescue_cw_done" = "Solved! The yellow squares spell the secret word."; +"web_learn_rescue_to_gate" = "To the gate"; +"web_learn_rescue_gate" = "The gate"; +"web_learn_rescue_word" = "Secret word"; +"web_learn_rescue_open" = "Open the gate"; +"web_learn_rescue_gate_case" = "Almost! equals tells capital and small letters apart. Write the word exactly as in the crossword."; +"web_learn_rescue_gate_wrong" = "The gate stays shut. Look at the yellow squares again."; +"web_learn_rescue_freed" = "🎉 The gate is open!"; + +/* VisuBot (mBot2-Modus), nur de/en/pt */ +"web_visubot_world_title" = "What do you want to work with?"; +"web_visubot_world_visustruct_hint" = "VisuStruct: structure charts and Java with the whole course. You can switch any time in the gear menu."; +"web_visubot_world_visubot_hint" = "VisuBot: program the mBot2 robot, with its own lessons and tasks. You can switch any time in the gear menu."; +"web_visubot_connect" = "Connect real mBot2"; +"web_visubot_upload_button" = "Upload"; +"web_visubot_upload_title" = "Upload program to the mBot2"; +"web_visubot_upload_step1" = "Connect the mBot2 with the USB cable and switch it on. This only works in Chrome or Edge."; +"web_visubot_upload_step2" = "Click “Upload now” and choose “USB Serial”. The mBot2 saves your program and restarts."; +"web_visubot_upload_step3" = "Unplug the cable and put the mBot2 at the start. When you press button A, your program starts. It stays saved, even after switching off."; +"web_visubot_upload_start" = "Upload now"; +"web_visubot_upload_busy" = "Uploading … do not unplug the cable."; +"web_visubot_upload_done" = "Done! Unplug the cable, put the mBot2 at the start, press button A."; +"web_visubot_upload_failed" = "The upload did not work. Restart the mBot2 and try again."; +"web_visubot_upload_label" = "A = Start"; +"web_visubot_upload_error_input" = "Your program asks for an input. The mBot2 has no keyboard, so this does not work."; +"web_visubot_upload_error_files" = "Your program works with files. This does not work on the mBot2."; +"web_visubot_upload_error_empty" = "Your program is still empty."; +"web_visubot_disconnect" = "Disconnect"; +"web_visubot_connecting" = "Connecting … (the CyberPi restarts briefly)"; +"web_visubot_connected" = "Real mBot2 drives along"; +"web_visubot_no_serial" = "Real mBot2: only in Chrome or Edge on a computer."; +"web_visubot_link_error" = "Connection lost"; +"web_visubot_world" = "VisuBot world"; +"web_visubot_no_3d" = "The 3D view cannot start in this browser."; +"web_visubot_distance" = "Distance"; +"web_visubot_line" = "Line"; +"web_visubot_bumps" = "bumped into the wall"; +"web_visubot_el_forward" = "move forward"; +"web_visubot_el_backward" = "move back"; +"web_visubot_el_right" = "turn right"; +"web_visubot_el_left" = "turn left"; +"web_visubot_el_led" = "LEDs on"; +"web_visubot_el_tone" = "play a tone"; +"web_visubot_drive" = "Drive"; +"web_visubot_depth_fmt" = "The loops must be nested %d deep."; +"web_visubot_tap_part" = "Rotate the mBot2 with the mouse or your finger. Tap a part to see its name."; +"web_visubot_quiz_right" = "Correct!"; +"web_visubot_quiz_wrong_fmt" = "That is: %@. Try again."; +"web_visubot_part_cyberpi" = "CyberPi"; +"web_visubot_part_screen" = "Screen"; +"web_visubot_part_joystick" = "Joystick"; +"web_visubot_part_buttons" = "Buttons A, B and Home"; +"web_visubot_part_leds" = "RGB LEDs"; +"web_visubot_part_lightSensor" = "Light sensor"; +"web_visubot_part_microphone" = "Microphone"; +"web_visubot_part_shield" = "mBot2 shield with battery"; +"web_visubot_part_powerSwitch" = "Power switch"; +"web_visubot_part_motors" = "Encoder motors"; +"web_visubot_part_wheels" = "Wheels"; +"web_visubot_part_ultrasonic" = "Ultrasonic sensor"; +"web_visubot_part_lineSensor" = "Line sensor (quad RGB)"; +"web_visubot_part_caster" = "Ball caster"; +"web_visubot_part_chassis" = "Chassis"; +"web_visubot_world_fmt" = "World %d"; +"web_visubot_goal_reached" = "Goal reached"; +"web_visubot_goal_missed" = "Goal not reached"; +"web_visubot_commands" = "mBot2 commands"; +"web_visubot_sensors" = "mBot2 sensors"; +"web_visubot_sensor_distance" = "Distance"; +"web_visubot_sensor_line" = "Line"; +"web_visubot_el_led_off" = "LEDs off"; +"web_visubot_el_led_color" = "set LED colour"; +"web_visubot_el_wait" = "wait a moment"; +"web_visubot_el_emotion" = "show a feeling"; +"web_visubot_el_text" = "show text"; +"web_visubot_sensor_color" = "Colour is red?"; +"web_visubot_sensor_button_a" = "Button A pressed?"; +"web_visubot_sensor_button_b" = "Button B pressed?"; +"web_visubot_sensor_joy_up" = "Joystick up?"; +"web_visubot_sensor_joy_down" = "Joystick down?"; +"web_visubot_sensor_joy_left" = "Joystick left?"; +"web_visubot_sensor_joy_right" = "Joystick right?"; +"web_visubot_sensor_brightness" = "Brightness"; +"web_visubot_sensor_loudness" = "Loudness"; +"web_visubot_sensor_pitch" = "Tilt forward/back"; +"web_visubot_sensor_roll" = "Tilt sideways"; +"web_visubot_sensor_shake" = "Shaken?"; +"web_visubot_el_drive" = "wheels separately"; +"web_visubot_el_stop" = "stop"; +"web_visubot_el_timer" = "reset stopwatch"; +"web_visubot_sensor_line_left" = "Line left?"; +"web_visubot_sensor_line_right" = "Line right?"; +"web_visubot_sensor_timer" = "Stopwatch (s)"; +"web_visubot_sensor_battery" = "Battery (%)"; +"web_visubot_actions" = "Commands"; +"web_visubot_led_on" = "LEDs on"; +"web_visubot_led_off" = "LEDs off"; +"web_visubot_tone_yes" = "tone"; +"web_visubot_tone_no" = "no tone"; +"web_visubot_controls" = "Try the sensors"; +"web_visubot_controls_hint" = "Without a real mBot2: set here what the sensors measure. Buttons, joystick and shaking last for one second."; +"web_visubot_shake" = "shake"; +"web_visubot_check" = "Test the mBot2"; +"web_visubot_check_hint" = "Try each actuator once. The sensor values update live: hold your hand in front of the ultrasonic sensor, press the buttons, tilt or shake the mBot2. Lift it up for the wheels."; +"web_visubot_check_forward" = "Wheels 1 s forward"; +"web_visubot_check_spin" = "Turn on the spot for 1 s"; + +/* Start: Ordner für Lernstand und Programme */ +"web_learn_start_title" = "Where do you keep your work?"; +"web_learn_start_hint" = "Your learning progress and programs live in a folder on your device. The progress is stored there in the file learnProgress.json."; +"web_learn_start_continue_fmt" = "Continue with “%@”"; +"web_learn_start_open" = "Open existing folder"; +"web_learn_start_create_fmt" = "Create new folder “%@”"; +"web_learn_start_create_hint" = "Next, choose where it should go, e.g. in “Documents”."; +"web_learn_start_folder" = "VisuStruct-Files"; +"web_learn_start_without" = "Continue without a folder"; +"web_learn_start_without_hint" = "Your learning progress is then lost when you close the page."; +"web_visubot_preview_title" = "mBot2 live"; +"web_visubot_preview_hint" = "Shows right away where your program drives the mBot2."; +"web_visubot_preview_sim_title" = "Simulation"; +"web_visubot_preview_sim_hint" = "The mBot2 drives here while the simulation runs."; +"web_visubot_world_in_preview" = "The mBot2 drives in the “Simulation” window."; +"web_visubot_preview_play" = "Play the drive"; +"web_visubot_preview_stop" = "Stop"; +"web_visubot_preview_hide" = "Collapse mBot2 live"; +"web_visubot_preview_show" = "Show mBot2 live"; +"web_visubot_preview_resize" = "Resize mBot2 live"; +"web_visubot_preview_stack" = "Below the code in the Code area"; +"web_visubot_preview_side" = "As a column of its own"; +"web_visubot_preview_distance_fmt" = "Distance: %d cm"; +"web_visubot_preview_input" = "needs an input, start the simulation for that"; +"web_visubot_preview_limit" = "runs for a very long time (endless loop?), showing the start"; +"web_visubot_group_drive" = "Driving and turning"; +"web_visubot_group_wheels" = "Wheels separately"; +"web_visubot_group_output" = "Light, sound and screen"; +"web_visubot_group_emotion" = "Emotions"; +"web_visubot_group_wait" = "Waiting and stopwatch"; +"web_visubot_group_distance" = "Distance"; +"web_visubot_group_line" = "Line"; +"web_visubot_group_color" = "Colours"; +"web_visubot_group_buttons" = "Buttons and joystick"; +"web_visubot_group_light" = "Light and loudness"; +"web_visubot_group_tilt" = "Tilt and shaking"; +"web_visubot_group_timer" = "Stopwatch and battery"; +"web_swap_to_code" = "Code large, structogram narrow"; +"web_swap_to_editor" = "Structogram large, code narrow"; +"web_editor_resize" = "Resize the structogram"; +"web_palette_resize" = "Resize the elements (double-click: reset)"; +"web_palette_hide" = "Hide elements"; +"web_palette_show" = "Show elements"; + +/* VisuObject */ +"web_visuobject_world_hint" = "VisuObject: write classes in Java and see or draw them as a class diagram (from year 12). You can switch any time in the gear menu."; +"web_visuobject_subtitle" = "Class diagram"; +"web_visuobject_code" = "Java code"; +"web_visuobject_diagram" = "Class diagram"; +"web_visuobject_add_interface" = "Interface"; +"web_visuobject_add_interface_tip" = "Add a new interface to the diagram and the code"; +"web_visuobject_layout" = "Arrange again"; +"web_visuobject_layout_tip" = "Arrange all classes automatically: superclasses at the top"; +"web_visuobject_add_field" = "new attribute …"; +"web_visuobject_add_method" = "new method …"; +"web_visuobject_delete_class" = "Delete class"; +"web_visuobject_new_class_name" = "NewClass"; +"web_visuobject_new_interface_name" = "NewInterface"; +"web_visuobject_example" = "Example"; +"web_visuobject_example_tip" = "Load the example project Zoo: Tier and Hund in package tiere, Besitzer in personen"; +"web_visuobject_new_tip" = "New: empty project (Undo brings the old one back)"; +"web_visuobject_empty" = "No class yet. Click “+ Class” on the left or type for example “public class Dog { }” into a file."; +"web_visuobject_edit_hint" = "Double-click to change. Write it as in UML: “- name: String” or “+ bark(): void”. Leave it empty to delete."; +"web_visuobject_member_label" = "Attribute or method in UML notation"; +"web_visuobject_name_label" = "Class name"; +"web_visuobject_bad_name" = "“%@” is not a valid name or already exists."; +"web_visuobject_bad_line" = "I don’t understand “%@”. Example: - name: String or + bark(): void"; +"web_visuobject_open_failed" = "The file could not be read."; +"web_visuobject_field_ph" = "- name: String"; +"web_visuobject_seq_diagram" = "Sequence diagram"; +"web_visuobject_seq_empty" = "The sequence diagram is built while debugging: click “Debug” above and step through the program."; +"web_visuobject_seq_no_calls" = "No calls of your own methods yet."; +"web_visuobject_seq_truncated" = "… shortened: too many calls from here on."; +"web_visuobject_seq_hint" = "Each arrow is a call of one of your methods, the dashed arrow brings the return value back. Click an arrow to see the line in the code."; +"web_visuobject_dbg" = "Debug"; +"web_visuobject_dbg_tip" = "Run the program step by step. Breakpoint: click the line number. The object diagram shows the objects in memory."; +"web_visuobject_dbg_continue" = "Resume"; +"web_visuobject_dbg_continue_tip" = "Run to the next breakpoint (F8)"; +"web_visuobject_dbg_pause" = "Pause"; +"web_visuobject_dbg_pause_tip" = "Pause the program"; +"web_visuobject_dbg_over" = "Step"; +"web_visuobject_dbg_over_tip" = "Next line; methods run completely (F6)"; +"web_visuobject_dbg_into" = "Into"; +"web_visuobject_dbg_into_tip" = "Step into the called method (F5)"; +"web_visuobject_dbg_out" = "Out"; +"web_visuobject_dbg_out_tip" = "Finish the method and return to the caller (F7)"; +"web_visuobject_dbg_input" = "Input for the Scanner, then Enter"; +"web_visuobject_dbg_running" = "Debugger: program running …"; +"web_visuobject_dbg_waiting" = "Debugger: the program is waiting for your input."; +"web_visuobject_dbg_paused_fmt" = "Debugger: paused in %1$@, line %2$@"; +"web_visuobject_dbg_exception" = "Program stopped with an exception."; +"web_visuobject_dbg_code_changed" = "Code changed: debugger stopped."; +"web_visuobject_dbg_line_fmt" = "%1$@:%2$@"; +"web_visuobject_dbg_stack" = "Call stack"; +"web_visuobject_dbg_vars" = "Variables"; +"web_visuobject_dbg_var_name" = "Name"; +"web_visuobject_dbg_var_type" = "Type"; +"web_visuobject_dbg_no_vars" = "No variables"; +"web_visuobject_dbg_err_syntax" = "%1$@, line %2$@: the debugger does not understand this (%3$@). ▶ Start shows Java's message."; +"web_visuobject_dbg_err_symbol" = "%1$@, line %2$@: %3$@ is unknown."; +"web_visuobject_dbg_err_import" = "%1$@, line %2$@: %3$@ is missing at the very top. Without this line Java doesn’t know the class."; +"web_visuobject_dbg_err_typename" = "%1$@, line %2$@: Java doesn’t know this data type. Did you mean %3$@?"; +"web_visuobject_dbg_err_unsupported" = "%1$@, line %2$@: the debugger cannot do %3$@ yet. ▶ Start runs the program in real Java."; +"web_visuobject_dbg_err_type" = "%1$@, line %2$@: something does not fit here (%3$@)."; +"web_visuobject_obj_diagram" = "Object diagram"; +"web_visuobject_obj_new" = "New object of class"; +"web_visuobject_obj_add" = "Object"; +"web_visuobject_obj_empty" = "No objects yet. Choose a class above and click “+ Object”."; +"web_visuobject_obj_no_classes" = "First create a class (not abstract) in the class diagram."; +"web_visuobject_obj_hint" = "Click an object to change its name, class and values here. Drag the handle to another object to connect them through a reference attribute."; +"web_visuobject_obj_live_hint" = "Live from the debugger: this is how the objects look in memory right now."; +"web_visuobject_obj_link" = "Drag to another object: set a reference"; +"web_visuobject_obj_name" = "Name"; +"web_visuobject_obj_class" = "Class"; +"web_visuobject_obj_attribute" = "Attribute"; +"web_visuobject_obj_value" = "Value"; +"web_visuobject_obj_delete" = "Delete object"; +"web_visuobject_obj_bad_name" = "“%@” is not a valid object name."; +"web_visuobject_obj_name_taken" = "There is already an object “%@”."; +"web_visuobject_obj_no_ref" = "%1$@ has no attribute that can refer to %2$@."; +"web_visuobject_tool_note" = "Note"; +"web_visuobject_tool_note_tip" = "Note: click into the class diagram, then type the text. Drag the handle to a class for a dashed line."; +"web_visuobject_note_ph" = "Note …"; +"web_visuobject_note_text" = "Text"; +"web_visuobject_note_attached" = "Attached to"; +"web_visuobject_note_attach" = "Drag to a class: dashed line"; +"web_visuobject_note_delete" = "Delete note"; +"web_visuobject_run" = "Run"; +"web_visuobject_run_tip" = "Run the program with real Java: all classes are compiled, the class with main is started (preferably the open one)."; +"web_visuobject_stop" = "Stop"; +"web_visuobject_stop_tip" = "End the program and close its windows"; +"web_visuobject_stopped" = "Program stopped."; +"web_visuobject_no_main" = "No class with public static void main(String[] args) found."; +"web_visuobject_running_fmt" = "%@ is running …"; +"web_visuobject_console_clear" = "Clear"; +"web_visuobject_section_fields" = "Attributes"; +"web_visuobject_section_refs" = "Reference attributes"; +"web_visuobject_section_ctors" = "Constructor"; +"web_visuobject_section_methods" = "Methods"; +"web_visuobject_insp_sections" = "Insert section comments"; +"web_visuobject_insp_sort" = "Sort into sections"; +"web_visuobject_insp_sections_tip" = "Writes // Attributes, // Reference attributes, // Constructor and // Methods into the class and sorts everything below them. New members from the class diagram then go straight to the right place."; +"web_visuobject_insp_doc" = "Description (Javadoc)"; +"web_visuobject_insp_doc_ph" = "What is the class for? Written in the code as a Javadoc comment above the class."; +"web_visuobject_insp_visibility" = "Visibility"; +"web_visuobject_insp_type" = "Type"; +"web_visuobject_insp_init" = "Initial value"; +"web_visuobject_insp_no_fields" = "No attributes yet."; +"web_visuobject_insp_add_field" = "Attribute"; +"web_visuobject_insp_params" = "Parameters"; +"web_visuobject_insp_return" = "Return type"; +"web_visuobject_insp_constructor" = "Constructor"; +"web_visuobject_insp_no_methods" = "No methods yet."; +"web_visuobject_insp_add_method" = "Method"; +"web_visuobject_insp_generate" = "Generate:"; +"web_visuobject_insp_gen_constructor" = "Constructor from attributes"; +"web_visuobject_insp_gen_constructor_tip" = "Like Eclipse “Generate Constructor using Fields”: a constructor that sets all attributes (except static)."; +"web_visuobject_insp_gen_accessors" = "Getters and setters"; +"web_visuobject_insp_gen_accessors_tip" = "Like Eclipse “Generate Getters and Setters”: get…/set… for each attribute (final attributes get only a getter)."; +"web_visuobject_insp_bad_params" = "Write parameters like this: name: Type, second: int (read “%@”)."; +"web_visuobject_insp_fields" = "Attributes"; +"web_visuobject_insp_methods" = "Methods"; +"web_visuobject_inspector_resize" = "Resize: drag the border between class diagram and object inspector up or down (double-click = default)"; +"web_visuobject_dep_title" = "Dependency «%@»"; +"web_visuobject_dep_create_text" = "%1$@ creates an object of class %2$@ in %3$@ (new)."; +"web_visuobject_dep_use_text" = "%1$@ uses the class %2$@ in %3$@."; +"web_visuobject_dep_hint" = "This is not an association: %@ does not keep the %@ object in an attribute, it only lives inside the method. That is why the line is dashed."; +"web_visuobject_dep_to_assoc" = "Keep as attribute (association to %@)"; +"web_visuobject_end_mult_ph" = "mult."; +"web_visuobject_end_tip" = "Click (line selected) or right-click: role, multiplicity and navigability at this end"; +"web_visuobject_end_role_ph" = "e.g. myCats"; +"web_visuobject_new_menu" = "New"; +"web_visuobject_new_menu_tip" = "Create a new project, source folder, package, class or interface"; +"web_visuobject_new_project" = "Java project"; +"web_visuobject_new_folder" = "Source folder"; +"web_visuobject_new_package" = "Package"; +"web_visuobject_new_class" = "Class"; +"web_visuobject_new_interface" = "Interface"; +"web_visuobject_new_project_title" = "New Java project"; +"web_visuobject_new_project_hint" = "In the workspace every project gets its own folder with src."; +"web_visuobject_new_folder_title" = "New source folder"; +"web_visuobject_new_folder_hint" = "Another folder for source code next to src, e.g. test for test classes."; +"web_visuobject_new_package_title" = "New package"; +"web_visuobject_new_package_hint" = "Package names are lower case, parts separated by dots: animals or school.office."; +"web_visuobject_new_class_title" = "New Java class"; +"web_visuobject_new_class_hint" = "Class names start with a capital letter, e.g. Dog or BankAccount."; +"web_visuobject_new_interface_title" = "New Java interface"; +"web_visuobject_new_interface_hint" = "An interface defines methods that classes implement later."; +"web_visuobject_new_root" = "Source folder"; +"web_visuobject_new_name" = "Name"; +"web_visuobject_new_modifiers" = "Modifiers"; +"web_visuobject_new_package_private" = "package (no modifier)"; +"web_visuobject_new_superclass" = "Superclass"; +"web_visuobject_new_interfaces" = "Interfaces (implements)"; +"web_visuobject_new_extends_interfaces" = "Extends interfaces (extends)"; +"web_visuobject_new_stubs" = "Which method stubs should be created?"; +"web_visuobject_new_stub_constructors" = "Constructors from superclass"; +"web_visuobject_new_stub_inherited" = "Inherited abstract methods"; +"web_visuobject_new_comment_legend" = "Comment"; +"web_visuobject_new_comment" = "Javadoc comment with @author"; +"web_visuobject_new_author" = "Your name"; +"web_visuobject_new_finish" = "Finish"; +"web_visuobject_new_name_missing" = "Please enter a name."; +"web_visuobject_new_exists" = "“%@” already exists in the project."; +"web_visuobject_new_upper" = "In Java, class names start with a capital letter."; +"web_visuobject_bad_folder" = "“%@” is not a valid folder name or already exists."; +"web_visuobject_inspector_hide" = "Collapse object inspector"; +"web_visuobject_inspector_show" = "Expand object inspector"; +"web_visuobject_inspector_empty" = "Click a relationship (line) in the diagram to edit it here."; +"web_visuobject_rel_end_a" = "End A: %@ (line starts here)"; +"web_visuobject_rel_end_b" = "End B: %@ (line ends here)"; +"web_visuobject_ws_title" = "Workspace folder on your computer"; +"web_visuobject_ws_question" = "Where do you keep your projects?"; +"web_visuobject_ws_hint" = "Like in Eclipse: a workspace folder on your computer with one folder per project, holding src and the .java files."; +"web_visuobject_ws_create" = "Create folder “%@”"; +"web_visuobject_ws_open" = "Open existing workspace"; +"web_visuobject_ws_skip" = "Without a folder (browser only)"; +"web_visuobject_ws_choose" = "Choose workspace"; +"web_visuobject_ws_reopen" = "Open workspace “%@”"; +"web_visuobject_ws_switch" = "Switch"; +"web_visuobject_ws_zip" = "ZIP"; +"web_visuobject_ws_zip_tip" = "Download the project as .zip, e.g. to hand it in"; +"web_visuobject_ws_saved" = "Saved to %@/%@"; +"web_visuobject_ws_created" = "New project “%@” in the workspace"; +"web_visuobject_ws_failed" = "Saving to the workspace failed: %@"; +"web_visuobject_ws_taken" = "The workspace already has a project “%@”."; +"web_visuobject_ws_open_project" = "Open project %@"; +"web_visuobject_save_ws_tip" = "Save to the workspace (Ctrl+S)"; +"web_visuobject_unsaved" = "not saved"; +"web_visuobject_rel_nav_navigable" = "navigable (arrow)"; +"web_visuobject_rel_nav_non-navigable" = "non-navigable (cross ×)"; +"web_visuobject_rel_nav_unspecified" = "unspecified (open)"; +"web_visuobject_rel_reading_flip" = "reverse"; +"web_visuobject_rel_reading_auto" = "With a name, the relationship reads in the direction you dragged."; +"web_visuobject_tools" = "Tools"; +"web_visuobject_tool_select" = "Select"; +"web_visuobject_tool_select_tip" = "Select and move"; +"web_visuobject_tool_class" = "Class"; +"web_visuobject_tool_class_tip" = "Class: drag onto the canvas, or pick it and click on the canvas"; +"web_visuobject_tool_interface" = "Interface"; +"web_visuobject_tool_interface_tip" = "Interface: drag onto the canvas, or pick it and click on the canvas"; +"web_visuobject_tool_link" = "Association"; +"web_visuobject_tool_link_tip" = "Association without navigation: draw a plain line between two classes"; +"web_visuobject_rel_link" = "Association (no navigation)"; +"web_visuobject_tool_not_link" = "%@ is an interface and cannot have attributes. Drag the relationship from a class."; +"web_visuobject_tool_association" = "Directed"; +"web_visuobject_tool_association_tip" = "Directed association: drag from the class that knows the other one to the other (arrow)"; +"web_visuobject_tool_aggregation" = "Aggregation"; +"web_visuobject_tool_aggregation_tip" = "Aggregation: drag from the whole to the part (has, parts live on)"; +"web_visuobject_tool_composition" = "Composition"; +"web_visuobject_tool_composition_tip" = "Composition: drag from the whole to the part (consists of, parts belong to it)"; +"web_visuobject_tool_extends" = "Inheritance"; +"web_visuobject_tool_extends_tip" = "Inheritance: drag from the subclass to the superclass (extends)"; +"web_visuobject_tool_implements" = "Realization"; +"web_visuobject_tool_implements_tip" = "Realization: drag from the class to the interface (implements)"; +"web_visuobject_tool_pick_second" = "Now click the second class (from %@). Esc cancels."; +"web_visuobject_tool_not_association" = "%@ is an interface and cannot have attributes. Drag the relationship from a class."; +"web_visuobject_tool_not_aggregation" = "%@ is an interface and cannot have attributes. Drag the relationship from a class."; +"web_visuobject_tool_not_composition" = "%@ is an interface and cannot have attributes. Drag the relationship from a class."; +"web_visuobject_tool_not_extends" = "%@ cannot inherit from %@: classes extend classes, interfaces extend interfaces. For an interface use realization."; +"web_visuobject_tool_not_implements" = "%@ cannot implement %@: only a class implements an interface."; +"web_visuobject_inspector" = "Object inspector"; +"web_visuobject_connect" = "Drag: relationship to another class"; +"web_visuobject_rel_association" = "Association"; +"web_visuobject_rel_directed" = "Directed association"; +"web_visuobject_rel_aggregation" = "Aggregation (has, parts live on)"; +"web_visuobject_rel_composition" = "Composition (consists of, parts belong to it)"; +"web_visuobject_rel_extends" = "Inheritance (extends)"; +"web_visuobject_rel_implements" = "Realization (implements)"; +"web_visuobject_rel_extends_text" = "%@ inherits from %@ (extends in the code)."; +"web_visuobject_rel_implements_text" = "%@ implements the interface %@ (implements in the code)."; +"web_visuobject_rel_kind" = "Kind"; +"web_visuobject_rel_name" = "Name of the relationship"; +"web_visuobject_rel_name_ph" = "e.g. owns"; +"web_visuobject_rel_reading" = "Reading direction"; +"web_visuobject_rel_navigable" = "Navigability"; +"web_visuobject_rel_role" = "Role"; +"web_visuobject_rel_multiplicity" = "Multiplicity"; +"web_visuobject_rel_role_field" = "= attribute %@.%@ in the code"; +"web_visuobject_rel_role_only_uml" = "diagram only (no attribute while the arrow points one way)"; +"web_visuobject_rel_delete" = "Delete relationship"; +"web_visuobject_rel_impossible" = "There is no suitable relationship from %@ to %@."; +"web_visuobject_rel_menu" = "%@ → %@"; +"web_visuobject_resize" = "Drag to resize (double-click: default)"; +"web_visuobject_pane_show" = "Expand area"; +"web_visuobject_pane_hide" = "Collapse area"; +"web_visuobject_close_tab" = "Close %@"; +"web_visuobject_collapse" = "Collapse"; +"web_visuobject_expand" = "Expand"; +"web_visuobject_tree_empty" = "Still empty. Create a package or class with “+ New”."; +"web_visuobject_delete" = "Delete"; +"web_visuobject_default_package" = "(default package)"; +"web_visuobject_bad_package" = "“%@” is not a valid package name or already exists. Package names are lower case, e.g. animals."; +"web_visuobject_new_package_name" = "newpackage"; +"web_visuobject_no_file" = "No file open"; +"web_visuobject_project_name" = "MyProject"; +"web_visuobject_explorer_show" = "Show Package Explorer"; +"web_visuobject_explorer_hide" = "Collapse Package Explorer"; +"web_visuobject_explorer" = "Package Explorer"; +"web_visuobject_save_tip" = "Save the project as .zip: ProjectName/src/package/Class.java"; +"web_visuobject_open_tip" = "Open a project (.zip as from Eclipse or BlueJ) or add .java files to the project"; +"web_visuobject_method_ph" = "+ bark(): void"; +"web_code_scopes" = "Colored blocks"; +"web_code_scopes_hint" = "Code and structogram: loop pink, branch blue, method yellow, class green"; +"web_pseudocode" = "Pseudocode"; + +/* VisuFlow (draw flowcharts) */ +"web_visuflow_subtitle" = "Draw flowcharts"; +"web_visuflow_world_hint" = "VisuFlow: draw a program flowchart freely and export it as an image or PDF. You can switch at any time in the gear menu."; +"web_visuflow_palette" = "Symbols"; +"web_visuflow_palette_hint" = "Tap a symbol to add it below the selected one, joined by an arrow. You can also drag it onto the canvas."; +"web_visuflow_shape_start" = "Start"; +"web_visuflow_shape_ende" = "End"; +"web_visuflow_shape_anweisung" = "Statement"; +"web_visuflow_shape_ein" = "Input/Output"; +"web_visuflow_shape_verzweigung" = "Decision"; +"web_visuflow_shape_unterprogramm" = "Subroutine"; +"web_visuflow_shape_start_tip" = "Oval: the flow starts here"; +"web_visuflow_shape_ende_tip" = "Oval: the flow ends here"; +"web_visuflow_shape_anweisung_tip" = "Rectangle: one statement, for example “Boil water”"; +"web_visuflow_shape_ein_tip" = "Parallelogram: input or output, for example “Input: number”"; +"web_visuflow_shape_verzweigung_tip" = "Diamond: a question with the exits yes and no"; +"web_visuflow_shape_unterprogramm_tip" = "Rectangle with two bars: calls a subroutine"; +"web_visuflow_text_start" = "Start"; +"web_visuflow_text_ende" = "End"; +"web_visuflow_text_anweisung" = "Statement"; +"web_visuflow_text_ein" = "Input: number"; +"web_visuflow_text_verzweigung" = "Condition?"; +"web_visuflow_text_unterprogramm" = "Subroutine"; +"web_visuflow_new_tip" = "New: empty flowchart with Start (Undo brings the old one back)"; +"web_visuflow_open_tip" = "Open a flowchart file (.visuflow)"; +"web_visuflow_save_tip" = "Save the flowchart as a file (.visuflow)"; +"web_visuflow_delete" = "Delete"; +"web_visuflow_delete_tip" = "Delete the selected symbol or arrow (Del)"; +"web_visuflow_swap" = "swap yes/no"; +"web_visuflow_swap_tip" = "Diamond: “yes” and “no” swap sides"; +"web_visuflow_example" = "Example"; +"web_visuflow_example_tip" = "Load the example “Make tea” from lesson 1 (Undo brings the old flowchart back)"; +"web_visuflow_example_title" = "Make tea"; +"web_visuflow_example_water" = "Boil water"; +"web_visuflow_example_bag" = "Tea bag into the cup"; +"web_visuflow_example_hot" = "Tea still too hot?"; +"web_visuflow_example_wait" = "Wait"; +"web_visuflow_example_drink" = "Drink tea"; +"web_visuflow_title_label" = "Flowchart title"; +"web_visuflow_title_ph" = "Flowchart title"; +"web_visuflow_canvas_label" = "Flowchart canvas"; +"web_visuflow_open_error" = "This file is not a VisuFlow flowchart."; +"web_visuflow_saved" = "Saved as %@"; +"web_visuflow_status_empty" = "Drag a symbol from the bar onto the canvas or tap it."; +"web_visuflow_status_idle" = "Tap a symbol to select it. Drag from the dot at its exit to draw an arrow to the next symbol."; +"web_visuflow_status_node" = "Drag to move the symbol, tap again to change the text. Drag an arrow from the dot at the exit."; +"web_visuflow_status_edge" = "Arrow selected. Delete removes it."; +"web_visuflow_status_connect" = "Let go over the symbol the arrow leads to."; +"web_visuflow_edit_label" = "Text in the symbol"; +`;export{e as default}; diff --git a/website/app/assets/es-BAduFB3L.js b/website/app/assets/es-BAduFB3L.js new file mode 100644 index 00000000..b05a09bc --- /dev/null +++ b/website/app/assets/es-BAduFB3L.js @@ -0,0 +1,180 @@ +const e=`/* Textos que solo existen en la versión web. Todo lo demás procede de los Localizable.strings de la app. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "Diagrama de VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Supr"; +"web_key_shift" = "Mayús"; +"web_export" = "Exportar…"; +"web_export_title" = "Guardar como imagen o PDF, o imprimir"; +"web_export_png" = "Imagen (PNG)"; +"web_export_svg" = "Gráfico vectorial (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "Archivo VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "Error al exportar: %@"; +"web_print_hint" = "Usa “Exportar… → PDF” para guardar el diagrama e imprimirlo desde allí."; +"web_delete" = "Eliminar"; +"web_language_title" = "Idioma de la interfaz"; +"web_simulation_start" = "Iniciar simulación"; +"web_simulation_end" = "Terminar simulación"; +"web_simulation_start_title" = "Ejecutar el diagrama paso a paso"; +"web_simulation_end_title" = "Terminar la simulación y seguir editando"; +"web_palette_hint" = "Arrastrar al diagrama"; +"web_tabs_label" = "Diagramas"; +"web_status_modified" = "modificado"; +"web_inspector_title" = "Propiedades"; +"web_inspector_help_drop" = "Arrastra elementos de la paleta sobre una pieza: arriba = antes, abajo = después, sobre “ø” = reemplazar. Los elementos existentes se pueden mover con el ratón."; +"web_inspector_help_files" = "También puedes soltar archivos en la ventana."; +"web_case_name" = "Nombre del caso"; +"web_case_name_placeholder" = "p. ej. 1, ok, default"; +"web_copied" = "Elemento copiado."; +"web_discard_message_fmt" = "Se perderán los cambios en “%@”."; +"web_err_unreadable_fmt" = "“%@” no es un archivo de VisuStruct legible (%@)."; +"web_saved_fmt" = "“%@” guardado."; +"web_saved_txt_fmt" = "Guardado como “%@”. Quita la extensión .txt para usarlo."; +"web_drop_impossible" = "No se puede soltar aquí"; +"web_sim_delay" = "Pausa por paso"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Lenguaje"; +"web_codegen_comments" = "Texto del diagrama como comentarios"; +"web_codegen_empty_else" = "Generar rama else vacía en el código"; +"web_copied_check" = "Copiado ✓"; +"web_copy_manual" = "Seleccionado, pulsa Ctrl+C para copiar"; +"web_run_stopped_loop" = "Ejecución detenida: posible bucle infinito."; +"web_run_cancelled" = "Ejecución cancelada."; +"web_run_error" = "Error durante la ejecución."; +"web_run_dropped_fmt" = "… %d líneas anteriores ocultas"; +"web_sim_call_arguments_fmt" = "La llamada no coincide con la cabecera de %@. Revisa los valores entre paréntesis."; +"web_sim_missing_return_fmt" = "%@ terminó sin devolver un valor con return."; +"web_sim_file_not_found_fmt" = "No existe ningún archivo llamado %@."; +"web_sim_end_of_file_fmt" = "El archivo %@ no tiene más líneas."; +"web_sim_null_value_fmt" = "%@ es null."; +"web_sim_written_file_fmt" = "%@ (guardado)"; +"web_site_home" = "Página de inicio"; +"web_site_imprint" = "Aviso legal"; +"web_site_privacy" = "Privacidad"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Programación"; +"web_live_hide" = "Ocultar programación"; +"web_scale_canvas" = "Tamaño del texto: diagrama"; +"web_scale_code" = "Tamaño del texto: programación"; +"web_live_indent" = "Sangrar"; +"web_live_indent_title" = "Sangrar el código: cuatro espacios por nivel (líneas seleccionadas, si no, todo)"; +"web_live_show" = "Mostrar programación"; +"web_live_resize" = "Cambiar el ancho del área de código (doble clic: restablecer)"; +"web_live_hint" = "El código crece con tu diagrama. Gris = marcador: escribe en el inspector y tu texto aparecerá ahí. Haz clic en una línea para seleccionar su elemento."; +"web_live_ph_selector" = "variable"; +"web_live_ph_code" = "Tu código"; +"web_live_ph_end" = "fin"; +"web_live_language" = "Lenguaje de programación"; +"web_live_java_class" = "Como clase"; +"web_live_java_class_hint" = "Nombre de la clase = título del diagrama"; +"web_live_java_main" = "Con método main"; +"web_settings_display" = "Visualización"; +"web_live_swing" = "Java real (con Swing)"; +"web_live_swing_hint" = "Java real con ventanas (CheerpJ). Descarga unos 40 MB una sola vez, en la primera ejecución."; +"web_live_swing_windows" = "Ventanas de Java"; +"web_live_swing_hide" = "Cerrar ventanas de Java"; +"web_live_swing_loading" = "Cargando Java (unos 40 MB la primera vez) …"; +"web_live_swing_compiling" = "Compilando …"; +"web_live_swing_running" = "El programa se está ejecutando."; +"web_live_swing_compile_failed" = "Error de compilación, mira arriba."; +"web_live_swing_failed" = "No se pudo cargar Java. Comprueba la conexión a internet."; +"web_live_hint_edit" = "Escribe aquí código Java y el diagrama se construye solo. O trabaja en el diagrama y el código crece con él. Gris = marcador, escribe encima."; +"web_live_edit_label" = "Código Java"; +"web_parse_line_fmt" = "Línea %d: %@"; +"web_parse_missing" = "Aquí falta: %@"; +"web_parse_extra" = "Sobra: %@"; +"web_parse_unclosed_string" = "Falta el %@ de cierre."; +"web_parse_else_without_if" = "Este «else» no tiene un «if»."; +"web_parse_case_outside_switch" = "«case» y «default» van dentro de un «switch»."; +"web_parse_missing_do_while" = "Después de «do { … }» falta «while (condición);»."; +"web_parse_more_methods" = "Por ahora solo cuenta un método. Crea otros subprogramas en pestañas propias."; +"web_parse_missing_import" = "Falta %@ al principio. Sin esta línea, Java no conoce Scanner."; +"web_parse_missing_scanner" = "Falta antes %@ Sin esta línea, el Scanner no existe."; +"web_parse_unknown_type" = "Java no conoce este tipo de datos. ¿Querías decir %@?"; +"web_editor_title" = "Diagrama"; +"web_editor_show" = "Mostrar diagrama"; +"web_editor_hide" = "Ocultar diagrama"; +"web_keywords_title" = "Palabras clave de código"; +"web_keywords_hint" = "if, while, for en lugar de los nombres de los elementos"; +"web_palette_compact" = "Elementos siempre compactos"; +"web_palette_compact_hint" = "Símbolo con el nombre pequeño debajo; si no, solo con la columna estrecha"; +"web_about_version_fmt" = "Versión %@"; +"web_about_software" = "Software utilizado"; +"web_about_software_text" = "El editor de código usa CodeMirror y Lezer (licencia MIT). Con la compatibilidad con Swing, VisuStruct carga CheerpJ de Leaning Technologies (licencia Community) y javac de OpenJDK."; +"web_about_licenses" = "Textos de las licencias"; +"web_live_run" = "Ejecutar"; +"web_live_run_title" = "Ejecutar el programa: la salida y la entrada aparecen abajo"; +"web_live_run_finished" = "Programa terminado."; +"web_live_run_stopped" = "Detenido."; +"web_console" = "Consola"; +"web_console_hide" = "Ocultar consola"; +"web_console_resize" = "Cambiar la altura de la consola"; +"web_diagram_tools" = "Herramientas del diagrama"; +"web_files_title" = "Archivos"; +"web_files_show" = "Mostrar archivos"; +"web_files_hide" = "Ocultar archivos"; +"web_files_resize" = "Cambiar el ancho de archivos"; +"web_files_new_folder" = "Nueva carpeta"; +"web_files_switch" = "Elegir otra carpeta"; +"web_files_delete" = "Eliminar"; +"web_files_in_browser" = "En el almacenamiento de este navegador"; +"web_files_save_hint_fmt" = "Al guardar, el programa se coloca en %@."; +"web_files_empty" = "Aún no hay nada guardado. Al guardar, VisuStruct crea aquí una carpeta con la fecha de hoy."; +"web_files_reconnect_hint" = "Tras recargar, el navegador vuelve a preguntar si VisuStruct puede usar tu carpeta."; +"web_files_reconnect_fmt" = "Abrir la carpeta «%@»"; +"web_files_connect_hint" = "Elige una carpeta como espacio de trabajo. VisuStruct crea en ella una carpeta para cada día y guarda el diagrama y el código."; +"web_files_connect" = "Elegir carpeta"; +"web_files_browser_hint" = "Este navegador no puede abrir carpetas del dispositivo (por ejemplo en el iPad). Tus archivos quedan en el almacenamiento de este navegador."; +"web_files_browser" = "Guardar en el navegador"; +"web_files_delete_confirm_fmt" = "¿Eliminar «%@»?"; +"web_files_folder_prompt" = "Nombre de la nueva carpeta:"; +"web_files_default_name" = "Programa"; +"web_files_saved_fmt" = "Guardado: %@"; +"web_files_create" = "Crear"; +"web_learn_ludwig_tip" = "El consejo de Ludwig"; +"web_game_title" = "Juego: ¿Verdadero o falso?"; +"web_game_intro" = "Ludwig te muestra valores y una condición. ¿Es verdadera (true) o falsa (false)? Diez rondas, cada vez más difíciles."; +"web_game_start" = "Empezar el juego"; +"web_game_round_fmt" = "Ronda %@ de %@"; +"web_game_score_fmt" = "Puntos: %@"; +"web_game_true" = "verdadero (true)"; +"web_game_false" = "falso (false)"; +"web_game_right" = "¡Correcto!"; +"web_game_wrong" = "No del todo. Así se calcula:"; +"web_game_next" = "Siguiente"; +"web_game_finish" = "Resultado"; +"web_game_done_fmt" = "%@ de %@ correctas."; +"web_game_perfect" = "¡Todo correcto! Ludwig está impresionado."; +"web_game_good" = "¡Muy bien! Revisa tus errores e inténtalo de nuevo."; +"web_game_practice" = "La práctica hace al maestro. Vuelve a leer la tabla de verdad y juega otra ronda."; +"web_game_again" = "Jugar otra vez"; +"web_game_wrong_short" = "Lo siento, es incorrecto."; +"web_game_practice_short" = "La práctica hace al maestro. Vuelve a leer las explicaciones y juega otra ronda."; +"web_game_clicks" = "Clics:"; +"web_game_nobody" = "Nadie escucha: no pasa nada."; +"web_game_event_fmt" = "Clic en «%@»: el oyente lo oye y ejecuta su código."; +"web_game_try" = "Ahora prueba tú los botones de la ventana."; +"web_game_time_fmt" = "Quedan %@ s"; +"web_game_defused" = "✂️ ¡Desactivada! Has encontrado el error."; +"web_game_boom_time" = "💥 ¡Bum! Se acabó el tiempo."; +"web_game_boom_wrong" = "💥 ¡Bum! Esa no era la línea."; +"web_game_fix" = "La línea correcta:"; +"web_game_order_hint" = "Toca los pasos en el orden correcto."; +"web_debug_step" = "Paso a paso"; +"web_debug_step_title" = "Paso a paso: ejecutar una instrucción y detenerse de nuevo"; +"web_debug_continue" = "Continuar hasta el siguiente punto de interrupción"; +"web_debug_paused_fmt" = "Detenido antes de la línea %d."; +"web_debug_gutter_title" = "Haz clic en un número de línea para poner o quitar un punto de interrupción"; +"web_swap_to_code" = "Programación grande"; +"web_swap_to_editor" = "Diagrama grande"; +"web_editor_resize" = "Cambiar el ancho del diagrama"; +"web_palette_resize" = "Cambiar el ancho de los elementos"; +"web_palette_hide" = "Ocultar elementos"; +"web_palette_show" = "Mostrar elementos"; +"web_code_scopes" = "Bloques de código en color"; +"web_code_scopes_hint" = "Clase, método, bucle, condición en sus propias cajas"; +"web_pseudocode" = "Pseudocódigo"; +`;export{e as default}; diff --git a/website/app/assets/flowApp-C_31XWhB.js b/website/app/assets/flowApp-C_31XWhB.js new file mode 100644 index 00000000..3cec0aef --- /dev/null +++ b/website/app/assets/flowApp-C_31XWhB.js @@ -0,0 +1,50 @@ +var dt=Object.defineProperty;var lt=(n,t,e)=>t in n?dt(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var y=(n,t,e)=>lt(n,typeof t!="symbol"?t+"":t,e);import{t as h,g as ct,i as I,w as ht,n as ut,f as ft,o as G,q as pt,u as gt,v as wt,x as vt,y as mt,l as xt}from"./index-Bmqo_CbG.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,yt=170;function bt(n,t,e){const i=[];for(const s of n.split(` +`)){let o="";for(const r of s.split(/\s+/).filter(Boolean)){const a=o?`${o} ${r}`:r;o&&e(a)>t?(i.push(o),o=r):o=a}i.push(o)}return i.length?i:[""]}const q=n=>Math.round(n/m)*m;function C(n,t){const e=bt(n.text,yt,t),i=Math.max(0,...e.map(t)),s=e.length*H;let o,r;if(n.shape==="verzweigung")o=Math.max(140,i*1.7+30),r=Math.max(80,s*1.8+24);else{const a=n.shape==="ein"?44:n.shape==="unterprogramm"?40:n.shape==="anweisung"?24:36;o=Math.max(n.shape==="start"||n.shape==="ende"?100:120,i+a),r=Math.max(40,s+18)}return{x:n.x,y:n.y,w:Math.ceil(o/m)*m,h:Math.ceil(r/m)*m,lines:e}}function V(n){return n==="ende"?[]:n==="verzweigung"?["ja","nein"]:["out"]}const D=n=>n!=="start";function P(n,t,e){var s;if(e==="out")return"bottom";const i=((s=n.yesRight)==null?void 0:s.includes(t.id))??!1;return e==="ja"===i?"right":"bottom"}function F(n,t){return t==="bottom"?[n.x,n.y+n.h/2]:[n.x+n.w/2,n.y]}const _t=n=>[n.x,n.y-n.h/2];function $t(n,t,e,i=0){const[s,o]=F(n,t),[r,a]=_t(e),d=m,u=Math.max(n.x+n.w/2,e.x+e.w/2)+d*(1.5+i);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(n=""){return{title:n,nodes:[],edges:[]}}function it(n,t){const e=new Set([...n.nodes.map(s=>s.id),...n.edges.map(s=>s.id)]);let i=1;for(;e.has(`${t}${i}`);)i++;return`${t}${i}`}function O(n,t,e,i,s){const o=it(n,"n");return{doc:{...n,nodes:[...n.nodes,{id:o,shape:t,x:q(e),y:q(i),text:s}]},id:o}}function J(n,t,e,i){return{...n,nodes:n.nodes.map(s=>s.id===t?{...s,x:Math.max(m*4,q(e)),y:Math.max(m*2,q(i))}:s)}}function Lt(n,t,e){return{...n,nodes:n.nodes.map(i=>i.id===t?{...i,text:e}:i)}}function _(n,t,e,i){const s=n.nodes.find(a=>a.id===t),o=n.nodes.find(a=>a.id===i);if(!s||!o||t===i||!V(s.shape).includes(e)||!D(o.shape))return n;const r=n.edges.filter(a=>!(a.from===t&&a.port===e));return{...n,edges:[...r,{id:it(n,"e"),from:t,port:e,to:i}]}}function Et(n,t){return V(t.shape).find(e=>!n.edges.some(i=>i.from===t.id&&i.port===e))}function kt(n,t){var e;return{...n,nodes:n.nodes.filter(i=>i.id!==t),edges:n.edges.filter(i=>i.from!==t&&i.to!==t),yesRight:(e=n.yesRight)==null?void 0:e.filter(i=>i!==t)}}function St(n,t){return{...n,edges:n.edges.filter(e=>e.id!==t)}}function ot(n,t){const e=new Set(n.yesRight??[]);return e.has(t)?e.delete(t):e.add(t),{...n,yesRight:[...e]}}function b(n){return JSON.stringify({format:"visuflow",version:1,...n},null,2)}function W(n){let t;try{t=JSON.parse(n)}catch{return}if(!t||typeof t!="object")return;const e=t;if(!Array.isArray(e.nodes)||!Array.isArray(e.edges))return;const i=[];for(const o of e.nodes)!o||typeof o.id!="string"||!et.includes(o.shape)||!Number.isFinite(o.x)||!Number.isFinite(o.y)||i.some(r=>r.id===o.id)||i.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:i,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"&&i.some(r=>r.id===o))),s}const z="http://www.w3.org/2000/svg",X="visuflow.doc",Mt=100,Y=14,rt=`${Y}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`,T="#1c1c1e",w=n=>n.replace(/[&<>"]/g,t=>({"&":"&","<":"<",">":">",'"':"""})[t]);function At(n){try{return localStorage.getItem(n)}catch{return null}}function Z(n,t){try{localStorage.setItem(n,t)}catch{}}function It(){const n=xt(),t=n==="pt-PT"?"pt":n==="de"?"de":"en";return`${/\/app\/(index\.html)?$/.test(location.pathname)?"../":"https://visustruct.org/"}${t}/index.html`}function j(n,t,e){const i=URL.createObjectURL(new Blob([t],{type:e})),s=document.createElement("a");s.href=i,s.download=n,s.click(),setTimeout(()=>URL.revokeObjectURL(i),1e3)}function v(n,t={}){const e=document.createElementNS(z,n);for(const[i,s]of Object.entries(t))e.setAttribute(i,String(s));return e}let N;function R(n){return N===void 0&&(N=document.createElement("canvas").getContext("2d")),N?(N.font=rt,N.measureText(n).width):n.length*Y*.55}const Ct=n=>h(`web_visuflow_shape_${n}`),B=n=>h(`web_visuflow_text_${n}`);function at(n,t){const e=t.x-t.w/2,i=t.x+t.w/2,s=t.y-t.h/2,o=t.y+t.h/2;return n==="verzweigung"?v("path",{d:`M${t.x} ${s} L${i} ${t.y} L${t.x} ${o} L${e} ${t.y} Z`}):n==="ein"?v("path",{d:`M${e+14} ${s} L${i} ${s} L${i-14} ${o} L${e} ${o} Z`}):n==="unterprogramm"?v("path",{d:`M${e} ${s} H${i} V${o} H${e} Z M${e+10} ${s} V${o} M${i-10} ${s} V${o}`}):v("rect",{x:e,y:s,width:t.w,height:t.h,rx:n==="anweisung"?2:t.h/2})}function Rt(n){const t=v("text",{"text-anchor":"middle","font-size":Y,fill:T});return n.lines.forEach((e,i)=>{const s=v("tspan",{x:n.x,y:n.y+5+(i-(n.lines.length-1)/2)*H});s.textContent=e,t.append(s)}),t}function Q(n){const t=v("svg",{viewBox:"0 0 64 36",width:64,height:36,"aria-hidden":"true"}),e=at(n,{x:32,y:18,w:n==="verzweigung"?54:56,h:n==="verzweigung"?32:26});return e.setAttribute("fill",st[n]),e.setAttribute("stroke",T),e.setAttribute("stroke-width","1.5"),t.append(e),t.outerHTML}function tt(){let n=nt(h("web_visuflow_example_title"));const t=[],e=(p,f,l,c)=>{const g=O(n,p,f,l,c);n=g.doc,t.push(g.id)};e("start",240,60,B("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,B("ende"));const[i,s,o,r,a,d,u]=t;return n=_(n,i,"out",s),n=_(n,s,"out",o),n=_(n,o,"out",r),n=ot(n,r),n=_(n,r,"ja",a),n=_(n,a,"out",r),n=_(n,r,"nein",d),n=_(n,d,"out",u),n}function Tt(){return O(nt(),"start",240,60,B("start")).doc}class Pt{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(At(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"))} +
+ ${t("new",h("toolbar_new"),I.newFile,h("web_visuflow_new_tip"))} + ${t("open",h("menu_open"),I.open,h("web_visuflow_open_tip"))} + ${t("save",h("menu_save"),I.save,h("web_visuflow_save_tip"))} + ${t("undo",h("toolbar_undo"),I.undo)} + ${t("redo",h("toolbar_redo"),I.redo)} + ${t("delete",h("web_visuflow_delete"),I.trash,h("web_visuflow_delete_tip"))} + + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+ +
+

+
+
+ `;const i=l=>this.shell.querySelector(l);this.svg=i(".vf-canvas"),this.scroller=i(".vf-scroll"),this.status=i(".vf-status"),this.titleInput=i(".vf-title");const s=(l,c)=>i(`[data-action=${l}]`).addEventListener("click",c);s("new",()=>this.replace(Tt())),s("example",()=>this.replace(tt())),s("open",()=>i("input[type=file]").click()),s("save",()=>this.save()),s("undo",()=>this.undo(!1)),s("redo",()=>this.undo(!0)),s("delete",()=>this.deleteSelection()),s("swap",()=>{var l;((l=this.selection)==null?void 0:l.kind)==="node"&&this.change(ot(this.doc,this.selection.id))});const o=i("input[type=file]");o.addEventListener("change",async()=>{var g;const l=(g=o.files)==null?void 0:g[0];if(o.value="",!l)return;const c=W(await l.text());if(!c)return this.showStatus(h("web_visuflow_open_error"));c.title||(c.title=l.name.replace(/\.(visuflow|json)$/i,"")),this.replace(c)});let r;this.titleInput.addEventListener("focus",()=>r=b(this.doc)),this.titleInput.addEventListener("input",()=>{this.doc={...this.doc,title:this.titleInput.value},Z(X,b(this.doc))}),this.titleInput.addEventListener("change",()=>{r!==void 0&&r!==b(this.doc)&&this.pushUndo(r),r=b(this.doc)});const a=i("[data-action=export]"),d=i(".vf-menu"),u=l=>{d.hidden=!l,a.setAttribute("aria-expanded",String(l))};a.addEventListener("click",()=>u(d.hidden)),d.addEventListener("click",l=>{var g;const c=(g=l.target.closest("[data-export]"))==null?void 0:g.dataset.export;c&&(u(!1),this.export(c))});const p=i("[data-action=settings]"),f=i(".settings-menu");p.addEventListener("click",()=>{f.hidden=!f.hidden,p.setAttribute("aria-expanded",String(!f.hidden))}),document.addEventListener("pointerdown",l=>{const c=l.target;!f.hidden&&!c.closest(".settings")&&(f.hidden=!0),!d.hidden&&!c.closest(".vf-export")&&u(!1)});for(const l of f.querySelectorAll("[data-world]"))l.addEventListener("click",()=>this.chooseWorld(l.dataset.world));for(const l of this.shell.querySelectorAll(".vf-shape"))this.setupPaletteButton(l);this.svg.addEventListener("pointerdown",l=>this.onPointerDown(l)),this.svg.addEventListener("dblclick",l=>{var g;const c=(g=l.target.closest("[data-node]"))==null?void 0:g.dataset.node;c&&this.editText(c)})}chooseWorld(t){if(t!=="flow"){if(t==="object"){ut(),location.href=`${location.pathname}?visuobject${location.hash}`;return}ft(t),location.href=`${location.pathname}?${t==="on"?"visubot":"visustruct"}${location.hash}`}}pushUndo(t){this.history.push(t),this.history.length>Mt&&this.history.shift(),this.future=[]}change(t,e){t!==this.doc&&(this.pushUndo(b(this.doc)),this.doc=t,e!==void 0&&(this.selection=e??void 0),this.afterChange())}replace(t){this.change(t,null),this.scroller.scrollTo(0,0)}afterChange(){Z(X,b(this.doc)),this.selection&&!this.find(this.selection)&&(this.selection=void 0),this.render()}find(t){return t.kind==="node"?this.doc.nodes.find(e=>e.id===t.id):this.doc.edges.find(e=>e.id===t.id)}undo(t){this.closeEditor(!0);const e=t?this.future:this.history,i=t?this.history:this.future,s=e.pop();s!==void 0&&(i.push(b(this.doc)),this.doc=W(s)??this.doc,this.afterChange())}deleteSelection(){const t=this.selection;t&&this.change(t.kind==="node"?kt(this.doc,t.id):St(this.doc,t.id),null)}save(){const t=G(this.doc.title)||"PAP";j(`${t}.visuflow`,b(this.doc),"application/json"),this.showStatus(h("web_visuflow_saved",`${t}.visuflow`))}boxes(t=this.doc){return new Map(t.nodes.map(e=>[e.id,C(e,R)]))}drawInto(t,e){var f,l;const i=this.boxes(),s=h("web_learn_pap_yes"),o=h("web_learn_pap_no");t.innerHTML=``;const r=v("g",{class:"vf-edges"}),a=v("g",{class:"vf-labels","font-size":12,"font-weight":600}),d=v("g",{class:"vf-nodes"}),u=v("g",{class:"vf-ports"});let p=0;for(const c of this.doc.edges){const g=this.doc.nodes.find(M=>M.id===c.from),x=i.get(c.from),$=i.get(c.to),k=P(this.doc,g,c.port),L=$.y-$.h/2M.join(",")).join(" "),E=v("g",{"data-edge":c.id,class:`vf-edge${!e&&((f=this.selection)==null?void 0:f.kind)==="edge"&&this.selection.id===c.id?" selected":""}`});e||E.append(v("polyline",{points:S,class:"vf-edge-hit",fill:"none",stroke:"transparent","stroke-width":16})),E.append(v("polyline",{points:S,class:"vf-edge-line",fill:"none",stroke:T,"stroke-width":2,"marker-end":"url(#vf-arrow)"})),r.append(E)}for(const c of this.doc.nodes){const g=i.get(c.id),x=!e&&((l=this.selection)==null?void 0:l.kind)==="node"&&this.selection.id===c.id,$=v("g",{"data-node":c.id,class:`vf-node${x?" selected":""}`}),k=at(c.shape,g);k.setAttribute("fill",st[c.shape]),k.setAttribute("stroke",T),k.setAttribute("stroke-width","2"),$.append(k,Rt(g)),d.append($);for(const L of V(c.shape)){const U=P(this.doc,c,L),[S,E]=F(g,U),M=this.doc.edges.some(A=>A.from===c.id&&A.port===L);if(L!=="out"&&(M||!e)){const A=v("text",U==="bottom"?{x:S+7,y:E+15}:{x:S+6,y:E-7});A.setAttribute("fill",L==="ja"?"#248a3d":"#d70015"),A.textContent=L==="ja"?s:o,a.append(A)}if(e)continue;const K=v("g",{"data-port":L,"data-from":c.id,class:`vf-port${M?" used":""}`});K.append(v("circle",{cx:S,cy:E,r:16,fill:"transparent"}),v("circle",{cx:S,cy:E,r:6,class:"vf-port-dot"})),u.append(K)}}return t.append(r,d,a,u),i}render(){this.closeEditor(!0);const t=this.drawInto(this.svg,!1);let e=0,i=0;for(const d of t.values())e=Math.max(e,d.x+d.w/2),i=Math.max(i,d.y+d.h/2);const s=Math.max(this.scroller.clientWidth,e+300),o=Math.max(this.scroller.clientHeight,i+300);this.svg.setAttribute("width",String(s)),this.svg.setAttribute("height",String(o)),this.svg.setAttribute("viewBox",`0 0 ${s} ${o}`),document.activeElement!==this.titleInput&&(this.titleInput.value=this.doc.title);const r=this.selection,a=(r==null?void 0:r.kind)==="node"?this.doc.nodes.find(d=>d.id===r.id):void 0;this.shell.querySelector("[data-action=swap]").disabled=(a==null?void 0:a.shape)!=="verzweigung",this.shell.querySelector("[data-action=delete]").disabled=!r,this.shell.querySelector("[data-action=undo]").disabled=this.history.length===0,this.shell.querySelector("[data-action=redo]").disabled=this.future.length===0,this.showStatus(h(this.doc.nodes.length===0?"web_visuflow_status_empty":(r==null?void 0:r.kind)==="edge"?"web_visuflow_status_edge":r?"web_visuflow_status_node":"web_visuflow_status_idle"))}showStatus(t){this.status.textContent=t}setupPaletteButton(t){const e=t.dataset.shape;t.addEventListener("pointerdown",i=>{if(i.button!==0)return;i.preventDefault();const s={x:i.clientX,y:i.clientY};let o;const r=d=>{!o&&Math.hypot(d.clientX-s.x,d.clientY-s.y)<6||(o||(o=document.createElement("div"),o.className="vf-ghost",o.innerHTML=Q(e),document.body.append(o)),o.style.left=`${d.clientX}px`,o.style.top=`${d.clientY}px`)},a=d=>{if(window.removeEventListener("pointermove",r),window.removeEventListener("pointerup",a),window.removeEventListener("pointercancel",a),!o)return this.appendShape(e);if(o.remove(),d.type==="pointercancel")return;const u=this.scroller.getBoundingClientRect();if(d.clientXu.right||d.clientYu.bottom)return;const p=this.toCanvas(d),{doc:f,id:l}=O(this.doc,e,p.x,p.y,B(e));this.change(f,{kind:"node",id:l}),this.editText(l)};window.addEventListener("pointermove",r),window.addEventListener("pointerup",a),window.addEventListener("pointercancel",a)}),t.addEventListener("keydown",i=>{i.key!=="Enter"&&i.key!==" "||(i.preventDefault(),this.appendShape(e))})}appendShape(t){var f;const e=this.selection,i=(e==null?void 0:e.kind)==="node"?this.doc.nodes.find(l=>l.id===e.id):void 0,s=i&&D(t)?Et(this.doc,i):void 0,o=C({shape:t,x:0,y:0,text:B(t)},R);let r=240,a=60;if(i&&s){const l=C(i,R);P(this.doc,i,s)==="right"?(r=l.x+l.w/2+3*m+o.w/2,a=l.y):(r=l.x,a=l.y+l.h/2+3*m+o.h/2)}else if(this.doc.nodes.length){const c=[...this.boxes().values()].reduce((g,x)=>x.y+x.h/2>g.y+g.h/2?x:g);r=i?C(i,R).x:c.x,a=c.y+c.h/2+3*m+o.h/2}let{doc:d,id:u}=O(this.doc,t,r,a,B(t));i&&s&&(d=_(d,i.id,s,u)),this.change(d,{kind:"node",id:u});const p=this.svg.querySelector(`[data-node="${u}"]`);(f=p==null?void 0:p.scrollIntoView)==null||f.call(p,{block:"nearest",inline:"nearest"}),this.editText(u)}toCanvas(t){const e=this.svg.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}nodeAt(t,e){const i=this.boxes();return[...this.doc.nodes].reverse().find(s=>{const o=i.get(s.id);return s.id!==e&&Math.abs(t.x-o.x)<=o.w/2+4&&Math.abs(t.y-o.y)<=o.h/2+4})}onPointerDown(t){var r,a;if(t.button!==0)return;const e=t.target,i=e.closest("[data-port]");if(i)return this.dragArrow(t,i.dataset.from,i.dataset.port);const s=(r=e.closest("[data-node]"))==null?void 0:r.dataset.node;if(s)return this.dragNode(t,s);const o=(a=e.closest("[data-edge]"))==null?void 0:a.dataset.edge;this.closeEditor(!0),this.selection=o?{kind:"edge",id:o}:void 0,this.render()}dragNode(t,e){var f;t.preventDefault();const i=((f=this.selection)==null?void 0:f.kind)==="node"&&this.selection.id===e;this.closeEditor(!0),this.selection={kind:"node",id:e},this.render();const s=this.doc.nodes.find(l=>l.id===e),o=this.toCanvas(t),r=b(this.doc),a={x:s.x,y:s.y};let d=!1;const u=l=>{const c=this.toCanvas(l);!d&&Math.hypot(c.x-o.x,c.y-o.y)<5||(d=!0,this.doc=J(this.doc,e,a.x+c.x-o.x,a.y+c.y-o.y),this.render())},p=()=>{window.removeEventListener("pointermove",u),window.removeEventListener("pointerup",p),window.removeEventListener("pointercancel",p),d?(b(this.doc)!==r&&this.pushUndo(r),this.afterChange()):i&&this.editText(e)};window.addEventListener("pointermove",u),window.addEventListener("pointerup",p),window.addEventListener("pointercancel",p)}dragArrow(t,e,i){t.preventDefault(),this.closeEditor(!0);const s=this.doc.nodes.find(p=>p.id===e),[o,r]=F(C(s,R),P(this.doc,s,i));this.dragLine=v("line",{x1:o,y1:r,x2:o,y2:r,class:"vf-drag-line","marker-end":"url(#vf-arrow)"}),this.svg.append(this.dragLine),this.showStatus(h("web_visuflow_status_connect"));let a=null;const d=p=>{const f=this.toCanvas(p);this.dragLine.setAttribute("x2",String(f.x)),this.dragLine.setAttribute("y2",String(f.y));const l=this.nodeAt(f,e);a==null||a.classList.remove("drop-target"),a=l&&D(l.shape)?this.svg.querySelector(`[data-node="${l.id}"]`):null,a==null||a.classList.add("drop-target")},u=p=>{var l;window.removeEventListener("pointermove",d),window.removeEventListener("pointerup",u),window.removeEventListener("pointercancel",u),(l=this.dragLine)==null||l.remove(),this.dragLine=void 0;const f=p.type==="pointercancel"?void 0:this.nodeAt(this.toCanvas(p),e);f&&D(f.shape)?this.change(_(this.doc,e,i,f.id),{kind:"node",id:f.id}):this.render()};window.addEventListener("pointermove",d),window.addEventListener("pointerup",u),window.addEventListener("pointercancel",u)}editText(t){this.closeEditor(!0);const e=this.doc.nodes.find(d=>d.id===t);if(!e)return;const i=C(e,R),s=document.createElement("textarea");s.className="vf-editor",s.value=e.text,s.setAttribute("aria-label",h("web_visuflow_edit_label"));const o=e.shape==="verzweigung"?.62:.92,r=Math.max(110,i.w*o);s.style.left=`${this.svg.getBoundingClientRect().left-this.scroller.getBoundingClientRect().left+this.scroller.scrollLeft+i.x-r/2}px`,s.style.top=`${this.svg.getBoundingClientRect().top-this.scroller.getBoundingClientRect().top+this.scroller.scrollTop+i.y-Math.max(28,i.lines.length*H+10)/2}px`,s.style.width=`${r}px`,s.style.height=`${Math.max(28,i.lines.length*H+10)}px`,s.dataset.node=t,this.scroller.append(s),this.editor=s,s.focus(),s.select();const a=()=>{s.style.height="auto",s.style.height=`${s.scrollHeight}px`};s.addEventListener("input",a),s.addEventListener("keydown",d=>{d.stopPropagation(),d.key==="Enter"&&!d.shiftKey?(d.preventDefault(),this.closeEditor(!0)):d.key==="Escape"&&(d.preventDefault(),this.closeEditor(!1))}),s.addEventListener("blur",()=>this.closeEditor(!0))}closeEditor(t){const e=this.editor;if(!e)return;this.editor=void 0,e.remove();const i=e.dataset.node,s=this.doc.nodes.find(r=>r.id===i),o=e.value.trim();t&&s&&o!==s.text&&this.change(Lt(this.doc,i,o))}onKey(t){var a,d;const e=(d=(a=t.target).closest)==null?void 0:d.call(a,"input, textarea, [contenteditable]"),i=t.ctrlKey||t.metaKey;if(i&&t.key.toLowerCase()==="s")return t.preventDefault(),this.save();if(e)return;if(i&&t.key.toLowerCase()==="z")return t.preventDefault(),this.undo(t.shiftKey);if(i&&t.key.toLowerCase()==="y")return t.preventDefault(),this.undo(!0);const s=this.selection;if(!s)return;if(t.key==="Delete"||t.key==="Backspace")return t.preventDefault(),this.deleteSelection();if(s.kind!=="node")return;if(t.key==="Enter"||t.key==="F2")return t.preventDefault(),this.editText(s.id);const o={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]}[t.key];if(!o)return;t.preventDefault();const r=this.doc.nodes.find(u=>u.id===s.id);this.change(J(this.doc,s.id,r.x+o[0]*m,r.y+o[1]*m))}exportImage(){if(this.doc.nodes.length===0)return;const t=document.createElementNS(z,"svg"),e=this.drawInto(t,!0);let i=1/0,s=1/0,o=-1/0,r=-1/0;for(const c of e.values())i=Math.min(i,c.x-c.w/2),s=Math.min(s,c.y-c.h/2),o=Math.max(o,c.x+c.w/2),r=Math.max(r,c.y+c.h/2);for(const c of t.querySelectorAll("polyline"))for(const g of(c.getAttribute("points")??"").split(" ")){const[x,$]=g.split(",").map(Number);i=Math.min(i,x),o=Math.max(o,x+4),s=Math.min(s,$),r=Math.max(r,$)}o+=30;const a=20,d=this.doc.title.trim(),u=d?32:0,p=Math.ceil(o-i+2*a),f=Math.ceil(r-s+2*a+u);t.setAttribute("xmlns",z),t.setAttribute("width",String(p)),t.setAttribute("height",String(f)),t.setAttribute("viewBox",`${i-a} ${s-a-u} ${p} ${f}`),t.setAttribute("font-family",rt.replace(/^\d+px /,""));const l=v("rect",{x:i-a,y:s-a-u,width:p,height:f,fill:"#ffffff"});if(t.insertBefore(l,t.firstChild.nextSibling),d){const c=v("text",{x:i-a+12,y:s-a-u+26,"font-size":16,"font-weight":700,fill:T});c.textContent=d,t.append(c)}return{svg:t,width:p,height:f}}async export(t){const e=this.exportImage();if(!e)return this.showStatus(h("web_visuflow_status_empty"));const i=G(this.doc.title)||"PAP";if(t==="svg")return j(`${i}.svg`,pt(e),"image/svg+xml");const s=await gt(e,t==="png"?2:3);if(t==="png")return j(`${i}.png`,await wt(s),"image/png");const o=await vt(mt(s),s.width,s.height,e,this.doc.title.trim()||"PAP");j(`${i}.pdf`,o,"application/pdf")}}export{Pt as FlowApp}; diff --git a/website/app/assets/fr-C_mSEvw5.js b/website/app/assets/fr-C_mSEvw5.js new file mode 100644 index 00000000..33ead673 --- /dev/null +++ b/website/app/assets/fr-C_mSEvw5.js @@ -0,0 +1,180 @@ +const e=`/* Textes propres à la version web. Tout le reste provient des Localizable.strings de l’app. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "Organigramme VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Suppr"; +"web_key_shift" = "Maj"; +"web_export" = "Exporter…"; +"web_export_title" = "Enregistrer comme image ou PDF, ou imprimer"; +"web_export_png" = "Image (PNG)"; +"web_export_svg" = "Graphique vectoriel (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "Fichier VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "Échec de l’exportation : %@"; +"web_print_hint" = "Utilisez « Exporter… → PDF » pour enregistrer le diagramme, puis imprimez-le."; +"web_delete" = "Supprimer"; +"web_language_title" = "Langue de l’interface"; +"web_simulation_start" = "Lancer la simulation"; +"web_simulation_end" = "Terminer la simulation"; +"web_simulation_start_title" = "Exécuter l’organigramme étape par étape"; +"web_simulation_end_title" = "Terminer la simulation et reprendre l’édition"; +"web_palette_hint" = "Glisser dans l’organigramme"; +"web_tabs_label" = "Diagrammes"; +"web_status_modified" = "modifié"; +"web_inspector_title" = "Propriétés"; +"web_inspector_help_drop" = "Glissez des éléments de la palette sur une tuile : en haut = avant, en bas = après, sur « ø » = remplacer. Les éléments existants se déplacent à la souris."; +"web_inspector_help_files" = "Vous pouvez aussi déposer des fichiers dans la fenêtre."; +"web_case_name" = "Nom du cas"; +"web_case_name_placeholder" = "p. ex. 1, ok, default"; +"web_copied" = "Élément copié."; +"web_discard_message_fmt" = "Les modifications de « %@ » seront perdues."; +"web_err_unreadable_fmt" = "« %@ » n’est pas un fichier VisuStruct lisible (%@)."; +"web_saved_fmt" = "« %@ » enregistré."; +"web_saved_txt_fmt" = "Enregistré sous « %@ ». Supprimez l’extension .txt pour l’utiliser."; +"web_drop_impossible" = "Impossible de déposer ici"; +"web_sim_delay" = "Pause par étape"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Langage"; +"web_codegen_comments" = "Texte du diagramme en commentaires"; +"web_codegen_empty_else" = "Générer une branche else vide dans le code"; +"web_copied_check" = "Copié ✓"; +"web_copy_manual" = "Sélectionné, appuyez sur Ctrl+C pour copier"; +"web_run_stopped_loop" = "Exécution arrêtée : boucle infinie possible."; +"web_run_cancelled" = "Exécution annulée."; +"web_run_error" = "Erreur lors de l’exécution."; +"web_run_dropped_fmt" = "… %d lignes précédentes masquées"; +"web_sim_call_arguments_fmt" = "L’appel ne correspond pas à l’en-tête de %@. Vérifie les valeurs entre parenthèses."; +"web_sim_missing_return_fmt" = "%@ s’est terminé sans renvoyer de valeur avec return."; +"web_sim_file_not_found_fmt" = "Il n’existe aucun fichier nommé %@."; +"web_sim_end_of_file_fmt" = "Le fichier %@ n’a plus de ligne."; +"web_sim_null_value_fmt" = "%@ vaut null."; +"web_sim_written_file_fmt" = "%@ (enregistré)"; +"web_site_home" = "Accueil"; +"web_site_imprint" = "Mentions légales"; +"web_site_privacy" = "Confidentialité"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Programmation"; +"web_live_hide" = "Masquer la programmation"; +"web_scale_canvas" = "Taille du texte : structogramme"; +"web_scale_code" = "Taille du texte : programmation"; +"web_live_indent" = "Indenter"; +"web_live_indent_title" = "Indenter le code : quatre espaces par niveau (lignes sélectionnées, sinon tout)"; +"web_live_show" = "Afficher la programmation"; +"web_live_resize" = "Modifier la largeur de la zone de code (double-clic : réinitialiser)"; +"web_live_hint" = "Le code évolue avec ton diagramme. Gris = espace réservé : écris dans l’inspecteur et ton texte apparaît ici. Clique sur une ligne pour sélectionner son élément."; +"web_live_ph_selector" = "variable"; +"web_live_ph_code" = "Ton code"; +"web_live_ph_end" = "fin"; +"web_live_language" = "Langage de programmation"; +"web_live_java_class" = "Comme classe"; +"web_live_java_class_hint" = "Nom de la classe = titre du diagramme"; +"web_live_java_main" = "Avec méthode main"; +"web_settings_display" = "Affichage"; +"web_live_swing" = "Vrai Java (avec Swing)"; +"web_live_swing_hint" = "Du vrai Java avec fenêtres (CheerpJ). Télécharge environ 40 Mo une seule fois, au premier lancement."; +"web_live_swing_windows" = "Fenêtres Java"; +"web_live_swing_hide" = "Fermer les fenêtres Java"; +"web_live_swing_loading" = "Chargement de Java (environ 40 Mo la première fois) …"; +"web_live_swing_compiling" = "Compilation …"; +"web_live_swing_running" = "Le programme s’exécute."; +"web_live_swing_compile_failed" = "Erreur de compilation, voir ci-dessus."; +"web_live_swing_failed" = "Impossible de charger Java. Vérifie la connexion Internet."; +"web_live_hint_edit" = "Tape ici du code Java et le diagramme se construit tout seul. Ou travaille dans le diagramme et le code suit. Gris = espace réservé, il suffit d’écrire par-dessus."; +"web_live_edit_label" = "Code Java"; +"web_parse_line_fmt" = "Ligne %d : %@"; +"web_parse_missing" = "Il manque encore ici : %@"; +"web_parse_extra" = "En trop : %@"; +"web_parse_unclosed_string" = "Le %@ de fermeture manque ici."; +"web_parse_else_without_if" = "Ce « else » n’a pas de « if »."; +"web_parse_case_outside_switch" = "« case » et « default » vont dans un « switch »."; +"web_parse_missing_do_while" = "Après « do { … } », il manque « while (condition); »."; +"web_parse_more_methods" = "Pour l’instant, une seule méthode compte ici. Crée les autres sous-programmes dans des onglets séparés."; +"web_parse_missing_import" = "Il manque %@ tout en haut. Sans cette ligne, Java ne connaît pas Scanner."; +"web_parse_missing_scanner" = "Il manque avant %@ Sans cette ligne, le Scanner n’existe pas."; +"web_parse_unknown_type" = "Java ne connaît pas ce type de données. Vouliez-vous dire %@ ?"; +"web_editor_title" = "Diagramme"; +"web_editor_show" = "Afficher le diagramme"; +"web_editor_hide" = "Masquer le diagramme"; +"web_keywords_title" = "Mots-clés du code"; +"web_keywords_hint" = "if, while, for au lieu des noms des éléments"; +"web_palette_compact" = "Éléments toujours compacts"; +"web_palette_compact_hint" = "Symbole avec le nom en petit dessous, sinon seulement si la colonne est étroite"; +"web_about_version_fmt" = "Version %@"; +"web_about_software" = "Logiciels utilisés"; +"web_about_software_text" = "L’éditeur de code utilise CodeMirror et Lezer (licence MIT). Avec la prise en charge de Swing, VisuStruct charge CheerpJ de Leaning Technologies (licence Community) et javac d’OpenJDK."; +"web_about_licenses" = "Textes des licences"; +"web_live_run" = "Exécuter"; +"web_live_run_title" = "Exécuter le programme : les sorties et les entrées apparaissent en dessous"; +"web_live_run_finished" = "Programme terminé."; +"web_live_run_stopped" = "Arrêté."; +"web_console" = "Console"; +"web_console_hide" = "Masquer la console"; +"web_console_resize" = "Redimensionner la console"; +"web_diagram_tools" = "Outils du diagramme"; +"web_files_title" = "Fichiers"; +"web_files_show" = "Afficher les fichiers"; +"web_files_hide" = "Masquer les fichiers"; +"web_files_resize" = "Redimensionner les fichiers"; +"web_files_new_folder" = "Nouveau dossier"; +"web_files_switch" = "Choisir un autre dossier"; +"web_files_delete" = "Supprimer"; +"web_files_in_browser" = "Dans le stockage de ce navigateur"; +"web_files_save_hint_fmt" = "L’enregistrement place le programme dans %@."; +"web_files_empty" = "Rien d’enregistré pour l’instant. À l’enregistrement, VisuStruct crée ici un dossier à la date du jour."; +"web_files_reconnect_hint" = "Après un rechargement, le navigateur redemande si VisuStruct peut utiliser ton dossier."; +"web_files_reconnect_fmt" = "Ouvrir le dossier « %@ »"; +"web_files_connect_hint" = "Choisis un dossier comme espace de travail. VisuStruct y crée un dossier pour chaque jour et enregistre le diagramme et le code."; +"web_files_connect" = "Choisir un dossier"; +"web_files_browser_hint" = "Ce navigateur ne peut pas ouvrir de dossiers de l’appareil (par exemple sur iPad). Tes fichiers restent alors dans le stockage de ce navigateur."; +"web_files_browser" = "Enregistrer dans le navigateur"; +"web_files_delete_confirm_fmt" = "Supprimer vraiment « %@ » ?"; +"web_files_folder_prompt" = "Nom du nouveau dossier :"; +"web_files_default_name" = "Programme"; +"web_files_saved_fmt" = "Enregistré : %@"; +"web_files_create" = "Créer"; +"web_learn_ludwig_tip" = "Le conseil de Ludwig"; +"web_game_title" = "Jeu : Vrai ou faux ?"; +"web_game_intro" = "Ludwig te montre des valeurs et une condition. Est-elle vraie (true) ou fausse (false) ? Dix manches, de plus en plus difficiles."; +"web_game_start" = "Commencer le jeu"; +"web_game_round_fmt" = "Manche %@ sur %@"; +"web_game_score_fmt" = "Points : %@"; +"web_game_true" = "vrai (true)"; +"web_game_false" = "faux (false)"; +"web_game_right" = "Correct !"; +"web_game_wrong" = "Pas tout à fait. Voici le calcul :"; +"web_game_next" = "Suivant"; +"web_game_finish" = "Résultat"; +"web_game_done_fmt" = "%@ sur %@ correctes."; +"web_game_perfect" = "Tout juste – Ludwig est très impressionné !"; +"web_game_good" = "Bravo ! Regarde encore tes erreurs et réessaie."; +"web_game_practice" = "C’est en forgeant qu’on devient forgeron. Relis la table de vérité et rejoue une partie."; +"web_game_again" = "Rejouer"; +"web_game_wrong_short" = "Dommage, c'est faux."; +"web_game_practice_short" = "C'est en forgeant qu'on devient forgeron. Relis les explications et rejoue une partie."; +"web_game_clicks" = "Clics :"; +"web_game_nobody" = "Personne n'écoute – rien ne se passe."; +"web_game_event_fmt" = "Clic sur « %@ » : l'écouteur l'entend et exécute son code."; +"web_game_try" = "Essaie maintenant toi-même les boutons de la fenêtre."; +"web_game_time_fmt" = "Encore %@ s"; +"web_game_defused" = "✂️ Désamorcée ! Tu as trouvé l’erreur."; +"web_game_boom_time" = "💥 Boum ! Le temps est écoulé."; +"web_game_boom_wrong" = "💥 Boum ! Ce n’était pas la bonne ligne."; +"web_game_fix" = "La ligne correcte :"; +"web_game_order_hint" = "Touche les étapes dans le bon ordre."; +"web_debug_step" = "Pas à pas"; +"web_debug_step_title" = "Pas à pas : exécuter une instruction et s’arrêter à nouveau"; +"web_debug_continue" = "Continuer jusqu’au prochain point d’arrêt"; +"web_debug_paused_fmt" = "Arrêté avant la ligne %d."; +"web_debug_gutter_title" = "Clique sur un numéro de ligne pour poser ou retirer un point d’arrêt"; +"web_swap_to_code" = "Programmation en grand"; +"web_swap_to_editor" = "Structogramme en grand"; +"web_editor_resize" = "Modifier la largeur du structogramme"; +"web_palette_resize" = "Modifier la largeur des éléments"; +"web_palette_hide" = "Masquer les éléments"; +"web_palette_show" = "Afficher les éléments"; +"web_code_scopes" = "Blocs de code en couleur"; +"web_code_scopes_hint" = "Classe, méthode, boucle, condition dans leurs propres cadres"; +"web_pseudocode" = "Pseudo-code"; +`;export{e as default}; diff --git a/website/app/assets/he-BAg3LrWK.js b/website/app/assets/he-BAg3LrWK.js new file mode 100644 index 00000000..2f086eab --- /dev/null +++ b/website/app/assets/he-BAg3LrWK.js @@ -0,0 +1,180 @@ +const e=`/* טקסטים שקיימים רק בגרסת הרשת. כל השאר מגיעים מקובץ Localizable.strings של האפליקציה. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "תרשים VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "ייצוא…"; +"web_export_title" = "שמירה כתמונה או כ‑PDF, או הדפסה"; +"web_export_png" = "תמונה (PNG)"; +"web_export_svg" = "גרפיקה וקטורית (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "קובץ VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "הייצוא נכשל: %@"; +"web_print_hint" = "השתמשו ב„ייצוא… → PDF” כדי לשמור את התרשים ולהדפיס אותו משם."; +"web_delete" = "מחיקה"; +"web_language_title" = "שפת הממשק"; +"web_simulation_start" = "התחלת סימולציה"; +"web_simulation_end" = "סיום סימולציה"; +"web_simulation_start_title" = "הרצת התרשים צעד אחר צעד"; +"web_simulation_end_title" = "סיום הסימולציה והמשך עריכה"; +"web_palette_hint" = "גררו לתוך התרשים"; +"web_tabs_label" = "תרשימים"; +"web_status_modified" = "שונה"; +"web_inspector_title" = "מאפיינים"; +"web_inspector_help_drop" = "גררו רכיבים מהלוח אל אריח: למעלה = לפני, למטה = אחרי, על „ø” = החלפה. ניתן להזיז רכיבים קיימים בעזרת העכבר."; +"web_inspector_help_files" = "אפשר גם לגרור קבצים לתוך החלון."; +"web_case_name" = "שם המקרה"; +"web_case_name_placeholder" = "למשל 1, ok, default"; +"web_copied" = "הרכיב הועתק."; +"web_discard_message_fmt" = "השינויים ב„%@” יאבדו."; +"web_err_unreadable_fmt" = "„%@” אינו קובץ VisuStruct קריא (%@)."; +"web_saved_fmt" = "„%@” נשמר."; +"web_saved_txt_fmt" = "נשמר בשם „%@”. הסירו את הסיומת .txt כדי להשתמש בו."; +"web_drop_impossible" = "לא ניתן לשחרר כאן"; +"web_sim_delay" = "השהיה לכל צעד"; +"web_sim_delay_value_fmt" = "%@ שנ׳"; +"web_codegen_language" = "שפה"; +"web_codegen_comments" = "טקסט התרשים כהערות"; +"web_codegen_empty_else" = "יצירת ענף else ריק בקוד"; +"web_copied_check" = "הועתק ✓"; +"web_copy_manual" = "נבחר, הקישו Ctrl+C להעתקה"; +"web_run_stopped_loop" = "ההרצה נעצרה: ייתכן שיש לולאה אינסופית."; +"web_run_cancelled" = "ההרצה בוטלה."; +"web_run_error" = "שגיאה בזמן ההרצה."; +"web_run_dropped_fmt" = "… %d שורות קודמות מוסתרות"; +"web_sim_call_arguments_fmt" = "הקריאה אינה תואמת את הכותרת של %@. בדוק את הערכים בסוגריים."; +"web_sim_missing_return_fmt" = "%@ הסתיים בלי להחזיר ערך עם return."; +"web_sim_file_not_found_fmt" = "אין קובץ בשם %@."; +"web_sim_end_of_file_fmt" = "בקובץ %@ אין עוד שורות."; +"web_sim_null_value_fmt" = "%@ הוא null."; +"web_sim_written_file_fmt" = "%@ (נשמר)"; +"web_site_home" = "דף הבית"; +"web_site_imprint" = "פרטי המפרסם"; +"web_site_privacy" = "פרטיות"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "תכנות"; +"web_live_hide" = "הסתרת תכנות"; +"web_scale_canvas" = "גודל טקסט: תרשים"; +"web_scale_code" = "גודל טקסט: תכנות"; +"web_live_indent" = "הזחה"; +"web_live_indent_title" = "הזחת הקוד: ארבעה רווחים לכל רמה (השורות המסומנות, אחרת הכול)"; +"web_live_show" = "הצגת תכנות"; +"web_live_resize" = "שינוי רוחב אזור הקוד (לחיצה כפולה: איפוס)"; +"web_live_hint" = "הקוד גדל יחד עם התרשים. אפור = ממלא מקום: כתבו במפקח והטקסט יופיע כאן. לחצו על שורה כדי לבחור את הרכיב."; +"web_live_ph_selector" = "משתנה"; +"web_live_ph_code" = "הקוד שלך"; +"web_live_ph_end" = "סוף"; +"web_live_language" = "שפת תכנות"; +"web_live_java_class" = "כמחלקה"; +"web_live_java_class_hint" = "שם המחלקה = כותרת התרשים"; +"web_live_java_main" = "עם מתודת main"; +"web_settings_display" = "תצוגה"; +"web_live_swing" = "Java אמיתית (עם Swing)"; +"web_live_swing_hint" = "ג׳אווה אמיתית עם חלונות (CheerpJ). מורידה פעם אחת כ-40 MB בהרצה הראשונה."; +"web_live_swing_windows" = "חלונות ג׳אווה"; +"web_live_swing_hide" = "סגירת חלונות ג׳אווה"; +"web_live_swing_loading" = "טוען ג׳אווה (בפעם הראשונה כ-40 MB) …"; +"web_live_swing_compiling" = "מהדר …"; +"web_live_swing_running" = "התוכנית רצה."; +"web_live_swing_compile_failed" = "שגיאת הידור, ראה למעלה."; +"web_live_swing_failed" = "לא ניתן לטעון את ג׳אווה. בדוק את החיבור לאינטרנט."; +"web_live_hint_edit" = "הקלד כאן קוד Java והתרשים נבנה בעצמו. או עבוד בתרשים והקוד יגדל איתו. אפור = ממלא מקום, פשוט כתוב מעליו."; +"web_live_edit_label" = "קוד Java"; +"web_parse_line_fmt" = "שורה %d: %@"; +"web_parse_missing" = "עדיין חסר כאן: %@"; +"web_parse_extra" = "מיותר: %@"; +"web_parse_unclosed_string" = "חסר כאן ה־%@ הסוגר."; +"web_parse_else_without_if" = "ל־“else” הזה אין “if”."; +"web_parse_case_outside_switch" = "“case” ו־“default” שייכים בתוך “switch”."; +"web_parse_missing_do_while" = "אחרי “do { … }” עדיין חסר “while (תנאי);”."; +"web_parse_more_methods" = "כרגע נחשבת כאן רק מתודה אחת. צור תוכניות משנה נוספות בכרטיסיות נפרדות."; +"web_parse_missing_import" = "חסר בראש הקוד %@ בלי השורה הזו Java לא מכירה את Scanner."; +"web_parse_missing_scanner" = "חסר קודם %@ בלי השורה הזו אין Scanner."; +"web_parse_unknown_type" = "Java לא מכירה את סוג הנתונים הזה. האם התכוונת ל-%@?"; +"web_editor_title" = "תרשים"; +"web_editor_show" = "הצגת התרשים"; +"web_editor_hide" = "הסתרת התרשים"; +"web_keywords_title" = "מילות מפתח של קוד"; +"web_keywords_hint" = "if, while, for במקום שמות הרכיבים"; +"web_palette_compact" = "רכיבים תמיד בתצוגה מצומצמת"; +"web_palette_compact_hint" = "סמל עם שם קטן מתחתיו, אחרת רק כשהעמודה צרה"; +"web_about_version_fmt" = "גרסה %@"; +"web_about_software" = "תוכנה בשימוש"; +"web_about_software_text" = "עורך הקוד משתמש ב-CodeMirror וב-Lezer (רישיון MIT). עם תמיכה ב-Swing, VisuStruct טוען את CheerpJ של Leaning Technologies (רישיון Community) ואת javac מ-OpenJDK."; +"web_about_licenses" = "נוסחי הרישיונות"; +"web_live_run" = "הרצה"; +"web_live_run_title" = "הרצת התוכנית: הפלט והקלט מופיעים למטה"; +"web_live_run_finished" = "התוכנית הסתיימה."; +"web_live_run_stopped" = "נעצר."; +"web_console" = "מסוף"; +"web_console_hide" = "הסתרת המסוף"; +"web_console_resize" = "שינוי גובה המסוף"; +"web_diagram_tools" = "כלי התרשים"; +"web_files_title" = "קבצים"; +"web_files_show" = "הצגת קבצים"; +"web_files_hide" = "הסתרת קבצים"; +"web_files_resize" = "שינוי רוחב הקבצים"; +"web_files_new_folder" = "תיקייה חדשה"; +"web_files_switch" = "בחירת תיקייה אחרת"; +"web_files_delete" = "מחיקה"; +"web_files_in_browser" = "באחסון של דפדפן זה"; +"web_files_save_hint_fmt" = "השמירה מכניסה את התוכנית אל %@."; +"web_files_empty" = "עדיין לא נשמר דבר. בשמירה VisuStruct יוצר כאן תיקייה עם התאריך של היום."; +"web_files_reconnect_hint" = "אחרי טעינה מחדש הדפדפן שואל שוב אם VisuStruct רשאי להשתמש בתיקייה."; +"web_files_reconnect_fmt" = "פתיחת התיקייה „%@“"; +"web_files_connect_hint" = "בחרו תיקייה כסביבת עבודה. VisuStruct יוצר בה תיקייה לכל יום ושומר את התרשים ואת הקוד."; +"web_files_connect" = "בחירת תיקייה"; +"web_files_browser_hint" = "דפדפן זה אינו יכול לפתוח תיקיות במכשיר (למשל ב-iPad). הקבצים נשארים באחסון של הדפדפן."; +"web_files_browser" = "שמירה בדפדפן"; +"web_files_delete_confirm_fmt" = "למחוק את „%@“?"; +"web_files_folder_prompt" = "שם התיקייה החדשה:"; +"web_files_default_name" = "תוכנית"; +"web_files_saved_fmt" = "נשמר: %@"; +"web_files_create" = "יצירה"; +"web_learn_ludwig_tip" = "הטיפ של לודוויג"; +"web_game_title" = "משחק: אמת או שקר?"; +"web_game_intro" = "לודוויג מראה ערכים ותנאי. האם התנאי אמת (true) או שקר (false)? עשרה סבבים, כל פעם קשה יותר."; +"web_game_start" = "התחלת המשחק"; +"web_game_round_fmt" = "סבב %@ מתוך %@"; +"web_game_score_fmt" = "נקודות: %@"; +"web_game_true" = "אמת (true)"; +"web_game_false" = "שקר (false)"; +"web_game_right" = "נכון!"; +"web_game_wrong" = "לא בדיוק. כך מחשבים:"; +"web_game_next" = "הבא"; +"web_game_finish" = "תוצאה"; +"web_game_done_fmt" = "%@ מתוך %@ נכונות."; +"web_game_perfect" = "הכול נכון – לודוויג מתרשם מאוד!"; +"web_game_good" = "מצוין! עברו שוב על הטעויות ונסו שוב."; +"web_game_practice" = "תרגול עושה מושלם. קראו שוב את טבלת האמת ושחקו עוד סבב."; +"web_game_again" = "לשחק שוב"; +"web_game_wrong_short" = "לצערי לא נכון."; +"web_game_practice_short" = "תרגול מביא לשלמות. קרא שוב את ההסברים ושחק סיבוב נוסף."; +"web_game_clicks" = "לחיצות:"; +"web_game_nobody" = "אף אחד לא מאזין – שום דבר לא קורה."; +"web_game_event_fmt" = "לחיצה על „%@”: המאזין שומע ומריץ את הקוד שלו."; +"web_game_try" = "עכשיו נסה בעצמך את הכפתורים בחלון."; +"web_game_time_fmt" = "נותרו %@ שנ׳"; +"web_game_defused" = "✂️ נוטרלה! מצאת את הטעות."; +"web_game_boom_time" = "💥 בום! הזמן נגמר."; +"web_game_boom_wrong" = "💥 בום! זו הייתה השורה הלא נכונה."; +"web_game_fix" = "השורה הנכונה:"; +"web_game_order_hint" = "הקש על השלבים בסדר הנכון."; +"web_debug_step" = "צעד"; +"web_debug_step_title" = "צעד: להריץ הוראה אחת ולעצור שוב"; +"web_debug_continue" = "להמשיך עד נקודת העצירה הבאה"; +"web_debug_paused_fmt" = "נעצר לפני שורה %d."; +"web_debug_gutter_title" = "לחיצה על מספר שורה מוסיפה או מסירה נקודת עצירה"; +"web_swap_to_code" = "תכנות גדול"; +"web_swap_to_editor" = "תרשים גדול"; +"web_editor_resize" = "שינוי רוחב התרשים"; +"web_palette_resize" = "שינוי רוחב הרכיבים"; +"web_palette_hide" = "הסתרת הרכיבים"; +"web_palette_show" = "הצגת הרכיבים"; +"web_code_scopes" = "בלוקי קוד צבעוניים"; +"web_code_scopes_hint" = "מחלקה, מתודה, לולאה, הסתעפות בתיבות משלהן"; +"web_pseudocode" = "פסאודו-קוד"; +`;export{e as default}; diff --git a/website/app/assets/ike-nassi-D2w47gvX.jpg b/website/app/assets/ike-nassi-D2w47gvX.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a0a78f3730fd90e8dd4f0bfab7c5bd2563c81dcc GIT binary patch literal 19505 zcmbTdWmH^E)GpX~AV`oVxD%uU!QBZS+%>p0F2MtVV2!)GOE2>N&f%)~$MC!r>LPee&fKtRqwPDw*cPft%s#`KYq4n$2y zPxs#>2(LrY-=O27qvO&M5fIV+e=h$z0l04vVi7(fAg75FLZ?JrOYp{Raj{CT1>f9$r3v0m;u&(lWAg^6DCzTG~3g zdS>PpmR8m_wytjO-#k3Myn}uQhlGZOL*f$>lafRWGjYbJ;rQ`}Kq4-$x(l6_Q|%mR>N1Hz zNXNB7fAJr*|BdYb9k9UvU&#J1VE;F+B>*N8!YlERZ~>x#gL*}fOS0x3Fv-zjG9Ehd z4fewwIgO`zTgz^$pKMinuCj~0M*m~%4yqF2kqk!C65Om4gT`#bP#b;AAF)&`p`4=R!8;>V`;E2|NJHW0yg{L3@~sT~J@q zNg(~b%5Ax3pIlo7RS!{ae>o^)(HMx2oTa7Hoz%CVFgy4wr8mEe_eXB3!sg;6$@%Y; zzn-F@Y@4^TNl{q}omc~S?SQd+uC7e1 zP*W({uM?e_g~Pn&0!Le}t3V(@OuMF*d-Lx^nMP0QUp_JNvu%w&rNjw4R1{ft0Po6Fh2hAR{duK>l*@E<;oR|{_Nd8E*t~$85HJy=0HQ9qt zMWlXc{6e(5%JUXl){WuZ-f@c7P8YHY;Z66I|3S>*RmF1=8rl_Cq#~o%rVU+NT{IAz z#~sI)>O$rUHAtD4 zGhnJFE@7M^Nlh=UbC)|x^K50vg%*zQ)Ftu{Am3vuevsbk!D%3`yv~djQU{??+MDEk zpP(n}n$=OS5v~_#Q%d*5f#Fl1=*$5M%Z@A7MM!W!%VjNcu1jy-(jC&l^j9;fr|@0gZ5b zh6gUkoc#j`l-gOTOS@JOV=j$j~N_!2!Nr5!VG zLkSgBGro%&2O5o`*~m=Hq(|BVmr+M?Omai0-Uzvm`XLo~LYC&A1O(k=A_hNaFd$Rp zY=ZX|h7rb#+_Uj6ICbGP=>}dhxV4vnYucvD;yT{^n_7`#eI1nY27EJ^3y$pu_wR@X z5z60$0`8&9_W46x8Mh&#$2pGPR|>zwT55E$c*fSH5CaS0y{Bl6!k{#8f0Bk^B&+lN zJXcoqLh+qQ@N@^uy}s&?FY~BF5-!6uWHG%M<{dQC?nfcuw=>pM4>`N=i+#@ND!qrh z6UKUYO?ZZ#>{W~6k%HZQ!S`P_SRAn3eH4v9@4dgZ9lTHmHC8g z5A@aW@p-0uSf}fq)30*So*O!dZd7edM*fqGgCpyk@&jD|;~T+RnY}M)}f`{j-`2~j+3@v=+i{%9NTlesibE_HcS4h>l`vxW4TbN8M4 z`qjBIpKu1VV7fb@c;O>x%io->zZ*64MU<=f5;(i!rPozKSQc30w|!eeJ&3f{3mE)^ z{A3Brxy?$h+H+8cU3U*qwzex$PEWn7-j85PUk=p0`fqB_0@F0D$^5KUE}V7oZD!|{ zhTtw6uyekCB{27cV7sEo?$F_ymb5R98Z&B$U4S_n zQoU^gJN-`_P8&WTwKKsmo!HYONlAE(7iE;;%fN5XNC@r>Hatqj!J9JR#-4(3C3d-w zIgbd*hT+K2Et{$?jHT3i?VHna!LO6d>neEe zjXM---@%Yw@B%uwbf@! zhR7e&{{U55r|w8)U#tY@@11lmAc|35Im%LYHT|P%9n-2^-P3m58jJ;=&qrFQ3i0ey zA+7~!B+`3Nbq{qsThXBMCz66ljM`gwPq=o`hmf@G7mlfy!90TjR1xdn*QWCcwlX}o z{{Y%A?ymv?9~$S&;L-{3U66VC3|wz1H(gu)dmx&n!NXbBEWgAi>EB}82g?BUv0IF7 zTt;rc7?zL4l(Y{!fS%gkDMP`1gz$GC!^#U1GI1`r<)X6$53Ouo$P!Z*N-3F$Z^}-E z1nr&Kl68p$&6#u1IG{4sZ) zw&scZlw3h^&enUC{P;s-`+O;D9Ld-<=Zl}uytY@Kf!KG65|4A_!N=WdRy){4!<|z> zOr;>G!4mTU0xxn>*xI{J@s zk_2K-RkWuJFNmV>GTSA^k=v14+xf|%m0i>~1^aAZKb2S5^o+=j zs_SrS#p=TrNZC#VN4)c?lv<2@OVWhDy)7x4NI$qlDTtt&1uuNL0 z`AR4lpDb2DE4)VU>vx1UJDz{7(wX9B-E${^T8{2T z(@2h2x^UZ_Qr_6>wzlLj$HwM4gLXbRuEt+}kCmk!Eh#Oxk^hS`_1+cm;I3i0w$4YJ z-NRTVTi99R8`Ggzas9?}^SkOgvO7GhM{QgW%w!LG3uyz2n`;(m;5d4;__JuX5;)-^ zC2-5#2A6+(t~y8Ba>G4uD}E%E3U%4x0E?cQH>yczN`hgu-ZFRo12Ff`SFu>uIqx9` zf7?Tg7scp4{}YkEr2Jtg)hrOb&-?AFzHQ6*o23r5{lX^)AA!@qcfivW|zZ4CyB z{1!?Q9hQ#5uhxKVZ9Y@wBDa1G6K+d)BLWRgx|*wn^!*P_(Y#B@?x7oe>l*X{qqcwg z-!uv8M{2pOG}%T!p1!R>cjAQX3kjFW%ZHAE@@DH8S+{gm5G#>D*z2BUZB#;)?L4P|IWTGkXF`uR${s3&d;7vlMI!fL!;fGy-df8{)ffqEUOc+qX}0(G7=E3&X1kN0f<0r6ImdrbnpyND-@yGCW^O@M{dK~!QHXt`%*aZaX@YU_ z&hJurLuagIk)oZ9K}*3RHzHAT8!H!(mqIz5a0AsmuT%TnI)i#GMSH`&v~a*C0l^62 zgRgbN=o8;H4pj&GXo+0c3nct>lR-fXrfMYpOg)pC8Lj*epqC{Y%CZv`ce1&JCQa^- zaRQ@`L0(5a(bcwo_w;J`jCmL;g~@a5dwr`uzf(#XwT8}qpba7CJTuTd3#tcc8IR=C z@zLX#-Ef~Y#=aj8nyW=N<Xl=4oXMQoz%L;z4 zFY1kC{G^AjkW35;5I&Mro^#N=wciqo1!HWk$r=DrV#@YG3eu5jAx@*wtA7vjIKPui zTf&b^X#;0A{KGF*pWDdCeEu?>OVST>$OiIFJM=W+?KStCe2JfuRq7!oRaTvdo>>M) zG{i^bb|M9O;|5A8u%?j>VULA!i=^1$;VnD8kGFjW9sPmXN}DJY(7;Y2;#M#Qe@~AL zOeWFe{Jw;3Y=!4{G0PDl34=+jO*x2$VHa?w;Bn;p@QwT9e*kas)j*l4w$n9NYI~h;XoHc8SHUexq0u@n%bz{2`p%Z04pa^zqU_B7nz90?29M*53`bE>+6l%q^`^I84embk}Y zap+<=P#R7CYHr3o2X%!Ty2ROwjbuh#RZNqpKp}@&=^SIbE<%5A`bVYS12<~fLoIS` zq*+Q~=KK%tVJsN;p8;2WM2!V;irQG}I>i8{}y_4PkO6ao& ziAL$B7svOBh#*Om)x?^j@JeHv!xsrel;xe!D5DgvfRg!-$F(k69|M>4r)6%*bXGOPTEK zZ}*@gt28V5rcOPLwro51Fp(Q^h#i$yLW$0%xmDEyO_stZe@nHp`HC48Q<(^Q|WrHUQ9HK%soUd?-^m!%L zc666>Ha@_P)ac=n-C{dB7q1>FpX1L<_LSY36CoC8RhXNg!f12S{2su~q^lyHQOmU{ z(A5B~`>(W4ar5*$Gzh&MZjFd0KiXB5coVI#pC_h&l8Ks7jrADzeoxCcZN9x6y`i=` zIRmWl)-$~KP`lN>_JNbkIrCH6gd~xZ=z7$!f!1k)Tm%oYE2Zh{W4XX~=QzkphXL0&&;yjpYN$G)A22q-y$O@Fd~2J(`$y%i(xSFUGEm?hd_jK)dO&7auvEhW>}55 z;&;-K{bkpZTG(G-I7C3k9TOy}7SflN5r?CByD{S+W3bi~28gL}N(Jute47zF*u21m`9C`u70VvF|~kcZOy;V@%P4iL*BlbrfeZ<&?+f_&>-H=qAh ze!#h)qyQtxW{x#%n^%yR-SvnN$(R&Uu=2Bu!Ot`0V}L-b6unsLBKqKGiFO8C&rkD- z_aHR{6?C>EIH)5<>+<6;lVBLkMq*sj+qGja+OwtScqxc)jA;F0t@*M*t&nkt^HA)Vs`rNvN}n_?u23q8AcV&FIPPQFI6_|@9Ikp88UU54?(oT!90Vqj}_gI zHd8|EC5ufxmExJ+oG$)ZhH`2dGYakcOvMYhh`Gv+F&S`9@d zVilR6NBo*A)%hAiczjbFTOjC`A_3Tn_V-a13hE!<7!CnD`Nn;zPdiAai)E1Ka3hf~vB0wwE^Ls67FWJ?{M8DM%p zxM9s+ZPG-b+4{iqvY|*Nj z-@l-=#=x6ea~gHlhFNO+xzOti!wEJ&kE;%DYaw@#*L;wvo2}Z7jmdB;{_?n2uk$PD zn8aeXFumY}t>(dz$O%c>pIZsB_%m=5#JSQ`=cmNGeb%f+o5UkyBlJlU-wl24nB2UZA97^Owj!$W#Wr;aT%Qo=alL@ zw(c4f%3iIY&vC64I5xODv^}<_lcLZ?zNRf=v#c-kli-K|eU4;va_-~tBNROH2;51n z<;DJ4rn-yW$q#VcjpgwD9zTE(}XJuEG%8Ni}%vioL=TKy_ z@3arvAd8aaMcbGvmf z{LFMxM0fnK&C%mZK|gpTVk z);(ygj)q3aYDM%cncv>&KEOoAJU*(H?e`b!th?X9$~PyczhDylgipvQCG{R8*nCI& zrO3Q%eR9fRe|##&Nm=Dzy20 zVmkHw`u0Mg+*zC!?IT^;vfk(&W`CY$vV-J5Y1{~~m`Uir6`u1ZUp_?+pq8Ea2lylN zsGZ@Nq25v#B70gVry?t+WlY41?cC?BcORl(DzDgXD59mszzjyxP3MQCV2JTQPL3o@ zEU`NfX76S6yOu31Dmd9$5JpM@`ccpi#jar-{{X&$nqj|8(Fch8+kK=9%x*JG-<_(l z2OStVq;34HNj{Y${r(S-Bu?q(Q64!xvtFUtQ0b*EBQ&pdyZ^MLi-;(A^$###RpGYG zX$A&^n{t>5B*!=;HrwIOwCE8Ecx2qo^-lkVE#_&G}mA6 z!|9lOR+M$&+q)Q}xw0#OlsBEqfs{Vxw%0=?^mXyE7yc0 z^+7k5e5|Kplg<_Agp>51`Dbmb!f<312L?5u%6VQ)8O&C;-VtvFot5HKEh~aa(u%T* zAPQw#F^GK0_HF!Fhy>f4m|T&x;(>9tv8#kJK)JVN`kb?ur9_uELO|{##$?PJrSE1l zkrT8D^C#xGY$^y;H~#=f+DTyB+bg!Q)7cZf3gUGa34r(>If_?kc-{WkuHlyF0J3p< zQ@ix+8G;R=R63Y@6Ahmv<3LP7lB zn~<(ce>N+CGbB4Ptd;@;BF(s6RqMfmWi+&T<&n;YzWt!+LPZ3Asuy?0M&{OFe)+f< zy_8@hW#T?olglKzts*{^PB(%bIP-Kf3#DWDk9}KyT5J~(JF5=cV8x_z8#b5|udmLN zJ2%&~Ov3is3M59H&7f&dq0&R^LfOm4-8(=*tR=OLJJsrlAGtsM1QacW>G93!1aJ@Q zyDkma{RrK}(pl2wij>^~U|0HJOrG;Zr)##Qq%iQNcyjO>7S!OF{8`I#&s|;}ws+fd z)f?RXIgaVv=epEUwkd0stjHt`ktz~2Y=`nnd~S9I09C4PQ5Uhyv&E0?vnW~jb}?R8&y?!oo4^T1`RjUmZvEOSp= zL-MZEPDg$2U(X}&(;2NoL3%E~jQ`io8s+YvV37ktcRM-HO_zgw;JO+JsSbN)_4mEF6OGEXH!O(_69v>_LJ3E@E%3?% z>uywBCi2G#I`_CEL>rOOcg$#O362NK9UYgnZt7`omYT_MytnH9+Ue>sOY_S1$M1<6 z;OHfjTd*?7qNR{UrBLyB-iRb3RJpK|BDC+AOb#x6FLbN)b6JB=O>>SETb}yl*v>}} zDAQC_tDxSR9h?}9M^t{FB3F3`FpvB-Kq-$Q^A^=n5v{3oxlsL1TGNVOsA!h{Ebh$p6X~!ZovwqU;`VW~tZBsC zoU0>E_bb*SE1^5q$#O(PRrn0RZTzb8W@c(tf+jgGLrXfx zNpnCZc@K;y5}{u&Fur=*h%TP^j6}f{PNOvExLK(tkbdNAQt~(Ixkj6rv+f(E((K?x zPCsz+eO}^RKGkaCpuvl~>md4jx@4p>a@%y{X8uEVLyPDnd@)JCO+I0{yl^tu`U-a4 zCnb=w?qpQbF!102(*MoE1r3UuAd#s2E6aed?`uFT0`OyUuBd!HYTUQMW|kt*QA6oA zB~pC-H=esutUX>qbUq(zHt0`)+VtWczo7V|X@&(p!xB=-AF6mT4|-}%OD6Ws)bbn4 z8q>n}{i6mY)jXB1E=%2wq`y>Kwn^q{+t@!3sqxF5t*8x}VU7^}dbR}%vl1rSCpeLd z0ilAy@+o?$>1BA$(q=)k8kra+_5{ud!9-|9Zc9l~Nlgzw#=N*ACwp2)MBUV~BTGkz zKD0QbzgevfCIXHf;fL?ymaS8G9cejoZ#UL1wu=h`xPPV~itknrvk#1#-n|jTvwaV8 zw2ljk%6+NtIuu)3K@F9C3Xu)9gLkyUE42d!^$G|yZL8GAqQ9w9Qzq0i5 z#}$BYJePak#^_yRf?UYjgF@*;hDjIkHTQf=^+rqfKLF>US3@36TW3ydplAP{&QebJ z>2<7BN3fS0XY55lPmBtGmGT8;57UMuPlD4t71Q6|AZ(fHeQ;V`2xHb(j-66rh!!8! z#av#2^&ofN_T3uwO#O*AtwQsAtVp;SEx^wkV}AOCyU5+fK8@&Nq@oU|$U8Akza@ZP zGKuyKqifbQ-&=)v43Bc7&-Bh8iNJJ`MTe>V{S!!2lR(2^~x_il_d01YVr zICeNRn#@T1hTk~iN_KS&tmiIb(^A~ddK>ZRK74YO_|HSmz^T;!sFwz%D>t+LM)r7OF}r5ncHysp~in308ToAg73hKtd%IUkl?VY z;dy(f^yGlRi+=!*93y5mE~}MC%V4aZVsf;GqnT+INc^`*0U!nIKE{G}uvu7)HUGM0 z67AcYl1<1*B#aQdM@>WNZqg?vsCksGp)BC>mfOjRnfTPWUhxiJ2Jf-eSVN9wQLc60 z)1d%!Nq8l8D1=9PX~_TQKR_@Kx$|+fhb7PY)l@5Gc)GbjaQYF6E8Q7|*4K~Q0@1Gy z--~XQNR39k5Rja$GjcwIg+A|0rF0L))kRol{A=9f^(~YXw8+v!=H)3A@1y;;BBGr_ zv|*vs!9FF;L_M7L?yKsFCd;!|$!dPpvTq7yk3f>>hBooS!LHU$+^X%J^d8o43^oO; zde`)jU)8;89JI%-?H|c{JT+ThYgg|2 zgEh7Np#Ulw=4pMBQStQaSopWV5Yw2!FU~S8u7Xj{(DU&gKW(^)gM(#?!lZZG!Ar;1 z-_)xK@8)M=@H9&$*KZu1;*%bR{bs1i zH`if_x`;qvaxJ$qw#`z`xU&srjsLhrF5k01ym1jhC~{g4@cp1-2QR5XXixpzx_2r#{WE;{k+&>nb0x{g5O;%JfKtxNerpdiRGpvYW8X#BHe) zPq4$@h)24c+Lx~UD6cJBNUeQ-*GDQZc862nYQsN}@9%91IsGaW|F}BvTQC1L^}mq3 zDJM*)@1~-(qHYa>Gx3^PSe5g=T@^g8sRq~!|Kcm-S`SevBG{Y3IJ&V%+;uY{Zyw_t z1V&hFfbVyZJ3FiB)OQt;!hLo1$Ou<$oibEK{AUM@d?dmz0p69OsTJ zGYUf;B!IczPf1n>xtmyqY0@Zp@3!P%9eBIuqt%B;3)Jj3SC_1Q#hZjX^+$ti&reh6 znDeEW#rC+i2j$We_FE(d;zh zXhu){1Dp`z0eU|%`veL=Hte}XS!bU`%c=?0-t$Ze`~&pYZf}G(mR8}ayNS9r?EeEu z&K2mrJUvv+Y@OV2r6C}@fIexQ?}nDKC;K?X^J<5kFq|K#9ksZ%VCT^%EqS?=Tzpz_ zUQC%)RM%#i{Xvl*Y&16RIvMq0cCNIm?L0aSf0JpizXRmoLxIqgVR!q@g~wZ&cOd8w z!=twL`Zz|Huf9g>=VYQ~bJgaJ6?cXi9Hre>uP*mtzJ<)adX3^0hcWM@MEYT1ndpya z(xQXIMh*iRKkv*;%#Sh)6u;FCMasT6TmaEN`e>)KwmRFCNxE7`Bl4{%lcoqkPAEBK zr$;=;hd>oL;St4KK+Bjax1VQZBB)|m;;rAi~5s?C60H_H{~r26_^-$ay+G5 zGYR`>u7)z9TzhrZx(qSH*fp0jSOA5iOEI z!=!DBoRxE@f5EuS)d;YZ`T%ObhA#C{M@o(>0QR3rfhoL0>$ytJfoXR0?C+B>wXB zsI6&Z^6uv^ql(O&9ob9qHW_3~$;eE%uddq0*=*Gn#;A8^2a5R)y z>Y5W$>A~PNtcY|>jDW|*M+>}^MwbBQ@gi0J&0jbvx6)TT9sdCtw*5B1pJYdb>fYUf zrFbb95uJ$qXlkQT6$w>5x${G9{VL;{E+2*m#wUB}n0QuWHUptAZ55`;m>SW~U04@qOX{mEJ)KkgM=acgx~k;Yci%=;;o<*y$cei*9= zG6A-+e`k4q>Nd17@vm)=+j^VheYfnTr$g&PVEzqe168Ct_WopxCNJ4p1WR-dCQz{k zu5Pi)J==i7|OG#8>#SZc0`TzTM41kxDVKCC!pV>I>u`gOd>+)wcHTe9Axv$dan(pGodOE)R@hGkAdiHXp2o_5C`hB4 zj&wZqpwM!%jf`Ky;L$#l16RX#Wp%XZG9{sg7Jh$>gZw|;w_m}Mq~ud^6VLr6I}k-> z^+;f_HZ5#&L8GxHF(q2g4tp)IzKwlj;Z$_f%#~yW{qIua>f_TKd+{MRQJg@ykqbv% z7Kfq4CMf)5JAN&4Jf=q*#s{h@ti_pilF*NbIsR_E`AoA$NHd4J?eKDO zL(|TaS63GTUjkXbqjP4|M4BqDl1>tlUD(ci$m&$P&WFqdj8b!{*Z{1!+RKU)Nn}kF z{cXRw%32#s$TFmxIXTGyX{)$;E+Z*!FbmaM4KTMrM+XL9A%9A>c$ng;v!J$IvAH?de>d{`9ZF>v9ZT^yvzk#fYm zBfo1db=Qm`_Y*N#Bh`PM=bCAo>R*H}4;TPeZxhDnYCrl8JK66NQ-v6;(H*=iH}+KJ})HkBWo~1ypw&nP$(n zveye%EwSY)Cs2)on7?BpW&?O97d$p@##4xE+6dJJ}O|ga~0g6GI{2FKB1Oz(S3l z38#3O=Q2((@-F z>wAsdnHwWfHseXzUNE>jAMNy|Z}ZN(n(Sczuouk354s)w*xyd zT6HxeuT>ci_O6$Duu8>n1B#LV;|m(Wb&XFHh#*@_?XGwqCr)Ne`)naRbUR;A<>RYShk zeH9ToHlvLCk~+zYX!bHux*h3Y7Go-Gs~@~v-*4*@(Blqp5uu&POW)zvh^(J^Gu;1N zr~cRP2!nAoYdh(E>3Vi?>r<&XvRTknTg9dk)OCYgKtIAXZ`-Nb+@+UW$PmJq_ucwKSX zSjtVhe*h&#_qb=~j$bvZe{1P3Kd0^h09*M_?r>X*kn&~H7FY%F77!EYu#ofmAcq@y;K`YeH>?>u7u^kaoaTyXr}j`r zRTEuz#ooqjoMZ*hRmp%6zB1DYs@aq}l+g=lLMw7#*{)A}q+zl_VUcIYV9ZZNAuxp) z6R3(8zW!?UR{}AyAsOLc4EM75Y-Vwag($D;mn9qHT;!Y+Js&M|lit@I`HQ%Q^#DdQ zQ7B3lv`0ifz2>YmO*{S(wVA!)Kkf0y>n39UaV&OVl&uwCdMFZ>#=^4l$k0WSxKt9# zVwK~tF7!(bF0qdBr!oe^=Fj4H%9?sw%<2%wvc1Q-b}#7aD#0t^sa}^BfMFhzqcUV` zeoaCsqNt!MK2T;I-PtQ_V}nIr7FOlwMAc|@HlaZxWUim4tc&fc;l5nOVSS=0&@pMN~g9-}f{_vAEX^cmt)8|eeEIjht)ls@ls zCY$<%LSx+P=Xccq!tALwEq?JiHk_OH$t-OnT;f3?VF3BMpL?*it6;g6es#6}GP5rn zi8Ep4WF6sQxA|7k&U+rh)vlnzSYYmSMjYiOvdA6E8^8j+avCa?rOwRBxZs1mSGf2S zZnp<{b4Kl%KWuu^#4w)_4_45^ z&i%T@KT+bXqB6HppxW1MF1*r+43!Wbb?eTTAL({(Z4vz(Dz7TbWIHC74`B{q%!mBP za{vNW2;=KUzyhds$ifOCQ#w ztJo#qZiEfPC4%AX1Q=f?Tar4NtaCHf5o$yx&ol?DxY?2Tg(jL# zbcfYKrCX($X8P=!2_EaKX-FWu?v25PX5Eo99XG?C(>jD&FS4TSdqAMoFlmaC&{z+b zmH@1ou0Qo8Z`RAwUcVu2z`}m(VSDSi2gx1tt;QNWGiZxI1nej)hSaR=oPf{v_K7T{SK}fwo9x zzHr%CgUrDgXPV0{gJd?oPf&!{MN#2Q15bh$nI!vdkpp^ZWD9$pj(RwX@=~tQMzFko z?hO?8Bhd+Rc3|5?t!EYdEw(GNeS13()T3o}uwe>Tq&@_H4b16pWT(}9VhBX^;m(db-;db_jDV#@_v)#X~S zTB*$S8#1@b>`+riTLF(OVt7x|A%7L$tk8!kBf%f@2}X@{MAELqTakVs3O`QQpvKa2 zwO>#_ocy^=rV1rkqSwa%k*xtL)^J9G0I^qv)-}rKR`@D?RlgwB(|@v+2N>0TJx%pVXuR#@6AAE6-bAf~X zS$-k0Vp;Du{q@ByFksR*9H2@tm3ye@wulga#;30eD~Mwo7+ z$je`Dif9{M*{drrV_00JNv^7})Pz*eWT)Xldw!A|q#PBt^T1sy1Jvu95@dYOhk)|M z0_D5a>_+m;9gVvx=L@Wsub|F*5KWS3lyBLlRns)L zLI%Ib$A(J+yC;&-?&G79Pi{9pSaOckn3MsoKh~hhk=JlgzgrHeFyz5_j|?OI>w6;u z{@Ag>1tPwnHw>Msi*DQ zE)Q4>Y@<9vj5DM>mEBU5LFSiF<-bV$yZiTyANC*wLXIeT$x^<3dR&ON2(!kv|MilJNGpy zBwas8ha@J=tLKL88iN!)RdsKzDGaxYIki^IL z;yoYpY;fMKP}yH8E$ZPxq)q#D$o^dYpzV{l--?`=LoRbUFdfFtP#-nw;cUCXyAvfBH zF#5XGD;)0n94zB{ez~?{Z>Tc-DZj6OFMTJY0^E+ZzHU0Y36%E8A2=(Q)C}Dm0?MHQUpxD~tBGja9`p5{=e$TR46Tct1WtkixygK+%5Gmc}0yDN@ z*=00Z#4O$AfOAbmpHFzOtf;ziI^i@VzBW;Bp>EncU4Sy|v^aKoFfk6k^U!4XtqUr+ zs)i*5chJm>>IBh5mWqT{a;{Vd74H>wjQDtLAGn| zz$%6kqmbxKt#<52g}K>0ye{Tp+%2lvX7^uzFRoz>-RBC$D{DG~Lu9g{)yMut4gyJZ zyX|DcUP|e9+huZ0ToEaH9et}go!VHhmutZ-iQk+DGsG!!{j6*}k> zPa^#}wcFkn6Tg|={kmHGnJT8u?|V{~eD>V;QQuJlzf7-}t>W{>pLV{S=y77nm*P)@ zsV<_66oK`h9Fw`I`OP{J^C@jI_lQsnnXtmHEV>dJ>ph^f!&uld?Q4|~UPGF0{fvZA zs#dFdXUQ+E7Zj!Lq}S$Ql&jMI!G6lku<}!#vqd#6QeN{Iy}EqvFCUl-fQ{n(+*gcJ z4!?3WRRCL%vAKr!%1QjJ0ht56dAzW$&ev;HvuPAE&lL)IbwamKayHZ|`1}-EptKpg z-RM12<^aHvQ4UIt!E%M4`129!l}r?jr~$1QjFq8`G#|p zK!rc|)v3=#X2y~}2YoBEE}Syfy2QvvCs;Q(D&Q7jLPso#^&pPj!emCPN8aXtRNrlZ zun%Jtu{`Fqw$!Fatdy>}B{L*M?zKy^5Pd6+IvLnOA~E@20o@8B_0;c^??aJLq>)Z7 zjJUNkOsS8Qa%xF$Ak)W`qjb2&(b|NpyP%|8pj!h{x{t=~Z%;_Y$ zypynBgRN=A(L^yA*gdKHvOe+r>Qx)N&D?HpWLEzGgm+J60pJbp zNv8h*!a1ZbTV($LzKvTXQ+KHBD_%(UBJa6P^gSyCEG$3VV^tf%noG9lwqifqkea)7 zsYh(NEHha5I<(XDV;X*@u&M0U=++8M(P?!3B0ZMSM6Hg9pjV!F=Jx7flR+Vlc9}5g z!2x;y01D}MdAY$M2i|XAYOxoF;npu95~2G%KQnuuO5nsP)?UsU9Ww3exd1aVzFx7^7}+Z@B_7l-B(5$#I~U)m5H?^@~HgHSwb{b}-BVRJXR zlwD+8vf!G?*Y4u8)25Y(0Ti0s)S_E^c_q#;GhR>e4_}n&ixgQcEA0c<6<4uPS9djh zC8)`JqNJZHxp&Tg-Zf8Gd*{B8MA0g)6l7;L&uW^D_rkp&L%F?*Nn*WOB)E?pq@6z{XH7XJ6x%+>T6n0`)4{HUaE}ys zq|FsV6!0@Z=}m5!^)$Jr0_KWJC;@XuX(*%uGvceruQA4OJ*vjqF;dmWR2DJkEH@u| zkXoSVpnWQ0D5c7Waxn@Z&ILm82RYkT7?awNFC5U&6du>U38n~&AG?8CSRRy~SUst7 zj^=O-#{#WK2@94rVPRG00;}pbvDw?Ry8r;9*42jkA_-;*o_bbBp{*=n#}N$O&tX{l zmb~+l5sD|Tb6M8V-s;R&)*?_IT$};;*DUI{q)np)wPlNqOLG=x+}@_8wY0sz!-$wg z*KyzxTRLBbZLL6->-{2LxIc7#1#L$dl0cwgM;NJ8TikB1Vuqcdv+Oq?EJ|`C?%!JI zB8?(lsG&xB0g6;mqMcn-=|&qEN^V=3o+X^ycz;osI4f--A6=%o4+&~(cc)w2O6BHQ zlMCD&V4u#qPaHna3|}sP)+W!)*B{}{G4%Zs4Mhn%9ortj@;-!Sy!>37u9E1Ex(RzN zdb6;O;$OY7uzhPz-bI=*kV*ox8-{n1w8)Dm&XWN$-SsYUEVi$sN3nq!^4YF3p%$u*aIc5vG}3TzR9 z;|*2(p=EFLODV<&rE%8Y9Xj`m^y>)*_$^1BG4=;PslcwS?SxMElYG*i7e4i^;TZ!wdR>k8g`Vd3Od5*WxRqfDSo8Aa07h||^6ev4 zp4P%RG>s|jEaMnRS_a%Zl6dNC+WcX7milQAj6M`(_pT)`7krz_t{>$9_V@Rwp65k1 z?xWXK)T>p|s%160ILQYTQVI?YRlrTau;!hgN@f9U0n?gzoDjC_c*&%Il;vP*OdqX2ZQCwb}6)jnTSFHZ2J2n4r;&i?@2KXiT_>uxv_ zFclOkj)6u1sdI(J0P{^jEs4FvY=KrS5ROemIUrT2Mg>w@iIa*cGm2W&lbP}RAM8;W z{y9{CI!z7*hr;%O#zO{TKBUrk-0!r32mJKU=~kwQ!=qW+slh0qpFxgm&XP{FrQ~%d zYH>w<7DK0LZ4`&)NnA(Ha+%_xM4MTd;h7*)hGE~>REcZ$*9pqPoN>l$UL;6kR8SQ_ zzyq~h7c#d*Or5seTT2^zWC)7VHoI0IIt25?fiUN%EpD z(e$iME9JVu9Ga8FTFh3<8vk!)HeoMDu(;PLjM3$MkQIq3+eKXe^Xi{?BElD?NZs(9ZyU{nwLtC#ScrmnUH(a zPHEgkz=K6rG8oT2DrA&6;)KG&lTF=9X@uf{6q*YFDl+vHvK(MixXDa{lYLj+fk&C| zQ*g02nM|1PjE`DqaY$c-MaD-QN`nAYn{i03PM`$ECwg@tOwa@48LKLADij+)r-r74 z$-&5=8e*C^aa1Fo@hTgOt7rh@c7HR9(7Ovf<`qBclmb07QC`L+)$McZ{Hn#Y1HEO5UxkSe1Jsk)3gkRn_Jy)bDJ55y;$>H1(C5%llGzlKTb6Wt1k?1`Vu?zl<@xKD z=bz53vW$@1W1dpcMSk-8cKtsh^4Vaaxlx>c+cGw4mty(z= zqB%fm)f{xY^Ii$@y zhr)a#X873^G<5ckzN+uwPN1wWf*P^3SGxyM+8(Za%#z@ zv|)`lgjVZKBBwE8m{z5skdsJQ;+(>wV~Rr*NrO`?nW{|u(6enlXiO|<1Dbd>NiGMi zPLhLFaTDgAwFqp~s@zi$@Nh*VzA7e^168KE_oUd;BEFEU(Mr8RAbn2)v=&2df(^fP z04p)$7e*|S3P`W@!L6wySqN_8u!?-mqej)0%D=pmh2VPA{-f1BC~sPY3+WjGq_@l zr@I}REe|HvGC&HTWSaAhZ^inDi?wFZJTdndiSIcIgFKx2e>!i9b*)Fm`jhx)Kw^<0 z#r5AsjDL4M>!Z<`j)93%!e^VOD~~41$G*>n7W(FndB|Jn0|(i#8& literal 0 HcmV?d00001 diff --git a/website/app/assets/index-Bmqo_CbG.js b/website/app/assets/index-Bmqo_CbG.js new file mode 100644 index 00000000..488b0045 --- /dev/null +++ b/website/app/assets/index-Bmqo_CbG.js @@ -0,0 +1,64473 @@ +var m2=Object.defineProperty;var d2=(i,e,t)=>e in i?m2(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var y=(i,e,t)=>d2(i,typeof e!="symbol"?e+"":e,t);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))n(a);new MutationObserver(a=>{for(const s of a)if(s.type==="childList")for(const r of s.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&n(r)}).observe(document,{childList:!0,subtree:!0});function t(a){const s={};return a.integrity&&(s.integrity=a.integrity),a.referrerPolicy&&(s.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?s.credentials="include":a.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function n(a){if(a.ep)return;a.ep=!0;const s=t(a);fetch(a.href,s)}})();const h2="modulepreload",g2=function(i,e){return new URL(i,e).href},Q0={},K=function(e,t,n){let a=Promise.resolve();if(t&&t.length>0){let r=function(c){return Promise.all(c.map(m=>Promise.resolve(m).then(d=>({status:"fulfilled",value:d}),d=>({status:"rejected",reason:d}))))};const o=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),u=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));a=r(t.map(c=>{if(c=g2(c,n),c in Q0)return;Q0[c]=!0;const m=c.endsWith(".css"),d=m?'[rel="stylesheet"]':"";if(!!n)for(let f=o.length-1;f>=0;f--){const b=o[f];if(b.href===c&&(!m||b.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${c}"]${d}`))return;const g=document.createElement("link");if(g.rel=m?"stylesheet":h2,m||(g.as="script"),g.crossOrigin="",g.href=c,u&&g.setAttribute("nonce",u),document.head.appendChild(g),m)return new Promise((f,b)=>{g.addEventListener("load",f),g.addEventListener("error",()=>b(new Error(`Unable to preload CSS for ${c}`)))})}))}function s(r){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=r,window.dispatchEvent(o),!o.defaultPrevented)throw r}return a.then(r=>{for(const o of r||[])o.status==="rejected"&&s(o.reason);return e().catch(s)})};var S=(i=>(i[i.anweisung=0]="anweisung",i[i.verzweigung=1]="verzweigung",i[i.fallauswahl=2]="fallauswahl",i[i.forSchleife=3]="forSchleife",i[i.whileSchleife=4]="whileSchleife",i[i.doUntilSchleife=5]="doUntilSchleife",i[i.endlosschleife=6]="endlosschleife",i[i.aussprung=7]="aussprung",i[i.aufruf=8]="aufruf",i[i.leerElement=9]="leerElement",i))(S||{});function p2(i){return i===3||i===4||i===5||i===6}function f2(i){return i===1||i===2}function Ae(i,e={}){return{type:i,zoomX:0,zoomY:0,textLines:[""],...e}}function b2(i){const e=i.textLines;if(!e.every(t=>t.trim()===""))switch(i.type){case S.forSchleife:return e.length<=1?e:[v2(e)];case S.verzweigung:return Ui("if",e);case S.whileSchleife:return Ui("while",e);case S.doUntilSchleife:return Ui("while",x2(e));case S.fallauswahl:return Ui("switch",e);default:return e}}function x2(i){if(i.length===0)return i;const e=i[0].trim(),t=e.toLowerCase(),n=[...i];if(t==="until")n[0]="";else if(t.startsWith("until "))n[0]=e.slice(6).trim();else if(t.startsWith("until("))n[0]=e.slice(5);else return i;return n}function U0(i){const e=new Set(["if","for","while","until","switch"]),t=["input:","output:","print:"],n=i.trim(),a=n.toLowerCase();for(const o of t){if(a===o)return{keyword:n,rest:""};if(a.startsWith(o+" "))return{keyword:n.slice(0,o.length),rest:n.slice(o.length).trim()}}const s=n.indexOf(" ");if(s<0)return;const r=n.slice(0,s);if(e.has(r.toLowerCase()))return{keyword:r,rest:n.slice(s+1).trim()}}function Ui(i,e){if(e.length===0)return e;const t=e[0].trim(),n=t.toLowerCase();if(n===i||n.startsWith(i+" "))return e;const a=[...e];return a[0]=i+" "+t,a}function v2(i){let e=[...i];for(;e.length<3;)e.push("");e=e.slice(0,3);const t=a=>{let s=a.trim();for(;s.endsWith(";");)s=s.slice(0,-1).trim();return s},n=e.map(t).join("; ").trim();return n===""?"for":"for "+n}const Ld={[S.anweisung]:"Anweisung",[S.verzweigung]:"Bedingung",[S.fallauswahl]:"Fallauswahl",[S.forSchleife]:"for 0 < i < anzahl",[S.whileSchleife]:"while …",[S.doUntilSchleife]:"while …",[S.endlosschleife]:"endless",[S.aussprung]:"break",[S.aufruf]:"Aufruf()",[S.leerElement]:"ø"};function y2(i){Object.assign(Ld,i)}function Ml(i){return b2(i)??[Ld[i.type]]}class Le extends Error{}const pn=i=>structuredClone(i);function nn(){return Ae(S.anweisung,{textLines:["ø"]})}function w2(){return{caption:"",elements:[nn()]}}function Zl(i){if(i.type===S.leerElement)return!0;if(i.type===S.anweisung){const e=i.textLines;return e.length===0||e.length===1&&e[0]==="ø"}return!1}function In(i,e){const t=Jt(i,e);return t!==void 0&&Zl(t)}function Ei(i,e){if(e.length===0)throw new Le("Invalid element path.");const[t,...n]=e;if(t<0||t>=i.length)throw new Le("Invalid element path.");if(n.length===0)return{list:i,index:t};const[a,...s]=n;if(s.length===0)throw new Le("Invalid element path.");return Ei(Ed(i[t],a),s)}function Ed(i,e){if(p2(i.type)){if(e!==0||!i.loopBody)throw new Le("Invalid element path.");return i.loopBody}if(f2(i.type)){if(!i.cases||e<0||e>=i.cases.length)throw new Le("Invalid element path.");return i.cases[e].elements}throw new Le("Invalid element path.")}function Pt(i,e){const{list:t,index:n}=Ei(i.elements,e);return t[n]}function Jt(i,e){try{return Pt(i,e)}catch{return}}function Pn(i,e,t){const n=pn(i),{list:a,index:s}=Ei(n.elements,e);return a[s]=pn(t),n}function N1(i,e,t){const n=pn(Pt(i,e));return n.textLines=t.length===0?[""]:t,Pn(i,e,n)}function dr(i,e){return e.length===0?!1:e.length===1&&i.elements.length===1?!In(i,e):Jt(i,e)!==void 0}function vi(i,e){const t=pn(i),{list:n,index:a}=Ei(t.elements,e);if(e.length===1&&n.length===1){if(Zl(n[0]))throw new Le("The last root element cannot be deleted.");return n[0]=nn(),t}return n.splice(a,1),e.length>1&&n.length===0&&n.push(nn()),t}function ai(i,e,t,n){const a=pn(i);let s;if(e.length===0)s=a.elements;else{const r=e.slice(0,-1),o=e[e.length-1],{list:l,index:u}=Ei(a.elements,r);s=Ed(l[u],o)}return s.splice(Math.min(Math.max(0,t),s.length),0,pn(n)),a}function Wd(i,e,t){if(t.length===0)throw new Le("Invalid element path.");return ai(i,t.slice(0,-1),t[t.length-1],e)}function co(i,e,t){if(t.length===0)throw new Le("Invalid element path.");return ai(i,t.slice(0,-1),t[t.length-1]+1,e)}function Ll(i,e){return i.lengthe[n]===t)}function El(i,e){if(e.length===0)return i;const t=e[e.length-1],n=e.slice(0,-1);if(i.length<=n.length||!n.every((r,o)=>i[o]===r))return i;const a=n.length;if(i[a]<=t)return i;const s=[...i];return s[a]-=1,s}const Wl=(i,e)=>i.length===e.length&&i.every((t,n)=>t===e[n]);function z2(i,e,t){if(Wl(e,t))return i;if(Ll(e,t))throw new Le("Invalid element path.");const n=Pt(i,e),a=vi(i,e);return Wd(a,n,El(t,e))}function I2(i,e,t){if(Wl(e,t))return i;if(Ll(e,t))throw new Le("Invalid element path.");const n=Pt(i,e),a=vi(i,e);return co(a,n,El(t,e))}function k2(i,e,t){if(!In(i,t))throw new Le("Invalid element path.");if(Wl(e,t))return i;if(Ll(e,t))throw new Le("Invalid element path.");const n=Pt(i,e),a=vi(i,e);return Pn(a,El(t,e),n)}function S2(i,e){const t=pn(Pt(i,e)),n=t.cases;if(t.type!==S.fallauswahl||!n||n.length===0)throw new Le("Invalid element path.");const a=n[n.length-1].name.toLowerCase()==="default",s=a?n.length-1:n.length,r=String(a?n.length:n.length+1);return n.splice(s,0,{name:r,elements:[nn()]}),{doc:Pn(i,e,t),path:[...e,s,0]}}function T2(i,e,t){const n=pn(Pt(i,e)),a=n.cases;if(n.type!==S.fallauswahl||!a)throw new Le("Invalid element path.");if(a.length<=2)throw new Le("A switch needs at least two cases.");if(t<0||t>=a.length)throw new Le("Invalid element path.");a.splice(t,1);const s=Math.min(t,a.length-1);return{doc:Pn(i,e,n),path:[...e,s,0]}}function _2(i,e,t,n){const a=pn(Pt(i,e)),s=a.cases;if(a.type!==S.fallauswahl||!s)throw new Le("Invalid element path.");if(t<0||t>=s.length)throw new Le("Invalid element path.");const r=n.trim();if(r==="")throw new Le("Invalid element path.");return s[t].name=r,Pn(i,e,a)}function A2(i,e){var t;if(!(!i||i.length===0))for(let n=i.length;n>=1;n--){const a=i.slice(0,n);if(((t=Jt(e,a))==null?void 0:t.type)===S.fallauswahl)return a}}function O2(i,e){if(!(!i||i.length<=e.length))return i[e.length]}function hr(i,e){if(e.elements.length!==0)return!i||!Jt(e,i)?[0]:i}const Nd=i=>i!==void 0&&/\s/.test(i);function $a(i){const e=i.trim().toLowerCase();return e.startsWith("input:")?"input":e.startsWith("output:")||e.startsWith("print:")?"output":"statement"}function C2(i){const e=i.trim(),t=e.toLowerCase();return t.startsWith("input:")?e.slice(6).trim():t.startsWith("output:")?e.slice(7).trim():t.startsWith("print:")?e.slice(6).trim():i}function $0(i,e){const t=e.trim();return t===""?`${i} `:`${i} ${t}`}function j2(i,e){const t=C2(e);switch(i){case"statement":return t;case"input":return $0("input:",t);case"output":return $0("output:",t)}}const Ba=i=>Nd(i[0])?i.slice(1):i;function P2(i){const e=i.replace(/^\s+/,""),t=e.toLowerCase();return t.startsWith("input:")?Ba(e.slice(6)):t.startsWith("output:")?Ba(e.slice(7)):t.startsWith("print:")?Ba(e.slice(6)):i}function Y0(i,e){const t=e.replace(/^\s+/,"");if(!t.toLowerCase().startsWith(i.toLowerCase()))return e;const n=t.slice(i.length);if(!(n===""||Nd(n[0])||n[0]==="("))return e;const a=Ba(n);return a.startsWith("(")&&a.endsWith(")")&&a.length>=2?a.slice(1,-1):a}function X0(i,e){if(i==="input:"||i==="output:")return P2(e);const t=Y0(i,e);if(i==="while"&&t===e){const n=Y0("until",e);if(n!==e)return n}return t}function D2(i,e){return e===""?`${i} `:`${i} ${e}`}function Fd(i){return i.replace(/[“”„«»]/g,'"').replace(/[’‘‚´]/g,"'")}function K0(i){const e=i.length===0?[""]:i.slice(0,3);for(;e.length<3;)e.push("");return e}function B2(i){let e=Fd(i);for(;;){const t=e.trim();if(!t.endsWith(";"))return e;e=t.slice(0,-1).trim()}}const Ns='system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';function M2(i,e){return`${e==="bold"?700:500} ${i}px ${Ns}`}const Jd=(i,e,t)=>[...i].length*e*(t==="bold"?.68:.62);function Z2(){if(typeof document>"u"||!document.body)return;const i="http://www.w3.org/2000/svg",e=document.createElementNS(i,"svg");e.setAttribute("aria-hidden","true"),e.setAttribute("width","0"),e.setAttribute("height","0"),e.style.cssText="position:absolute;left:-9999px;top:0;visibility:hidden;overflow:hidden";const t=document.createElementNS(i,"text");if(t.setAttribute("font-family",Ns),t.style.whiteSpace="pre",e.append(t),document.body.append(e),typeof t.getComputedTextLength!="function"||typeof t.getBBox!="function"){e.remove();return}if(t.textContent="Mg",t.setAttribute("font-size","20"),!(t.getComputedTextLength()>0)){e.remove();return}return t}let gr;function Rd(){return gr===void 0&&(gr=Z2()??null),gr??void 0}function Gd(i,e,t){i.setAttribute("font-size",String(e)),i.setAttribute("font-weight",t==="bold"?"700":"500")}function eu(i,e){const t=`${i}|${e}`;let n=tu.get(t);if(!n){const a=Rd();if(n={ascent:i*.95,descent:i*.24},a){Gd(a,i,e),a.setAttribute("y","0"),a.textContent="Mg";const s=a.getBBox();s.height>0&&(n={ascent:-s.y,descent:s.height+s.y})}tu.set(t,n)}return n}const tu=new Map;function L2(){const i=Rd();if(i){const n=new Map;return(a,s,r)=>{const o=`${s}|${r}|${a}`;let l=n.get(o);return l===void 0&&(Gd(i,s,r),i.textContent=a,l=a===""?0:i.getComputedTextLength(),n.size>2e3&&n.clear(),n.set(o,l)),l}}const e=typeof document<"u"?document.createElement("canvas").getContext("2d"):null;if(!e)return Jd;const t=new Map;return(n,a,s)=>{const r=`${a}|${s}|${n}`;let o=t.get(r);return o===void 0&&(e.font=M2(a,s),o=e.measureText(n).width,t.size>2e3&&t.clear(),t.set(r,o)),o}}const Hd={fontSize:15,lineHeight:20,charWidth:7,baseHeaderExtra:20,minSidePadding:42,cellTextInsetY:15,doUntilDoLabelTopInset:2,doUntilFooterTopInset:6,doUntilFooterBottomInset:8};function E2(i){return{...Hd,fontSize:14,lineHeight:21,charWidth:5.5*(14/12),baseHeaderExtra:21,minSidePadding:40}}const $i=i=>i===S.forSchleife||i===S.whileSchleife||i===S.doUntilSchleife||i===S.endlosschleife,Yi=i=>i===S.fallauswahl||i===S.verzweigung;function Xi(i,e,t,n=0){return{idPath:i,element:e,frame:t,headerBandHeight:n,topBandHeight:0,loopBodyLeadingInset:0,caseColumnFrames:[],children:[]}}function it(i){return{...i,frame:{...i.frame}}}class Vd{constructor(e=Hd,t=Jd){this.metrics=e,this.measure=t}layout(e,t={left:28,top:28}){const a=this.layoutList(e.elements,t.left,t.top,[]).map(l=>this.stretchLoopBodiesVertically(l));let s=0,r=0;const o=l=>{s=Math.max(s,l.frame.x+l.frame.width),r=Math.max(r,l.frame.y+l.frame.height),l.children.forEach(o)};return a.forEach(o),{canvasSize:{width:s+t.left,height:r+t.top},elements:a}}lineWidth(e){return Math.ceil(this.measure(e,this.metrics.fontSize,"medium"))}lineWidthBold(e){return Math.ceil(this.measure(e,this.metrics.fontSize,"bold"))}layoutList(e,t,n,a){let s=[],r=n;e.forEach((l,u)=>{const c=this.layoutElement(l,t,r,[...a,u]);s.push(c),r+=c.frame.height});const o=Math.max(0,...s.map(l=>l.frame.width));return o>0&&(s=s.map(l=>this.stretchNodeTreeToWidth(l,o))),s}stretchMultiwayNodeToWidth(e,t){const n=it(e),a=n.frame.width;if(!(a>0)||n.caseColumnFrames.length===0)return n;const s=t/a;n.frame.width=t;let r=n.frame.x;const o=n.caseColumnFrames.map(l=>{const u=l.width*s,c={x:r,y:l.y,width:u,height:l.height};return r+=u,c});return n.caseColumnFrames=o,n.dividerX=o.length>0?o[o.length-1].x:n.frame.x+t,n.columns&&n.columns.length===o.length&&(n.columns=n.columns.map((l,u)=>{const c=o[u];return l.map(m=>{const d=it(m);return d.frame.x=c.x,d.frame.width=c.width,this.stretchDescendantsWidths(d,c.width)})}),n.children=n.columns.flat()),n}stretchLoopChildren(e,t){const n=this.effectiveLoopBodyLeading(e),a=Math.max(0,t-n);e.children=e.children.map(s=>{const r=it(s);return r.frame.x=e.frame.x+n,r.frame.width=a,this.stretchDescendantsWidths(r,a)})}stretchNodeTreeToWidth(e,t){const n=it(e);return n.frame.width>0?Yi(n.element.type)&&n.caseColumnFrames.length>0?this.stretchMultiwayNodeToWidth(n,t):(n.frame.width=t,$i(n.element.type)?this.stretchLoopChildren(n,t):n.children=n.children.map(s=>this.stretchDescendantsWidths(s,t)),n):n}stretchDescendantsWidths(e,t){let n=it(e);return Yi(n.element.type)?n=this.stretchNodeTreeToWidth(n,t):$i(n.element.type)?(n.frame.width=t,this.stretchLoopChildren(n,t)):(n.frame.width=t,n.children=n.children.map(a=>this.stretchDescendantsWidths(a,t))),n}stretchLoopBodiesVertically(e){const t=it(e);if(t.columns&&t.columns.length>0)return t.columns=t.columns.map(s=>s.map(r=>this.stretchLoopBodiesVertically(r))),t.children=t.columns.flat(),t;t.children=t.children.map(s=>this.stretchLoopBodiesVertically(s));const n=s=>s===S.anweisung||s===S.leerElement||s===S.aufruf||s===S.aussprung||$i(s);let a;switch(t.element.type){case S.forSchleife:case S.whileSchleife:case S.endlosschleife:{const s=t.element.type===S.endlosschleife?40:0;a=t.frame.y+t.frame.height-s;break}case S.doUntilSchleife:a=t.frame.y+t.frame.height-t.headerBandHeight;break}if(a!==void 0&&t.children.length>0){const s=t.children.length-1;let r=it(t.children[s]);const o=a-(r.frame.y+r.frame.height);o>.5&&n(r.element.type)&&(r.frame.height+=o,r=this.stretchLoopBodiesVertically(r),t.children=[...t.children.slice(0,s),r])}return t}headerHeight(e){const t=this.metrics,n=Math.max(1,e.textLines.length);if(e.type===S.doUntilSchleife)return t.doUntilFooterTopInset+n*t.lineHeight+t.doUntilFooterBottomInset+e.zoomY;let a;switch(e.type){case S.fallauswahl:a=40;break;case S.verzweigung:a=20;break;case S.forSchleife:case S.whileSchleife:case S.endlosschleife:a=t.baseHeaderExtra+4;break;default:a=14}return a+n*t.lineHeight+e.zoomY}doUntilBodyLeadingInset(){return Math.max(20,this.lineWidthBold("do")+12)}effectiveLoopBodyLeading(e){return e.element.type===S.doUntilSchleife?e.loopBodyLeadingInset>0?e.loopBodyLeadingInset:this.doUntilBodyLeadingInset():20}horizontalPaddingInsideCell(e){return Yi(e)?Math.max(100,this.metrics.minSidePadding*2.45):this.metrics.minSidePadding}minWidth(e){const t=e.textLines.length===0?0:Math.max(...e.textLines.map(s=>this.lineWidth(s)));let n=t+e.zoomX+this.horizontalPaddingInsideCell(e.type);if(e.type===S.aufruf){const s=Math.max(68,this.metrics.minSidePadding*1.7),r=Math.max(8,this.metrics.minSidePadding*.2);n=Math.max(n,t+e.zoomX+s+r)}const a=e.type===S.leerElement?76:e.type===S.aufruf?104:72;return Math.max(a,n)}layoutElement(e,t,n,a){if(Yi(e.type))return this.layoutMultiway(e,t,n,a);if($i(e.type))return this.layoutLoop(e,t,n,a);const s=this.headerHeight(e);return Xi(a,e,{x:t,y:n,width:this.minWidth(e),height:s},s)}layoutLoop(e,t,n,a){const s=b=>b.reduce((x,v)=>x+v.frame.height,0),r=b=>Math.max(0,...b.map(x=>x.frame.width)),o=e.loopBody??[];if(e.type===S.doUntilSchleife){const b=this.doUntilBodyLeadingInset(),x=e.zoomY,v=this.headerHeight(e),w=this.layoutList(o,t+b,n+x,[...a,0]),I=Math.max(this.minWidth(e),r(w)+b),z=s(w)+v+x,k=Math.max(0,I-b),T=Xi(a,e,{x:t,y:n,width:I,height:z},v);return T.topBandHeight=x,T.loopBodyLeadingInset=b,T.children=w.map(A=>{const D=it(A);return D.frame.x=t+b,D.frame.width=k,this.stretchDescendantsWidths(D,k)}),T}const l=20,u=this.headerHeight(e),c=e.type===S.endlosschleife?40:0,m=this.layoutList(o,t+l,n+u,[...a,0]),d=Math.max(this.minWidth(e),r(m)+l),h=u+c+s(m),g=Math.max(0,d-l),f=Xi(a,e,{x:t,y:n,width:d,height:h},u);return f.children=m.map(b=>{const x=it(b);return x.frame.x=t+l,x.frame.width=g,this.stretchDescendantsWidths(x,g)}),f}layoutMultiway(e,t,n,a){const s=this.headerHeight(e),r=e.cases??[],o=Math.max(1,r.length),l=Math.max(this.minWidth(e)/o,132);let u=[],c=[],m=0,d=0;if(r.forEach((b,x)=>{const v=t+m,w=this.layoutList(b.elements,v,n+s,[...a,x]),I=Math.max(0,...w.map(T=>T.frame.width));let z;e.type===S.verzweigung&&o===2?z=Math.max(I,(x===0?"true":"false").length*this.metrics.charWidth+24):z=Math.max(l,I);const k=w.reduce((T,A)=>T+A.frame.height,0);d=Math.max(d,k),u.push({x:v,y:n+s,width:z,height:k}),c.push(w.map(T=>{const A=it(T);return A.frame.x=v,A.frame.width=z,this.stretchDescendantsWidths(A,z)})),m+=z}),e.type===S.verzweigung&&o===2&&u.length===2){const b=Math.max(u[0].width,u[1].width),x=t,v=t+b,w=v-u[1].x;u[0]={...u[0],x,width:b},u[1]={...u[1],x:v,width:b},m=b*2,c[0]=c[0].map(I=>{const z=it(I);return z.frame.x=x,z.frame.width=b,this.stretchDescendantsWidths(z,b)}),c[1]=c[1].map(I=>{const z=mo(I,w);return z.frame.width=b,this.stretchDescendantsWidths(z,b)})}if(c.length>0){const b=W2(c,n+s);c=b.columns.map(x=>x.map(v=>this.stretchLoopBodiesVertically(v)));for(let x=0;x0?Math.max(...b.columnHeights):d}let h=Math.max(m,this.minWidth(e));if(m>.5&&h>m+.5){const b=h/m;let x=t;const v=[],w=[];u.forEach((I,z)=>{const k=I.width*b;w.push(c[z].map(T=>{const A=it(T);return A.frame.x=x,A.frame.width=k,this.stretchDescendantsWidths(A,k)})),v.push({x,y:I.y,width:k,height:I.height}),x+=k}),u=v,c=w,m=x-t,h=m}const g=u.length>0?u[u.length-1].width:m/o,f=Xi(a,e,{x:t,y:n,width:h,height:s+d},s);return f.caseColumnFrames=u,f.dividerX=u.length>0?u[u.length-1].x:t+m-g,f.dividerYInset=e.type===S.fallauswahl?-20:0,f.columns=c,f.children=c.flat(),f}}function qd(i,e){if(Math.abs(e)<=1e-4)return i;const t=it(i),n=a=>{const s=it(a);return s.frame.y+=e,qd(s,e)};return t.columns?(t.columns=t.columns.map(a=>a.map(n)),t.children=t.columns.flat()):t.children=t.children.map(n),t}function mo(i,e){if(Math.abs(e)<=1e-4)return i;const t=it(i);return t.frame.x+=e,t.columns?(t.columns=t.columns.map(n=>n.map(a=>mo(a,e))),t.children=t.columns.flat()):t.children=t.children.map(n=>mo(n,e)),t}function W2(i,e){if(i.length<2)return{columns:i,columnHeights:i.map(u=>u.reduce((c,m)=>c+m.frame.height,0))};const t=.5,n=[e];for(const u of i)for(const c of u)n.push(c.frame.y+c.frame.height);const a=Math.max(...n);n.push(a),n.sort((u,c)=>u-c);let s=[];for(const u of n)s.length>0&&Math.abs(u-s[s.length-1])<=t||s.push(u);(s.length===0||Math.abs(s[0]-e)>t)&&s.unshift(e),s.length===0?s=[e,a]:s[s.length-1]{let m=Math.max(0,c);for(;m{let g=it(d);const f=s[m],b=d.frame.y+d.frame.height,x=h===u.length-1?s.length-1:r(b,m+1),v=s[x],w=f-g.frame.y;g.frame.y=f,g.frame.height=Math.max(0,v-f),g=qd(g,w),c.push(g),m=x}),o.push(c),l.push(s[s.length-1]-e)}return{columns:o,columnHeights:l}}const N2=[{item:"anweisung",label:"Anweisung"},{item:"verzweigung",label:"Verzweigung"},{item:"fallauswahl",label:"Fallauswahl"},{item:"forZaehlSchleife",label:"For-Schleife"},{item:"whileSchleife",label:"While-Schleife"},{item:"doUntilSchleife",label:"Do-while-Schleife"},{item:"endlosschleife",label:"Endlosschleife"},{item:"aufruf",label:"Aufruf"},{item:"aussprung",label:"Aussprung"}];function nu(i){const e=nn;switch(i){case"anweisung":return Ae(S.anweisung);case"verzweigung":return Ae(S.verzweigung,{cases:[{name:"true",elements:[e()]},{name:"false",elements:[e()]}]});case"fallauswahl":return Ae(S.fallauswahl,{cases:[{name:"1",elements:[e()]},{name:"2",elements:[e()]},{name:"default",elements:[e()]}]});case"forZaehlSchleife":return Ae(S.forSchleife,{textLines:["","",""],loopBody:[e()]});case"whileSchleife":return Ae(S.whileSchleife,{loopBody:[e()]});case"doUntilSchleife":return Ae(S.doUntilSchleife,{loopBody:[e()]});case"endlosschleife":return Ae(S.endlosschleife,{loopBody:[e()]});case"aussprung":return Ae(S.aussprung);case"aufruf":return Ae(S.aufruf)}}function Ya(i){if(i==="")return"-1;";let e="";for(const t of i)e+=t.codePointAt(0)+";";return e}function ho(i){const e=i.split(";").filter(n=>n!=="");if(e.length===1&&e[0]==="-1")return"";let t="";for(const n of e){if(!/^[+-]?\d+$/.test(n))continue;const a=Number(n);a!==-1&&(a<0||a>1114111||a>=55296&&a<=57343||(t+=String.fromCodePoint(a)))}return t}class iu extends Error{}function Nl(i){const e=new DOMParser().parseFromString(i,"application/xml");if(e.getElementsByTagName("parsererror").length>0)throw new iu("Could not read XML.");const t=e.documentElement;if(!t||t.tagName!=="struktogramm")throw new iu("Invalid XML: root element is not .");const n={caption:su(t,"caption")??"",elements:po(t)},a=su(t,"fontfamily");a!==void 0&&(n.fontFamily=a);const s=si(t,"fontsize");s!==void 0&&(n.fontSize=s);const r=si(t,"fontstyle");return r!==void 0&&(n.fontStyle=r),t.getAttribute("pseudocode")==="true"&&(n.pseudocode=!0),n}function u1(i){const e=(n,a)=>a===void 0?"":` ${n}="${Qd(a)}"`;let t=` +`;t+=" +`;for(const n of i.elements)t+=go(n," ");return t+=` +`,t}function go(i,e){let t=`${e} +`;for(const n of i.textLines)t+=`${e} ${F2(Ya(n))} +`;if(i.loopBody){t+=`${e} +`;for(const n of i.loopBody)t+=go(n,e+" ");t+=`${e} +`}if(i.cases)for(const n of i.cases){t+=`${e} +`;for(const a of n.elements)t+=go(a,e+" ");t+=`${e} +`}return t+=`${e} +`,t}function Qd(i){return i.replace(/&/g,"&").replace(/"/g,""").replace(//g,">")}function F2(i){return i.replace(/&/g,"&").replace(//g,">")}function au(i){return String(i.a<<24|i.r<<16|i.g<<8|i.b|0)}function Ma(i,e){return Array.from(i.children).filter(t=>t.tagName===e)}function po(i){const e=[];for(const t of Ma(i,"strelem")){const n=J2(t);n&&e.push(n)}return e}function J2(i){const e=si(i,"typ");if(e===void 0||S[e]===void 0)return;const t={type:e,zoomX:si(i,"zx")??0,zoomY:si(i,"zy")??0,textLines:Ma(i,"text").map(o=>ho((o.textContent??"").trim()))},n=ru(i.getAttribute("textcolor"));n&&(t.textColor=n);const a=ru(i.getAttribute("bgcolor"));a&&(t.backgroundColor=a),t.textLines.length===0&&(t.textLines=[""]);const s=Ma(i,"schleifeninhalt")[0];if(s){const o=po(s);o.length>0&&(t.loopBody=o)}const r=Ma(i,"fall").map(o=>({name:ho(o.getAttribute("fallname")??""),elements:po(o)}));return r.length>0&&(t.cases=r),t}function su(i,e){const t=i.getAttribute(e);return t===null?void 0:ho(t)}function si(i,e){const t=i.getAttribute(e);if(!(t===null||!/^[+-]?\d+$/.test(t)))return Number(t)}function ru(i){if(i===null||!/^[+-]?\d+$/.test(i))return;const e=Number(i);if(e<-2147483648||e>2147483647)return;const t=e>>>0;return{a:t>>>24&255,r:t>>>16&255,g:t>>>8&255,b:t&255}}const R2="http://www.w3.org/2000/svg",Ee={diagramLineWidth:2,outerFrameLineWidth:2,selectionLineWidth:3.5,canvasOuterMargin:16,cellTextInsetX:18,cellTextInsetY:15,multiHeaderFirstLineY:14,branchLabelInsetX:10,fallauswahlCaseLabelBand:26,callSideBarInset:14,callTextInsetFromSideBar:20,loopBodyLeadingInset:20};function Ud(i){switch(i){case S.forSchleife:case S.whileSchleife:case S.doUntilSchleife:case S.endlosschleife:return"loop";case S.verzweigung:case S.fallauswahl:return"if";default:return}}function Se(i,e={}){const t=document.createElementNS(R2,i);for(const[n,a]of Object.entries(e))t.setAttribute(n,String(a));return t}class $d{constructor(e,t){y(this,"usesSimulationHighlight",!1);y(this,"fillsSelection",!1);this.metrics=e,this.measure=t}get lineHeight(){return this.metrics.lineHeight}get fontSize(){return this.metrics.fontSize}render(e,t,n,a=Ee.canvasOuterMargin){const s=Se("svg",{width:t.width,height:t.height,viewBox:`0 0 ${t.width} ${t.height}`,"font-family":Ns,"font-size":this.fontSize,class:"diagram"});s.append(Se("rect",{x:0,y:0,width:t.width,height:t.height,fill:"#fafafa"}));const r=a;s.append(Se("rect",{x:r,y:r,width:e.canvasSize.width-2*r-1,height:e.canvasSize.height-2*r-1,fill:"none",stroke:"black","stroke-width":Ee.outerFrameLineWidth}));const o=Se("g");for(const l of e.elements)this.drawNode(l,o,n,{},void 0,"method");return s.append(o),s}line(e,t){e.append(Se("polyline",{points:t.map(n=>n.join(",")).join(" "),fill:"none",stroke:"black","stroke-width":Ee.diagramLineWidth,"stroke-linejoin":"miter"}))}strokeCellBorder(e,t,n){const a=t.x,s=t.y,r=t.x+t.width,o=t.y+t.height;if(!n.top&&!n.left&&!n.bottom&&!n.right){e.append(Se("rect",{x:a,y:s,width:t.width,height:t.height,fill:"none",stroke:"black","stroke-width":Ee.diagramLineWidth}));return}n.top||this.line(e,[[a,s],[r,s]]),n.right||this.line(e,[[r,s],[r,o]]),n.bottom||this.line(e,[[r,o],[a,o]]),n.left||this.line(e,[[a,o],[a,s]])}textWidth(e){const t=U0(e);return t?this.measure(t.keyword,this.fontSize,"bold")+(t.rest===""?0:this.measure(" "+t.rest,this.fontSize,"medium")):this.measure(e,this.fontSize,"medium")}drawKeywordLine(e,t,n,a){const s=Se("text",{x:n,y:a+eu(this.fontSize,"medium").ascent,"font-weight":500});s.style.whiteSpace="pre";const r=U0(t);if(r){const o=Se("tspan",{"font-weight":700});if(o.textContent=r.keyword,s.append(o),r.rest!==""){const l=Se("tspan",{});l.textContent=" "+r.rest,s.append(l)}}else s.textContent=t;e.append(s)}drawLabel(e,t,n,a,s,r){const o=eu(this.fontSize,s?"bold":"medium"),l=Se("text",{x:n,y:r==="top"?a+o.ascent:a-o.descent,"font-weight":s?700:500});l.style.whiteSpace="pre",l.textContent=t,e.append(l)}roofMetrics(e,t,n,a){const s=t.y+n,r=e.dividerYInset??0,o=12,l=Math.max(e.element.textLines.length,1)*this.lineHeight,u=t.y+Ee.multiHeaderFirstLineY;if(e.element.type===S.fallauswahl){const m=Math.max(Ee.fallauswahlCaseLabelBand,this.lineHeight+10),d=s-m,h=Math.min(s+r,d-8),g=Math.max(h,u+l+6);return{apex:{x:a,y:g},maxTextBottom:d-o,roofBottom:s}}const c={x:a,y:s+r};return{apex:c,maxTextBottom:c.y-o,roofBottom:s}}drawNode(e,t,n,a,s,r){var A;const o=e.frame,l=e.element,u=o.x+o.width,c=o.y+o.height,m=l.type===S.verzweigung||l.type===S.fallauswahl,d=m?e.headerBandHeight:0,h=n!==void 0&&fo(e.idPath,n),g=Ml(l),f=Se("g",{"data-path":e.idPath.join(",")});t.append(f);const b=this.usesSimulationHighlight,x=l.backgroundColor,v=x&&x.a>0?`rgba(${x.r}, ${x.g}, ${x.b}, ${x.a/255})`:"white",w=h&&(b||this.fillsSelection)?"rgba(199, 230, 255, 0.55)":v,I=Ud(l.type)??(l.type===S.leerElement?r:"method"),z=Se("rect",{x:o.x,y:o.y,width:o.width,height:o.height,fill:w});w==="white"&&I&&z.setAttribute("class",`ns-scope ns-scope-${I}`),f.append(z),this.strokeCellBorder(f,o,a);const k=Ee.callSideBarInset;if(l.type===S.aufruf?(this.line(f,[[o.x+k,o.y],[o.x+k,c]]),this.line(f,[[u-k,o.y],[u-k,c]])):l.type===S.aussprung&&this.line(f,[[o.x+k,o.y],[o.x,o.y+o.height/2],[o.x+k,c]]),m&&e.dividerX!==void 0){const D=e.dividerX,P=this.roofMetrics(e,o,d,D),j=Math.max(g.length,1)*this.lineHeight,O=o.y+Ee.multiHeaderFirstLineY;this.line(f,[[o.x,o.y],[P.apex.x,P.apex.y],[u,o.y]]),l.type===S.fallauswahl&&this.line(f,[[o.x,P.roofBottom],[u,P.roofBottom]]);let Z;O+j<=P.maxTextBottom?Z=O:Z=Math.max(o.y+2,P.maxTextBottom-(Math.max(g.length,1)-1)*this.lineHeight-this.lineHeight),g.forEach((W,U)=>{const ee=this.textWidth(W);let he;if(l.type===S.verzweigung){const Ie=o.x+Ee.cellTextInsetX,fe=u-ee-Ee.cellTextInsetX;he=Math.min(Math.max(D-ee/2,Ie),fe)}else he=o.x+o.width/2-ee/2;this.drawKeywordLine(f,W,he,Z+U*this.lineHeight)})}else if(l.type!==S.doUntilSchleife)if(l.type===S.anweisung||l.type===S.aufruf||l.type===S.aussprung){const D=Ee.cellTextInsetX;let P=o.x+D,j=u-D;l.type===S.aufruf?(P=o.x+k+Ee.callTextInsetFromSideBar,j=u-k-Ee.callTextInsetFromSideBar):l.type===S.aussprung&&(P=o.x+k+D);const O=Math.max(0,j-P);let Z=o.y+o.height/2-Math.max(1,g.length)*this.lineHeight/2;for(const W of g)this.drawKeywordLine(f,W,P+(O-this.textWidth(W))/2,Z),Z+=this.lineHeight}else{const D=Math.max(1,g.length)*this.lineHeight;let P=s===S.doUntilSchleife?o.y+o.height/2-D/2:o.y+Ee.cellTextInsetY;for(const j of g)this.drawKeywordLine(f,j,o.x+Ee.cellTextInsetX,P),P+=this.lineHeight}e.children.forEach((D,P)=>{const j=l.type===S.doUntilSchleife&&P===0?{top:!0,left:!0}:{};this.drawNode(D,t,n,j,l.type,I)});const T=Se("g");if(t.append(T),l.type===S.doUntilSchleife){const D=((A=e.children[0])==null?void 0:A.frame.x)??o.x+(e.loopBodyLeadingInset>0?e.loopBodyLeadingInset:Ee.loopBodyLeadingInset);this.drawLabel(T,"do",o.x+4,o.y+this.metrics.doUntilDoLabelTopInset,!0,"top");const P=c-e.headerBandHeight;this.line(T,[[D,P],[u,P]]),this.line(T,[[D,o.y],[D,P]]);let j=P+this.metrics.doUntilFooterTopInset;for(const O of g)this.drawKeywordLine(T,O,o.x+Ee.cellTextInsetX,j),j+=this.lineHeight}if(m&&e.dividerX!==void 0&&e.caseColumnFrames.length>1){const D=this.roofMetrics(e,o,d,e.dividerX),P=D.apex;e.caseColumnFrames.forEach((O,Z)=>{if(Z>=e.caseColumnFrames.length-1)return;const W=O.x+O.width,U=G2(W,o,P),ee=Number.isFinite(U)?Math.min(Math.max(U,o.y),c):o.y;this.line(T,[[W,c],[W,ee]])});const j=l.cases;if(j&&j.length===e.caseColumnFrames.length){const O=l.type===S.fallauswahl?D.roofBottom-6:o.y+d-8,Z=Ee.branchLabelInsetX;if(l.type===S.verzweigung&&j.length===2){this.drawLabel(T,"true",o.x+Z,O,!0,"bottom");const W=e.caseColumnFrames[1],U=this.measure("false",this.fontSize,"bold");this.drawLabel(T,"false",W.x+W.width-Z-U,O,!0,"bottom")}else j.forEach((W,U)=>{const ee=e.caseColumnFrames[U],he=["default","true","false"].includes(W.name.toLowerCase()),Ie=this.measure(W.name,this.fontSize,he?"bold":"medium");this.drawLabel(T,W.name,ee.x+ee.width/2-Ie/2,O,he,"bottom")})}}h&&T.append(Se("rect",{x:o.x,y:o.y,width:o.width,height:o.height,class:"selection-frame",fill:"none",stroke:b?"rgba(66, 140, 242, 0.78)":"rgba(0, 122, 255, 0.9)","stroke-width":Ee.selectionLineWidth}))}}function G2(i,e,t){const n=e.y;if(i<=t.x){const s=t.x-e.x;return Math.abs(s)<.5?t.y:n+(t.y-n)/s*(i-e.x)}const a=e.x+e.width-t.x;return Math.abs(a)<.5?t.y:t.y+(n-t.y)/a*(i-t.x)}function fo(i,e){return i.length===e.length&&i.every((t,n)=>t===e[n])}function H2(i){const e=[],t=n=>{e.push(n),n.children.forEach(t)};return i.forEach(t),e}function Xa(i){var e,t;return{...i,textLines:Ml(i),loopBody:(e=i.loopBody)==null?void 0:e.map(Xa),cases:(t=i.cases)==null?void 0:t.map(n=>({name:n.name,elements:n.elements.map(Xa)}))}}const V2=[{code:"de",name:"Deutsch"},{code:"en",name:"English"},{code:"es",name:"Español"},{code:"fr",name:"Français"},{code:"it",name:"Italiano"},{code:"pl",name:"Polski"},{code:"tr",name:"Türkçe"},{code:"ko",name:"한국어"},{code:"ja",name:"日本語"},{code:"el",name:"Ελληνικά"},{code:"uk",name:"Українська"},{code:"ar",name:"العربية"},{code:"ru",name:"Русский"},{code:"he",name:"עברית"},{code:"nl",name:"Nederlands"},{code:"sv",name:"Svenska"},{code:"da",name:"Dansk"},{code:"nb",name:"Norsk bokmål"},{code:"zh-Hans",name:"中文(简体)"},{code:"zh-Hant",name:"中文(繁體)"},{code:"pt-PT",name:"Português"},{code:"java",name:"Java (Keywords)"}],Yd=["de","en","pt-PT"],Xd=V2.filter(i=>Yd.includes(i.code)),ou=i=>Yd.includes(i),q2=Object.assign({"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ar.lproj/Localizable.strings":()=>K(()=>import("./Localizable-CxCno28C.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/da.lproj/Localizable.strings":()=>K(()=>import("./Localizable-BAutdlBb.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/de.lproj/Localizable.strings":()=>K(()=>import("./Localizable-Dk8F86qS.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/el.lproj/Localizable.strings":()=>K(()=>import("./Localizable-rqA-20hM.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/en.lproj/Localizable.strings":()=>K(()=>import("./Localizable-DBLIUcBd.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/es.lproj/Localizable.strings":()=>K(()=>import("./Localizable-LSTVB2Q5.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/fr.lproj/Localizable.strings":()=>K(()=>import("./Localizable-ByPZS4RL.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/he.lproj/Localizable.strings":()=>K(()=>import("./Localizable-R-16GCrk.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/it.lproj/Localizable.strings":()=>K(()=>import("./Localizable-DXAPah1g.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ja.lproj/Localizable.strings":()=>K(()=>import("./Localizable-CkJEmEEP.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ko.lproj/Localizable.strings":()=>K(()=>import("./Localizable-BudCXCER.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/nb.lproj/Localizable.strings":()=>K(()=>import("./Localizable-DSvkBkp-.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/nl.lproj/Localizable.strings":()=>K(()=>import("./Localizable-BJ55WGVD.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/pl.lproj/Localizable.strings":()=>K(()=>import("./Localizable-BYJK0mdR.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/pt-PT.lproj/Localizable.strings":()=>K(()=>import("./Localizable-CHv0OL9S.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/ru.lproj/Localizable.strings":()=>K(()=>import("./Localizable-1QZ0wfvJ.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/sv.lproj/Localizable.strings":()=>K(()=>import("./Localizable-M33nNbEe.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/tr.lproj/Localizable.strings":()=>K(()=>import("./Localizable-BM86Igqt.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/uk.lproj/Localizable.strings":()=>K(()=>import("./Localizable-UGog_aku.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/zh-Hans.lproj/Localizable.strings":()=>K(()=>import("./Localizable-CaVEL1es.js"),[],import.meta.url).then(i=>i.default),"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/zh-Hant.lproj/Localizable.strings":()=>K(()=>import("./Localizable-DqIDp_hh.js"),[],import.meta.url).then(i=>i.default)}),Kd=Object.assign({"../../../VisuStruct-iOS/VisuStructXcodeOpen/VisuStruct/Java.strings":()=>K(()=>import("./Java-Bpx1Vwvg.js"),[],import.meta.url).then(i=>i.default)}),Q2=Object.assign({"../i18n/ar.strings":()=>K(()=>import("./ar-DeE-RHam.js"),[],import.meta.url).then(i=>i.default),"../i18n/da.strings":()=>K(()=>import("./da-D4INXE4p.js"),[],import.meta.url).then(i=>i.default),"../i18n/de.strings":()=>K(()=>import("./de-3XOrIl-I.js"),[],import.meta.url).then(i=>i.default),"../i18n/el.strings":()=>K(()=>import("./el-CtIZyj0I.js"),[],import.meta.url).then(i=>i.default),"../i18n/en.strings":()=>K(()=>import("./en-sZM_O17d.js"),[],import.meta.url).then(i=>i.default),"../i18n/es.strings":()=>K(()=>import("./es-BAduFB3L.js"),[],import.meta.url).then(i=>i.default),"../i18n/fr.strings":()=>K(()=>import("./fr-C_mSEvw5.js"),[],import.meta.url).then(i=>i.default),"../i18n/he.strings":()=>K(()=>import("./he-BAg3LrWK.js"),[],import.meta.url).then(i=>i.default),"../i18n/it.strings":()=>K(()=>import("./it-ClGS2uQV.js"),[],import.meta.url).then(i=>i.default),"../i18n/ja.strings":()=>K(()=>import("./ja-JQ8MwNFB.js"),[],import.meta.url).then(i=>i.default),"../i18n/ko.strings":()=>K(()=>import("./ko-tfdKG8Fb.js"),[],import.meta.url).then(i=>i.default),"../i18n/nb.strings":()=>K(()=>import("./nb-BpibUAkX.js"),[],import.meta.url).then(i=>i.default),"../i18n/nl.strings":()=>K(()=>import("./nl-HArZjiga.js"),[],import.meta.url).then(i=>i.default),"../i18n/pl.strings":()=>K(()=>import("./pl-C3HmQqUD.js"),[],import.meta.url).then(i=>i.default),"../i18n/pt-PT.strings":()=>K(()=>import("./pt-PT-De0Ipirm.js"),[],import.meta.url).then(i=>i.default),"../i18n/ru.strings":()=>K(()=>import("./ru-B4vTuE57.js"),[],import.meta.url).then(i=>i.default),"../i18n/sv.strings":()=>K(()=>import("./sv-Dau75zUV.js"),[],import.meta.url).then(i=>i.default),"../i18n/tr.strings":()=>K(()=>import("./tr-DrZsTe-O.js"),[],import.meta.url).then(i=>i.default),"../i18n/uk.strings":()=>K(()=>import("./uk-DQrOpK2W.js"),[],import.meta.url).then(i=>i.default),"../i18n/zh-Hans.strings":()=>K(()=>import("./zh-Hans-CeIYjS3N.js"),[],import.meta.url).then(i=>i.default),"../i18n/zh-Hant.strings":()=>K(()=>import("./zh-Hant-7-ScZHAu.js"),[],import.meta.url).then(i=>i.default)});function Za(i,e){var t;return(t=Object.entries(i).find(([n])=>n.endsWith(e)))==null?void 0:t[1]}function eh(i){const e=new Map,t=i.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,""),n=/"((?:[^"\\]|\\.)*)"\s*=\s*"((?:[^"\\]|\\.)*)"\s*;/g,a=s=>s.replace(/\\(u[0-9a-fA-F]{4}|.)/g,(r,o)=>o==="n"?` +`:o==="t"?" ":o.startsWith("u")&&o.length===5?String.fromCharCode(parseInt(o.slice(1),16)):o);for(const s of t.matchAll(n))e.set(a(s[1]),a(s[2]));return e}async function bo(i){const e=i==="java"?Za(Kd,"/Java.strings"):Za(q2,`/${i}.lproj/Localizable.strings`),t=Za(Q2,`/${i}.strings`),n=new Map;for(const a of[e,t])if(a)for(const[s,r]of eh(await a()))n.set(s,r);return n}let th="en",nh=new Map,Xn=new Map;const Ka="appLanguageCode",Fl="visustruct.keywords";let xo=new Map,Jl=!1;const U2=i=>i.startsWith("element_")||i.startsWith("canvas_stub_");function $2(){try{const i=new URLSearchParams(location.search).get("lang")==="java"||localStorage.getItem(Ka)==="java";return i&&(localStorage.setItem(Ka,"en"),localStorage.setItem(Fl,"1")),i}catch{return!1}}function Y2(){try{return localStorage.getItem(Fl)==="1"}catch{return!1}}async function ih(i,e=!0){if(i&&xo.size===0){Xn.size===0&&(Xn=await bo("en"));const t=Za(Kd,"/Java.strings");if(t)for(const[n,a]of eh(await t()))U2(n)&&a!==Xn.get(n)&&xo.set(n,a)}if(Jl=i,e)try{localStorage.setItem(Fl,i?"1":"0")}catch{}}function X2(){return Jl}function K2(){if($2())return"en";const i=new URLSearchParams(location.search).get("lang");if(i&&ou(i))return i;try{const e=localStorage.getItem(Ka);if(e&&ou(e))return e}catch{}for(const e of navigator.languages??[navigator.language]){const t=e.toLowerCase();if(t.startsWith("pt"))return"pt-PT";const n=Xd.find(a=>a.code===t.split("-")[0]);if(n)return n.code}return"en"}async function ah(i,e=!0){if(Xn.size===0&&(Xn=await bo("en")),nh=i==="en"?Xn:await bo(i),th=i,e)try{localStorage.setItem(Ka,i)}catch{}const t=document.documentElement;t.lang=i==="java"?"en":i,t.dir=i==="ar"||i==="he"?"rtl":"ltr"}function s1(){return th}function p(i,...e){const t=(Jl?xo.get(i):void 0)??nh.get(i)??Xn.get(i)??i;if(e.length===0)return t;let n=0;return t.replace(/%(?:(\d+)\$)?[@d]/g,(a,s)=>String(e[s?Number(s)-1:n++]??""))}const es=243,e3=244,sh=40,pr=4,t3=1;function Rl(i){const e=i.length,t=es+(e&255)+(e>>8)&255,n=i.reduce((a,s)=>a+s,0)&255;return Uint8Array.from([es,t,e&255,e>>8,...i,n,e3])}function n3(i,e,t){const n=Array.from(new TextEncoder().encode(i));return Rl([sh,e,t&255,t>>8&255,n.length&255,n.length>>8,...n])}function i3(i){if(i[0]!==sh||i.length<6)return;const e=new TextDecoder().decode(Uint8Array.from(i.slice(6))),t=/"ret"\s*:\s*([^}]*)\}/.exec(e);return t?{idx:i[2]|i[3]<<8,value:s3(t[1].trim())}:void 0}function a3(i){const e=[];for(;;){const t=i.indexOf(es);if(t<0){i.length=0;break}if(i.splice(0,t),i.length<4)break;const n=i[2]|i[3]<<8;if(i[1]!==(es+i[2]+i[3]&255)||n>4096){i.splice(0,1);continue}if(i.lengthArray.from({length:e},(t,n)=>i>>>8*n&255);function u3(i){let e=0;for(let t=0;t>>0;return ri(e,4)}const fr=(i,e)=>Rl([1,0,rh,i,...ri(e.length,2),...e]);function c3(i,e=r3){const t=new TextEncoder().encode(i),n=(4-t.length%F1+F1)%F1,a=new Uint8Array(t.length+n).fill(10);a.set(t);const s=[fr(1,[0,...ri(a.length,4),...u3(a),...Array.from(new TextEncoder().encode(e))])],r=a.length-4;for(let o=0;oi.length===3&&i[0]===13,d3=i=>i.length===7||i.some((e,t)=>e===rh&&i[t+1]===240),oh=()=>typeof navigator>"u"?void 0:navigator.serial,br=()=>oh()!==void 0,h3=(...i)=>`exec(${JSON.stringify(i.join("; "))})`,Fs=(i,e=24)=>h3("cyberpi.display.clear()",`cyberpi.display.show_label(${JSON.stringify(i)}, ${e}, 'center')`),lh=Fs("VisuBot",32);class g3{constructor(){y(this,"port");y(this,"writer");y(this,"reader");y(this,"loop");y(this,"rx",[]);y(this,"idx",1);y(this,"frameWaiters",[]);y(this,"waiting",new Map);y(this,"queue",Promise.resolve());y(this,"listeners",new Set);y(this,"error");y(this,"connecting",!1)}listen(e){return this.listeners.add(e),()=>this.listeners.delete(e)}changed(){for(const e of this.listeners)e()}get connected(){return this.writer!==void 0&&!this.connecting}async connect(){const e=oh();if(!e)throw new Error("Web Serial");const t=await e.requestPort();await t.open({baudRate:115200}),this.port=t,this.writer=t.writable.getWriter(),this.error=void 0,this.connecting=!0,this.changed(),this.loop=this.readLoop(),window.addEventListener("pagehide",()=>void this.disconnect(),{once:!0}),await new Promise(n=>setTimeout(n,3e3)),this.writer&&(this.rx.length=0,this.connecting=!1,this.changed(),await this.run(lh))}async disconnect(e){if(!this.port)return this.error=e,this.changed();if(!e&&this.writer&&!this.connecting)for(const r of["mbot2.EM_stop('ALL')","cyberpi.led.off()",Fs("Bis bald!")])await this.send(r,pr,2e3).catch(()=>{});const t=this.port,n=this.writer,a=this.reader,s=this.loop;this.port=this.writer=this.reader=this.loop=void 0,this.error=e,this.connecting=!1;for(const r of this.waiting.values())r.reject(new Error(e??"getrennt"));this.waiting.clear();try{await(a==null?void 0:a.cancel()),await s,await(n==null?void 0:n.close())}catch{}try{n==null||n.releaseLock(),await t.close()}catch(r){console.warn("[mBot2] Schließen",r.message)}this.changed()}run(e){return this.send(e,pr,3e4).then(()=>{})}ask(e){return this.send(e,t3,3e3)}async upload(e,t=()=>{}){if(this.port||await this.connect(),!this.writer)throw new Error(this.error??"nicht verbunden");const n=c3(e),a=6+n.length+3;let s=0;const r=()=>t(++s,a),o=async()=>{await this.sendFrame(Rl(o3),m3),r();for(const l of l3)await this.send(l,pr,3e3),r()};await o(),await o();for(const l of n)await this.sendFrame(l,d3),r();s=a-3,await o(),await this.restart()}sendFrame(e,t){const n=this.queue.then(async()=>{for(let a=0;a<3;a++){if(!this.writer)throw new Error("nicht verbunden");let s=()=>{};const r=new Promise(u=>s=u),o={match:t,resolve:s};this.frameWaiters.push(o),await this.writer.write(e);const l=await Promise.race([r.then(()=>!0),new Promise(u=>setTimeout(()=>u(!1),3e3))]);if(this.frameWaiters=this.frameWaiters.filter(u=>u!==o),l)return}throw new Error("keine Antwort")});return this.queue=n.catch(()=>{}),n}async restart(){const e=this.port;await this.disconnect("restart"),this.error=void 0,await new Promise(t=>setTimeout(t,300)),await e.open({baudRate:115200}),await new Promise(t=>setTimeout(t,500)),await e.close(),this.changed()}send(e,t,n){const a=this.queue.then(()=>new Promise((s,r)=>{if(!this.writer)return r(new Error("nicht verbunden"));const o=this.idx;this.idx=this.idx%65535+1;const l=setTimeout(()=>{this.waiting.delete(o),r(new Error("keine Antwort"))},n);this.waiting.set(o,{resolve:u=>(clearTimeout(l),s(u)),reject:u=>(clearTimeout(l),r(u))}),this.writer.write(n3(e,t,o)).catch(u=>{this.waiting.delete(o),r(u)})}));return this.queue=a.catch(()=>{}),a}async readLoop(){var e;for(;(e=this.port)!=null&&e.readable;){const t=this.port.readable.getReader();this.reader=t;try{for(;;){const{value:n,done:a}=await t.read();if(a)break;this.rx.push(...n);for(const s of a3(this.rx)){const r=this.frameWaiters.findIndex(u=>u.match(s));r>=0&&this.frameWaiters.splice(r,1)[0].resolve();const o=i3(s);if(!o)continue;const l=this.waiting.get(o.idx);this.waiting.delete(o.idx),l==null||l.resolve(o.value)}}}catch(n){const a=["BufferOverrunError","FramingError","BreakError","ParityError"].includes(n.name);console.warn("[mBot2] Lesefehler",n.name,n.message),!a&&this.port&&this.disconnect(n.message)}finally{t.releaseLock()}if(!this.writer)break}}}const ge=new g3,uh=5,p3=i=>Number.isInteger(i)&&i>=0&&iString(Math.round(i*100)/100),yi={forward:{args:1,defaults:[lu],python:([i])=>`mbot2.straight(${ke(i)})`,label:([i])=>`${ke(i)} cm vorwärts`},backward:{args:1,defaults:[lu],python:([i])=>`mbot2.straight(${ke(-i)})`,label:([i])=>`${ke(i)} cm rückwärts`},turnLeft:{args:1,defaults:[90],python:([i])=>`mbot2.turn(${ke(-i)})`,label:([i])=>`${ke(i)}° nach links drehen`},turnRight:{args:1,defaults:[90],python:([i])=>`mbot2.turn(${ke(i)})`,label:([i])=>`${ke(i)}° nach rechts drehen`},stop:{args:0,python:()=>'mbot2.EM_stop("ALL")',label:()=>"anhalten"},drive:{args:2,python:([i,e])=>`mbot2.drive_power(${ke(i)}, ${ke(-e)})`,label:([i,e])=>`Räder links ${ke(i)} %, rechts ${ke(e)} %`},setLed:{args:3,python:([i,e,t])=>`cyberpi.led.on(${ke(i)}, ${ke(e)}, ${ke(t)})`,label:([i,e,t])=>`LEDs (${ke(i)}, ${ke(e)}, ${ke(t)})`},ledOff:{args:0,python:()=>"cyberpi.led.off()",label:()=>"LEDs aus"},ledColor:{args:1,text:!0,choices:Object.keys(ts),valid:([i])=>p3(i),python:([i],e)=>`cyberpi.led.on(${ts[e].join(", ")}, id=${i+1})`,label:([i],e)=>`LED ${i}: ${e}`},playTone:{args:2,python:([i,e])=>`cyberpi.audio.play_tone(${ke(i)}, ${ke(e/1e3)})`,label:([i,e])=>`Ton ${ke(i)} Hz, ${ke(e)} ms`},pause:{args:1,label:([i])=>`${ke(i)} ms warten`},resetTimer:{args:0,python:()=>"cyberpi.timer.reset()",label:()=>"Stoppuhr auf 0"},emotion:{args:0,text:!0,choices:f3,python:(i,e)=>`cyberpi.emotion.${e}()`,label:(i,e)=>`Gefühl: ${e}`},showText:{args:0,text:!0,python:(i,e)=>Fs(e),label:(i,e)=>`Bildschirm: ${e}`}},uu={red:{de:"rot",en:"red"},green:{de:"grün",en:"green"},blue:{de:"blau",en:"blue"},yellow:{de:"gelb",en:"yellow"},cyan:{de:"türkis",en:"cyan"},purple:{de:"lila",en:"purple"},white:{de:"weiß",en:"white"},black:{de:"schwarz",en:"black"}};let Gl="en";function b3(i){Gl=i==="de"?"de":"en"}const x3=()=>Gl;function ch(i){const e=i.trim().toLowerCase(),t=uu[e]??Object.values(uu).find(n=>n.de===e);return t?t[Gl]:e}const c1=i=>({python:`cyberpi.controller.is_press('${i}')`,simulated:!1}),At={getDistance:{python:"mbuild.ultrasonic2.get(1)",simulated:100},getLine:{python:"mbuild.quad_rgb_sensor.get_line_sta('all', 1)",simulated:0},isLineLeft:{python:"mbuild.quad_rgb_sensor.is_line('L1', 1)",simulated:!1},isLineRight:{python:"mbuild.quad_rgb_sensor.is_line('R1', 1)",simulated:!1},getColor:{python:"mbuild.quad_rgb_sensor.get_color_sta('L1', 1)",simulated:"white"},isButtonA:c1("a"),isButtonB:c1("b"),isJoystickUp:c1("up"),isJoystickDown:c1("down"),isJoystickLeft:c1("left"),isJoystickRight:c1("right"),getBrightness:{python:"cyberpi.get_bri()",simulated:50},getLoudness:{python:"cyberpi.get_loudness('maximum')",simulated:0},getPitch:{python:"cyberpi.get_pitch()",simulated:0},getRoll:{python:"cyberpi.get_roll()",simulated:0},isShaken:{python:"cyberpi.is_shake()",simulated:!1},getBattery:{python:"cyberpi.get_battery()",simulated:100},getTimer:{python:"cyberpi.timer.get()",simulated:0}};function v3(i){const e=new Set;for(const t of i.matchAll(/\bmbot\s*\.\s*([A-Za-z_]\w*)\s*\(\s*\)/gu))t[1]in At&&e.add(t[1]);return[...e]}function y3(i){const e=/^mbot\s*\.\s*led\s*\(([^()]*(?:\([^()]*\)[^()]*)*)\)\s*\.\s*setColor\s*\(([\s\S]*)\)\s*;?$/u.exec(i.trim());if(e)return{method:"ledColor",args:[e[1].trim(),e[2].trim()]};const t=/^mbot\s*\.\s*([A-Za-z_]\w*)\s*\(([\s\S]*)\)\s*;?$/u.exec(i.trim());if(!t)return;const n=t[2].trim();return{method:t[1],args:n===""?[]:I3(n)}}function ns(i,e){const t=yi[i];if(!t)return;const n=e.length===0&&t.defaults?t.defaults:e;if(n.length===t.args)return!t.valid||t.valid(n)?n:void 0}function cu(i,e,t=""){var a;const n=yi[i];return{method:i,args:e,python:(a=n.python)==null?void 0:a.call(n,e,t),waitMs:i==="pause"?Math.max(0,e[0]):void 0,label:n.label(e,t),...n.text?{text:t}:{}}}function mh(i){return i.map(e=>[e.method,...e.args.map(ke),...e.text!==void 0?[JSON.stringify(e.text)]:[]].join(" "))}function w3(i){let e=0;const t=i.trim(),n=()=>{const s=[];for(;;){for(;t[e]===" "||t[e]===",";)e++;if(e>=t.length||t[e]===")")return s;const r=/^(\d+)\s*[x×]\s*\(/u.exec(t.slice(e));if(r){e+=r[0].length;const m=n();if(t[e]!==")")throw new Error(`„)“ fehlt in „${i}“`);e++;for(let d=0;d{if(!(n in At))return t;const a=e(n);return typeof a=="string"?JSON.stringify(n==="getColor"?ch(a):a):String(a)}):i}function I3(i){const e=[];let t=0,n=!1,a=0;for(let s=0;s{const a=t==="turn"?((n+180)%360+360)%360-180:n;if(Math.abs(a)<1e-6)return[];const s=Math.round(Math.abs(a)*100)/100;return t==="drive"?[`${a>0?"forward":"backward"} ${s}`]:[a===-180?"turnRight 180":`${a>0?"turnRight":"turnLeft"} ${s}`]})}function dh(i){let e=0;const t=i.trim(),n=()=>{const s=[];for(;;){for(;t[e]===" "||t[e]===",";)e++;if(e>=t.length||t[e]===")")return s;const r=/^(\d+)\s*[x×]\s*\(/u.exec(t.slice(e));if(r){e+=r[0].length;const u=n();if(t[e]!==")")throw new Error(`„)“ fehlt in „${i}“`);e++;for(let c=0;ca===i[s%t])){const a=X1(i.slice(0,t));return`${n} x ${t===1?a:`(${a})`}`}}return i.join(", ")}const hh=["cyberpi","screen","joystick","buttons","leds","lightSensor","microphone","shield","powerSwitch","motors","wheels","ultrasonic","lineSensor","caster","chassis"],k3=i=>hh.includes(i),S3=100;function gh(i){switch(i.kind){case"finished":return"Simulation finished.";case"infiniteLoopWithoutBody":return"Infinite loop has no body.";case"unsupportedStatement":return`Unsupported statement: ${i.text}`;case"invalidExpression":return`Invalid expression: ${i.text}`;case"unknownVariable":return`Unknown variable: ${i.text}`;case"divisionByZero":return"Division by zero.";case"wholeNumberExpected":return"Please enter a whole number.";case"numberExpected":return"Please enter a number.";case"booleanExpected":return"Please enter true or false.";case"subprogramNotFound":return`No open diagram is called ${i.text}. The call was skipped.`;case"callTooDeep":return"Too many nested calls. Does a subprogram call itself?";case"callArguments":return`The call does not match the header of ${i.text}. Check the values in the parentheses.`;case"missingReturn":return`${i.text} ended without returning a value with return.`;case"fileNotFound":return`There is no file called ${i.text}.`;case"endOfFile":return`The file ${i.text} has no more lines.`;case"nullValue":return`${i.text} is null.`;case"other":return i.text}}class Ne extends Error{constructor(e){super(gh(e)),this.notice=e}}const Ke=i=>new Ne({kind:"unsupportedStatement",text:i}),R=i=>new Ne({kind:"invalidExpression",text:i}),K1=i=>new Ne({kind:"unknownVariable",text:i}),T3=()=>new Ne({kind:"divisionByZero"}),as=new Map;function _3(i,e){as.set(i,e)}const ph=()=>[...as];function mu(i){return i instanceof Ne?i.notice:{kind:"other",text:i instanceof Error?i.message:String(i)}}function A3(i){if(i===0)return"0";if(!Number.isFinite(i))return Number.isNaN(i)?"nan":i>0?"inf":"-inf";const e=Math.floor(Math.log10(Math.abs(Number(i.toPrecision(12)))));if(e<-4||e>=12){const[n,a]=i.toExponential(11).split("e"),s=n.includes(".")?n.replace(/0+$/,"").replace(/\.$/,""):n,r=Number(a);return`${s}e${r<0?"-":"+"}${String(Math.abs(r)).padStart(2,"0")}`}const t=i.toFixed(Math.max(0,11-e));return t.includes(".")?t.replace(/0+$/,"").replace(/\.$/,""):t}function du(i){return Number.isFinite(i)&&Math.round(i)===i?i.toFixed(1):A3(i)}function _e(i){switch(i.kind){case"int":return String(i.value);case"double":return du(i.value);case"string":return i.value;case"boolean":return String(i.value);case"intArray":return"["+i.value.map(String).join(", ")+"]";case"doubleArray":return"["+i.value.map(du).join(", ")+"]";case"stringArray":return"["+i.value.join(", ")+"]";case"booleanArray":return"["+i.value.map(String).join(", ")+"]";case"grid":return"["+O3(i).join(", ")+"]";case"reader":return`${i.className}(${i.file})`;case"writer":return`PrintWriter(${i.file})`;case"null":return"null"}}function O3(i){return i.value.map(e=>"["+e.map(t=>_e(vo(i.elementType,t))).join(", ")+"]")}function vo(i,e){switch(i){case"int":return{kind:"int",value:e};case"double":return{kind:"double",value:e};case"string":return{kind:"string",value:e};case"boolean":return{kind:"boolean",value:e}}}function hu(i){return i==="string"?"":i==="boolean"?!1:0}function yo(i){return i.kind==="intArray"||i.kind==="doubleArray"||i.kind==="stringArray"||i.kind==="booleanArray"||i.kind==="grid"}function C3(i){return i.kind==="int"||i.kind==="double"?i.value:NaN}const It=i=>({kind:"int",value:i}),kt=i=>({kind:"double",value:i}),Hl=i=>i!==void 0&&/\s/u.test(i),ss=i=>new RegExp("\\p{L}","u").test(i),ei=i=>new RegExp("\\p{N}","u").test(i);function oi(i){const e=Array.from(i);return e.length===0||!(ss(e[0])||e[0]==="_")?!1:e.every(t=>ss(t)||ei(t)||t==="_")}function tn(i){switch(i.toLowerCase()){case"int":return"int";case"double":return"double";case"string":return"string";case"char":return"string";case"boolean":case"bool":return"boolean";default:return}}function gu(i){return i.kind==="int"?"int":i.kind==="double"?"double":i.kind==="boolean"?"boolean":"string"}function lt(i){const e=Array.from(i);if(e.length===3&&e[0]==="'"&&e[2]==="'")return e[1];if(e.length<2||e[0]!=='"'||e[e.length-1]!=='"')return;const t=e.slice(1,-1).join("");if(/^(?:[^"\\]|\\.)*$/u.test(t))return t.replaceAll('\\"','"').replaceAll("\\n",` +`)}function pu(i){return i.replaceAll("(int)","").replaceAll("(double)","").trim()}function Vl(i){const e=new Array(i.length).fill(!1);let t=0,n=!1,a=!1;return i.forEach((s,r)=>{if(n){a?a=!1:s==="\\"?a=!0:s==='"'&&(n=!1);return}switch(s){case'"':n=!0;break;case"(":case"[":t+=1;break;case")":case"]":t-=1;break;default:e[r]=t===0}}),e}function rs(i,e){const t=Array.from(i),n=Array.from(e),a=Vl(t),s=[];let r=[],o=0;for(;ot[o+c]===u)&&a.slice(o,l).every(Boolean)){s.push(r.join("").trim()),r=[],o=l;continue}r.push(t[o]),o+=1}return s.push(r.join("").trim()),s}function j3(i){const e=Array.from(i),t=Vl(e);for(let n=0;n=","<=","==","!="].includes(o)&&(a=o)}if(a===void 0&&(e[n]==="<"||e[n]===">")&&(a=e[n]),a===void 0)continue;const s=e.slice(0,n).join("").trim(),r=e.slice(n+a.length).join("").trim();return{lhs:s,op:a,rhs:r}}}function Js(i,e){let t=0,n=!1,a=!1;for(let s=e;se.length||!t.every((r,o)=>e[a+o]===r))continue;const s=a+t.length-1;if(Js(e,s)===e.length-1)return{lhs:e.slice(0,a).join("").trim(),rhs:e.slice(s+1,-1).join("").trim()}}}function Ki(i){const e=i.trim();for(const t of["if","while","until","switch"]){if(!e.startsWith(t))continue;const n=e.slice(t.length);if(!(n===""||Hl(n[0])||n[0]==="("))continue;let a=n.trim();const s=fh(a);return s!==void 0&&(a=s),a===""?"true":a}return e===""?"true":e}function g1(i){const e=i.trim(),t=e.indexOf("[");if(!e.endsWith("]")||t<0)return;const n=e.slice(0,t).trim();if(!oi(n))return;const a=[];let s=t;for(;s2))return{arrayName:n,indexExpressions:a}}function D3(i){const e=i.trim();if(!e.endsWith(")"))return;const t=/^([A-Za-z_]\w*(?:\s*\[[^\[\]]*\])*|"(?:[^"\\]|\\.)*")\s*\.\s*([A-Za-z_]\w*)\s*\(/u.exec(e);if(!t)return;const n=Array.from(e),a=Array.from(t[0]).length-1;if(Js(n,a)!==n.length-1)return;const s=n.slice(a+1,-1).join("").trim();return{target:t[1],method:t[2],args:s===""?[]:rs(s,",")}}function fu(i){return oi(i)||g1(i)!==void 0}function xr(i){const e=[];let t="",n=!1,a=!1,s=0;for(const r of i){if(a){t+=r,a=!1;continue}if(r==="\\"){t+=r,a=!0;continue}if(r==='"'){n=!n,t+=r;continue}if(!n&&r==="("&&(s+=1),!n&&r===")"&&(s-=1),r==="+"&&!n&&s===0){e.push(t),t="";continue}t+=r}if(n)throw R(i);return e.push(t),e}function B3(i){const e=[];let t=0,n="";for(const a of i){if(a==="{"&&(t+=1),a==="}"&&(t-=1),a===","&&t===0){e.push(n),n="";continue}n+=a}return n.trim()!==""&&e.push(n),e}function bu(i){const e=Array.from(i),t=[];let n=0;for(;n1)throw R(i)}else if(!ei(e[n]))break;n+=1}const o=e.slice(s,n).join("");if(o==="."||!/^[0-9]*\.?[0-9]*$/.test(o))throw R(i);t.push({t:"number",literal:o,value:Number(o)});continue}if(ss(a)||a==="_"){const s=n;for(;n=0&&s=0&&o=0&&s|&&|\|\||^\s*!/u.test(e)}function Kn(i){let e=i.trim();for(;e.endsWith(";");)e=e.slice(0,-1).trim();return e}function vu(i){const e=i.slice(0,3);for(;e.length<3;)e.push("");return e}function zo(i){const e=i.map(t=>Kn(t).trim());return e.length===1&&e[0].includes(";")?vu(e[0].split(";").map(t=>t.trim())):vu(e)}const dt=i=>i.frame?{frame:i.frame,callPath:i.callPath}:{};function $t(i,e=[],t={}){const n=[],a=s=>n.push(t.frame?{...s,...t}:s);return i.forEach((s,r)=>{const o=[...e,r],l=s.textLines.join(" ").trim();switch(s.type){case S.anweisung:l!==""&&l!=="ø"&&a({path:o,text:l,kind:"statement"});break;case S.verzweigung:a({path:o,text:l||"true",kind:"branch",cases:s.cases});break;case S.fallauswahl:a({path:o,text:l||"0",kind:"switchSelection",cases:s.cases});break;case S.forSchleife:a({path:o,text:l,kind:"forLoopStart",loopBody:s.loopBody,forParts:zo(s.textLines)});break;case S.whileSchleife:a({path:o,text:l||"true",kind:"whileLoop",loopBody:s.loopBody});break;case S.doUntilSchleife:a({path:o,text:l||"true",kind:"doUntilLoop",loopBody:s.loopBody});break;case S.endlosschleife:a({path:o,text:l||"true",kind:"infiniteLoop",loopBody:s.loopBody});break;case S.aussprung:a({path:o,text:l,kind:"jump"});break;case S.aufruf:l!==""&&l!=="ø"&&a({path:o,text:l,kind:"call"});break}}),n}function Z3(i,e){const t=i.trim().replaceAll(",",".");switch(e){case"int":if(!/^[+-]?[0-9]+$/.test(t))throw new Ne({kind:"wholeNumberExpected"});return It(Number(t));case"double":if(!/^[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?$/.test(t))throw new Ne({kind:"numberExpected"});return kt(Number(t));case"string":return{kind:"string",value:i};case"boolean":switch(t.toLowerCase()){case"true":case"wahr":return{kind:"boolean",value:!0};case"false":case"falsch":return{kind:"boolean",value:!1};default:throw new Ne({kind:"booleanExpected"})}}}function yu(){return{stepIndex:0,variables:new Map,outputLines:[],isHalted:!1,files:new Map,robotActions:[]}}function L3(i,e){for(let t=0;tt===e.path[n])}function zt(i){const e=/^(void|int|double|String|boolean)\s+([A-Za-z_]\w*)\s*\((.*)\)$/u.exec(Kn(i));if(!e)return;const t=[];if(e[3].trim()!=="")for(const n of e[3].split(",")){const a=/^(int|double|String|boolean|char)\s*((?:\[\s*\]){0,2})\s+([A-Za-z_]\w*)$/u.exec(n.trim());if(!a)return;const s=(a[2].match(/\[/gu)??[]).length;t.push({type:tn(a[1]),name:a[3],...s>0?{dims:s}:{}})}return{returnType:tn(e[1]),name:e[2],params:t}}function bh(i){const e=/^(?:(?:(int|double|String|boolean)\s+)?([A-Za-z_]\w*)\s*=\s*)?([A-Za-z_]\w*)\s*\((.*)\)$/u.exec(Kn(i));if(e)return{targetType:e[1]?tn(e[1]):void 0,target:e[2],name:e[3],args:e[4].trim()===""?[]:rs(e[4],",")}}function os(i){var t,n;const e=Kn(i);return((t=zt(e))==null?void 0:t.name)??((n=bh(e))==null?void 0:n.name)??e.replace(/\(\s*\)$/u,"").trim()}class wi{constructor(e,t=()=>{}){y(this,"steps");y(this,"state",yu());y(this,"nextFrame",1);y(this,"callDepth",0);y(this,"frames",new Map);y(this,"peeking",!1);y(this,"robotSensors",{});y(this,"pseudocode");y(this,"decided");y(this,"afterOutput",!1);this.resolveSubprogram=t,this.steps=$t(e.elements),this.pseudocode=!!e.pseudocode}get currentStepPath(){const e=this.steps[this.state.stepIndex];return(e==null?void 0:e.callPath)??(e==null?void 0:e.path)}get canStep(){return!this.state.isHalted&&!this.state.inputRequest&&this.state.stepIndex ${_e(n)}`}catch(n){this.state.inputErrorNotice=mu(n);return}this.state.inputRequest=void 0,this.state.inputErrorNotice=void 0,this.state.stepIndex+=1,this.state.notice=this.finishedIfAtEnd()}}provideDecision(e){var s;if(((s=this.state.inputRequest)==null?void 0:s.valueType)==="string")return this.state.inputRequest=void 0,this.decided=e.trim(),this.step();const t=e.trim().toLowerCase(),n=["true","wahr","ja","yes","sim","verdadeiro"].includes(t),a=["false","falsch","nein","no","não","nao","falso"].includes(t);if(!n&&!a){this.state.inputErrorNotice={kind:"booleanExpected"};return}this.state.inputRequest=void 0,this.state.inputErrorNotice=void 0,this.decided=n,this.step()}condition(e){if(!this.pseudocode)return this.evaluateBool(e);const t=this.decided;if(typeof t=="boolean")return this.decided=void 0,t;this.state.inputRequest={variableName:"",valueType:"boolean",prompt:`${e} (true/false)`,decision:!0},this.state.inputErrorNotice=void 0,this.state.notice=void 0}finishedIfAtEnd(){return this.state.stepIndex>=this.steps.length?{kind:"finished"}:void 0}splice(e){this.steps.splice(this.state.stepIndex,1,...e)}noticeAfterEntering(e){return e.length>0?void 0:this.finishedIfAtEnd()}executeBranch(e){const t=e.cases;if(!t||t.length<2)throw Ke(e.text);const n=Ki(e.text),a=this.condition(n);if(a===void 0)return;const s=a?0:1,r=$t(t[s].elements,[...e.path,s],dt(e));this.splice(r),this.state.lastTrace=`${n} -> ${a}`,this.state.notice=this.noticeAfterEntering(r)}executeSwitchSelection(e){const t=e.cases;if(!t||t.length===0)throw Ke(e.text);const n=Ki(e.text);let a;if(this.pseudocode){const r=this.decided;if(typeof r!="string"){const l=t.map(u=>u.name).join(" / ");this.state.inputRequest={variableName:"",valueType:"string",prompt:`${n} (${l})`,decision:!0},this.state.notice=void 0;return}this.decided=void 0;const o=t.findIndex(l=>l.name.trim().toLowerCase()===r.toLowerCase());a=o>=0?o:t.length-1}else a=L3(this.evaluateSwitchSelector(n),t)??t.length-1;const s=$t(t[a].elements,[...e.path,a],dt(e));this.splice(s),this.state.lastTrace=`${n} -> ${t[a].name}`,this.state.notice=this.noticeAfterEntering(s)}executeForLoopStart(e){if(this.pseudocode)return this.splice([{...e,kind:"whileLoop"}]);const t=zo(e.forParts??[e.text]);t[0]!==""&&this.executeStatement(t[0]),this.splice([{...dt(e),path:e.path,text:t[1],kind:"forLoopCondition",loopBody:e.loopBody,forParts:t}])}executeForLoopCondition(e){const t=zo(e.forParts??[e.text]),n=t[1]===""?"true":t[1],a=this.condition(n);if(a!==void 0)if(this.state.lastTrace=`${n} -> ${a}`,a){const s=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...s,{...dt(e),path:e.path,text:t[2],kind:"forLoopIncrement",loopBody:e.loopBody,forParts:t},{...dt(e),path:e.path,text:t[1],kind:"forLoopCondition",loopBody:e.loopBody,forParts:t}])}else this.splice([]),this.state.notice=this.finishedIfAtEnd()}executeForLoopIncrement(e){const t=e.text.trim();t!==""&&this.executeIncrement(t),this.splice([])}executeWhileLoop(e){const t=Ki(e.text),n=this.condition(t);if(n!==void 0)if(this.state.lastTrace=`${t} -> ${n}`,n){const a=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...a,{...dt(e),path:e.path,text:e.text,kind:"whileLoop",loopBody:e.loopBody}]),this.state.notice=this.noticeAfterEntering(a)}else this.splice([]),this.state.notice=this.finishedIfAtEnd()}enterDoUntilLoop(e){const t=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...t,{...dt(e),path:e.path,text:e.text,kind:"doUntilCondition",loopBody:e.loopBody}]),this.state.notice=this.noticeAfterEntering(t)}executeDoUntilCondition(e){const t=Ki(e.text),n=this.condition(t);if(n!==void 0)if(this.state.lastTrace=`${t} -> ${n}`,n){const a=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...a,{...dt(e),path:e.path,text:e.text,kind:"doUntilCondition",loopBody:e.loopBody}])}else this.splice([]),this.state.notice=this.finishedIfAtEnd()}enterInfiniteLoop(e){const t=$t(e.loopBody??[],[...e.path,0],dt(e));this.splice([...t,{...dt(e),path:e.path,text:e.text,kind:"infiniteLoop",loopBody:e.loopBody}]),this.state.lastTrace="true -> true",this.state.notice=t.length>0?void 0:{kind:"infiniteLoopWithoutBody"}}executeJump(e){const t=e.frame??0,n=o=>o.lengthl===e.path[u]);let a=this.steps.length,s="end";for(let o=this.state.stepIndex+1;o ${s}`,s==="return"&&this.finishFrame(r),this.state.notice=this.finishedIfAtEnd()}executeCall(e){const t=e.text,n=this.resolveSubprogram(os(t));if(!n){this.splice([]),this.state.lastTrace=`${t} -> ?`,this.state.notice={kind:"subprogramNotFound",text:t},this.state.stepIndex>=this.steps.length&&(this.state.notice={kind:"finished"});return}const a=bh(t),s=zt(n.caption);if(s?((a==null?void 0:a.args.length)??0)!==s.params.length||(a==null?void 0:a.target)!==void 0&&!s.returnType:a!==void 0&&(a.args.length>0||a.target!==void 0))throw new Ne({kind:"callArguments",text:(s==null?void 0:s.name)??os(t)});if(this.callDepth>=S3)throw new Ne({kind:"callTooDeep"});const o=new Map,l=[];s==null||s.params.forEach((d,h)=>{const g=a.args[h].trim();if(!d.dims){o.set(d.name,this.evaluateExpression(g,d.type));return}const f=this.state.variables.get(g);if(!f)throw/^[A-Za-z_]\w*$/u.test(g)?new Ne({kind:"unknownVariable",text:g}):R(g);if(!(d.dims===1?f.kind===`${d.type}Array`:f.kind==="grid"&&f.elementType===d.type))throw R(g);o.set(d.name,f),l.push({param:d.name,callerName:g})}),this.callDepth+=1;const u={frame:this.nextFrame++,callPath:e.callPath??e.path};s&&(this.frames.set(u.frame,{saved:this.state.variables,header:s,call:a,references:l}),this.state.variables=o);const c=$t(n.elements,[],u);this.splice([...c,{...u,path:e.path,text:t,kind:"callEnd"}]);const m=s==null?void 0:s.params.map((d,h)=>`${d.name} = ${d.dims?a.args[h].trim():_e(o.get(d.name))}`).join(", ");this.state.lastTrace=m?`${t} -> ${m}`:`${t} -> call`}executeCallEnd(e){this.callDepth-=1,this.splice([]),this.state.lastTrace=`${e.text} -> return`,this.finishFrame(e),this.state.notice=this.finishedIfAtEnd()}executeReturn(e){const t=e.frame??0,n=Kn(e.text).slice(6).trim(),a=this.frames.get(t);if(a&&n!==""){if(!a.header.returnType)throw R(e.text);a.returnValue=this.evaluateExpression(n,a.header.returnType)}const s=a!=null&&a.returnValue?`${e.text} -> ${_e(a.returnValue)}`:`${e.text} -> return`;if(t===0){this.steps.splice(this.state.stepIndex),this.state.lastTrace=s,this.state.notice={kind:"finished"};return}let r=this.state.stepIndex+1;for(;r0?new Map(t.saved):t.saved;for(const c of t.references){const m=this.state.variables.get(c.param);m&&n.set(c.callerName,m)}this.state.variables=n;const a=t.returnValue;if(t.header.returnType&&!a)throw new Ne({kind:"missingReturn",text:t.header.name});const s=(l=t.call)==null?void 0:l.target;if(!s||!a)return;let r=(u=t.call)==null?void 0:u.targetType;if(!r)try{r=this.inferTargetValueType(s)}catch{r=t.header.returnType}const o=r==="double"&&a.kind==="int"?kt(a.value):r==="string"?{kind:"string",value:_e(a)}:a;if(gu(o)!==r)throw R(e.text);this.assignValue(o,s),this.state.lastTrace=`${s} = ${e.text.slice(e.text.indexOf("=")+1).trim()} -> ${_e(o)}`}executeStatement(e){const t=this.state,n=e.trim(),a=n.toLowerCase(),s=this.afterOutput;if(this.afterOutput=!1,a.startsWith("input:")){t.inputRequest=this.parseInputRequest(n,s),t.outputLineOpen=!1,t.inputErrorNotice=void 0;return}const r=/^System\s*\.\s*out\s*\.\s*(println|print)\s*\(([\s\S]*)\)\s*;?$/u.exec(n);if(a.startsWith("output:")||a.startsWith("print:")||r){const v=r?r[2]:n.slice(a.startsWith("output:")?7:6),w=this.peek(()=>this.renderOutputExpression(v)),I=v.trim()===""?"":this.evaluateOutputExpression(v);t.outputLineOpen&&t.outputLines.length?t.outputLines[t.outputLines.length-1]+=I:t.outputLines.push(I),t.outputLineOpen=(r==null?void 0:r[1])==="print",this.afterOutput=!0,t.lastTrace=`${w} -> ${I}`;return}const o=y3(n);if(o){this.executeMBotCommand(o.method,o.args,n);return}if(this.executeFileStatement(n))return;if(n.endsWith("++")||n.endsWith("--")||n.includes("+=")||n.includes("-=")){this.executeIncrement(n);return}const l=/^(?:final\s+)?([A-Za-z]+)\s+([A-Za-z_]\w*(?:\s*,\s*[A-Za-z_]\w*)*)$/u.exec(Kn(n).trim()),u=l?tn(l[1]):void 0;if(l&&u){const v=l[2].split(",").map(w=>w.trim());for(const w of v)t.variables.set(w,vo(u,hu(u)));t.lastTrace=v.map(w=>`${w} = ${_e(t.variables.get(w))}`).join(", ");return}const c=n.indexOf("=");if(c<0)throw Ke(n);const m=n.slice(0,c).trim(),d=n.slice(c+1),h=this.parseArrayDeclaration(m,d);if(h){t.variables.set(h.name,h.value),t.lastTrace=`${h.name} = new ${h.typeName}[${h.count}]`;return}const g=this.parseAssignmentTarget(m);let f;try{f=this.peek(()=>this.renderNumericExpression(d))}catch{f=d.trim()}let b=g.valueType;if(!b)try{b=this.inferTargetValueType(g.variableName)}catch{b="int"}const x=this.evaluateExpression(d,b);this.assignValue(x,g.variableName),t.lastTrace=`${g.variableName} = ${f} -> ${_e(x)}`}executeMBotCommand(e,t,n){var r;if((r=yi[e])!=null&&r.text){const o=yi[e];if(t.length!==o.args+1)throw R(n);const l=ns(e,t.slice(0,-1).map(m=>this.evaluateDouble(m)));if(!l)throw R(n);const u=cu(e,l,this.evaluateOutputExpression(t[t.length-1])),c=o.choices;if(c&&!c.includes(u.text??""))throw R(`${n} (${c.join(", ")})`);this.state.robotActions.push(u),this.state.lastTrace=`${n} -> ${u.label}`;return}const a=ns(e,t.map(o=>this.evaluateDouble(o)));if(!a)throw R(n);const s=cu(e,a);this.state.robotActions.push(s),this.state.lastTrace=`${n} -> ${s.label}`}executeFileStatement(e){const t=this.state,n=Kn(e).trim(),a=/^(?:(Scanner|BufferedReader|PrintWriter)\s+)?([A-Za-z_]\w*)\s*=\s*new\s+(Scanner|BufferedReader|PrintWriter)\s*\(([\s\S]*)\)$/u.exec(n);if(a){const[,c,m,d,h]=a;if(c&&c!==d)throw R(n);const g=d==="Scanner"?/^new\s+File\s*\(([\s\S]+)\)$/u.exec(h.trim()):d==="BufferedReader"?/^new\s+FileReader\s*\(([\s\S]+)\)$/u.exec(h.trim()):/^(?:new\s+(?:File|FileWriter)\s*\(([\s\S]+)\)|([\s\S]+))$/u.exec(h.trim());if(!g)throw Ke(n);const f=this.fileNameValue(g[1]??g[2]);if(d==="PrintWriter")t.variables.set(m,{kind:"writer",file:f,text:""});else{const x=this.fileContent(f).split(/\r?\n/u);x[x.length-1]===""&&x.pop(),t.variables.set(m,{kind:"reader",className:d,file:f,lines:x,next:0})}return t.lastTrace=`${m} = new ${d}(${f})`,!0}const s=/^Files\s*\.\s*writeString\s*\(\s*(?:Path\s*\.\s*of|Paths\s*\.\s*get)\s*\(([^()]+)\)\s*,([\s\S]+)\)$/u.exec(n);if(s){const c=this.fileNameValue(s[1]),m=this.evaluateOutputExpression(s[2]);return t.files.set(c,m),t.lastTrace=`${c} ← ${JSON.stringify(m)}`,!0}const r=/^([A-Za-z_]\w*)\s*\.\s*(println|print|close)\s*\(([\s\S]*)\)$/u.exec(n),o=r&&t.variables.get(r[1]);if(!r||!o)return!1;if(o.kind==="null")throw new Ne({kind:"nullValue",text:r[1]});if(o.kind==="reader"&&r[2]==="close")return t.lastTrace=`${r[1]}.close()`,!0;if(o.kind!=="writer")return!1;if(r[2]==="close")return t.files.set(o.file,o.text),t.lastTrace=`${o.file} ← ${JSON.stringify(o.text)}`,!0;const l=r[3].trim()===""?"":this.evaluateOutputExpression(r[3]),u=r[2]==="println"?l+` +`:l;return t.variables.set(r[1],{...o,text:o.text+u}),t.lastTrace=`${r[1]}.${r[2]}(${JSON.stringify(l)})`,!0}fileNameValue(e){const t=e.trim(),n=lt(t);if(n!==void 0)return n;const a=this.evaluateReference(t);if((a==null?void 0:a.kind)==="string")return a.value;throw R(t)}fileContent(e){const t=this.state.files.get(e)??as.get(e);if(t===void 0)throw new Ne({kind:"fileNotFound",text:e});return t}readerMethod(e,t,n,a){if(n.args.length)throw R(a);const s=t.next0?"+":"-";if(r.kind==="int"){t.set(s,It(r.value+a)),this.state.lastTrace=`${s} = ${r.value} ${o} 1 -> ${r.value+a}`;return}if(r.kind==="double"){const l=r.value+a;t.set(s,kt(l)),this.state.lastTrace=`${s} = ${_e(r)} ${o} 1 -> ${_e(kt(l))}`;return}throw Ke(e)}for(const[n,a]of[["+=",1],["-=",-1]]){const s=e.indexOf(n);if(s<0)continue;const r=e.slice(0,s).trim(),o=e.slice(s+2),l=t.get(r);if(!oi(r)||!l)throw Ke(e);const u=a>0?"+":"-";if(l.kind==="int"){const c=this.evaluateInt(o),m=l.value+a*c;t.set(r,It(m)),this.state.lastTrace=`${r} = ${l.value} ${u} ${c} -> ${m}`;return}if(l.kind==="double"){const c=this.evaluateDouble(o),m=l.value+a*c;t.set(r,kt(m)),this.state.lastTrace=`${r} = ${_e(l)} ${u} ${_e(kt(c))} -> ${_e(kt(m))}`;return}throw Ke(e)}this.executeStatement(e)}parseAssignmentTarget(e){if(g1(e))return{variableName:e.trim()};const t=e.split(/\s+/u).filter(Boolean);let n,a;if(t.length===1)n=t[0];else if(t.length===2&&tn(t[0]))n=t[1],a=tn(t[0]);else if(t.length===3&&t[0]==="const"&&tn(t[1]))n=t[2],a=tn(t[1]);else throw Ke(e);if(!fu(n))throw Ke(e);return{variableName:n,valueType:a}}parseInputRequest(e,t=!1){const n=e.slice(6).trim(),a=/^(\S+)(?:\s+(\S+))?(?:\s+([\s\S]*))?$/u.exec(n);if(!a)throw Ke(e);const s=[a[1],a[2],a[3]].filter(m=>m!==void 0);let r,o,l;const u=tn(s[0]);if(s.length>=2&&u?(r=s[1],o=u,l=(s[2]??"").trim()):(r=s[0],o=this.inferTargetValueType(r),l=(s[1]??"").trim()),!fu(r))throw Ke(e);const c=lt(l)??l;return c===""&&t?this.state.outputLineOpen?{variableName:r,valueType:o,prompt:"",continuesLine:!0}:{variableName:r,valueType:o,prompt:""}:{variableName:r,valueType:o,prompt:c===""?`${r}:`:c}}parseArrayDeclaration(e,t){const n=e.split(/\s+/u).filter(Boolean);if(n.length!==2||!n[0].endsWith("[]"))return;const a=n[0].endsWith("[][]"),s=n[0].slice(0,a?-4:-2),r=tn(s),o=n[1];if(!r||!oi(o))throw Ke(e);if(a)return this.parseGridDeclaration(o,s,r,t);const l=t.trim();if(l.startsWith("{")&&l.endsWith("}")){const h=l.slice(1,-1).split(",").map(f=>f.trim());let g;switch(r){case"int":g={kind:"intArray",value:h.map(f=>this.evaluateInt(f))};break;case"double":g={kind:"doubleArray",value:h.map(f=>this.evaluateDouble(f))};break;case"string":g={kind:"stringArray",value:h.map(f=>lt(f)??this.evaluateOutputExpression(f))};break;case"boolean":g={kind:"booleanArray",value:h.map(f=>this.evaluateBool(f))};break}return{name:o,typeName:s,count:h.length,value:g}}const u=`new ${s}[`;if(!l.startsWith(u)){const h=this.evaluateStringMethod(l);if((h==null?void 0:h.kind)==="stringArray"&&r==="string")return{name:o,typeName:s,count:h.value.length,value:h}}if(!l.startsWith(u)||!l.endsWith("]"))throw Ke(t);const c=l.slice(u.length,-1),m=this.evaluateInt(c);if(m<0)throw R(c);const d=r==="int"?{kind:"intArray",value:new Array(m).fill(0)}:r==="double"?{kind:"doubleArray",value:new Array(m).fill(0)}:r==="boolean"?{kind:"booleanArray",value:new Array(m).fill(!1)}:{kind:"stringArray",value:new Array(m).fill("")};return{name:o,typeName:s,count:m,value:d}}parseGridDeclaration(e,t,n,a){var m;const s=a.trim(),r=d=>{switch(n){case"int":return this.evaluateInt(d);case"double":return this.evaluateDouble(d);case"boolean":return this.evaluateBool(d);case"string":return lt(d.trim())??this.evaluateOutputExpression(d)}};if(s.startsWith("{")&&s.endsWith("}")){const d=B3(s.slice(1,-1)).map(h=>{const g=h.trim();if(!g.startsWith("{")||!g.endsWith("}"))throw R(g);return g.slice(1,-1).trim()===""?[]:g.slice(1,-1).split(",").map(f=>r(f.trim()))});return{name:e,typeName:t,count:`${d.length}][${((m=d[0])==null?void 0:m.length)??0}`,value:{kind:"grid",elementType:n,value:d}}}const o=new RegExp(String.raw`^new\s+${t}\s*\[(.+)\]\s*\[(.+)\]$`,"u").exec(s);if(!o)throw Ke(a);const l=this.evaluateInt(o[1]),u=this.evaluateInt(o[2]);if(l<0)throw R(o[1]);if(u<0)throw R(o[2]);const c={kind:"grid",elementType:n,value:Array.from({length:l},()=>new Array(u).fill(hu(n)))};return{name:e,typeName:t,count:`${l}][${u}`,value:c}}arrayIndex(e){const t=this.evaluateInt(e);if(t<0)throw R(e);return t}evaluateReference(e){const t=e.trim(),n=this.state.variables.get(t);if(n)return n;const a=this.evaluateStringMethod(t);if(a)return a;const s=/^\(\s*char\s*\)\s*(.+)$/su.exec(t);if(s){const o=this.evaluateInt(s[1]);if(!(o>=0&&o<=1114111))throw R(t);return{kind:"string",value:String.fromCodePoint(o)}}const r=g1(t);if(r)return this.valueInArray(r.arrayName,r.indexExpressions.map(o=>this.arrayIndex(o)))}evaluateStringMethod(e){const t=D3(e);if(!t)return;const n=this.evaluateStaticCall(e,t);if(n)return n;const a=this.state.variables.get(t.target.trim());if((a==null?void 0:a.kind)==="reader")return this.readerMethod(t.target.trim(),a,t,e);if((a==null?void 0:a.kind)==="null")throw new Ne({kind:"nullValue",text:t.target.trim()});const s=lt(t.target)??this.stringValueOf(t.target);if(s===void 0)return;const r=t.args,o=d=>{const h=r[d];if(h===void 0)throw R(e);const g=lt(h.trim());if(g!==void 0)return g;const f=this.evaluateReference(h);if((f==null?void 0:f.kind)==="string")return f.value;throw R(h)},l=d=>{if(r[d]===void 0)throw R(e);return this.evaluateInt(r[d])},u=d=>{if(r.length!==d)throw R(e)},c=Array.from(s),m=(d,h)=>{if(d<0||d>h)throw R(e);return d};switch(t.method){case"length":return u(0),It(c.length);case"charAt":return u(1),{kind:"string",value:c[m(l(0),c.length-1)]};case"substring":{if(r.length!==1&&r.length!==2)throw R(e);const d=m(l(0),c.length),h=r.length===2?m(l(1),c.length):c.length;if(h0&&h[h.length-1]==="";)h.pop();return{kind:"stringArray",value:h}}default:return}}evaluateStaticCall(e,t){const n=()=>{if(t.args.length!==1)throw R(e);return t.args[0]},a=s=>{const r=lt(s.trim());if(r!==void 0)return r;const o=this.evaluateReference(s);if((o==null?void 0:o.kind)==="string")return o.value;throw R(s)};switch(`${t.target}.${t.method}`){case"Integer.parseInt":{const s=a(n()).trim();if(!/^[+-]?\d+$/u.test(s))throw new Ne({kind:"wholeNumberExpected"});return It(Number(s))}case"Double.parseDouble":{const s=Number(a(n()).trim());if(!Number.isFinite(s))throw new Ne({kind:"numberExpected"});return kt(s)}case"String.valueOf":return{kind:"string",value:this.evaluateOutputExpression(n())};case"Files.readString":{const s=/^(?:Path\s*\.\s*of|Paths\s*\.\s*get)\s*\(\s*("(?:[^"\\]|\\.)*")\s*\)$/u.exec(n().trim());if(!s)throw R(e);const r=lt(s[1]),o=as.get(r);if(o===void 0)throw new Ne({kind:"fileNotFound",text:r});return{kind:"string",value:o}}default:return}}stringValueOf(e){const t=e.trim(),n=this.state.variables.get(t);if(n)return n.kind==="string"?n.value:void 0;const a=g1(t);if(!a)return;const s=this.valueInArray(a.arrayName,a.indexExpressions.map(r=>this.arrayIndex(r)));return s.kind==="string"?s.value:void 0}substituteStringCalls(e){if(!e.includes("("))return e;let t="",n=e;const a=/([A-Za-z_]\w*(?:\[[^\[\]]*\])*|"(?:[^"\\]|\\.)*")\s*\.\s*(length|indexOf|lastIndexOf|compareTo|charAt|parseInt|parseDouble)\s*\(/u;for(let s=a.exec(n);s;s=a.exec(n)){const r=s.index+s[0].length-1,o=Js(Array.from(n),Array.from(n.slice(0,r)).length);if(o===void 0)break;const l=Array.from(n),u=l.slice(Array.from(n.slice(0,s.index)).length,o+1).join(""),c=this.evaluateStringMethod(u),m=l.slice(0,Array.from(n.slice(0,s.index)).length).join(""),d=(c==null?void 0:c.kind)==="string"?wo(c.value):void 0;(c==null?void 0:c.kind)==="int"?t+=m+String(c.value):(c==null?void 0:c.kind)==="double"?t+=m+(Number.isInteger(c.value)?c.value.toFixed(1):String(c.value)):d!==void 0?t+=m+String(d):t+=m+u,n=l.slice(o+1).join("")}return t+n}valueInArray(e,t){const n=this.state.variables.get(e);if(!n)throw K1(e);const a=`${e}[${t.join("][")}]`;if(n.kind==="grid"){if(t.length!==2)throw R(a);const r=n.value[t[0]];if(!r||t[1]>=r.length)throw R(a);return vo(n.elementType,r[t[1]])}if(t.length!==1)throw R(a);const s=t[0];if(!yo(n))throw R(e);if(s>=n.value.length)throw R(a);switch(n.kind){case"intArray":return It(n.value[s]);case"doubleArray":return kt(n.value[s]);case"stringArray":return{kind:"string",value:n.value[s]};case"booleanArray":return{kind:"boolean",value:n.value[s]};default:throw R(e)}}inferTargetValueType(e){const t=e.trim(),n=this.state.variables.get(t);if(n)return gu(n);const a=g1(t);if(a){const s=this.state.variables.get(a.arrayName);if(!s)throw K1(a.arrayName);if(s.kind==="intArray")return"int";if(s.kind==="doubleArray")return"double";if(s.kind==="stringArray")return"string";if(s.kind==="booleanArray")return"boolean";if(s.kind==="grid")return s.elementType;throw R(a.arrayName)}throw Ke(e)}assignValue(e,t){const n=t.trim(),a=g1(n);if(!a){this.state.variables.set(n,e);return}const s=a.indexExpressions.map(u=>this.arrayIndex(u)),r=this.state.variables.get(a.arrayName);if(!r)throw K1(a.arrayName);if(r.kind==="grid"){if(s.length!==2||s[0]>=r.value.length||s[1]>=r.value[s[0]].length)throw R(n);const u=r.elementType==="double"&&e.kind==="int"||e.kind===r.elementType?e.value:void 0;if(u===void 0||yo(e))throw R(n);const c=r.value.map(m=>[...m]);c[s[0]][s[1]]=u,this.state.variables.set(a.arrayName,{...r,value:c});return}if(s.length!==1)throw R(n);const o=s[0];let l;if(r.kind==="intArray"&&e.kind==="int")l={kind:"intArray",value:[...r.value]};else if(r.kind==="doubleArray"&&(e.kind==="double"||e.kind==="int"))l={kind:"doubleArray",value:[...r.value]};else if(r.kind==="stringArray"&&e.kind==="string")l={kind:"stringArray",value:[...r.value]};else if(r.kind==="booleanArray"&&e.kind==="boolean")l={kind:"booleanArray",value:[...r.value]};else throw R(n);if(o>=l.value.length)throw R(n);l.value[o]=e.value,this.state.variables.set(a.arrayName,l)}evaluateOutputExpression(e){const t=this.withSensors(e).trim();if(xu(t)&&xr(t).every(s=>lt(s.trim())===void 0)&&!this.evaluateReference(t))return String(this.evaluateBool(t));let n,a;for(const s of xr(this.withSensors(e))){const r=s.trim(),o=lt(r),l=o!==void 0?{kind:"string",value:o}:this.evaluateReference(r)??(xu(r)?{kind:"boolean",value:this.evaluateBool(r)}:this.evaluateNumeric(r)),u=l.kind==="int"||l.kind==="double";if(a===void 0&&u){n?n=n.kind==="int"&&l.kind==="int"?It(n.value+l.value):kt(n.value+l.value):n=l;continue}a=(a??(n?_e(n):""))+_e(l),n=void 0}return a??(n?_e(n):"")}renderOutputExpression(e){return xr(e).map(t=>{const n=t.trim();if(lt(n)!==void 0)return n;const a=this.evaluateReference(n);if(a)return _e(a);try{return this.renderNumericExpression(n)}catch{return n}}).join(" + ")}evaluateExpression(e,t){switch(t){case"int":return It(this.evaluateInt(e));case"double":return kt(this.evaluateDouble(e));case"string":{const n=e.trim(),a=lt(n);if(a!==void 0)return{kind:"string",value:a};if(n==="null")return{kind:"null"};const s=this.evaluateReference(n);return(s==null?void 0:s.kind)==="null"?s:s?{kind:"string",value:_e(s)}:{kind:"string",value:this.evaluateOutputExpression(e)}}case"boolean":return{kind:"boolean",value:this.evaluateBool(e)}}}evaluateNumeric(e){const{v:t,int:n}=this.parser(e).parseNumber();return n||Number.isFinite(t)&&Math.round(t)===t?It(t):kt(t)}parser(e){const t=this.withSensors(e);return new M3(bu(pu(this.substituteStringCalls(t))),this.state.variables)}withSensors(e){return z3(e,t=>this.robotSensors[t]??At[t].simulated)}evaluateInt(e){return this.parser(e).parseInt()}evaluateDouble(e){return this.parser(e).parseDouble()}evaluateBool(e){const t=this.withSensors(e).trim();if(t==="true")return!0;if(t==="false")return!1;const n=this.evaluateReference(t);if((n==null?void 0:n.kind)==="boolean")return n.value;const a=rs(t,"||");if(a.length>1)return a.some(u=>this.evaluateBool(u));const s=rs(t,"&&");if(s.length>1)return s.every(u=>this.evaluateBool(u));if(t.startsWith("!")&&!t.startsWith("!="))return!this.evaluateBool(t.slice(1));const r=fh(t);if(r!==void 0)return this.evaluateBool(r);const o=P3(t);if(o)return this.evaluateComparison(o.lhs,"==",o.rhs);const l=j3(t);if(l)return this.evaluateComparison(l.lhs,l.op,l.rhs);if(this.stringOperand(t)!==void 0)throw R(t);return this.evaluateDouble(t)!==0}evaluateComparison(e,t,n){if((e.trim()==="null"||n.trim()==="null")&&(t==="=="||t==="!=")){const c=d=>{var h;return d.trim()==="null"||((h=this.evaluateReference(d))==null?void 0:h.kind)==="null"},m=c(e)===c(n);return t==="=="?m:!m}const a=this.booleanOperand(e),s=this.booleanOperand(n);if((a!==void 0||s!==void 0)&&(t==="=="||t==="!=")){const c=a??this.evaluateBool(e),m=s??this.evaluateBool(n);return t==="=="?c===m:c!==m}const r=this.stringOperand(e),o=this.stringOperand(n);let l,u;if(r!==void 0||o!==void 0){if(r===void 0||o===void 0)throw R(`${e} ${t} ${n}`);l=r,u=o}else l=this.evaluateDouble(e),u=this.evaluateDouble(n);switch(t){case"==":return l===u;case"!=":return l!==u;case"<":return l":return l>u;case">=":return l>=u;default:throw R(`${e} ${t} ${n}`)}}booleanOperand(e){const t=e.trim();if(t==="true")return!0;if(t==="false")return!1;const n=this.evaluateReference(t);return(n==null?void 0:n.kind)==="boolean"?n.value:void 0}stringOperand(e){const t=e.trim(),n=lt(t);if(n!==void 0)return n;const a=this.evaluateReference(t);return(a==null?void 0:a.kind)==="string"?a.value:void 0}evaluateSwitchSelector(e){const t=this.withSensors(e).trim(),n=lt(t);if(n!==void 0)return{kind:"text",value:n};const a=this.state.variables.get(t);if(a)switch(a.kind){case"int":return{kind:"int",value:a.value};case"double":return{kind:"int",value:Math.trunc(a.value)};case"string":return{kind:"text",value:a.value};default:throw R(t)}return/^[+-]?[0-9]+$/.test(t)?{kind:"int",value:Number(t)}:{kind:"int",value:this.evaluateInt(t)}}renderNumericExpression(e){return bu(pu(e)).map(t=>{if(t.t==="number")return t.literal;if(t.t==="identifier"){const n=this.state.variables.get(t.name);if(!n)throw K1(t.name);return _e(n)}return t.t}).join(" ").replaceAll("( ","(").replaceAll(" )",")").replaceAll(" . ",".").replaceAll("[ ","[").replaceAll(" ]","]")}}const xh={baseIndent:0,indentPerLevel:4,includeDiagramTextAsComments:!1,includeEmptyElseBranch:!0,pseudocodeNote:"Pseudocode – not a runnable program"};function ls(i,e,t={},n=[]){const a=ql(i,e,t);let s="";e==="javascript"&&(s+=`"use strict"; + +`);const r=[i,...e==="java"?[]:n];if(e==="python"&&r.some(Dh)&&(s+=`import random + +`),e!=="java"&&(s+=So(r,e)),e==="java"&&ms(i)&&(s+=`// import java.util.Scanner; +`,s+=`Scanner scanner = new Scanner(System.in); + +`),i.pseudocode&&(s+=(e==="python"?"# ":"// ")+a.pseudocodeNote+` + +`),e!=="java")for(const u of n){if(u===i)continue;const c=zt(u.caption);c&&(s+=Io(u,c,e,t,0)+` +`)}const o=zt(i.caption),l={out:""};if(o)l.out=Io(i,o,e,t,a.baseIndent);else for(const u of i.elements)Vs(u,e,a,a.baseIndent,l);if(s+=l.out,s.trim()===""){const u=N3(e);return e==="javascript"?`"use strict"; + +`+u:u}return Lh(s.replace(/^[\n\r]+|[\n\r]+$/g,""),e)}function ql(i,e,t){const n={...xh,...t,jsIntVariables:new Set,arrayElementTypes:U3(i),stringVariables:Q3(i)};return e!=="java"&&(n.jsIntVariables=fb(i)),n}const wu=i=>i==="string"?"String":i===void 0?"void":i;function vh(i){const e=i.params.map(t=>`${wu(t.type)}${"[]".repeat(t.dims??0)} ${t.name}`).join(", ");return`public static ${wu(i.returnType)} ${i.name}(${e}) {`}function Io(i,e,t,n,a){const s=ql(i,t,n);for(const l of e.params)l.dims||(l.type==="int"&&s.jsIntVariables.add(l.name),l.type==="string"&&s.stringVariables.add(l.name));const r=e.params.map(l=>l.name).join(", "),o={out:""};for(const l of i.elements)Vs(l,t,s,a+s.indentPerLevel,o);switch(o.out.trim()===""&&(o.out=M(a+s.indentPerLevel)+(t==="python"?`pass +`:` +`)),t){case"java":return`${M(a)}${vh(e)} +${o.out}${M(a)}} +`;case"python":return`${M(a)}def ${e.name}(${r}): +${o.out}`;case"javascript":return`${M(a)}function ${e.name}(${r}) { +${o.out}${M(a)}} +`}}const M=i=>i>0?" ".repeat(i):"";function ve(i,e){const t=i.exec(e);return t?Array.from(t,n=>n??""):void 0}function N3(i,e){return i==="python"?"# empty element":"// empty element"}const ko=i=>i.trim()==="ø";function yh(i,e){return M(i)+(e==="python"?`# empty element +`:`// empty element +`)}function F3(i){switch(i.type){case S.leerElement:return!0;case S.anweisung:case S.aufruf:return i.textLines.map(e=>e.trim()).every(e=>e===""||ko(e));default:return!1}}function J3(i){return i.every(F3)}function Ql(i,e,t){const n=i.map(a=>a.replace(/^[ \t]+|[ \t]+$/g,"")).filter(a=>a!=="");return n.length===0?"":e==="python"?M(t)+`""" +`+n.map(a=>M(t)+a+` +`).join("")+M(t)+`""" +`:n.length===1?M(t)+"/* "+n[0]+` */ +`:M(t)+`/* +`+n.map(a=>M(t)+" * "+a+` +`).join("")+M(t)+` */ +`}const R3=i=>i==="java"||i==="javascript";function us(i){const e=i.trim();if(e==="")return"";if(e.startsWith("//")||e.startsWith("/*")||e.startsWith("*")||e.startsWith("#")||e.startsWith("{")||e.startsWith("}")||e.endsWith("{")||e.endsWith(";"))return e;const t=e.toLowerCase();for(const n of["if ","else","for ","while ","do ","switch ","case ","default"])if(t.startsWith(n))return e;return e+";"}function La(i){const e=i.map(t=>t.trim()).filter(t=>t!=="");return G3(e.length===0?"true":e.join(" "))}function G3(i){const e=i.trim();for(const t of["if","while","until","switch"]){const n=wh(t,e);if(n!==void 0)return n===""?"true":n}return e}function wh(i,e){if(!e.toLowerCase().startsWith(i))return;const t=e.slice(i.length);if(!(t===""||/^\s/.test(t)||t[0]==="("))return;let n=t.trim();return n.startsWith("(")&&n.endsWith(")")&&n.length>=2&&(n=n.slice(1,-1).trim()),n}function qt(i){let e=i.trim();for(;e.endsWith(";");)e=e.slice(0,-1).trim();return e}function H3(i){const e=i.trim(),t=e.toLowerCase();let n;if(t.startsWith("output:"))n=e.slice(7).trim();else if(t.startsWith("print:"))n=e.slice(6).trim();else return;return n===""?void 0:n}const Rs=i=>i.name.includes("[")&&i.name.includes("]");function Ul(i){const e=i.trim();if(e==="")return;const t=ve(/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s+([a-zA-Z_]\w*(?:\s*\[[^\]]+\])?)(?:\s+"([^"]*)")?\s*$/i,e);if(t){const s=t[2].replaceAll(" ","");if(s==="")return;const r=(t[3]??"").trim();return{type:cs(t[1]),name:s,customPrompt:r===""?void 0:r}}const n=ve(/^\s*([a-zA-Z_]\w*(?:\s*\[[^\]]+\])?)\s+"([^"]*)"\s*$/i,e);if(n){const s=n[1].replaceAll(" ","");return["int","integer","long","float","double","string","boolean","char","bool","void"].includes(s.toLowerCase())?void 0:{type:s.includes("[")?"String":"int",name:s,customPrompt:n[2].trim()}}const a=V3(e);if(a)return{type:cs(a[0]),name:a[1]}}function cs(i){switch(i.trim().toLowerCase()){case"integer":case"int":return"int";case"long":return"long";case"float":return"float";case"double":return"double";case"string":return"String";case"boolean":case"bool":return"boolean";case"char":return"char";default:return i}}function V3(i){const e=i.split(/[ \t]+/).filter(Boolean);if(e.length===0)return;if(e.length>=2)return[e[0],e[1]];if(!["int","double","string","boolean","char","long","float","short","byte","void","bool","integer"].includes(e[0].toLowerCase()))return["int",e[0]]}function q3(i,e,t,n,a){const s=qt(i).trim();if(s.startsWith('"'))switch(e){case"java":return M(t)+"System.out.println("+s+`); +`;case"javascript":return M(t)+"console.log("+s+`); +`;case"python":return M(t)+"print("+Dn(s,n,a)+`) +`}}function zi(i){return i.replaceAll("\\","\\\\").replaceAll('"','\\"').replaceAll(` +`,"\\n").replaceAll("\r","\\r")}function $l(i,e){const t=i.trim();if(!t.toLowerCase().startsWith("input:"))return;const n=t.slice(6).trim();if(n==="")return;const a=Ul(n);if(a&&Rs(a)&&!/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s/i.test(n)){const s=e.get(a.name.slice(0,a.name.indexOf("[")).trim());if(s)return{...a,type:s}}return a}function Q3(i){const e=new Set;return fn(i.elements,t=>{for(const n of t.textLines){const a=n.trim();if(a.toLowerCase().startsWith("input:")){const o=Ul(a.slice(6).trim());(o==null?void 0:o.type)==="String"&&!Rs(o)&&e.add(o.name);continue}const s=ve(/^\s*(?:const\s+)?string\s+([a-zA-Z_]\w*)\s*=/i,a);s&&e.add(s[1]);const r=ve(/^\s*string\s*\[\s*\]\s*([a-zA-Z_]\w*)\s*=/i,a);r&&e.add(r[1]+"[]")}}),e}function U3(i){const e=new Map;return fn(i.elements,t=>{for(const n of t.textLines){const a=ve(/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s*\[\s*\]\s*([a-zA-Z_]\w*)/i,n)??ve(/^\s*(integer|int|long|float|double|string|boolean|char|bool)\s+([a-zA-Z_]\w*)\s*\[\s*\]/i,n);a&&e.set(a[2],cs(a[1]))}}),e}function $3(i,e,t){const n=$l(i,t);if(!n)return;const a=n.customPrompt?n.customPrompt:n.name+": ",s=M(e)+'System.out.println("'+zi(a)+`"); +`,r=o=>Rs(n)?n.name:`${o} ${n.name}`;switch(n.type){case"int":return s+M(e)+`${r("int")} = scanner.nextInt(); +`;case"double":return s+M(e)+`${r("double")} = scanner.nextDouble(); +`;case"String":return s+M(e)+`${r("String")} = scanner.next(); +`;case"boolean":return s+M(e)+`${r("boolean")} = scanner.nextBoolean(); +`;default:return}}function Y3(i,e,t){const n=$l(i,t);if(!n)return;const a=!!n.customPrompt,s=a?"":M(e)+'console.log("'+zi(n.name+": ")+`"); +`,r=l=>{const u=a?n.customPrompt:n.name+": ";return`(prompt("${zi(u)}") ?? "${l}")`},o=Rs(n)?n.name:`let ${n.name}`;switch(n.type){case"int":return s+M(e)+`${o} = parseInt(${r("0")}, 10); +`;case"double":return s+M(e)+`${o} = Number(${r("0")}); +`;case"String":return s+M(e)+`${o} = ${r("")}; +`;case"boolean":return s+M(e)+`${o} = ${r("")}.trim().toLowerCase() === "true"; +`;default:return}}function X3(i,e,t){const n=$l(i,t);if(!n)return;const a=!!n.customPrompt,s=a?"":M(e)+'print("'+zi(n.name+": ")+`") +`,r=`input("${zi(a?n.customPrompt:n.name+": ")}")`;switch(n.type){case"int":return s+M(e)+`${n.name} = int(${r}) +`;case"double":return s+M(e)+`${n.name} = float(${r}) +`;case"String":return s+M(e)+`${n.name} = ${r} +`;case"boolean":return s+M(e)+`${n.name} = ${r}.strip().lower() in ("true", "wahr") +`;default:return}}const vr=String.raw`("(?:[^"\\]|\\.)*"|[A-Za-z_]\w*)`,K3=[[new RegExp(String.raw`^new\s+Scanner\s*\(\s*new\s+File\s*\(\s*${vr}\s*\)\s*\)$`),"Scanner"],[new RegExp(String.raw`^new\s+BufferedReader\s*\(\s*new\s+FileReader\s*\(\s*${vr}\s*\)\s*\)$`),"BufferedReader"],[new RegExp(String.raw`^new\s+PrintWriter\s*\(\s*(?:new\s+(?:File|FileWriter)\s*\(\s*)?${vr}\s*\)?\s*\)$`),"PrintWriter"]];function zh(i){const e=i.trim();for(const[t,n]of K3){const a=t.exec(e);if(a)return{kind:n,name:a[1]}}}function eb(i,e,t,n,a){if(e==="java")return;const s=qt(i).trim(),r=/^(?:(?:Scanner|BufferedReader|PrintWriter)\s+)?([A-Za-z_]\w*)\s*=\s*(new\s[\s\S]+)$/.exec(s),o=r&&zh(r[2]);if(r&&o){const c=/^(?:Scanner|BufferedReader|PrintWriter)\s/.test(s);return e==="python"?M(t)+`${r[1]} = ${o.kind}(${o.name}) +`:M(t)+`${c?"let ":""}${r[1]} = new ${o.kind}(${o.name}); +`}const l=/^([A-Za-z_]\w*)\.(println|print)\s*\(([\s\S]*)\)$/.exec(s);if(l&&l[1]!=="System"){const c=l[3].trim(),m=e==="python"&&c!==""?Dn(c,n,a):c;return M(t)+`${l[1]}.${l[2]}(${m})${e==="javascript"?";":""} +`}const u=/^Files\.writeString\s*\(\s*(?:Path\.of|Paths\.get)\s*\(\s*("(?:[^"\\]|\\.)*")\s*\)\s*,\s*([\s\S]+)\)$/.exec(s);if(u){const c=u[2].trim();return e==="python"?M(t)+`open(${u[1]}, "w", encoding="utf-8").write(${Dn(c,n,a)}) +`:M(t)+`require("fs").writeFileSync(${u[1]}, ${c}); +`}}function tb(i){const e=new Set;for(const t of i)fn(t.elements,n=>{for(const a of n.textLines){const s=/=\s*(new\s.+?);?\s*$/.exec(a),r=s&&zh(s[1]);r&&e.add(r.kind)}});return e}const nb={Scanner:`class Scanner: + def __init__(self, name): + self.lines = open(name, encoding="utf-8").read().splitlines() + def hasNextLine(self): + return len(self.lines) > 0 + def nextLine(self): + return self.lines.pop(0) + def close(self): + pass +`,BufferedReader:`class BufferedReader: + def __init__(self, name): + self.lines = open(name, encoding="utf-8").read().splitlines() + def readLine(self): + return self.lines.pop(0) if self.lines else None + def close(self): + pass +`,PrintWriter:`class PrintWriter: + def __init__(self, name): + self.file = open(name, "w", encoding="utf-8") + def println(self, text=""): + self.file.write(str(text) + "\\n") + def print(self, text): + self.file.write(str(text)) + def close(self): + self.file.close() +`},ib={Scanner:`class Scanner { + constructor(name) { this.lines = require("fs").readFileSync(name, "utf8").split(/\\r?\\n/); if (this.lines.at(-1) === "") this.lines.pop(); } + hasNextLine() { return this.lines.length > 0; } + nextLine() { return this.lines.shift(); } + close() {} +} +`,BufferedReader:`class BufferedReader { + constructor(name) { this.lines = require("fs").readFileSync(name, "utf8").split(/\\r?\\n/); if (this.lines.at(-1) === "") this.lines.pop(); } + readLine() { return this.lines.length > 0 ? this.lines.shift() : null; } + close() {} +} +`,PrintWriter:`class PrintWriter { + constructor(name) { this.name = name; this.text = ""; } + println(text = "") { this.text += text + "\\n"; } + print(text) { this.text += text; } + close() { require("fs").writeFileSync(this.name, this.text); } +} +`};function So(i,e){const t=tb(i);if(t.size===0)return"";const n=e==="python"?nb:ib;return[...t].map(a=>n[a]).join(` +`)+` +`}function ab(i,e,t,n,a){const s=/^System\s*\.\s*out\s*\.\s*print\s*\(([\s\S]*)\)$/.exec(qt(i).trim());if(s){const o=s[1].trim();switch(e){case"java":return M(t)+"System.out.print("+o+`); +`;case"javascript":return M(t)+"process.stdout.write(String("+o+`)); +`;case"python":return M(t)+"print("+(o===""?"":Dn(o,n,a)+", ")+`end="") +`}}const r=H3(i);if(r===void 0)return/^\s*(?:output|print):\s*$/i.test(i)?M(t)+{java:"System.out.println();",javascript:"console.log();",python:"print()"}[e]+` +`:void 0;switch(e){case"java":return M(t)+"System.out.println("+r+`); +`;case"javascript":return M(t)+"console.log("+r+`); +`;case"python":return M(t)+"print("+Dn(r,n,a)+`) +`}}function Yl(i){const e=i.map(qt).filter(t=>t!=="");return e.length===0?";;":e.join("; ")}function sb(i){const t=Yl(i).split(";"),n=Ih(t[0]);return n!==void 0&&(t[0]=n),t.join(";")}function Ih(i){const e=ve(/^(\s*)(?:integer|int|long|float|double|string|boolean|char|bool)\s+(\w+)(?:\s*=\s*(.*))?\s*$/i,i);if(!e)return;const t=e[2].trim();if(t==="")return;const n=(e[3]??"").trim();return i.includes("=")&&n!==""?e[1]+`let ${t} = ${n}`:e[1]+`let ${t}`}function rb(i){const e=i.map(n=>qt(n).trim()).filter(n=>n!=="");let t=e;if(e.length===1){let n=e[0];const a=wh("for",n);a!==void 0&&(n=a),t=n.split(";").map(s=>s.trim())}if(!(t.length!==3||t.some(n=>n==="")))return[t[0],t[1],t[2]]}function kh(i,e){let t=ve(/^\s*(\w+)\s*(\+\+|--)\s*$/,i)??ve(/^\s*(\+\+|--)\s*(\w+)\s*$/,i);if(t){const[n,a]=t[1]==="++"||t[1]==="--"?[t[2],t[1]]:[t[1],t[2]];return n===e?a==="++"?1:-1:void 0}if(t=ve(/^\s*(\w+)\s*(\+|-)=\s*(\d+)\s*$/,i),t)return t[1]===e?(t[2]==="+"?1:-1)*Number(t[3]):void 0;if(t=ve(/^\s*(\w+)\s*=\s*(\w+)\s*(\+|-)\s*(\d+)\s*$/,i),t)return t[1]===e&&t[2]===e?(t[3]==="+"?1:-1)*Number(t[4]):void 0}function To(i,e){if(/^-?\d+$/.test(i))return String(Number(i)+e);const t=/^[\w.()[\]]+$/.test(i)?i:`(${i})`;return e>0?`${t} + ${e}`:`${t} - ${-e}`}function ob(i,e){const t=rb(i);if(!t)return;const[n,a,s]=t,r=ve(/^\s*(?:integer|int|long|short|byte|double|float)?\s*([a-zA-Z_]\w*)\s*=\s*(.+)$/i,n);if(!r)return;const o=r[1],l={variable:o,init:`${o} = ${Me(r[2],e)}`,condition:a,increment:s},u=ve(/^\s*(\w+)\s*(<=|<|>=|>)\s*(.+)$/,a),c=kh(s,o);if(!u||u[1]!==o||c===void 0||c===0)return l;const m=Me(r[2],e);let d=Me(u[3],e);const h=u[2];if(c>0&&h==="<=")d=To(d,1);else if(c<0&&h===">=")d=To(d,-1);else if(!(c>0&&h==="<")&&!(c<0&&h===">"))return l;const g=c===1?m==="0"?[d]:[m,d]:[m,d,String(c)];return l.rangeLine=`for ${o} in range(${g.join(", ")}):`,l}function Sh(i){const e=qt(i).trim();if(e==="")return;const t=ve(/^\s*const\s+(integer|int|long|float|double|string|boolean|char|bool)\s+(\w+)(?:\s*=\s*(.*))?$/i,e);if(!t)return;const n=t[2].trim();if(n==="")return;if(!e.includes("="))return{rawType:t[1].trim(),name:n};const a=(t[3]??"").trim();if(a!=="")return{rawType:t[1].trim(),name:n,rhs:a}}function lb(i,e,t,n){var o;const a=Sh(i);if(!a)return;const s=cs(a.rawType),r=(o=a.rhs)==null?void 0:o.trim();switch(e){case"java":return M(t)+us(r?`final ${s} ${a.name} = ${r}`:`final ${s} ${a.name}`)+` +`;case"javascript":return r?M(t)+us(`const ${a.name} = ${r}`)+` +`:M(t)+`let ${a.name}; // from diagram: const ${s} ${a.name} +`;case"python":return r?M(t)+`${a.name} = ${Hs(r,n)} # const ${s} +`:M(t)+`${a.name} = None # const ${s}, uninitialized +`}}function ub(i){const e=qt(i).trim();if(e===""||jh(e))return;const t=ve(/^\s*(?:integer|int|long|float|double|string|boolean|char|bool)(?:\s*\[\s*\]\s+(\w+)|\s+(\w+)(\s*\[\s*\])?)\s*=\s*(.*)$/i,e);if(!t)return;const n=t[1]===""?t[2]:t[1],a=t[4].trim();if(a!=="")return{name:n,rhs:a,isArray:t[1]!==""||t[3]!==""}}function Gs(i){const e=ve(/^\s*\(\s*int(?:eger)?\s*\)\s*(.+?)\s*$/i,i),t=e==null?void 0:e[1].trim();if(!(!t||Th(t)))return t.startsWith("(")&&_o(t,0)===t.length-1?t.slice(1,-1).trim():t}function _o(i,e){let t=0;for(let n=e;n/^'.'$/u.test(i)||/\.charAt\(.*\)$/.test(i);function cb(i,e){if(i[e]==="("){const a=_o(i,e);return a<0?-1:a+1}if(i[e]==="'")return i[e+2]==="'"?e+3:-1;const t=/^(?:[A-Za-z_]\w*|\d+)/.exec(i.slice(e));if(!t)return-1;let n=e+t[0].length;for(;;){const a=/^\.[A-Za-z_]\w*/.exec(i.slice(n));if(a)n+=a[0].length;else if(i[n]==="("||i[n]==="["){const s=_o(i,n);if(s<0)return-1;n=s+1}else return n}}function Ao(i,e){return Xl(i,t=>{const n=/\(\s*(int|char)\s*\)\s*/g;let a="",s=0;for(let r=n.exec(t);r;r=n.exec(t)){const o=r.index+r[0].length,l=cb(t,o);if(l<0)continue;const u=t.slice(o,l);if(r[1]==="int"&&!Th(u))continue;const c=Ao(u.startsWith("(")?u.slice(1,-1).trim():u,e),m=r[1]==="int"?e==="python"?`ord(${c})`:`${c}.charCodeAt(0)`:e==="python"?`chr(${c})`:`String.fromCharCode(${c})`;a+=t.slice(s,r.index)+m,s=l,n.lastIndex=l}return a+t.slice(s)})}function Hs(i,e=new Set){const t=i.trim();if(t==="null")return"None";const n=Gs(t);return n!==void 0?`int(${Hs(n,e)})`:Me(t,e)}function Xl(i,e){let t="",n="",a=0;for(;a/^\d+$/.test(a)||e.has(a);return Xl(t,a=>a.replace(/\bMath\.random\s*\(\s*\)/gi,"random.random()").replace(/===/g,"==").replace(/!==/g,"!=").replace(/\s*&&\s*/g," and ").replace(/\s*\|\|\s*/g," or ").replace(/!(?!=)\s*/g,"not ").replace(/\btrue\b/g,"True").replace(/\bfalse\b/g,"False").replace(/\bnull\b/g,"None").replace(new RegExp("(?n(r)&&n(o)?`${r} // ${o}`:s))}function _h(i){const e=[];let t=0,n="",a=!1;for(let s=0;s/^"(?:[^"\\]|\\.)*"$/.test(i);function Dn(i,e,t){const n=_h(i),a=s=>Kl(s)||t.has(s)||t.has(s.replace(/^([A-Za-z_]\w*)\[[^[\]]*\]$/u,"$1[]"));return n.length<2||!n.some(a)||n.some(s=>s==="")?Me(i,e):n.map(s=>a(s)?s:`str(${Me(s,e)})`).join(" + ")}function Ah(i,e,t=new Set){const n=qt(i).trim(),a=ve(/^(\w+(?:\[[^\]]*\])?)\s*(\+\+|--)$/,n)??ve(/^(\+\+|--)\s*(\w+(?:\[[^\]]*\])?)$/,n);if(a){const[o,l]=a[1]==="++"||a[1]==="--"?[a[2],a[1]]:[a[1],a[2]];return`${Me(o,e)} ${l==="++"?"+=":"-="} 1`}const s=ve(/^(\w+)\s*\/=\s*(.+)$/,n);if(s&&e.has(s[1]))return`${s[1]} //= ${Me(s[2],e)}`;const r=ve(/^([\w[\]. ]+?)\s*(=|\+=|-=|\*=|\/=|%=)\s*(.+)$/,n);if(r&&!r[3].startsWith("=")){const[,o,l,u]=r;let c;if(l==="+="&&t.has(o.trim())){const m=_h(u);c=Dn(`"" + ${u}`,e,t).replace(/^"" \+ /,""),m.length===1&&!Kl(u.trim())&&!t.has(u.trim())&&(c=`str(${Me(u,e)})`)}else l==="="&&Gs(u)===void 0&&u.trim()!=="null"?c=Dn(u,e,t):c=l==="="?Hs(u,e):Me(u,e);return`${o} ${l} ${c}`}return Me(n,e)}const mb=i=>i.replace(/\bMath\.random\b(?!\s*\()/gi,"Math.random()");function Oh(i){const e=i.trim();return e.startsWith("{")&&e.endsWith("}")?"["+e.slice(1,-1)+"]":i}function Ch(i){const e=ve(/^\s*new\s+(?:byte|short|int|long|float|double|boolean|char|string)\s*\[\s*(.+)\s*\]\s*$/i,i),t=e==null?void 0:e[1].trim();return t||void 0}function jh(i){const e=ve(/^\s*(int|double|string|boolean)\s*\[\s*\]\s*\[\s*\]\s*([a-zA-Z_]\w*)\s*=\s*(.+)$/i,qt(i).trim());return e?{elementType:e[1].toLowerCase(),name:e[2],rhs:e[3].trim()}:void 0}function db(i){const e=ve(/^\s*new\s+(?:int|double|string|boolean)\s*\[\s*(.+?)\s*\]\s*\[\s*(.+?)\s*\]\s*$/i,i);return e?[e[1],e[2]]:void 0}const zu=i=>i.replaceAll("{","[").replaceAll("}","]");function Iu(i,e){return i==="boolean"?e==="python"?"False":"false":i==="string"?'""':i==="double"?"0.0":"0"}function hb(i,e,t){const n=db(i.rhs);return e==="javascript"?n?`Array.from({ length: ${n[0]} }, () => new Array(${n[1]}).fill(${Iu(i.elementType,e)}))`:zu(i.rhs):n?`[[${Iu(i.elementType,e)}] * ${Me(n[1],t)} for _ in range(${Me(n[0],t)})]`:Me(zu(i.rhs),t)}function Ph(i,e){const t=i.trim();if(e){const a=Ch(t);return a!==void 0?`new Array(${a})`:Oh(t)}const n=Gs(t);return n!==void 0?`Math.floor(${Ph(n,!1)})`:mb(t)}function gb(i,e,t){const n=i.trim();if(e){const a=Ch(n);return a!==void 0?`[None] * ${a}`:Me(Oh(n),t)}return Hs(n,t)}function pb(i,e,t,n,a){if(e==="java")return;const s=jh(i);if(s){const u=hb(s,e,n);return e==="javascript"?M(t)+`let ${s.name} = ${u}; +`:M(t)+`${s.name} = ${u} +`}const r=ub(i);if(!r)return;if(e==="javascript")return M(t)+us(`let ${r.name} = ${Ph(r.rhs,r.isArray)}`)+` +`;const l=!r.isArray&&Gs(r.rhs)===void 0&&r.rhs.trim()!=="null"?Dn(r.rhs,n,a):gb(r.rhs,r.isArray,n);return M(t)+`${r.name} = ${l} +`}function fn(i,e){for(const t of i){e(t),t.loopBody&&fn(t.loopBody,e);for(const n of t.cases??[])fn(n.elements,e)}}function fb(i){const e=n=>["int","integer","long","short","byte"].includes(n.trim().toLowerCase()),t=new Set;return fn(i.elements,n=>{for(const a of n.textLines){const s=a.trim();if(s==="")continue;if(s.toLowerCase().startsWith("input:")){const l=Ul(s.slice(6).trim());l&&e(l.type)&&!l.name.includes("[")&&t.add(l.name);continue}const r=Sh(s);if(r&&e(r.rawType)){t.add(r.name);continue}const o=ve(/^\s*(integer|int|long|short|byte)\s+([a-zA-Z_]\w*)\s*=/i,s);o&&t.add(o[2].trim())}}),t}function Oo(i,e){const t=r=>/^\d+$/.test(r)||e.has(r),n=String.raw`(?:[a-zA-Z_]\w*|\d+(?:\.\d+)?)`,a=new RegExp(String.raw`(?{const o=r.split(/\s*([*/%])\s*/);if(!o.some(c=>c==="/"))return r;let l=o[0],u=t(o[0]);for(let c=1;cr.replace(a,s).replace(new RegExp("(?t(l)&&t(u)?`${l} = Math.trunc(${l} / ${u})`:o))}function ms(i){let e=!1;return fn(i.elements,t=>{t.type===S.anweisung&&t.textLines.some(n=>n.trim().toLowerCase().startsWith("input:"))&&(e=!0)}),e}function e0(i){let e=!1,t=!1,n=!1;return fn(i.elements,a=>{for(const s of a.textLines)/\bFiles\s*\./.test(s)&&(e=!0),/\bnew\s+(?:File|PrintWriter|FileReader|FileWriter|BufferedReader)\s*\(/.test(s)&&(t=!0),/\bnew\s+Scanner\s*\(\s*new\s+File\b/.test(s)&&(n=!0)}),[...t?["import java.io.*;"]:[],...e?["import java.nio.file.*;"]:[],...n?["import java.util.Scanner;"]:[]]}function bb(i){return e0(i).length>0}function Dh(i){let e=!1;return fn(i.elements,t=>{t.textLines.some(n=>/\bMath\.random\s*\(/i.test(n))&&(e=!0)}),e}function ea(i,e){const t=i.trim();return t===""?e==="python"?'""':"0":e==="java"||new RegExp("^\\p{N}+$","u").test(t)||Kl(t)?t:'"'+t.replaceAll('"','\\"')+'"'}function J1(i,e){const t=i.trim();if(t==="")return"";switch(e){case"java":return"/* "+t+" */";case"python":return" # "+t;case"javascript":return" /* "+t+" */"}}function xb(i,e,t,n,a){const s=i.map(r=>r.trim());if(s.every(r=>r==="")){t.live&&(a.out+=M(n)+(e==="python"?"pass":";")+` +`);return}if(t.includeDiagramTextAsComments){const r=s.filter(o=>o!==""&&!ko(o));r.length>0&&(a.out+=Ql(r,e,n))}for(const r of s){if(r==="")continue;if(ko(r)){a.out+=t.live?n0(n,t.live):yh(n,e);continue}const o=t.jsIntVariables??new Set,l=t.arrayElementTypes??new Map,u=t.stringVariables??new Set,c=(e==="java"?$3(r,n,l):void 0)??(e==="javascript"?Y3(r,n,l):void 0)??(e==="python"?X3(r,n,l):void 0)??eb(r,e,n,o,u)??ab(r,e,n,o,u)??lb(r,e,n,o)??pb(r,e,n,o,u)??q3(r,e,n,o,u);if(c!==void 0){a.out+=e==="javascript"?Oo(c,o):c;continue}let m=r;R3(e)?m=us(e==="javascript"?Oo(r,o):r):e==="python"&&(m=Ah(r,o,u)),m!==""&&(a.out+=M(n)+m+` +`)}}function li(i,e,t,n,a,s,r,o=(l=>(l=a.live)==null?void 0:l.labels.condition)()){if(a.includeDiagramTextAsComments&&(r.out+=Ql(t,n,s)),o!==void 0&&i0(t)){r.out+=M(s)+i+e1(o)+e;return}const u=La(t),c=a.jsIntVariables??new Set,m=n==="python"?Me(u,c):n==="javascript"?Oo(u,c):u;r.out+=M(s)+i+m+e}function b1(i,e,t,n,a){const s=a.out.length;for(const o of i)Vs(o,e,t,n,a);if(t.live&&a.out.length===s&&(a.out+=n0(n,t.live)),e!=="python")return;a.out.slice(s).split(` +`).map(o=>o.trim()).every(o=>o===""||o.startsWith("#"))&&(a.out+=M(n)+`pass +`)}function vb(i,e){var n;if(e.includeDiagramTextAsComments||i.length!==1)return;const t=i[0];return t.type===S.verzweigung&&(((n=t.cases)==null?void 0:n.length)??0)>=2?t:void 0}function Co(i,e,t,n,a,s){const r=i.cases;if(!r||r.length<2)return;const o=e==="python",l=n+t.indentPerLevel,u=!t.includeEmptyElseBranch&&J3(r[1].elements),c=u?void 0:vb(r[1].elements,t);if(o){li(s?"elif ":"if ",`: +`,i.textLines,e,t,n,a),b1(r[0].elements,e,t,l,a),c?Co(c,e,t,n,a,!0):u||(a.out+=M(n)+`else: +`,b1(r[1].elements,e,t,l,a));return}if(li(s?"} else if (":"if (",`) { +`,i.textLines,e,t,n,a),b1(r[0].elements,e,t,l,a),c){const m=a.out.length;Co(c,e,t,n,a,!0),Mh(t,c,a,m)}else u||(a.out+=M(n)+`} else { +`,b1(r[1].elements,e,t,l,a)),a.out+=M(n)+`} +`}function Vs(i,e,t,n,a){const s=a.out.length;yb(i,e,t,n,a),Mh(t,i,a,s)}function yb(i,e,t,n,a){var c;const s=t.indentPerLevel,r=e==="python",o=(m,d)=>b1(m,e,t,d,a),l=(m,d)=>li(m,d,i.textLines,e,t,n,a),u=(m=n)=>{t.includeDiagramTextAsComments&&(a.out+=Ql(i.textLines,e,m))};switch(i.type){case S.leerElement:a.out+=t.live?n0(n,t.live):yh(n,e);return;case S.anweisung:case S.aufruf:xb(i.textLines,e,t,n,a);return;case S.aussprung:{const m=La(i.textLines);i.textLines.some(d=>d.trim()!=="")&&u(),r?a.out+=M(n)+(m===""?`break +`:`break # ${m} +`):a.out+=M(n)+(m===""?`break; +`:`break; // ${m} +`);return}case S.verzweigung:Co(i,e,t,n,a,!1);return;case S.fallauswahl:{const m=i.cases;if(!m||m.length===0)return;if(r&&t.pythonWithoutMatch){const d=`wahl${n/s+1}`;li(d+" = ",` +`,i.textLines,e,t,n,a),m.forEach((h,g)=>{const f=g===m.length-1;f&&g===0?a.out+=M(n)+"if True:"+J1(h.name,e)+` +`:f?a.out+=M(n)+"else:"+J1(h.name,e)+` +`:a.out+=M(n)+(g===0?"if ":"elif ")+d+" == "+ea(h.name,e)+`: +`,o(h.elements,n+s)});return}li(r?"match ":"switch (",r?`: +`:`) { +`,i.textLines,e,t,n,a,(c=t.live)==null?void 0:c.labels.selector),m.forEach((d,h)=>{const g=h===m.length-1;if(e==="java"){const f=g?"default -> { "+J1(d.name,e)+` +`:"case "+ea(d.name,e)+` -> { +`;a.out+=M(n+s)+f,o(d.elements,n+s*2),a.out+=M(n+s)+`} +`}else if(r){const f=g?"case _:"+J1(d.name,e):"case "+ea(d.name,e)+":";a.out+=M(n+s)+f+` +`,o(d.elements,n+s*2)}else{const f=g?"default:"+J1(d.name,e):"case "+ea(d.name,e)+":";a.out+=M(n+s)+f+` +`,o(d.elements,n+s*2),a.out+=M(n+s*2)+`break; +`}}),r||(a.out+=M(n)+`} +`);return}case S.forSchleife:if(e==="java"){u();const m=t.live?Bh(i.textLines,t.live.labels):Yl(i.textLines);a.out+=M(n)+"for ("+m+`) { +`}else if(r){const m=t.jsIntVariables??new Set,d=ob(i.textLines,m);if((d==null?void 0:d.rangeLine)!==void 0)u(),a.out+=M(n)+d.rangeLine+` +`;else if(d){u(),a.out+=M(n)+d.init+` +`,a.out+=M(n)+"while "+Me(d.condition,m)+`: +`;for(const h of i.loopBody??[])Vs(h,e,t,n+s,a);a.out+=M(n+s)+Ah(d.increment,m)+` +`;return}else t.live?a.out+=M(n)+zb(i.textLines,t.live.labels,m)+` +`:l("for ",`: +`)}else{u();const m=t.live?wb(i.textLines,t.live.labels):sb(i.textLines);a.out+=M(n)+"for ("+m+`) { +`}o(i.loopBody??[],n+s),r||(a.out+=M(n)+`} +`);return;case S.whileSchleife:l(r?"while ":"while (",r?`: +`:`) { +`),o(i.loopBody??[],n+s),r||(a.out+=M(n)+`} +`);return;case S.doUntilSchleife:{const m=t.live&&i0(i.textLines)?e1(t.live.labels.condition):La(i.textLines);if(r){a.out+=M(n)+`while True: +`;const d=n+s;o(i.loopBody??[],d),u(d);const h=m.includes(Wi)?m:Me(m,t.jsIntVariables??new Set);a.out+=M(d)+"if not ("+h+`): +`,a.out+=M(d+s)+`break +`}else a.out+=M(n)+`do { +`,o(i.loopBody??[],n+s),u(),a.out+=M(n)+"} while ("+m+`); +`;return}case S.endlosschleife:{const m=La(i.textLines),d=m===""||m==="true";d||u(),r?a.out+=M(n)+(d?`while True: +`:`while True: # ${m} +`):a.out+=M(n)+(d?`while (true) { +`:`while (true) /* ${m} */ { +`),o(i.loopBody??[],n+s),r||(a.out+=M(n)+`} +`);return}}}const Wi="",t0="",e1=i=>Wi+i+t0,n0=(i,e)=>M(i)+e1(e.target==="python"?`pass # ${e.labels.code}`:`// ${e.labels.code}`)+` +`,i0=i=>i.every(e=>e.trim()==="");function Bh(i,e){return i0(i)||i.length===3?[e.start,e.condition,e.step].map((n,a)=>{const s=qt(i[a]??"");return s===""?e1(n):s}).join("; "):Yl(i)}function wb(i,e){const t=Bh(i,e).split(";"),n=t[0].includes(Wi)?void 0:Ih(t[0]);return n!==void 0&&(t[0]=n),t.join(";")}function zb(i,e,t){var h;const[n="",a="",s=""]=i.length===3?i.map(g=>qt(g)):[],r=ve(/^\s*(?:integer|int|long|short|byte|double|float)?\s*([a-zA-Z_]\w*)\s*=\s*(.+)$/i,n),o=(r==null?void 0:r[1])??((h=ve(/^\s*([a-zA-Z_]\w*)\s*(?:<=|<|>=|>)/,a))==null?void 0:h[1]),l=r?Me(r[2],t):e1(e.start),u=ve(/^\s*(\w+)\s*(<=|<)\s*(.+)$/,a);let c=e1(e.end);u&&(o===void 0||u[1]===o)&&(c=Me(u[3],t),u[2]==="<="&&(c=To(c,1)));const m=o===void 0?void 0:kh(s,o),d=[l,c,...m!==void 0&&m!==1?[String(m)]:[]];return`for ${o??e1(e.selector)} in range(${d.join(", ")}):`}function jo(i,e=[],t=new Map){return i.forEach((n,a)=>{var r;const s=[...e,a];t.has(n)||t.set(n,s),n.loopBody&&jo(n.loopBody,[...s,0],t),(r=n.cases)==null||r.forEach((o,l)=>jo(o.elements,[...s,l],t))}),t}function Mh(i,e,t,n){const a=i.live,s=a==null?void 0:a.paths.get(e);if(!a||!s||t.out.length===n)return;const r=o=>t.out.slice(0,o).split(` +`).length-1;a.spans.push({path:s,from:r(n),to:r(t.out.length-1)})}function Zh(i,e,t){const n={target:e,labels:t,paths:jo(i.elements),spans:[]},a=ql(i,e,{includeEmptyElseBranch:!0,live:n}),s=zt(i.caption);let r="";if(e==="java"){const u=e0(i);for(const c of u)r+=c+` +`;ms(i)?(u.includes("import java.util.Scanner;")||(r+=`import java.util.Scanner; +`),r+=`Scanner scanner = new Scanner(System.in); + +`):u.length&&(r+=` +`),s&&(r+=vh(s)+` +`)}else{if(s)for(const c of s.params)c.dims||(c.type==="int"&&a.jsIntVariables.add(c.name),c.type==="string"&&a.stringVariables.add(c.name));const u=s==null?void 0:s.params.map(c=>c.name).join(", ");e==="javascript"?(r+=`"use strict"; + +`,r+=So([i],"javascript"),s&&(r+=`function ${s.name}(${u}) { +`)):(Dh(i)&&(r+=`import random + +`),r+=So([i],"python"),s&&(r+=`def ${s.name}(${u}): +`))}const o={out:""};b1(i.elements,e,a,s?a.indentPerLevel:0,o),s&&e!=="python"&&(o.out+=`} +`);const l=r.split(` +`).length-1;return{text:Lh((r+o.out).replace(/\n+$/,""),e),spans:n.spans.map(u=>({...u,from:u.from+l,to:u.to+l}))}}function Lh(i,e){switch(e){case"javascript":return Sb(Ao(i,"javascript")).replace(/\.length\(\)/g,".length").replace(/\.contains\(/g,".includes(");case"python":return Ib(Ao(i,"python")).replace(/\b([a-zA-Z_]\w*(?:\[[^[\]]*\])?)\.length(?:\(\)|\b)/g,"len($1)");case"java":return Ab(i)}}function Ib(i){for(let e=0;e<5;e++){const t=Eh(kb(i),"python");if(t===i)break;i=t}return i}const ku={indexOf:"find",lastIndexOf:"rfind",toUpperCase:"upper",toLowerCase:"lower",trim:"strip",startsWith:"startswith",endsWith:"endswith"};function kb(i){return a0(i,["charAt","substring","contains","isEmpty","equalsIgnoreCase","compareTo","repeat","concat",...Object.keys(ku)],(e,t,n)=>{switch(t){case"charAt":return`${e}[${n}]`;case"substring":{const a=Tb(n);return a.length===2?`${e}[${a[0].trim()}:${a[1].trim()}]`:`${e}[${n.trim()}:]`}case"contains":return`(${n.trim()} in ${e})`;case"isEmpty":return`(len(${e}) == 0)`;case"equalsIgnoreCase":return`(${e}.lower() == ${n.trim()}.lower())`;case"compareTo":return`((${e} > ${n.trim()}) - (${e} < ${n.trim()}))`;case"repeat":return`(${e} * ${n.trim()})`;case"concat":return`(${e} + ${n.trim()})`;default:return`${e}.${ku[t]}(${n})`}})}function Sb(i){for(let e=0;e<5;e++){const t=Eh(a0(i,["isEmpty","equalsIgnoreCase","compareTo","replace"],(n,a,s)=>{switch(a){case"isEmpty":return`(${n}.length === 0)`;case"equalsIgnoreCase":return`(${n}.toLowerCase() === ${s.trim()}.toLowerCase())`;case"compareTo":return`${n}.localeCompare(${s.trim()})`;default:return`${n}.replaceAll(${s})`}}),"javascript");if(t===i)break;i=t}return i}function Eh(i,e){const t=/\bFiles\.readString\(\s*(?:Path\.of|Paths\.get)\(\s*("(?:[^"\\]|\\.)*")\s*\)\s*\)/g;return e==="python"?i.replace(t,'open($1, encoding="utf-8").read()').replace(/\bInteger\.parseInt\(/g,"int(").replace(/\bDouble\.parseDouble\(/g,"float(").replace(/\bString\.valueOf\(/g,"str("):i.replace(t,'require("fs").readFileSync($1, "utf8")').replace(/\bInteger\.parseInt\(/g,"parseInt(").replace(/\bDouble\.parseDouble\(/g,"parseFloat(").replace(/\bString\.valueOf\(/g,"String(")}function Tb(i){let e=0;const t=[...i].findIndex(n=>n==="("?(e+=1,!1):n===")"?(e-=1,!1):n===","&&e===0);return t<0?[i]:[i.slice(0,t),i.slice(t+1)]}function a0(i,e,t){const n=new RegExp(`([A-Za-z_]\\w*(?:\\[[^[\\]]*\\]|\\.\\w+\\(\\))*|"(?:[^"\\\\]|\\\\.)*")\\.(${e.join("|")})\\(`,"g");let a="",s=0;for(let r=n.exec(i);r;r=n.exec(i)){const o=r.index+r[0].length-1;let l=0,u=-1;for(let m=o;me.has(n.toLowerCase())?t:`${n}.length()`)}const Ob=new Set("abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while true false null var record sealed permits yield module open opens requires exports to uses provides with transitive".split(" "));function qs(i){const e=i.trim();if(e==="")return"Main";let t="";return Array.from(e).forEach((n,a)=>{a===0?new RegExp("\\p{L}","u").test(n)||n==="_"||n==="$"?t+=n:new RegExp("\\p{Nd}","u").test(n)?t+="_"+n:t+="_":/[\p{L}\p{M}\p{N}]/u.test(n)||n==="_"||n==="$"?t+=n:t+="_"}),t=t.replace(/_{2,}/g,"_").replace(/^_+|_+$/g,""),t===""?"Main":(new RegExp("^\\p{Nd}","u").test(t)&&(t="_"+t),Ob.has(t.toLowerCase())&&(t="_"+t),t)}function Su(i,e,t={},n=[]){const a={...xh,...t},s=qs(e),r=[i,...n].filter((I,z,k)=>k.indexOf(I)===z).map(I=>({d:I,header:zt(I.caption)})).filter(I=>I.header!==void 0),o=r.map(I=>Io(I.d,I.header,"java",t,a.indentPerLevel)),l=zt(i.caption),u=r.some(I=>ms(I.d)),c=ls(i,"java",a),m=a.indentPerLevel*2,d=ms(i),h=d?Cb(c):c,g=M(m),f=h.trim()===""?"":h.split(` +`).map(I=>I.trim()===""?g:g+I).join(` +`);let b="";const x=o.length>0&&(d||u),v=[...new Set([i,...r.map(I=>I.d)].flatMap(e0))],w=v.length>0;(d||u)&&!v.includes("import java.util.Scanner;")&&v.push("import java.util.Scanner;");for(const I of v)b+=I+` +`;v.length&&(b+=` +`),b+=`public class ${s} { +`,x&&(b+=M(a.indentPerLevel)+`static Scanner scanner = new Scanner(System.in); + +`),l||(b+=M(a.indentPerLevel)+`public static void main(String[] args)${w?" throws Exception":""} { +`,d&&!x&&(b+=M(m)+`Scanner scanner = new Scanner(System.in); +`,f!==""&&(b+=` +`)),b+=f,f!==""&&!f.endsWith(` +`)&&(b+=` +`),b+=M(a.indentPerLevel)+`} +`);for(const[I,z]of o.entries())b+=(I>0||!l?` +`:"")+z;return b+=`} +`,b}function Cb(i){const e=i.split(` +`);let t=0;for(e[t]==="// import java.util.Scanner;"&&t++;t=e.length?"":e.slice(t).join(` +`)}const vn={target:"visustruct.codegen.target",javaMode:"visustruct.codegen.javaOutputMode",comments:"visustruct.codegen.includeDiagramComments",emptyElse:"visustruct.codegen.includeEmptyElse"};function ta(i){try{return localStorage.getItem(i)}catch{return null}}function na(i,e){try{localStorage.setItem(i,e)}catch{}}const jb=()=>p("web_run_stopped_loop"),Wh=()=>p("web_run_cancelled"),We=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,""");function Pb(i){let e=0;return i.replace(/^(\s*)while\s*\(\s*true\s*\)(?:\s*\/\*.*?\*\/)?\s*\{/gm,(t,n)=>{const a=`__visuStructLoopGuard${e++}`;return`${n}for (let ${a} = 0; ${a} < 100000 || (() => { throw new Error(${JSON.stringify(jb())}); })(); ${a}++) {`})}function Db(i){return Pb(i).replace(/\bprompt\s*\(/g,"await __visuStructPrompt(")}const Bb=` +let answer +let lines = [] +// Text von \`process.stdout.write\` ohne neue Zeile (wie \`System.out.print\`). +let partial = '' +const flush = (all) => { + if (all && partial) { + lines.push(partial) + partial = '' + } + if (lines.length) postMessage({ type: 'log', lines }) + lines = [] +} +const send = (type, text) => { + flush(true) + postMessage({ type, text }) +} +const fmt = (a) => (typeof a === 'string' ? a : JSON.stringify(a)) +// Ausgaben gesammelt senden, sonst bremsen viele kleine Nachrichten (z. B. in Endlosschleifen) die Seite aus. +console.log = (...args) => { + lines.push(partial + args.map(fmt).join(' ')) + partial = '' + if (lines.length >= 500) flush() +} +const process = { stdout: { write: (text) => { + const parts = (partial + String(text)).split('\\n') + partial = parts.pop() + lines.push(...parts) + if (lines.length >= 500) flush() +} } } +setInterval(flush, 50) +const __visuStructPrompt = (label) => new Promise((resolve, reject) => { + answer = (value) => (value === null ? reject(new Error(${JSON.stringify(Wh())})) : resolve(value)) + send('prompt', String(label ?? '')) +}) +onmessage = async (e) => { + if (e.data.type === 'answer') return answer && answer(e.data.value) + try { + const AsyncFunction = (async () => {}).constructor + await new AsyncFunction('__visuStructPrompt', e.data.code)(__visuStructPrompt) + send('done') + } catch (err) { + send('error', String(err)) + } +} +`,yr=2e3;class Mb{constructor(e,t,n,a,s=()=>[]){y(this,"element");y(this,"target");y(this,"javaMode");y(this,"comments");y(this,"emptyElse");y(this,"code","");y(this,"codeView");y(this,"javaModeRow");y(this,"runButton");y(this,"saveButton");y(this,"copyButton");y(this,"runner");y(this,"runOutput");y(this,"runInput");y(this,"pseudocodeBox");y(this,"pseudocodeHint");y(this,"worker");y(this,"outputLines",[]);y(this,"droppedLines",0);y(this,"outputFrame");y(this,"pendingAnswer");this.currentDocument=e,this.saveFile=t,this.onClose=n,this.setPseudocode=a,this.subprograms=s;const r=ta(vn.target);this.target=r==="python"||r==="javascript"?r:"java",this.javaMode=ta(vn.javaMode)==="class"?"class":"snippet",this.comments=ta(vn.comments)==="true",this.emptyElse=ta(vn.emptyElse)!=="false",this.element=document.createElement("aside"),this.element.className="codepanel",this.build()}refresh(){const e=this.currentDocument(),t=this.options();this.code=this.target==="java"&&this.javaMode==="class"?Su(e,this.classStem(),t,this.subprograms()):ls(e,this.target,t,this.subprograms()),this.codeView.textContent=this.code,this.javaModeRow.hidden=this.target!=="java",this.saveButton.hidden=this.target!=="java",this.runButton.hidden=this.target!=="javascript"||!!e.pseudocode,this.runButton.hidden&&this.stopRun(!0),this.pseudocodeBox.checked=!!e.pseudocode,this.pseudocodeHint.hidden=!e.pseudocode;for(const n of this.element.querySelectorAll("[data-target]"))n.setAttribute("aria-pressed",String(n.dataset.target===this.target));for(const n of this.element.querySelectorAll("[data-java-mode]"))n.setAttribute("aria-pressed",String(n.dataset.javaMode===this.javaMode))}close(){this.stopRun(!0)}options(){return{includeDiagramTextAsComments:this.comments,includeEmptyElseBranch:this.emptyElse,pseudocodeNote:p("codegen_pseudocode_note")}}classStem(){return os(this.currentDocument().caption)||"Main"}build(){this.element.innerHTML=` +
+

${We(p("codegen_placeholder_title"))}

+ +
+
+ +
+
+ +
+ + + + +
+ + + +
+

+      
+      

${We(p("codegen_generated_hint"))}

+ `;const e=a=>this.element.querySelector(a);this.codeView=e(".code-view"),this.javaModeRow=e(".java-mode"),this.runButton=e("[data-act=run]"),this.saveButton=e("[data-act=save]"),this.copyButton=e("[data-act=copy]"),this.runner=e(".runner"),this.runOutput=e(".runner-out"),this.runInput=e(".runner-input"),this.pseudocodeBox=e("[data-opt=pseudocode]"),this.pseudocodeHint=e(".pseudocode-hint"),this.pseudocodeBox.addEventListener("change",()=>this.setPseudocode(this.pseudocodeBox.checked)),e(".code-close").addEventListener("click",()=>this.onClose());for(const a of this.element.querySelectorAll("[data-target]"))a.addEventListener("click",()=>{this.target=a.dataset.target,na(vn.target,this.target),this.refresh()});for(const a of this.element.querySelectorAll("[data-java-mode]"))a.addEventListener("click",()=>{this.javaMode=a.dataset.javaMode,na(vn.javaMode,this.javaMode),this.refresh()});const t=e("[data-opt=comments]");t.checked=this.comments,t.addEventListener("change",()=>{this.comments=t.checked,na(vn.comments,String(this.comments)),this.refresh()});const n=e("[data-opt=emptyElse]");n.checked=this.emptyElse,n.addEventListener("change",()=>{this.emptyElse=n.checked,na(vn.emptyElse,String(this.emptyElse)),this.refresh()}),this.copyButton.addEventListener("click",()=>this.copy()),this.saveButton.addEventListener("click",()=>{const a=qs(this.classStem()),s=Su(this.currentDocument(),this.classStem(),this.options());this.saveFile(`${a}.java`,s)}),this.runButton.addEventListener("click",()=>this.run()),e("[data-act=stop]").addEventListener("click",()=>this.stopRun(!1)),e("[data-act=cancel]").addEventListener("click",()=>this.answer(null)),this.runInput.addEventListener("submit",a=>{a.preventDefault(),this.answer(this.runInput.querySelector("input").value)})}async copy(){var t;let e=!1;try{await navigator.clipboard.writeText(this.code),e=!0}catch{const n=document.createRange();n.selectNodeContents(this.codeView);const a=getSelection();a==null||a.removeAllRanges(),a==null||a.addRange(n),e=((t=document.execCommand)==null?void 0:t.call(document,"copy"))??!1}this.copyButton.textContent=p(e?"web_copied_check":"web_copy_manual"),setTimeout(()=>this.copyButton.textContent=p("codegen_copy"),2e3)}run(){this.stopRun(!0),this.runner.hidden=!1,this.runOutput.textContent="",this.outputLines=[],this.droppedLines=0,this.runOutput.classList.remove("error");const e=Db(this.code),t=n=>this.onRunnerMessage(n);try{const n=URL.createObjectURL(new Blob([Bb],{type:"text/javascript"})),a=new Worker(n);URL.revokeObjectURL(n),a.onmessage=s=>t(s.data),a.onerror=s=>{s.preventDefault(),t({type:"error",text:s.message||p("web_run_error")})},a.postMessage({type:"run",code:e}),this.worker=a}catch{this.runInPage(e,t)}this.setRunning(!0)}runInPage(e,t){const n={log:(...r)=>t({type:"log",lines:[r.map(o=>typeof o=="string"?o:JSON.stringify(o)).join(" ")]})},a=r=>new Promise((o,l)=>{this.pendingAnswer=u=>u===null?l(new Error(Wh())):o(u),t({type:"prompt",text:r})}),s=(async()=>{}).constructor;new s("__visuStructPrompt","console",e)(a,n).then(()=>t({type:"done"})).catch(r=>t({type:"error",text:String(r)}))}onRunnerMessage(e){switch(e.type){case"log":this.appendOutput(e.lines??[]);break;case"prompt":{this.runInput.hidden=!1,this.runInput.querySelector("label").textContent=e.text??"";const t=this.runInput.querySelector("input");t.value="",t.focus();break}case"error":this.appendOutput([e.text??""]),this.runOutput.classList.add("error"),this.stopRun(!1);break;case"done":this.stopRun(!1);break}}appendOutput(e){this.outputLines.push(...e),this.outputLines.length>yr&&(this.droppedLines+=this.outputLines.length-yr,this.outputLines.splice(0,this.outputLines.length-yr)),this.outputFrame===void 0&&(this.outputFrame=requestAnimationFrame(()=>{this.outputFrame=void 0;const t=this.droppedLines>0?p("web_run_dropped_fmt",this.droppedLines)+` +`:"";this.runOutput.textContent=t+this.outputLines.join(` +`)+(this.outputLines.length?` +`:""),this.runOutput.scrollTop=this.runOutput.scrollHeight}))}answer(e){var t;this.runInput.hidden=!0,this.worker?this.worker.postMessage({type:"answer",value:e}):(t=this.pendingAnswer)==null||t.call(this,e),this.pendingAnswer=void 0}stopRun(e){var t;(t=this.worker)==null||t.terminate(),this.worker=void 0,this.pendingAnswer=void 0,this.runInput&&(this.runInput.hidden=!0),e&&this.runner&&(this.runner.hidden=!0),this.setRunning(!1)}setRunning(e){const t=this.element.querySelector("[data-act=stop]");t&&(t.disabled=!e)}}const De=(i,e=!1)=>``,se={newFile:De(''),open:De(''),save:De(''),undo:De(''),redo:De(''),cut:De(''),copy:De(''),paste:De(''),trash:De(''),share:De(''),book:De(''),code:De(''),play:De('',!0),step:De(''),indent:De(''),stop:De('',!0),folder:De(''),newFolder:De(''),diagram:De(''),fileText:De('')},Zb="visustruct.learn.progress",wr={"04-sequenz":"05-sequenz","05-variablen-und-datentypen":"04-variablen-und-datentypen","07-verzweigung":"08-verzweigung","08-bedingungen-verknuepfen":"09-bedingungen-verknuepfen","09-fallauswahl":"10-fallauswahl","10-while-schleife":"11-while-schleife","11-do-while-schleife":"12-do-while-schleife","12-for-schleife":"13-for-schleife","13-verschachteln":"14-verschachteln","14-arrays":"15-arrays","15-aufruf-und-aussprung":"18-aufruf-und-aussprung","16-aufruf-und-aussprung":"18-aufruf-und-aussprung","17-aufruf-und-aussprung":"18-aufruf-und-aussprung","17-suchen-und-sortieren":"19-suchen-und-sortieren","18-suchen-und-sortieren":"19-suchen-und-sortieren","16-simulation-und-schreibtischtest":"07-simulation-und-schreibtischtest","17-java":"20-java","18-java":"20-java","19-java":"20-java","18-python-und-javascript":"21-python-und-javascript","19-python-und-javascript":"21-python-und-javascript","20-python-und-javascript":"21-python-und-javascript","22-erstes-fenster":"28-erstes-fenster","23-knopf-im-fenster":"29-knopf-im-fenster","24-der-knopf-reagiert":"30-der-knopf-reagiert","23-erstes-fenster":"28-erstes-fenster","24-knopf-im-fenster":"29-knopf-im-fenster","25-der-knopf-reagiert":"30-der-knopf-reagiert","26-zahl-verdoppeln":"31-zahl-verdoppeln","27-klickzaehler":"32-klickzaehler","28-ampel":"33-ampel","29-notenrechner":"34-notenrechner","30-taschenrechner":"35-taschenrechner","31-zahlenraten":"36-zahlenraten","13-lautsprecher":"16-lautsprecher","14-bildschirm":"18-bildschirm","15-motoren":"20-motoren","16-stoppuhr-akku":"21-stoppuhr-akku","03-sensoren":"04-sensoren","04-bis-zur-wand":"05-bis-zur-wand","05-abstand":"06-abstand","06-linie":"07-linie","07-farben":"08-farben","08-tasten-joystick":"10-tasten-joystick","09-licht":"11-licht","10-lautstaerke":"12-lautstaerke","11-neigung":"13-neigung","12-leds":"14-leds","13-einzelne-leds":"15-einzelne-leds","14-lautsprecher":"16-lautsprecher","15-bildschirm":"18-bildschirm","16-motoren":"20-motoren","17-stoppuhr-akku":"21-stoppuhr-akku"};function Lb(i){var n;const e={...i.lessons};for(const[a,s]of Object.entries(wr))i.lessons[a]&&!i.lessons[s]&&(e[s]=i.lessons[a]),i.lessons[a]&&delete e[a];const t=(n=i.view)!=null&&n.lesson&&wr[i.view.lesson]?{...i.view,lesson:wr[i.view.lesson]}:i.view;return{...i,lessons:e,view:t}}function Eb(){try{localStorage.removeItem(Zb)}catch{}}const Nh=()=>({lessons:{},exercises:{}});Eb();let et=Nh();const Po=new Set;function ia(){for(const i of Po)i()}const Tu="visustruct-lernstand";function Fh(i,e){return i||e||void 0}function Wb(i,e){if(!i)return e;const t={...e.checks};for(const[n,a]of Object.entries(i.checks??{}))t[n]=a||t[n]||!1;return{step:Math.max(i.step??0,e.step??0),done:Fh(i.done,e.done),checks:Object.keys(t).length?t:void 0,quiz:i.quiz||e.quiz?{...e.quiz,...i.quiz}:void 0}}function Nb(i,e){const t={...i.lessons};for(const[a,s]of Object.entries(e.lessons))t[a]=Wb(i.lessons[a],s);const n={...i.exercises};for(const[a,s]of Object.entries(e.exercises)){const r=i.exercises[a];n[a]=r?{done:Fh(r.done,s.done),xml:r.xml??s.xml}:s}return{lessons:t,exercises:n}}const be={lesson(i){return et.lessons[i]??{step:0}},updateLesson(i,e){et.lessons[i]={...be.lesson(i),...e},ia()},exercise(i){return et.exercises[i]??{}},updateExercise(i,e){et.exercises[i]={...be.exercise(i),...e},ia()},resetExercise(i){delete et.exercises[i],ia()},view(){return et.view},hasContent(){return Object.values(et.lessons).some(i=>i.step>0||i.done||i.checks||i.quiz)||Object.keys(et.exercises).length>0},setView(i){et.view=i,ia()},onChange(i){return Po.add(i),()=>Po.delete(i)},toFile(){return JSON.stringify({format:Tu,version:1,saved:new Date().toISOString(),lessons:et.lessons,exercises:et.exercises,view:et.view},null,2)},loadFile(i,e=!1){let t;try{t=JSON.parse(i)}catch{return!1}if((t==null?void 0:t.format)!==Tu)return!1;const n=Lb({lessons:t.lessons??{},exercises:t.exercises??{},view:t.view});return et=e?{...Nb(et,n),view:n.view??et.view}:n,!0},clear(){et=Nh()}};function _u(i=new Date){const e=t=>String(t).padStart(2,"0");return`${i.getFullYear()}-${e(i.getMonth()+1)}-${e(i.getDate())}`}const Au=i=>/^\d{4}-\d{2}-\d{2}$/.test(i);function Fb(i,e){return i.kind!==e.kind?i.kind==="directory"?-1:1:Au(i.name)&&Au(e.name)?e.name.localeCompare(i.name):i.name.localeCompare(e.name,void 0,{numeric:!0,sensitivity:"base"})}function Jb(i,e){return i.replace(/\.(visustruct|strk|java)$/i,"").replace(/[\\/:*?"<>|\u0000-\u001f]/g,"-").replace(/\s+/g," ").trim().replace(/^\.+/,"")||e}function Rb(i,e){const t=new Set([...e].map(a=>a.toLowerCase())),n=a=>!t.has(`${a}.visustruct`.toLowerCase())&&!t.has(`${a}.java`.toLowerCase());if(n(i))return i;for(let a=2;;a++)if(n(`${i} ${a}`))return`${i} ${a}`}function Gb(i){const e=i.replace(/[\\/:*?"<>|\u0000-\u001f]/g,"").trim();return e&&e!=="."&&e!==".."?e:void 0}const Qn=10;function Hb(i){let e=i.replace(/\r/g,"").split(` +`).filter(c=>!c.startsWith("//"));const t=e.filter(c=>/^linie:/.test(c)).map(c=>c.slice(6).trim());e=e.filter(c=>!/^linie:/.test(c));const n=e.findIndex(c=>/^raster:\s*\d+\s*$/.test(c));if(n>=0){const c=Number(e[n].split(":")[1]);e.splice(n,1),e=e.flatMap(m=>Array.from({length:c},(d,h)=>Array.from(m).map(g=>Array.from({length:c},(f,b)=>"^>v<".includes(g)?h===c>>1&&b===c>>1?g:".":g).join("")).join("")))}for(;e.length&&e[e.length-1].trim()==="";)e.pop();for(;e.length&&e[0].trim()==="";)e.shift();const s=Math.max(...e.map(c=>c.length))*Qn,r=e.length*Qn,o=(c,m)=>({x:-s/2+(c+.5)*Qn,y:r/2-(m+.5)*Qn}),l={width:s,depth:r,start:{x:0,y:0,heading:0},walls:[],lines:[],blocks:[],marks:[],goals:[],targets:[],colors:[]};let u=0;e.forEach((c,m)=>{Array.from(c).forEach((d,h)=>{const g=o(h,m);d==="#"?l.blocks.push(g):d==="="?l.marks.push(g):d==="Z"?l.goals.push(g):d==="o"?l.targets.push(g):d in Ou?l.colors.push({at:g,color:Ou[d]}):"^>v<".includes(d)&&(u++,l.start={...g,heading:{"^":0,">":90,v:180,"<":270}[d]})})});for(const c of t)l.lines.push(c.split(/\s+/).map(m=>{const[d,h]=m.split(",").map(Number);if(!Number.isFinite(d)||!Number.isFinite(h))throw new Error(`Linie: „${m}“ ist kein Feld (Spalte,Zeile).`);return o(d,h)}));if(u!==1)throw new Error(`Die Weltkarte braucht genau einen Start (^ > v <), gefunden: ${u}`);return l}const Ou={r:"red",g:"green",b:"blue",y:"yellow"},R1=(i,e)=>Math.abs(i.x-e.x)<=Qn/2&&Math.abs(i.y-e.y)<=Qn/2,Cu=10,ju=9,Vb=300,m1=8,qb=[-3.6,-1.2,1.2,3.6],Qb=2.5,Ub=20,$b=12,s0=100,Ii={width:200,depth:200,start:{x:0,y:0,heading:0},walls:[],lines:[]},Pu=i=>i*Math.PI/180,d1=i=>({x:Math.sin(Pu(i)),y:Math.cos(Pu(i))}),aa=()=>Array.from({length:uh},()=>{}),Du=([i,e,t])=>i>0||e>0||t>0?[i,e,t]:void 0;class ds{constructor(e=Ii){y(this,"pose");y(this,"trail");y(this,"bumps",0);y(this,"leds",aa());y(this,"screen");y(this,"wheels",[0,0]);y(this,"time",0);y(this,"timerStart",0);y(this,"blocked",!1);y(this,"blockWallCache");this.setup=e,this.pose={...e.start},this.trail=[{x:e.start.x,y:e.start.y}]}reset(){this.pose={...this.setup.start},this.trail=[{x:this.pose.x,y:this.pose.y}],this.bumps=0,this.leds=aa(),this.screen=void 0,this.wheels=[0,0],this.time=0,this.timerStart=0,this.blocked=!1}get allWalls(){const e=this.setup.width/2,t=this.setup.depth/2,n=[{x:-e,y:-t},{x:e,y:-t},{x:e,y:t},{x:-e,y:t}];return[...this.setup.walls,...n.map((a,s)=>({from:a,to:n[(s+1)%4]})),...this.blockWalls]}get blockWalls(){return this.blockWallCache??(this.blockWallCache=(this.setup.blocks??[]).flatMap(e=>{const t=Qn/2,n=[{x:e.x-t,y:e.y-t},{x:e.x+t,y:e.y-t},{x:e.x+t,y:e.y+t},{x:e.x-t,y:e.y+t}];return n.map((a,s)=>({from:a,to:n[(s+1)%4]}))})),this.blockWallCache}atGoal(){const e=d1(this.pose.heading),t={x:this.pose.x+e.x*m1,y:this.pose.y+e.y*m1};return(this.setup.goals??[]).some(n=>R1(this.pose,n)||R1(t,n))||(this.setup.targets??[]).some(n=>R1(this.pose,n))}apply(e){switch(e.method){case"forward":return this.wheels=[0,0],this.drive(e.args[0]);case"backward":return this.wheels=[0,0],this.drive(-e.args[0]);case"turnRight":return this.wheels=[0,0],this.turn(e.args[0]);case"turnLeft":return this.wheels=[0,0],this.turn(-e.args[0]);case"stop":this.wheels=[0,0];return;case"drive":this.wheels=[Bu(e.args[0]),Bu(e.args[1])];return;case"pause":return this.tick(e.args[0]);case"resetTimer":this.timerStart=this.time;return;case"setLed":this.leds=aa().map(()=>Du(e.args));return;case"ledOff":this.leds=aa();return;case"ledColor":this.leds[e.args[0]]=Du(ts[e.text??""]??[0,0,0]);return;case"showText":this.screen=e.text;return}}tick(e){if(e<=0)return;this.time+=e;const[t,n]=this.wheels.map(o=>o/100*Ub);if(t===0&&n===0)return;const a=Math.ceil(e/10),s=e/1e3/a;let r=!1;for(let o=0;o{const r={x:this.pose.x+e.x*m1+t.x*a,y:this.pose.y+e.y*m1+t.y*a};([...this.setup.marks??[],...this.setup.goals??[]].some(l=>R1(r,l))||this.setup.lines.some(l=>Xb(r,l)<=Qb/2))&&(n|=1<<3-s)}),n}colorUnder(){var n;const e=d1(this.pose.heading),t={x:this.pose.x+e.x*m1,y:this.pose.y+e.y*m1};return(n=(this.setup.colors??[]).find(a=>R1(t,a.at)))==null?void 0:n.color}sensors(){const e=this.lineState();return{getDistance:this.distance(),getLine:e,getColor:this.colorUnder()??(e&6?"black":"white"),isLineLeft:(e&4)!==0,isLineRight:(e&2)!==0,getTimer:this.timer}}freeDistance(e,t){let n=1/0;for(const a of this.allWalls){const s=Yb(e,t,a.from,a.to);s!==void 0&&sMath.max(-100,Math.min(100,i));function Mu(i){const e=(i%360+360)%360;return Math.abs(e-360)<1e-9?0:e}function Yb(i,e,t,n){const a={x:n.x-t.x,y:n.y-t.y},s=e.x*a.y-e.y*a.x;if(Math.abs(s)<1e-12)return;const r={x:t.x-i.x,y:t.y-i.y},o=(r.x*a.y-r.y*a.x)/s,l=(r.x*e.y-r.y*e.x)/s;return o>=0&&l>=0&&l<=1?o:void 0}function Xb(i,e){let t=1/0;for(let n=0;n+10&&o.tick(s0),s.robotSensors={...o.sensors(),...ax(a,u)};const m=()=>({outputs:[...c.outputLines],files:new Map(c.files),drive:c.robotActions.length?is(c.robotActions):void 0,...n?{atGoal:o.atGoal(),bumps:o.bumps}:{},led:o.leds.some(d=>d!==void 0),tone:c.robotActions.some(d=>d.method==="playTone"),screen:o.screen,actions:mh(c.robotActions.filter(d=>!nx.has(d.method)))});if(c.inputRequest){const d=r.shift();if(d===void 0)return{...m(),missingInput:!0};if(s.provideInput(d),c.inputErrorNotice)return{...m(),error:c.inputErrorNotice};continue}if(c.isHalted)return{...m(),error:c.notice};if(!s.canStep)return{...m(),unusedInputs:r.length||void 0};s.step()}return{outputs:[...s.state.outputLines],files:new Map(s.state.files),drive:is(s.state.robotActions),tooManySteps:!0}}function ax(i,e){const t=Math.floor(e/ex);return Object.fromEntries(Object.entries(i??{}).map(([n,a])=>[n,a[Math.min(t,a.length-1)]]))}function Jh(i){return i===void 0||i===""?[]:i.replace(/\n$/,"").split(` +`)}function sa(i,e){return i.length!==e.length?!1:i.every((t,n)=>Zu(t)===Zu(e[n]))}function Zu(i){const e=i.trim().replace(/\s+/g," ");return/^-?\d+\.0+$/.test(e)?e.replace(/\.0+$/,""):e}function sx(i,e,t,n){return e.map(a=>{var d,h,g;const s=a.world?n==null?void 0:n(a.world):void 0;if(a.world&&!s)throw new Error(`Weltkarte „${a.world}“ fehlt.`);const r=ix(i,a.inputs,t,s,a.sensors),o=(a.files??[]).every(f=>{var b;return sa(Jh((b=r.files)==null?void 0:b.get(f.name)),f.lines)}),l=!a.drive||sa(r.drive??[],a.drive),u=!a.world||r.bumps===0&&(!((d=s==null?void 0:s.goals)!=null&&d.length||(h=s==null?void 0:s.targets)!=null&&h.length)||r.atGoal===!0),c=(a.led===void 0||r.led===a.led)&&(a.tone===void 0||r.tone===a.tone)&&(a.screen===void 0||r.screen===a.screen)&&(a.drives===void 0||(((g=r.drive)==null?void 0:g.length)??0)>0===a.drives)&&(!a.actions||sa(r.actions??[],a.actions)),m=!r.error&&!r.missingInput&&!r.tooManySteps&&sa(r.outputs,a.expected)&&o&&l&&u&&c;return{test:a,result:r,passed:m}})}function rx(i){const e=new Set,t=n=>{for(const a of n){e.add(a.type),a.loopBody&&t(a.loopBody);for(const s of a.cases??[])t(s.elements)}};return t(i.elements),e}function Do(i){const e=[S.forSchleife,S.whileSchleife,S.doUntilSchleife,S.endlosschleife];let t=0;for(const n of i){const a=Math.max(Do(n.loopBody??[]),...(n.cases??[]).map(s=>Do(s.elements)));t=Math.max(t,a+(e.includes(n.type)?1:0))}return t}class ki extends Error{}function ox(i,e){const t=[],n=[];for(const a of i){const s=a.trim();if(!s)continue;if(s.startsWith("?")){const o=s.slice(1).trim();hs(o,lx(t)),n.push(o);continue}const r=/^([A-Za-z_]\w*)\s*:\s*(?:(-?\d+)\s*\.\.\s*(-?\d+)|(boolean))$/.exec(s);if(!r)throw new ki(`${e}: Unbekannte Zeile im Spiel: „${s}“`);t.push(r[4]?{name:r[1],kind:"boolean"}:{name:r[1],kind:"int",min:Number(r[2]),max:Number(r[3])})}if(!n.length)throw new ki(`${e}: Das Spiel braucht mindestens eine Zeile „? bedingung“.`);return{vars:t,conditions:n}}function lx(i){return Object.fromEntries(i.map(e=>[e.name,e.kind==="boolean"?!0:e.min]))}function ux(i){const e=[],t=/\s*(?:(\d+)|(true|false)\b|([A-Za-z_]\w*)|(&&|\|\||==|!=|<=|>=|<|>|!|\(|\)))/y;let n=0;for(;nt[n],s=d=>{var h;return((h=a())==null?void 0:h.kind)==="op"&&a().value===d},r=()=>{throw new ki(`Bedingung nicht lesbar: „${i}“`)},o=()=>{const d=t[n++]??r();if(d.kind==="num"||d.kind==="bool")return d.value;if(d.kind==="name"){if(!(d.value in e))throw new ki(`Unbekannte Variable „${d.value}“ in „${i}“`);return e[d.value]}if(d.value==="("){const h=c();return s(")")||r(),n++,h}if(d.value==="!"){const h=o();return typeof h!="boolean"&&r(),!h}return r()},l=()=>{const d=o(),h=a();if((h==null?void 0:h.kind)==="op"&&["==","!=","<","<=",">",">="].includes(h.value)){n++;const g=o();switch(h.value){case"==":return d===g;case"!=":return d!==g}(typeof d!="number"||typeof g!="number")&&r();const[f,b]=[d,g];return h.value==="<"?f"?f>b:f>=b}return d},u=()=>{let d=l();for(;s("&&");){n++;const h=l();d=d&&h}return d},c=()=>{let d=u();for(;s("||");){n++;const h=u();d=d||h}return d},m=c();return n!==t.length||typeof m!="boolean"?r():m}function cx(i,e){const t=[i],n=i.replace(/\b[A-Za-z_]\w*\b/g,r=>r in e?String(e[r]):r);n!==i&&t.push(n);const a=n.replace(/(-?\d+|true|false)\s*(==|!=|<=|>=|<|>)\s*(-?\d+|true|false)/g,r=>String(hs(r,{})));a!==t[t.length-1]&&t.push(a);const s=String(hs(i,e));return s!==t[t.length-1]&&t.push(s),t}function mx(i,e){const t=[],n=new RegExp(`\\b${e}\\s*(?:==|!=|<=|>=|<|>)\\s*(-?\\d+)|(-?\\d+)\\s*(?:==|!=|<=|>=|<|>)\\s*${e}\\b`,"g");for(const a of i.matchAll(n)){const s=Number(a[1]??a[2]);t.push(s-1,s,s+1)}return t}function dx(i,e,t,n=Math.random){const a=i.conditions.length,s=Math.floor(e*a/t),r=Math.min(a-1,s+(n()<.5?0:1)),o=i.conditions[r],l={};for(const u of i.vars){if(u.kind==="boolean"){l[u.name]=n()<.5;continue}const c=mx(o,u.name).filter(m=>m>=u.min&&m<=u.max);l[u.name]=c.length&&n()<.6?c[Math.floor(n()*c.length)]:u.min+Math.floor(n()*(u.max-u.min+1))}return{condition:o,values:l,answer:hs(o,l)}}function hx(i){return Object.entries(i.values).filter(([e])=>new RegExp(`\\b${e}\\b`).test(i.condition))}const gx=`--- +titel: Was ist ein Struktogramm? +bereich: Erste Schritte +kurz: Algorithmen als Folge klarer Schritte darstellen und lesen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, was ein Algorithmus ist +- ein Struktogramm lesen +- die drei Grundbausteine Sequenz, Verzweigung und Wiederholung erkennen +- einen PAP (englisch *flowchart*) lesen und selbst zusammenbauen +- erklären, warum Sprünge im PAP zu Fehlern führen +- einen einfachen Algorithmus als Pseudocode lesen +::: + +## Ein Algorithmus ist eine genaue Anleitung + +Ein **Algorithmus** beschreibt Schritt für Schritt, wie man eine Aufgabe löst. Jeder Schritt muss so eindeutig sein, dass ihn jemand ohne Nachfragen ausführen kann, ein Mensch genauso wie ein Computer. + +Du kennst Algorithmen aus dem Alltag: ein Kochrezept, eine Wegbeschreibung oder die Anleitung für einen Schrank. + +::: diagramm l1-tee.visustruct +Tee kochen als Struktogramm: Jeder Kasten ist ein Schritt. +::: + +## So liest du ein Struktogramm + +Ein Struktogramm wird **von oben nach unten** gelesen. Jeder Kasten ist ein Schritt. Erst wenn ein Schritt fertig ist, kommt der nächste dran. + +Die Darstellung stammt von **Isaac Nassi und Ben Shneiderman** (1973). Deshalb heißt sie auch Nassi-Shneiderman-Diagramm. In Deutschland ist sie als DIN 66261 genormt. + +::: bild ike-nassi.jpg ben-shneiderman.jpg +Links Isaac „Ike“ Nassi (Foto: [Ed Schipul](https://commons.wikimedia.org/wiki/File:Me_with_Ike_Nassi!!!!!_%286893328729%29.jpg), [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/deed.de), zugeschnitten), rechts Ben Shneiderman (Foto: [Robert Kosara](https://commons.wikimedia.org/wiki/File:Ben_Shneiderman_at_UNCC_%283x4_cropped%29.jpg), CC0). +::: + +> Ein Struktogramm hat immer genau einen Anfang (oben) und ein Ende (unten). Es gibt keine Pfeile und keine Sprünge kreuz und quer. Programme, die kreuz und quer springen, nennt man **Spaghetticode**, weil sich ihr Ablauf verheddert wie Nudeln auf dem Teller. Mehr dazu in Schritt 10. + +::: angeberwissen +Määäh, aufgepasst! 1972 waren Nassi und Shneiderman noch Doktoranden an der Stony Brook University bei New York, Shneiderman etwa 25 und Nassi etwa 23. Also quasi zwei Studis, die nebenbei Informatikgeschichte geschrieben haben. +::: + +## Baustein 1: Die Sequenz + +Jeder Algorithmus lässt sich aus nur **drei Grundbausteinen** zusammensetzen: **Sequenz**, [**Verzweigung**]{.blau} und [**Wiederholung**]{.rosa}. Die Farben helfen dir beim Zuordnen: [Anweisungen]{.gelb} sind gelb, Verzweigungen blau, Schleifen rosa. Die Sequenz hat keine eigene Farbe, sie ist einfach die Reihe von Anweisungen untereinander. Dieselben Farben siehst du im Editor und später im Code. Du kannst sie in den Einstellungen unter „Blöcke farbig“ ausschalten. In diesem und den nächsten beiden Schritten lernst du sie einzeln kennen. + +Die **Sequenz** ist der einfachste Baustein: Mehrere Anweisungen werden **nacheinander** ausgeführt, jede genau einmal. + +So sieht sie aus: + +- Jede Anweisung ist ein **einfaches Rechteck**. +- Die Rechtecke stehen ohne Lücke **untereinander**. +- Ausgeführt wird von oben nach unten, eine Anweisung nach der anderen. + +::: diagramm l1-sequenz.visustruct +Vier Anweisungen als Sequenz. Erst wird aufgestanden, dann Zähne geputzt und so weiter. +::: + +> Auch das Tee-Beispiel von oben ist eine Sequenz. + +::: angeberwissen +15 Minuten! So lange hat Shneiderman für die erste Skizze mit Sequenz, Verzweigung und Schleife gebraucht. Ich brauche länger, um mich zwischen Heu und Klee zu entscheiden. +::: + +## Baustein 2: Die Verzweigung + +Oft hängt der nächste Schritt von einer **Bedingung** ab. Eine Bedingung ist eine Frage, die man nur mit **ja oder nein** beantworten kann, zum Beispiel *Regnet es?* In VisuStruct heißt ja **true** (wahr) und nein **false** (falsch). + +Für solche Entscheidungen gibt es die **Verzweigung**. So sieht sie aus: + +- Oben steht die Bedingung in einem **Dreieck**. +- Darunter teilt sich der Kasten in **zwei Spalten**: links der Weg für **true**, rechts der Weg für **false**. +- Es wird **immer nur einer** der beiden Wege ausgeführt. Danach geht es unter der Verzweigung für beide gemeinsam weiter. + +::: diagramm l1-verzweigung.visustruct +Regnet es, wird der linke Weg ausgeführt, sonst der rechte. Danach geht es in beiden Fällen mit „Losgehen“ weiter. +::: + +> Soll in einem Fall nichts passieren, bleibt dieser Weg leer. Das zeigt das Zeichen **ø**. + +::: angeberwissen +Rechtschreib-Alarm! Es heißt Shneiderman, ohne c. Wer „Schneiderman“ schreibt, bekommt von mir einen sanften Hornstupser. Er selbst weist übrigens darauf hin, dass ihm ständig ein c untergeschmuggelt wird. +::: + +## Baustein 3: Die Wiederholung + +Soll etwas **mehrmals** passieren, schreibt man es nicht mehrmals hin. Stattdessen benutzt man eine **Wiederholung**, auch **Schleife** genannt. + +So sieht sie aus: + +- Oben steht die Bedingung, zum Beispiel *Teller nicht leer*. +- Die Schritte, die wiederholt werden, stehen **eingerückt** darunter. Oben und links bildet der Kasten ein **gekipptes L** um sie. +- Vor jedem Durchlauf wird die Bedingung geprüft. Solange sie **true** ist, werden die Schritte im gekippten L noch einmal ausgeführt. Ist sie **false**, geht es unter der Schleife weiter. + +::: diagramm l1-wiederholung.visustruct +Solange der Teller nicht leer ist, wird ein Bissen gegessen. Danach wird der Teller abgeräumt. +::: + +> Es gibt noch weitere Arten von Schleifen. Du lernst sie in späteren Lektionen kennen. + +## Alle drei zusammen + +Richtig nützlich werden die Bausteine, wenn man sie kombiniert. Das Diagramm enthält alle drei: eine Sequenz von oben nach unten, eine [Verzweigung]{.blau} und eine [Schleife]{.rosa}. Gelb sind die einfachen [Anweisungen]{.gelb}. Auch die Anweisungen in einer Verzweigung oder Schleife sind gelb. Genau genommen ist das ganze Diagramm eine Sequenz, denn auch Verzweigung und Schleife stehen in der Reihe von oben nach unten. + +::: diagramm l1-grundbausteine.visustruct +Die Verzweigung erkennst du am Dreieck, die Schleife am gekippten L. Alles zusammen steht in einer Sequenz. +::: + +Die Kästen können auch **ineinander geschachtelt** werden: In einer Schleife oder einem Zweig können wieder Sequenzen, Verzweigungen und Schleifen stehen. + +::: angeberwissen +Trostpflaster für alle mit einer verpatzten Arbeit: Die berühmte Fachzeitschrift *Communications of the ACM* hat den Struktogramm-Artikel abgelehnt. Laut Nassi meinte der Gutachter sogar, sie sollten alle Exemplare einsammeln und verbrennen. Autsch! Er erschien 1973 dann in einem kleineren Heft und wird heute tausendfach zitiert. Ätsch! +::: + +## Andere Darstellungen: Der PAP + +Es gibt noch zwei weitere Arten, Algorithmen darzustellen: den **Programmablaufplan**, kurz **PAP**, und den **Pseudocode**. Beide wirst du im Unterricht treffen. Auf Englisch heißt der PAP **flowchart**, auf Deutsch auch Flussdiagramm. Das englische Wort begegnet dir oft, zum Beispiel in Programmen und im Internet. + +Hier siehst du noch einmal unser Struktogramm zum Teetrinken aus „Alle drei zusammen“. Als Nächstes schauen wir uns den PAP an, und zwar mit demselben Beispiel. + +::: diagramm l1-grundbausteine.visustruct +Das Tee-Beispiel als Struktogramm: erst die Tasse, dann die Verzweigung für den Zucker, dann die Schleife. +::: + +### Derselbe Algorithmus als PAP + +::: grafik l01-pap.svg +Das Tee-Beispiel als Programmablaufplan. Der Pfeil von „1 Minute warten“ zurück nach oben bildet die Schleife. +::: + +### Die Elemente + +Ein PAP besteht aus wenigen Symbolen, die mit **Pfeilen** verbunden sind. Er ist nach DIN 66001 genormt. + +- **Oval:** Start oder Ende. Jeder PAP hat genau einen Start und ein Ende. +- **Rechteck:** eine Anweisung, zum Beispiel *Tasse auf den Tisch stellen*. +- **Raute:** eine Verzweigung. In der Raute steht eine Frage, heraus führen zwei Pfeile: **ja** und **nein**. +- **Parallelogramm:** eine Ein- oder Ausgabe. Im Tee-Beispiel kommt sie nicht vor. +- **Pfeil:** zeigt, welcher Schritt als Nächstes kommt. + +Eine Schleife hat im PAP kein eigenes Symbol. Du erkennst sie daran, dass ein Pfeil **zurück nach oben** führt. + +### Die Vorteile + +- **Sehr gut lesbar**, auch für Leute, die noch nie einen PAP gesehen haben. Man folgt einfach den Pfeilen mit dem Finger. +- Flussdiagramme benutzt man nicht nur beim Programmieren, sondern überall, wo ein Ablauf erklärt wird: in Bedienungsanleitungen, bei der Fehlersuche („Leuchtet die Lampe? Nein: Steckt der Stecker?“) oder in Firmen für Arbeitsabläufe. + +## Übung: Kuchen backen als PAP + +Jetzt baust du selbst einen PAP. Ludwig backt einen Kuchen und geht so vor: + +Er gibt die Zutaten in die Schüssel und rührt den Teig. Ist der Teig noch nicht glatt, rührt er weiter. Ist er glatt, füllt er den Teig in die Form und backt den Kuchen 30 Minuten. Dann prüft er mit einem Holzstäbchen: Klebt noch Teig daran, backt er 5 Minuten weiter und prüft noch einmal. Ist das Stäbchen sauber, nimmt er den Kuchen heraus und ruft: „Der Kuchen ist fertig!“ + +::: pap +titel: Übung: Kuchen backen als PAP +auftrag: Die Plätze im Plan sind leer. Lege jedes Element an seinen Platz. Die Form des Platzes hilft dir. +start: Start +anweisung: Zutaten in die Schüssel geben +anweisung: Teig rühren +frage: Teig glatt? | nein -> Teig rühren +anweisung: Teig in die Form füllen +anweisung: Kuchen 30 Minuten backen +frage: Stäbchen sauber? | nein: 5 Minuten weiterbacken +anweisung: Kuchen herausnehmen +ausgabe: „Der Kuchen ist fertig!“ +ende: Ende +erklärung: Zwei Schleifen, zwei Pfeile zurück nach oben: Beim Rühren führt der Pfeil zurück zu „Teig rühren“, beim Backen von „5 Minuten weiterbacken“ zurück zur Frage. Die Ausgabe steht im Parallelogramm. +legende: ja +::: + +## Nachteile des PAP: Sprünge + +Ein Pfeil im PAP darf von jedem Symbol zu jedem anderen führen. Das klingt praktisch, ist aber gefährlich. + +Früher hat man Programme genau so geschrieben. Jede Zeile hatte eine **Nummer**, und der Befehl **GOTO**, auf Deutsch „gehe zu“, sprang zu einer Zeilennummer. Jedes GEHE ZU ist ein Pfeil aus dem PAP. Unser Tee-Beispiel sähe so aus: + +\`\`\` +10 Tasse auf den Tisch stellen +20 WENN kein Zucker gewünscht, GEHE ZU 40 +30 Zucker hineingeben +40 WENN Tee nicht zu heiß, GEHE ZU 70 +50 1 Minute warten +60 GEHE ZU 40 +70 Tee trinken +\`\`\` + +### Eine Zeile mehr, und schon springt es falsch + +Jetzt verbesserst du den Algorithmus: Nach dem Zucker soll der Teebeutel heraus. Du fügst die neue Zeile 40 ein, und alle Zeilen darunter rutschen eine Nummer weiter. Die Sprünge zeigen aber noch auf die alten Nummern: + +\`\`\` +10 Tasse auf den Tisch stellen +20 WENN kein Zucker gewünscht, GEHE ZU 40 +30 Zucker hineingeben +40 Teebeutel herausnehmen +50 WENN Tee nicht zu heiß, GEHE ZU 70 +60 1 Minute warten +70 GEHE ZU 40 +80 Tee trinken +\`\`\` + +Spiel es durch: Zeile 70 schickt dich nicht mehr zur Prüfung in Zeile 50, sondern zum Teebeutel. Und wenn der Tee kühl genug ist, springt Zeile 50 zu Zeile 70 und nicht mehr zu *Tee trinken*. Du nimmst also immer wieder den Teebeutel heraus und trinkst nie. Bei jeder Änderung musst du jedes GEHE ZU prüfen. In einem großen Programm mit Hunderten Sprüngen geht dabei leicht etwas schief. + +### Kreuz und quer: Spaghetticode + +Mit Pfeilen kann man auch mitten aus einer Schleife herausspringen oder von außen mitten in eine Schleife hinein. Solche **Aussprünge** und Einsprünge machen den Plan schnell unübersichtlich. Bei vielen Sprüngen kreuzen sich die Pfeile, bis der Plan aussieht wie ein Teller Spaghetti. Deshalb nennt man das **Spaghetticode**. Den Ablauf kann man kaum noch verfolgen, und Fehler verstecken sich gut. + +Im Struktogramm gibt es keine Pfeile. Fügst du einen Kasten ein, rutscht alles darunter einfach mit, und kein Sprung kann auf die falsche Stelle zeigen. Für das vorzeitige Verlassen einer Schleife gibt es dort einen eigenen, ordentlichen Kasten, den Aussprung. Den lernst du in Lektion 18 kennen. + +::: angeberwissen +1968 schrieb der Informatiker Edsger Dijkstra einen berühmten Brief: „Go To Statement Considered Harmful“, auf Deutsch „GOTO gilt als schädlich“. Seitdem baut man Programme nur noch aus Sequenz, Verzweigung und Wiederholung. In Java ist \`goto\` bis heute ein reserviertes Wort, benutzen darf man es aber nicht. Mäh, Spaghetti esse ich lieber, als sie zu programmieren. +::: + +## Pseudocode und Vergleich + +**Pseudocode** ist Text, der wie ein Programm aussieht, aber in normaler Sprache geschrieben ist. Feste Wörter wie WENN und SOLANGE zeigen die Bausteine, die **Einrückung** zeigt, was dazugehört. Sprünge gibt es auch hier nicht. Das ist unser Tee-Beispiel: + +\`\`\` +Tasse auf den Tisch stellen +WENN Zucker gewünscht DANN + Zucker hineingeben +ENDE WENN +SOLANGE Tee noch zu heiß + 1 Minute warten +ENDE SOLANGE +Tee trinken +\`\`\` + +Pseudocode hat **keine feste Schreibweise**. Manche schreiben FALLS statt WENN, andere setzen einen Pfeil für die Zuweisung (\`zahl ← 5\`) oder schreiben ganz ohne ENDE-Zeilen. Das ist alles erlaubt. Wichtig ist nur, dass jeder Mensch ihn ohne Erklärung versteht. Pseudocode ist also keine weitere Programmiersprache, die man lernen muss. + +::: angeberwissen +Kommt dir Pseudocode bekannt vor? Die Programmiersprache Python sieht ihm sehr ähnlich, und das ist Absicht: Ihr Erfinder Guido van Rossum wollte, dass sich Programme fast wie normaler Text lesen. Auch Python zeigt mit der Einrückung, was zusammengehört. Aber Vorsicht: Python ist eine echte Programmiersprache mit festen Regeln. Ein Leerzeichen zu viel, und der Computer meckert. Pseudocode ist da großzügiger, so wie ich beim Frühstück. +::: + +### Im Vergleich + +- **Struktogramm:** Kästen ineinander, die Schleife ist ein gekipptes L. Die Struktur siehst du auf einen Blick, wilde Sprünge sind unmöglich. +- **PAP:** Symbole mit Pfeilen, die Schleife ist ein Pfeil zurück nach oben. Sehr anschaulich, aber bei großen Plänen schnell unübersichtlich, und Sprünge kreuz und quer sind möglich. +- **Pseudocode:** Text mit Einrückung, die Schleife steht zwischen SOLANGE und ENDE SOLANGE. Schnell geschrieben und schon nah am Programmcode. + +> Alle drei beschreiben denselben Algorithmus. Wenn du eine Form lesen kannst, lernst du die anderen schnell. + +::: angeberwissen +Nassi und Shneiderman wollten den Pfeilen an den Kragen! Ihr Artikel von 1973 hieß „Flowchart Techniques for Structured Programming“. Flowchart ist das englische Wort für Ablaufplan. Mit Pfeilen kann man nämlich kreuz und quer springen, bis der Plan aussieht wie ein Teller Spaghetti. Im Struktogramm geht das gar nicht. Mäh, so mag ich das: ordentlich, wie mein Stall. +::: + +## Erst die Struktur, dann der Code + +Beim Programmieren passieren zwei Dinge gleichzeitig: Du musst dir den Ablauf überlegen und die Schreibweise der Programmiersprache beachten. Mit einem Struktogramm trennst du beides. + +1. Du denkst zuerst über die **Logik** nach: Welche Schritte, welche Bedingungen, welche Wiederholungen? +2. Danach übersetzt du die fertige Struktur in **Java, Python oder JavaScript**. VisuStruct kann dir den Code sogar erzeugen. + +Mit der **Simulation** kannst du dein Struktogramm außerdem Schritt für Schritt ausführen und prüfen, ob es wirklich tut, was es soll. + +## Spiel: Welcher Baustein? + +::: spiel frage +titel: Spiel: Welcher Baustein? +intro: Ludwig beschreibt Dinge aus seinem Alltag. Welcher der drei Bausteine steckt darin? Acht Runden. +antworten: Sequenz | Verzweigung | Wiederholung + +runde: +frage: „Zahnpasta auf die Bürste, Zähne putzen, Mund ausspülen.“ +richtig: Sequenz +> Drei Schritte, jeder genau einmal und immer in dieser Reihenfolge. + +runde: +frage: „Wenn es regnet, nimm den Schirm mit, sonst die Sonnenbrille.“ +richtig: Verzweigung +> Eine Bedingung entscheidet, welcher der zwei Wege genommen wird. + +runde: +frage: „Rühre, bis der Teig glatt ist.“ +richtig: Wiederholung +> Das Rühren wird wiederholt, solange der Teig noch nicht glatt ist. + +runde: +frage: „Laufe zehn Runden um den Sportplatz.“ +richtig: Wiederholung +> Dieselbe Runde wird zehnmal gelaufen. + +runde: +frage: „Schuhe an, Jacke an, Tür auf, losgehen.“ +richtig: Sequenz +> Ein Schritt nach dem anderen, nichts wird übersprungen oder wiederholt. + +runde: +frage: „Ist die Ampel grün, gehst du über die Straße.“ +richtig: Verzweigung +> Auch ohne „sonst“ ist es eine Verzweigung. Der Sonst-Zweig ist einfach leer. + +runde: +frage: „Würfle so lange, bis du eine Sechs hast.“ +richtig: Wiederholung +> Du weißt vorher nicht, wie oft. Gewürfelt wird, bis die Bedingung erfüllt ist. + +runde: +frage: „Sagt jemand ‚Herein‘, gehst du hinein. Sonst wartest du vor der Tür.“ +richtig: Verzweigung +> Die Antwort entscheidet zwischen zwei Wegen: hineingehen oder warten. +::: + +## 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. + +::: checkliste +- Ich kann erklären, was ein Algorithmus ist. → Ein Algorithmus ist eine genaue Anleitung +- Ich kann ein Struktogramm von oben nach unten lesen. → So liest du ein Struktogramm +- Ich kann die drei Grundbausteine Sequenz, Verzweigung und Wiederholung nennen. → Baustein 1: Die Sequenz +- Ich kann jeden Baustein im Struktogramm an seiner Form erkennen. → Alle drei zusammen +- Ich kann die Elemente eines PAP benennen und einen einfachen PAP lesen. → Andere Darstellungen: Der PAP +- Ich kann einen einfachen Algorithmus selbst als PAP zusammenbauen. → Übung: Kuchen backen als PAP +- Ich kann erklären, warum Sprünge mit GOTO zu Fehlern und Spaghetticode führen. → Nachteile des PAP: Sprünge +- Ich kann einen einfachen Algorithmus als Pseudocode lesen. → Pseudocode und Vergleich +::: + +## Wissenstest + +::: quiz +? In welcher Richtung wird ein Struktogramm gelesen? +→ So liest du ein Struktogramm +- [ ] Von links nach rechts +- [x] Von oben nach unten +- [ ] Von unten nach oben +> Jeder Kasten ist ein Schritt, und die Schritte folgen von oben nach unten aufeinander. + +? Welcher Baustein gehört NICHT zu den drei Grundbausteinen? +→ Baustein 1: Die Sequenz +- [ ] Sequenz +- [ ] Verzweigung +- [x] Sprung +- [ ] Wiederholung +> Sprünge gibt es im Struktogramm nicht. Sequenz, Verzweigung und Wiederholung reichen für jeden Algorithmus. + +? Woran erkennst du im Struktogramm eine Verzweigung? +→ Alle drei zusammen +- [ ] An einem gekippten L +- [x] An einem Dreieck mit der Bedingung und zwei Spalten darunter +- [ ] An mehreren Rechtecken untereinander +> Das gekippte L gehört zur Schleife, Rechtecke untereinander sind eine Sequenz. + +? Wann wird der Inhalt einer Schleife noch einmal ausgeführt? +→ Alle drei zusammen +- [x] Solange die Bedingung true ist +- [ ] Nur, wenn die Bedingung false ist +- [ ] Immer genau zweimal +> Vor jedem Durchlauf wird die Bedingung geprüft. Ist sie false, geht es unter der Schleife weiter. + +? Was ist ein Algorithmus? +→ Ein Algorithmus ist eine genaue Anleitung +- [x] Eine eindeutige Schritt-für-Schritt-Anleitung zum Lösen einer Aufgabe +- [ ] Ein bestimmtes Programm in Java +- [ ] Ein Bild, das ein Programm erklärt +> Ein Algorithmus ist unabhängig von der Programmiersprache. Ein Struktogramm ist eine Möglichkeit, ihn aufzuschreiben. + +? Woran erkennst du in einem Programmablaufplan (PAP) eine Schleife? +→ Andere Darstellungen: Der PAP +- [ ] An einem gekippten L +- [x] An einem Pfeil, der zurück nach oben führt +- [ ] Am Wort SOLANGE +> Das gekippte L gehört zum Struktogramm, SOLANGE zum Pseudocode. + +? Ordne jedem Symbol im PAP seine Bedeutung zu. +→ Andere Darstellungen: Der PAP += Oval -> Start oder Ende += Rechteck -> Anweisung += Raute -> Verzweigung += Parallelogramm -> Ein- oder Ausgabe +> Die Raute hat zwei Ausgänge: ja und nein. + +? Wie heißt der Programmablaufplan auf Englisch? +→ Andere Darstellungen: Der PAP +- [x] Flowchart +- [ ] Structure chart +- [ ] Pseudocode +> Auf Deutsch sagt man auch Flussdiagramm. Structure chart ist das Struktogramm. + +? Du fügst in ein Programm mit GOTO eine neue Zeile ein. Was kann passieren? +→ Nachteile des PAP: Sprünge +- [x] Die Sprünge zeigen auf die falschen Zeilen, weil sich die Nummern verschoben haben +- [ ] Nichts, die Sprünge passen sich von selbst an +- [ ] Das Programm wird automatisch schneller +> Jedes GEHE ZU zeigt auf eine feste Zeilennummer. Rutschen die Zeilen weiter, springt das Programm an die falsche Stelle. + +? Was zeigt im Pseudocode, welche Zeilen zu einer Schleife gehören? +→ Pseudocode und Vergleich +- [ ] Die Farbe +- [x] Die Einrückung und das ENDE SOLANGE +- [ ] Ein Pfeil +> Alles zwischen SOLANGE und ENDE SOLANGE ist eingerückt und wird wiederholt. +::: +`,px=`--- +titel: Der Editor +bereich: Erste Schritte +kurz: Elemente einfügen, Text eingeben, verschieben und löschen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- ein Element aus dem Bereich Elemente einfügen und einen Platzhalter ersetzen +- den Text eines Kastens ändern und zwischen Anweisung, Eingabe und Ausgabe umschalten +- Kästen verschieben, kopieren, löschen und Schritte rückgängig machen +::: + +## Die Oberfläche + +VisuStruct hat zwei Editoren: den [Struktogramm-Editor](#zeige-editor), um den es in dieser Lektion geht, und rechts den Bereich [Code](#zeige-codelive) für Java-Code (ab Lektion 4). Ist der Struktogramm-Editor eingeklappt, öffnet ihn diese Lektion von selbst. Die blauen Wörter zeigen dir die Bereiche, auch wenn sie gerade eingeklappt sind: Fährst du mit der Maus darüber, öffnet sich der Bereich neben dem Lernbereich und leuchtet auf. Klickst du darauf (oder tippst es an), bleibt er offen. + +Der Struktogramm-Editor besteht aus mehreren Bereichen. Fahre mit der Maus über ein blaues Wort oder tippe es an, dann leuchtet der Bereich im Editor auf, eingeklappte Bereiche wie die Elemente öffnen sich dabei. + +- **Ganz oben die [Leiste](#zeige-leiste):** Neu, Öffnen und Speichern. Ganz rechts das Zahnrad für die [Einstellungen](#zeige-einstellungen): Textgröße und Sprache. +- **Darunter die [Werkzeuge](#zeige-werkzeuge)** über den Elementen und dem Struktogramm: Rückgängig, Ausschneiden, Kopieren, Einfügen, Löschen, Exportieren, Code und Simulation. Die Knöpfe zeigen nur Symbole. Hältst du die Maus darüber, erscheint ihr Name. +- **Links die [Elemente](#zeige-elemente):** Hier liegen alle Bausteine, die du ins Struktogramm ziehen kannst. Manche nennen diesen Bereich auch Palette. +- **In der Mitte das [Struktogramm](#zeige-struktogramm):** Ein neues Diagramm enthält nur einen leeren Platzhalter, erkennbar an **ø**. +- **Unten der [Objektinspektor](#zeige-objektinspektor):** Hier bearbeitest du den Text des ausgewählten Elements. + +> Diesen Lernbereich kannst du jederzeit mit dem [Seitenleisten-Symbol](#zeige-lernen) oben in diesem Bereich einklappen. Dann bleibt links nur die schmale Leiste „🎓 Lernen“, ein Klick darauf öffnet ihn wieder. Er bleibt neben dem Editor offen, damit du gleich ausprobieren kannst, was du liest. Genauso gibt es links die Spalte [📁 Dateien](#zeige-dateien) für deine gespeicherten Programme (Lektion 3) und rechts den Bereich [Code](#zeige-codelive) für Java (ab Lektion 4). + +## Ein Element einfügen + +Ziehe ein Element aus dem Bereich **Elemente** auf das Struktogramm. Beim Ziehen zeigt eine blaue Linie, wo es landet: + +- **Auf den Platzhalter ø:** Das Element ersetzt den Platzhalter. +- **Auf die obere Hälfte eines Kastens:** Das Element kommt davor. +- **Auf die untere Hälfte eines Kastens:** Das Element kommt dahinter. + +::: grafik l02-einfuegen.svg +Wohin du ziehst, entscheidet, wo das neue Element landet. +::: + +Es geht auch ohne Ziehen: **Klicke** auf ein Element im Bereich Elemente (oder tippe es an). Dann wird es hinter dem ausgewählten Kasten eingefügt. Ist der Platzhalter **ø** ausgewählt, ersetzt es ihn. + +Mit der Tastatur springst du mit der **Tab**-Taste zu einem Element und drückst **Enter**. Das neue Element landet dann ebenfalls hinter dem ausgewählten Kasten. + +::: angeberwissen +Kästen packen und herumziehen, so wie du gerade, hat einen schicken Namen: **direkte Manipulation**. Den Begriff hat 1982 Ben Shneiderman geprägt, genau, der vom Struktogramm. Der Mann war fleißiger als ich beim Grasen. +::: + +## Text eingeben + +Klicke einen Kasten an. Er wird blau umrandet, und im Objektinspektor unter dem Diagramm erscheint sein Text. Was du dort tippst, siehst du sofort im Diagramm. + +Der Kasten aus dem Bereich Elemente heißt **Anweisung**. Oben wählst du, welche Art von Anweisung er sein soll: + +- **Anweisung:** etwas berechnen oder festlegen, z. B. \`int zahl = 5\`. Wie das geht, lernst du in Lektion 4. +- **Eingabe:** beim Ausführen einen Wert abfragen. Das kommt in Lektion 6. +- **Ausgabe:** etwas anzeigen. Im Diagramm steht dann \`output:\` davor, z. B. \`output: "Hallo"\`. + +Für den Anfang brauchst du nur die Ausgabe. Texte, die genau so angezeigt werden sollen, schreibst du in **Anführungszeichen**. + +::: diagramm l2-ausgabe.visustruct +Zwei Ausgaben nacheinander. Öffne das Diagramm im Editor und starte die Simulation, um die Ausgabe zu sehen. +::: + +## Verschieben, kopieren, löschen + +- **Verschieben:** Einen vorhandenen Kasten mit der Maus an eine neue Stelle ziehen. +- **Kopieren und Einfügen:** Kasten auswählen, dann Strg+C und Strg+V (am Mac ⌘C und ⌘V). Die Kopie kommt hinter den ausgewählten Kasten. +- **Löschen:** Kasten auswählen und Entf drücken oder in den Werkzeugen auf den [Mülleimer](#zeige-loeschen) „Auswahl löschen“ klicken. +- **Rückgängig:** Strg+Z macht den letzten Schritt rückgängig, Strg+Umschalt+Z stellt ihn wieder her (am Mac ⌘Z und ⌘⇧Z). + +## Übung: Hallo Welt + +::: übung l2-hallo +titel: Hallo Welt +auftrag: Baue ein Struktogramm, das **Hallo Welt** ausgibt. +Ziehe eine **Anweisung** aus den Elementen auf den Platzhalter **ø** und klicke den Kasten an. Im Objektinspektor unter dem Struktogramm stehen oben drei Knöpfe: Anweisung, Eingabe und Ausgabe. Klicke auf **Ausgabe**. Schreibe dann in das Textfeld darunter \`"Hallo Welt"\`, mit Anführungszeichen. +test: - -> Hallo Welt +braucht: anweisung +tipp: Du brauchst nur einen einzigen Kasten. Der Text, der erscheinen soll, steht im Objektinspektor im Eingabefeld. +tipp: Achte auf die Anführungszeichen. Ohne sie sucht VisuStruct nach einer Variablen mit dem Namen Hallo. +lösung: l2-hallo-loesung.visustruct +::: + +Klicke auf **Prüfen**, wenn du fertig bist. VisuStruct führt dein Struktogramm aus und vergleicht die Ausgabe. + +## Übung: Zwei Zeilen + +::: übung l2-zwei-zeilen +titel: Zwei Zeilen +auftrag: Gib zuerst **Hallo** und danach **Ich lerne Struktogramme** aus, jeweils in einer eigenen Zeile. +test: - -> Hallo | Ich lerne Struktogramme +tipp: Zwei Zeilen heißt: zwei Ausgaben. Die Kästen stehen untereinander und werden von oben nach unten ausgeführt. +tipp: Jede Ausgabe ist ein eigener Kasten. Ziehe die zweite Anweisung auf die untere Hälfte der ersten. +lösung: l2-zwei-zeilen-loesung.visustruct +::: + +## Spiel: Editor-Profi + +::: spiel frage +titel: Spiel: Editor-Profi +intro: Ludwig testet, ob du den Editor im Griff hast. Sieben Runden. + +runde: +frage: Du ziehst eine Anweisung auf den Platzhalter **ø**. Was passiert? +- [x] Die Anweisung ersetzt den Platzhalter. +- Die Anweisung kommt hinter den Platzhalter. +- Nichts, auf ø darf man nichts ziehen. +> Der Platzhalter hält nur den Platz frei. Das neue Element nimmt ihn ein. + +runde: +frage: Du ziehst ein Element auf die **obere** Hälfte eines Kastens. Wo landet es? +- [x] davor +- dahinter +- Es ersetzt den Kasten. +> Obere Hälfte heißt davor, untere Hälfte heißt dahinter. Die blaue Linie zeigt es dir beim Ziehen. + +runde: +frage: Du ziehst ein Element auf die **untere** Hälfte eines Kastens. Wo landet es? +- davor +- [x] dahinter +- ganz am Ende des Struktogramms +> Untere Hälfte heißt: direkt hinter diesen Kasten. + +runde: +frage: Du hast aus Versehen einen Kasten gelöscht. Was holt ihn zurück? +- Strg+C / ⌘C +- [x] Strg+Z / ⌘Z +- Strg+V / ⌘V +> Strg+Z / ⌘Z macht den letzten Schritt rückgängig. Strg+C / ⌘C kopiert, Strg+V / ⌘V fügt ein. + +runde: +frage: Beim Ausführen soll genau **Hallo** erscheinen. Was steht im Kasten? +- [x] output: "Hallo" +- output: Hallo +- "Hallo" +> Text, der genau so angezeigt werden soll, steht in Anführungszeichen. Das \`output:\` setzt der Editor davor, wenn du die Art Ausgabe wählst. + +runde: +frage: Wo änderst du den Text des ausgewählten Kastens? +- in den Elementen +- [x] im Objektinspektor +- in der Leiste ganz oben +> Der Objektinspektor unter dem Diagramm zeigt den Text des ausgewählten Kastens. + +runde: +frage: Du klickst im Bereich Elemente auf ein Element, ohne zu ziehen. Wo landet es? +- [x] hinter dem ausgewählten Kasten +- ganz am Anfang +- ganz am Ende +> Ohne Ziehen (Klick oder Tab und Enter) kommt das neue Element hinter den Kasten, der gerade ausgewählt ist. +::: + +## 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. + +::: checkliste +- Ich kann ein Element aus dem Bereich Elemente einfügen und einen Platzhalter ersetzen. → Ein Element einfügen +- Ich kann den Text eines Kastens ändern und zwischen Anweisung, Eingabe und Ausgabe umschalten. → Text eingeben +- Ich kann Kästen verschieben, kopieren, löschen und Schritte rückgängig machen. → Verschieben, kopieren, löschen +::: + +## Wissenstest + +::: quiz +? Was bedeutet das Zeichen ø in einem Kasten? +→ Ein Element einfügen +- [ ] Der Kasten enthält einen Fehler. +- [x] Hier ist noch ein leerer Platzhalter. +- [ ] Das Programm endet hier. +> Ein Platzhalter wird ersetzt, wenn du ein Element darauf ziehst. + +? Du ziehst eine Anweisung auf die untere Hälfte eines Kastens. Wo landet sie? +→ Ein Element einfügen +- [ ] Davor +- [x] Dahinter +- [ ] Der Kasten wird ersetzt. + +? Wie gibst du den Text Guten Tag genau so aus? +→ Text eingeben +- [ ] output: Guten Tag +- [x] output: "Guten Tag" +- [ ] input: "Guten Tag" +> Ohne Anführungszeichen wird Guten Tag als Name einer Variablen verstanden. +::: +`,fx=`--- +titel: Speichern, Öffnen, Exportieren +bereich: Erste Schritte +kurz: Dateien sichern, deinen Workspace nutzen, mehrere Diagramme öffnen und als Bild oder PDF weitergeben. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- einem Diagramm einen Titel geben +- ein Diagramm als .visustruct-Datei speichern und wieder öffnen +- ein Diagramm als Bild (PNG) oder PDF exportieren +- ein zweites Diagramm in einem neuen Reiter öffnen +- meinen Workspace \`VisuStruct-Dateien\` anlegen +- ein Programm in meinem Workspace speichern +::: + +## Die Datei .visustruct + +Struktogramme werden als **.visustruct**-Datei gespeichert. Dasselbe Format nutzen alle VisuStruct-Versionen: im Browser, auf Mac, iPad und iPhone und die Java-App am Rechner. Du kannst also in der Schule im Browser anfangen und zu Hause in der App weitermachen. + +::: angeberwissen +Zu Nassis Studienzeit gab es keine Dateien zum Speichern, sondern Lochkarten. Nassi erzählt, dass ein Date am Samstagabend so aussah: seine spätere Frau saß mit ihm im Rechenzentrum und stanzte seine Lochkarten. Romantik, Informatik-Style! +::: + +::: grafik l03-lochkarte.svg l03-lochkarte-beschriftet.svg +So sah eine Lochkarte aus. Eine Karte war eine Zeile Programm, hier \`PRINT *, 'HALLO WELT'\` in der Sprache Fortran. Jede Spalte ist ein Zeichen, die Löcher darin sind sein Code. Ein ganzes Programm war ein Stapel solcher Karten. Fiel er herunter, musste man alles wieder sortieren. +::: + +## Speichern und Öffnen + +- **[Speichern](#zeige-speichern)** (Strg+S, am Mac ⌘S): Das Diagramm wird als Datei gespeichert. Ist die Spalte **Dateien** eingerichtet (siehe unten), landet es dort. Sonst fragt der Browser nach dem Ort oder legt die Datei in den Download-Ordner. +- **[Öffnen](#zeige-oeffnen)** (Strg+O, am Mac ⌘O): Eine gespeicherte Datei wieder laden. Du kannst eine Datei auch einfach ins Browserfenster ziehen. + +> Deine Übungen merkt sich der Browser automatisch. Das klappt aber nur in diesem Browser auf diesem Gerät. Wichtige Arbeiten solltest du deshalb immer zusätzlich als Datei speichern. + +## Die Spalte Dateien + +Links neben dem Lernbereich findest du die Spalte [📁 Dateien](#zeige-dateien). Dort sammelst du alle deine Programme an einem Ort, deinem **Workspace** (Arbeitsbereich). + +**Jetzt du:** Richte deinen Workspace jetzt gleich ein, bevor du weiterliest. Ab heute speicherst du alle deine Programme dort. + +1. Lege einen Workspace an: Öffne die Spalte und klicke auf **Ordner wählen**. Gehe im Fenster zu deinen **Dokumenten**, lege dort mit **Neuer Ordner** einen Ordner namens \`VisuStruct-Dateien\` an und wähle ihn aus. Erlaube VisuStruct, den Ordner zu benutzen. Das geht in Chrome und Edge. Auf dem iPad und in anderen Browsern klickst du stattdessen auf **Im Browser speichern**. +2. Speichere wie gewohnt. VisuStruct legt in deinem Workspace automatisch einen Ordner mit dem heutigen Datum an, zum Beispiel \`2026-10-23\`, und speichert das Programm darin. Der Dateiname kommt aus dem Titel. + +So sieht dein Workspace danach aus: + +\`\`\`text +VisuStruct-Dateien ← Workspace +└── 2026-10-23 ← Tag + └── Fakultaet.visustruct +\`\`\` + +Ein Klick auf ein Programm in der Spalte öffnet es wieder. So findest du später jede Stunde schnell wieder. + +Auch dein **Lernstand** landet im Workspace: in der Datei \`learnProgress.json\` stehen deine erledigten Lektionen und Übungen. Öffnest du den Workspace in einem anderen Browser, ist dein Lernstand wieder da. + +> Warum ein echter Ordner? Dein Lernstand und deine Programme liegen dann als Dateien darin. Den Ordner kannst du mitnehmen, zum Beispiel auf einem USB-Stick oder in deinem Cloud-Ordner wie OneDrive. So machst du zu Hause an einem anderen Rechner genau da weiter, wo du aufgehört hast. Speicherst du nur im Browser, bleibt alles in diesem einen Browser auf diesem Gerät. Löscht jemand die Browserdaten, ist auch dein Lernstand weg. + +## Mehrere Diagramme in Reitern + +Über dem Struktogramm siehst du die [Reiter](#zeige-reiter). Mit **+** oder [Neu](#zeige-neu) öffnest du ein weiteres, leeres Diagramm. Ein Punkt • vor dem Namen zeigt, dass es ungespeicherte Änderungen gibt. + +Den [Titel](#zeige-titel) eines Diagramms trägst du in das Feld über dem Struktogramm ein. Er erscheint auch beim Exportieren und wird als Dateiname vorgeschlagen. + +## Weitergeben: Bild, PDF oder Datei + +Über [Exportieren](#zeige-exportieren) bei den Werkzeugen (Symbol mit Pfeil nach oben) gibst du dein Struktogramm weiter: + +- **Bild (PNG):** zum Einfügen in ein Arbeitsblatt oder eine Präsentation +- **Vektorgrafik (SVG):** bleibt in jeder Größe scharf +- **PDF (A4):** eine Seite zum Abgeben oder Ausdrucken +- **VisuStruct-Datei (.visustruct):** zum Weitergeben an jemanden, der dein Struktogramm in VisuStruct öffnen und weiterbearbeiten soll, zum Beispiel per Mail oder über die Lernplattform +- **Drucken** (Strg+P, am Mac ⌘P): direkt auf den Drucker + +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. + +## Spiel: Wie gibst du es weiter? + +::: spiel frage +titel: Spiel: Wie gibst du es weiter? +intro: Ludwig will sein Struktogramm weitergeben. Welches Format passt am besten? Sechs Runden. +frage: Welches Format passt? +antworten: .visustruct | PNG | SVG | PDF + +runde: +frage: Du willst morgen an deinem Struktogramm weiterarbeiten. +richtig: .visustruct +> Nur die .visustruct-Datei kann VisuStruct wieder öffnen und bearbeiten. + +runde: +frage: Das Struktogramm soll als Bild in eine Präsentation. +richtig: PNG +> Ein PNG-Bild lässt sich in jede Präsentation und jedes Arbeitsblatt einfügen. + +runde: +frage: Die Lehrkraft will deine Abgabe als eine A4-Seite ausdrucken. +richtig: PDF +> Das PDF ist genau eine A4-Seite zum Abgeben oder Ausdrucken. + +runde: +frage: Das Struktogramm kommt auf ein Plakat und soll auch riesig noch scharf sein. +richtig: SVG +> Eine Vektorgrafik bleibt in jeder Größe scharf. Ein PNG wird beim Vergrößern pixelig. + +runde: +frage: Deine Freundin soll das Struktogramm in ihrer VisuStruct-App auf dem iPad ändern. +richtig: .visustruct +> Alle VisuStruct-Versionen öffnen dieselbe .visustruct-Datei: im Browser, auf Mac, iPad und iPhone. + +runde: +frage: Du willst ein Bild schnell in einen Chat schicken. +richtig: PNG +> Ein PNG kann jeder sofort ansehen, ohne VisuStruct. +::: + +## Ausprobieren + +Öffne eine deiner Übungen aus Lektion 2 und probiere Folgendes aus: + +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. + +::: checkliste +- Ich kann einem Diagramm einen Titel geben. → Ausprobieren +- Ich kann ein Diagramm als .visustruct-Datei speichern und wieder öffnen. → Speichern und Öffnen +- Ich kann ein Diagramm als Bild (PNG) oder PDF exportieren. → Weitergeben: Bild, PDF oder Datei +- Ich kann ein zweites Diagramm in einem neuen Reiter öffnen. → Mehrere Diagramme in Reitern +- Ich kann meinen Workspace \`VisuStruct-Dateien\` anlegen. → Die Spalte Dateien +- Ich kann ein Programm in meinem Workspace speichern. → Die Spalte Dateien +::: + +## Wissenstest + +::: quiz +? Welche Datei kannst du in der Mac-App und in der Java-App wieder öffnen? +→ Speichern und Öffnen +- [x] Die .visustruct-Datei +- [ ] Das exportierte PNG-Bild +- [ ] Das exportierte PDF +> Bilder und PDFs sind nur zum Ansehen. Weiterbearbeiten kannst du nur die .visustruct-Datei. + +? Deine Übungen werden im Browser gemerkt. Warum solltest du trotzdem speichern? +→ Speichern und Öffnen +- [ ] Weil die Übungen sonst nicht geprüft werden +- [x] Weil der Browser die Daten nur auf diesem Gerät behält und sie verloren gehen können +- [ ] Weil man ohne Speichern nicht exportieren kann + +? Du speicherst heute ein Programm in deinem Workspace. Wo landet es? +→ Die Spalte Dateien +- [ ] Im Download-Ordner +- [x] Im Workspace in einem Ordner mit dem heutigen Datum +- [ ] Direkt im Workspace ohne Unterordner +> VisuStruct legt für jeden Tag automatisch einen Datumsordner an. So bleiben die Programme nach Stunden sortiert. +::: +`,bx=`--- +titel: Variablen und Datentypen +bereich: Grundlagen +kurz: Werte speichern, die Datentypen int, double, String und boolean kennen und rechnen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- eine Variable mit Datentyp, Namen und Wert anlegen +- die Datentypen int, double, String und boolean unterscheiden +- erklären, dass = eine Zuweisung ist und kein Vergleich +- mit + - * / % rechnen und die ganzzahlige Division anwenden +- Variablen in Java anlegen und ausgeben +::: + +## Was ist eine Variable? + +Eine **Variable** ist wie eine beschriftete Kiste. Sie hat einen **Namen**, einen **Datentyp** und einen **Wert**. + +\`\`\` +int alter = 14 +\`\`\` + +Hier heißt die Variable \`alter\`, ihr Datentyp ist \`int\` (ganze Zahl), und ihr Wert ist 14. Über den Namen kannst du den Wert später wieder benutzen. + +::: grafik l04-variable.svg +Die Variable als Kiste: Name auf dem Etikett, Datentyp als Aufkleber, Wert darin. +::: + +> Variablennamen beginnen mit einem **Kleinbuchstaben** und enthalten keine Leerzeichen. Gute Namen sagen, was drinsteht: \`preis\` ist besser als \`p\`. + +::: angeberwissen +Im September 1999 ging die Mars-Sonde Mars Climate Orbiter verloren. Ein Team rechnete die Schubkraft in amerikanischen Einheiten (Pfund), das andere erwartete metrische Einheiten (Newton). In den Daten stand nur die Zahl, nicht die Einheit. Die Sonde flog zu tief in die Mars-Atmosphäre und verglühte, Schaden rund 125 Millionen Dollar. Ein sprechender Name wie \`impulsInNewtonSekunden\` hätte gesagt, was drinsteht. Ich schreibe auf mein Heufach übrigens immer \`heuInKilo\`. +::: + +Besteht ein Name aus mehreren Wörtern, schreibst du sie zusammen und beginnst jedes weitere Wort mit einem Großbuchstaben: \`preisMitSteuer\`, \`anzahlSchueler\`. Diese Schreibweise heißt **CamelCase**. + +::: angeberwissen +CamelCase heißt so, weil die Großbuchstaben in der Mitte wie die Höcker eines Kamels aus dem Wort ragen: \`preisMitSteuer\` hat zwei Höcker. Ich als Geißbock habe übrigens null Höcker, dafür zwei Hörner. Leider hat noch niemand die GeißbockSchreibweise erfunden. +::: + +::: grafik l04-camelcase.svg +Die Großbuchstaben M und S ragen heraus wie die zwei Höcker des Kamels. +::: + +## Die vier Datentypen + +Der Datentyp legt fest, welche Art von Wert in der Variablen stehen darf. + +- **int:** ganze Zahlen, z. B. \`int anzahl = 3\` oder \`int temperatur = -5\` +- **double:** Kommazahlen, z. B. \`double preis = 2.5\`. Statt Komma schreibst du einen **Punkt**. +- **String:** Text, z. B. \`String name = "Mia"\`. Text steht in Anführungszeichen. +- **boolean:** Wahrheitswerte, nur \`true\` (wahr) oder \`false\` (falsch) + +Es gibt noch mehr Datentypen. Einen wirst du bald brauchen: \`char\` für ein **einzelnes Zeichen**, z. B. \`char note = 'C'\`. Ein \`char\` steht in **einfachen** Anführungszeichen. Genauer lernst du ihn in Lektion 17 kennen. + +::: diagramm l05-datentypen.visustruct +Drei Variablen mit verschiedenen Datentypen. Öffne das Diagramm und starte die Simulation. +::: + +Wahrheitswerte begegnen dir vor allem in **Bedingungen**: \`alter >= 18\` ist entweder \`true\` oder \`false\`. Darum geht es in Lektion 8. Eine Variable vom Typ \`boolean\` bekommt einfach \`true\` oder \`false\`: + +\`\`\` +boolean volljaehrig = false +\`\`\` + +::: angeberwissen +Am 4. Juni 1996 explodierte die Rakete Ariane 5 schon 37 Sekunden nach dem Start. Schuld war eine einzige Zeile: Eine Kommazahl für die Geschwindigkeit wurde in eine Ganzzahl-Variable gesteckt, die für so große Werte zu klein war. Der Datentyp ist also keine Nebensache, er kann eine halbe Milliarde Euro kosten. +::: + +## Zuweisung mit = + +Das Zeichen \`=\` heißt **Zuweisung**. Es bedeutet nicht „ist gleich“ wie in Mathe, sondern: Berechne die rechte Seite und speichere das Ergebnis in der Variablen links. + +\`\`\` +int punkte = 10 +punkte = punkte + 5 +\`\`\` + +In Mathe wäre die zweite Zeile falsch, denn keine Zahl ist gleich sich selbst plus 5. Beim Programmieren liest du sie so: Nimm den alten Wert 10, rechne plus 5 und speichere 15 in \`punkte\`. Den Datentyp schreibst du nur beim ersten Mal, wenn die Variable angelegt wird. + +::: grafik l04-zuweisung.svg +Erst wird rechts gerechnet, dann landet das Ergebnis in der Variablen links. +::: + +## Rechnen + +Mit Zahlen kannst du rechnen: + +- \`+\` plus, \`-\` minus, \`*\` mal, \`/\` geteilt +- \`%\` Rest beim Teilen (gesprochen „Modulo“), z. B. ist \`17 % 5\` gleich 2 + +**Teilen mit Rest** kennst du aus der Grundschule, als du noch keine Kommazahlen hattest: 17 : 5 = 3 Rest 2. Die 5 passt dreimal in die 17, das sind 15. Bis 17 fehlen dann noch 2, das ist der Rest. Genau so rechnet der Computer mit ganzen Zahlen: \`/\` liefert das Ergebnis ohne Rest, \`%\` nur den Rest. + +| Grundschule | mit \`/\` | mit \`%\` | +|---|---|---| +| 17 : 5 = 3 Rest 2 | \`17 / 5\` ergibt 3 | \`17 % 5\` ergibt 2 | +| 20 : 5 = 4 Rest 0 | \`20 / 5\` ergibt 4 | \`20 % 5\` ergibt 0 | +| 3 : 5 = 0 Rest 3 | \`3 / 5\` ergibt 0 | \`3 % 5\` ergibt 3 | + +Ist der Rest 0, geht die Teilung auf. So prüfst du später, ob eine Zahl gerade ist: Bei geraden Zahlen ist \`zahl % 2\` gleich 0. + +Es gilt **Punkt vor Strich**, und Klammern werden zuerst ausgerechnet: \`2 * (3 + 4)\` ist 14. + +## Übung: Rechteck + +::: übung l05-rechteck +titel: Rechteck berechnen +auftrag: Ein Rechteck ist 7 lang und 4 breit. Lege die Variablen \`laenge\` und \`breite\` an. Berechne die Fläche und den Umfang in eigenen Variablen und gib beide aus, so wie hier: +\`Fläche: 28\` und in der nächsten Zeile \`Umfang: 22\`. +test: - -> Fläche: 28 | Umfang: 22 +braucht: anweisung +tipp: Überlege zuerst, welche Variablen du brauchst: zwei für die Maße und zwei für die Ergebnisse. Alle sind ganze Zahlen. +tipp: Die Fläche ist Länge mal Breite, der Umfang ist 2 mal (Länge plus Breite). Für die Ausgabe schreibst du z. B. \`output: "Fläche: " + flaeche\`. Das \`+\` hängt dabei den Text und den Wert der Variablen aneinander. +lösung: l05-rechteck-loesung.visustruct +::: + +## Ganzzahlige Division + +Teilst du zwei ganze Zahlen und speicherst das Ergebnis in einer \`int\`-Variablen, fällt alles nach dem Komma weg. Es wird **nicht gerundet**. + +\`\`\` +int x = 7 / 2 ergibt 3 +int r = 7 % 2 ergibt 1 (der Rest) +double d = 7.0 / 2 ergibt 3.5 +\`\`\` + +Mit \`/\` und \`%\` zusammen kannst du gut umrechnen, zum Beispiel Minuten in Stunden und Minuten: + +::: diagramm l05-division.visustruct +135 Minuten sind 2 Stunden (135 / 60) und 15 Minuten Rest (135 % 60). +::: + +## Übung: Sekunden umrechnen + +::: übung l05-sekunden +titel: Sekunden umrechnen +auftrag: 200 Sekunden sollen als Minuten und Sekunden ausgegeben werden. Die erste und die letzte Anweisung sind schon da. Füge dazwischen Anweisungen ein, die \`minuten\` und \`rest\` berechnen. +start: l05-sekunden-start.visustruct +test: - -> 3 Minuten und 20 Sekunden +braucht: anweisung +tipp: Wie viele ganze Minuten passen in 200 Sekunden, und wie viele Sekunden bleiben übrig? Rechne es erst im Kopf aus. +tipp: Eine Minute hat 60 Sekunden. Nutze \`/\` für die ganzen Minuten und \`%\` für den Rest. Beide Variablen sind vom Typ \`int\`. +lösung: l05-sekunden-loesung.visustruct +::: + +## Übung: Einkauf + +::: übung l05-einkauf +titel: Einkauf +auftrag: Du kaufst 3 Hefte zu je 2.5 Euro. Lege \`anzahl\` als \`int\` und \`preis\` als \`double\` an, berechne den Gesamtpreis in einer Variablen \`gesamtPreis\` und gib \`Gesamt: 7.5 Euro\` aus. +test: - -> Gesamt: 7.5 Euro +braucht: anweisung +tipp: Anzahl mal Preis ergibt den Gesamtpreis. Überlege für jede Variable, ob sie eine ganze Zahl oder eine Kommazahl ist. +tipp: Der Gesamtpreis ist eine Kommazahl, also braucht \`gesamtPreis\` den Typ \`double\`. +lösung: l05-einkauf-loesung.visustruct +::: + +## Jetzt in Java + +Ein Struktogramm ist ein Plan. In **Java** wird daraus ein Programm, das der Computer ausführt. Dein Einkauf aus der Übung sieht so aus: + +\`\`\`java +int anzahl = 3; +double preis = 2.5; +double gesamtPreis = anzahl * preis; +System.out.println("Gesamt: " + gesamtPreis + " Euro"); +\`\`\` + +- Erst der Datentyp, dann der Name, dann der Wert, genau wie im Kasten. +- Jede Anweisung endet mit einem **Semikolon** \`;\`. +- Eine Ausgabe heißt in Java \`System.out.println(…)\`. + +::: angeberwissen +Java hieß zuerst **Oak** (Eiche), nach dem Baum vor dem Bürofenster von James Gosling. Sein Team bei Sun Microsystems wollte ab 1991 kleine Geräte wie Fernseh-Boxen programmieren. Den Namen Oak hatte aber schon eine andere Firma. Also wurde es 1995 **Java**, wie der Kaffee von der Insel Java. Deshalb ist das Logo eine dampfende Tasse. +::: + +## Text in Java + +Variablen speichern nicht nur Zahlen. Für Text gibt es den Datentyp \`String\`: + +\`\`\`java editor +String name = "Mia"; +int alter = 14; +double groesse = 1.62; +System.out.println(name + " ist " + alter + " Jahre alt."); +System.out.println("Größe: " + groesse + " m"); +\`\`\` + +- Text steht in Anführungszeichen. +- \`String\` schreibst du groß, \`int\`, \`double\` und \`boolean\` klein. Java unterscheidet das. +- Mit \`+\` hängst du Text und Zahlen aneinander. + +Java tippst du im Bereich [Code](#zeige-codelive). Das Struktogramm entsteht dabei von selbst. „Im Editor öffnen“ holt das Beispiel in den Bereich Code. Klicke dort auf „Ausführen“, ändere dann Name, Alter oder Größe und probiere es noch einmal. + +::: übung l04-java-steckbrief +titel: Steckbrief in Java +code: java +auftrag: Schreibe einen Steckbrief für Ludwig den Geißbock. Lege drei Variablen an: den Namen **Ludwig**, das Alter **7** und die Größe **1.2**. Gib dann diese zwei Zeilen aus: + **Ludwig ist 7 Jahre alt.** und **Größe: 1.2 m** + „Im Editor öffnen“ öffnet rechts auch den Bereich Code. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. +test: - -> Ludwig ist 7 Jahre alt. | Größe: 1.2 m +braucht: anweisung +tipp: Du brauchst einen \`String\`, einen \`int\` und einen \`double\`. Jede Zeile endet mit einem Semikolon. +tipp: \`String name = "Ludwig";\`, \`int alter = 7;\` und \`double groesse = 1.2;\`. Die Ausgabe setzt du mit \`+\` zusammen: \`System.out.println(name + " ist " + alter + " Jahre alt.");\` +lösung: l04-java-steckbrief-loesung.visustruct +::: + +## Lückentext: Datentypen + +::: lückentext +titel: Steckbrief in Java +auftrag: Ergänze die fehlenden Wörter. Ganz außen steht der Rahmen, den jedes Java-Programm in einer eigenen Datei braucht. Darin stehen die Variablen. +\`\`\`java +[[public]] class Steckbrief { + public static [[void]] main(String[] args) { + [[int]] alter = 14; + [[double]] groesse = 1.62; + [[String]] name = "Mia"; + [[boolean]] hatHaustier = true; + System.out.[[println]](name + " ist " + alter + " Jahre alt."); + } +} +\`\`\` +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“. +::: + +## Fehler finden: Sekunden + +::: übung l04-java-fehler +titel: Sekunden reparieren +code: java +auftrag: Das Programm soll 200 Sekunden in Minuten und Sekunden umrechnen und **3 min 20 s** ausgeben. Es gibt aber **20 min 3 s** aus. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l04-java-fehler-start.visustruct +test: - -> 3 min 20 s +braucht: anweisung +tipp: \`/\` teilt ganzzahlig, \`%\` liefert den Rest. Welches Zeichen brauchst du für die Minuten, welches für die übrigen Sekunden? +tipp: Die beiden Zeichen sind vertauscht: \`int minuten = sekunden / 60;\` und \`int rest = sekunden % 60;\` +lösung: l04-java-fehler-loesung.visustruct +::: + +## Spiel: Welcher Datentyp? + +::: spiel frage +titel: Spiel: Welcher Datentyp? +intro: Ludwig hat Werte gesammelt. Welcher Datentyp passt zu jedem Wert? Acht Runden. +antworten: int | double | String | boolean + +runde: +frage: Welcher Datentyp passt zu \`17\`? +richtig: int +> Eine ganze Zahl ohne Komma ist ein \`int\`. + +runde: +frage: Welcher Datentyp passt zu \`3.5\`? +richtig: double +> Kommazahlen sind \`double\`. In Java steht statt des Kommas ein Punkt. + +runde: +frage: Welcher Datentyp passt zu \`"Hallo"\`? +richtig: String +> Text in Anführungszeichen ist ein \`String\`. + +runde: +frage: Welcher Datentyp passt zu \`true\`? +richtig: boolean +> \`true\` und \`false\` sind die beiden Wahrheitswerte, Datentyp \`boolean\`. + +runde: +frage: Welcher Datentyp passt zu \`"17"\`? +richtig: String +> Vorsicht, Anführungszeichen! Hier ist 17 ein Text, mit dem man nicht rechnen kann. + +runde: +frage: Welcher Datentyp passt zu \`-4\`? +richtig: int +> Auch negative ganze Zahlen sind \`int\`. + +runde: +frage: Welcher Datentyp passt zu \`0.0\`? +richtig: double +> Der Punkt macht es zur Kommazahl, auch wenn hinten nur eine 0 steht. + +runde: +frage: Welcher Datentyp passt zu \`"false"\`? +richtig: String +> In Anführungszeichen ist auch false nur ein Text. Der Wahrheitswert steht ohne Anführungszeichen. +::: + +## 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. + +::: checkliste +- Ich kann eine Variable mit Datentyp, Namen und Wert anlegen. → Was ist eine Variable? +- Ich kann die Datentypen int, double, String und boolean unterscheiden. → Die vier Datentypen +- Ich kann erklären, dass = eine Zuweisung ist und kein Vergleich. → Zuweisung mit = +- Ich kann mit + - * / % rechnen und die ganzzahlige Division anwenden. → Rechnen +- Ich kann Variablen in Java anlegen und ausgeben. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Welcher Datentyp passt zu dem Wert 3.75? +→ Die vier Datentypen +- [ ] int +- [x] double +- [ ] String +- [ ] boolean +> Kommazahlen haben den Typ double. In VisuStruct schreibst du sie mit Punkt. + +? Welchen Wert hat x nach \`int x = 17 / 5\`? +→ Rechnen +- [ ] 3.4 +- [x] 3 +- [ ] 4 +> Bei ganzen Zahlen fällt alles nach dem Komma weg. Es wird nicht gerundet. + +? Was ergibt \`17 % 5\`? +→ Rechnen +- [x] 2 +- [ ] 3 +- [ ] 3.4 +> 17 geteilt durch 5 ist 3, Rest 2. Der Operator % liefert den Rest. + +? Am Anfang ist \`int punkte = 10\`. Was steht nach \`punkte = punkte * 2\` in punkte? +→ Zuweisung mit = +- [ ] 10 +- [ ] 12 +- [x] 20 +> Rechts wird mit dem alten Wert 10 gerechnet, das Ergebnis 20 wird in punkte gespeichert. + +? Welche Zeile legt in Java richtig eine Kommazahl an? +→ Jetzt in Java +- [ ] double preis = 2,5; +- [x] double preis = 2.5; +- [ ] Double preis = 2.5 +> Kommazahlen schreibst du mit Punkt, und am Ende steht ein Semikolon. +::: +`,xx=`--- +titel: Sequenz +bereich: Grundlagen +kurz: Schritte nacheinander ausführen, auf die Reihenfolge achten und Werte tauschen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, dass eine Sequenz von oben nach unten ausgeführt wird +- erklären, warum die Reihenfolge der Schritte wichtig ist +- zwei Werte mit einer Hilfsvariablen tauschen +- eine Sequenz in Java schreiben +::: + +## Schritt für Schritt + +Eine **Sequenz** ist eine Folge von Schritten, die genau einmal und genau in dieser Reihenfolge ausgeführt werden. Im Struktogramm stehen die Kästen einfach untereinander. + +Jeder Kasten wird erst begonnen, wenn der Kasten darüber fertig ist. Es wird nichts übersprungen und nichts wiederholt. + +::: diagramm l05-sequenz.visustruct +Eine Sequenz aus vier Kästen: Zuerst bekommen \`laenge\` und \`breite\` ihre Werte, dann wird die Fläche berechnet, und zum Schluss wird sie ausgegeben. Jeder Kasten läuft genau einmal, von oben nach unten. Ausgabe: 15. +::: + +> Die Sequenz ist der einfachste der drei Grundbausteine. Fast jedes Struktogramm besteht zum größten Teil aus Sequenzen. + +## Die Reihenfolge zählt + +Beim Tee kochen merkst du sofort, wenn die Reihenfolge falsch ist. Bei Rechnungen ist es genauso, nur fällt es weniger auf. + +::: diagramm l04-rechnen.visustruct +Erst verdoppeln, dann 1 addieren: Das Ergebnis ist 7. Tauschst du die beiden mittleren Kästen, kommt 8 heraus. +::: + +Die Anweisung \`zahl = zahl * 2\` bedeutet: Nimm den Wert von \`zahl\`, rechne mal 2 und speichere das Ergebnis wieder in \`zahl\`. Was in \`zahl\` steht, hängt also davon ab, was vorher passiert ist. + +::: angeberwissen +Struktogramme sind kein reiner Schulkram. Laut Shneiderman haben auch Firmen wie IBM und Siemens damit ihre Programme geplant. Du lernst hier also Profi-Zeug. Määäh-ga! +::: + +## Übung: Reihenfolge ordnen + +::: übung l04-reihenfolge +titel: Reihenfolge ordnen +auftrag: Im Startdiagramm stehen die richtigen Kästen, aber in der falschen Reihenfolge. Verschiebe sie so, dass am Ende **20** ausgegeben wird. +start: l04-reihenfolge-start.visustruct +test: - -> 20 +braucht: anweisung +tipp: Lies jeden Kasten und frage dich: Welche Variable braucht er, und wo bekommt diese Variable ihren Wert? +tipp: Eine Variable muss zuerst angelegt werden, bevor du mit ihr rechnest. Die Ausgabe kommt ganz zum Schluss. Rechne im Kopf nach: (2 + 3) · 4 = 20. +lösung: l04-reihenfolge-loesung.visustruct +::: + +## Zwei Werte tauschen + +Stell dir zwei Gläser vor: eins mit Saft, eins mit Wasser. Willst du die Inhalte tauschen, brauchst du ein drittes, leeres Glas. + +Mit Variablen ist es genauso. Schreibst du einfach \`a = b\` und danach \`b = a\`, ist der alte Wert von \`a\` schon verloren. Am Ende haben beide Variablen denselben Wert. + +Die Lösung ist eine **Hilfsvariable**, die den alten Wert kurz aufbewahrt: + +::: grafik l05-tauschen.svg +Drei Schritte mit einem leeren Glas: erst Saft in hilf, dann Wasser nach links, dann den Saft aus hilf nach rechts. +::: + +::: diagramm l04-tauschen.visustruct +Zuerst wird a in hilf gemerkt. Dann bekommt a den Wert von b, und b bekommt den gemerkten Wert aus hilf. +::: + +## Übung: Gläser tauschen + +::: übung l04-glaeser-tauschen +titel: Gläser tauschen +auftrag: Im linken Glas ist Saft, im rechten Wasser. Tausche die Inhalte der Variablen \`links\` und \`rechts\`, bevor sie ausgegeben werden. +Ändere dazu nicht die ersten beiden Kästen, sondern füge dazwischen neue Anweisungen ein. +start: l04-tauschen-start.visustruct +test: - -> Links: Wasser | Rechts: Saft +braucht: anweisung +tipp: Wie tauschst du zwei volle Gläser im echten Leben? Du brauchst ein drittes, leeres Glas. +tipp: Lege mit \`String hilf = links\` eine Hilfsvariable an. Danach brauchst du noch zwei Zuweisungen. +lösung: l04-tauschen-loesung.visustruct +::: + +## Jetzt in Java + +Wie in Lektion 4 kannst du auch eine Sequenz direkt in Java schreiben. Das Tauschen von oben sieht so aus: + +\`\`\`java +int a = 5; +int b = 9; +int hilf = a; +a = b; +b = hilf; +System.out.println("a = " + a); +System.out.println("b = " + b); +\`\`\` + +- Jeder Kasten wird zu einer Zeile. Die Zeilen laufen von oben nach unten, genau wie die Kästen. +- Am Ende jeder Anweisung steht ein **Semikolon** \`;\`. +- Eine Ausgabe heißt in Java \`System.out.println(…)\`. Achte auf das große S bei \`System\`, Java unterscheidet Groß- und Kleinbuchstaben. + +Java tippst du im Bereich [Code](#zeige-codelive) rechts neben dem Struktogramm. Während du tippst, baut VisuStruct das Struktogramm mit. So siehst du sofort, welcher Kasten zu welcher Zeile gehört. + +::: übung l05-java-kino +titel: Kinokarten in Java +code: java +auftrag: Eine Kinokarte kostet 9 Euro. Schreibe ein Java-Programm, das den Preis für 3 Karten ausrechnet und **Gesamt: 27** ausgibt. + „Im Editor öffnen“ öffnet rechts auch den Bereich Code. Tippe dort deinen Code, das Struktogramm entsteht dabei von selbst. Klicke dann auf Prüfen. +test: - -> Gesamt: 27 +braucht: anweisung +tipp: Du brauchst drei Variablen: den Preis, die Anzahl und das Ergebnis. Jede Zeile endet mit einem Semikolon. +tipp: \`int preis = 9;\` und \`int anzahl = 3;\` legen die Variablen an. \`int gesamt = preis * anzahl;\` rechnet, und \`System.out.println("Gesamt: " + gesamt);\` gibt das Ergebnis aus. +lösung: l05-java-kino-loesung.visustruct +::: + +## Lückentext: Gläser tauschen + +::: lückentext +titel: Zwei Werte tauschen +auftrag: Die Werte von \`a\` und \`b\` sollen getauscht werden. Ergänze die fehlenden Wörter. +\`\`\`java +int a = 3; +int b = 8; +[[int]] hilf = [[a]]; +a = [[b]]; +b = [[hilf]]; +System.out.println("a = " + a + ", b = " + b); +\`\`\` +erklärung: Erst rettest du \`a\` in die Hilfsvariable, dann bekommt \`a\` den Wert von \`b\`, und zuletzt bekommt \`b\` den geretteten Wert. Ausgabe: **a = 8, b = 3** +::: + +## Fehler finden: Guthaben + +::: übung l05-java-fehler +titel: Guthaben reparieren +code: java +auftrag: Auf der Mensakarte sind 20 Euro. Ein Essen kostet 7 Euro. Das Programm soll das Guthaben **nach** dem Bezahlen ausgeben, also **Übrig: 13**. Es gibt aber **Übrig: 20** aus. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l05-java-fehler-start.visustruct +test: - -> Übrig: 13 +braucht: anweisung +tipp: Alle Zeilen stimmen, nur die Reihenfolge nicht. Wann wird das Guthaben ausgegeben, wann wird bezahlt? +tipp: Tausche die letzten beiden Zeilen: erst \`guthaben = guthaben - preis;\`, dann die Ausgabe. +lösung: l05-java-fehler-loesung.visustruct +::: + +## Spiel: Kästen sortieren + +::: spiel reihenfolge +titel: Spiel: Kästen sortieren +intro: Ludwig hat die Kästen durcheinandergeworfen. Bring sie in die richtige Reihenfolge. Vier Runden. + +runde: +frage: Am Ende soll **7** ausgegeben werden. +- \`int zahl = 3\` +- \`zahl = zahl * 2\` +- \`zahl = zahl + 1\` +- \`output: zahl\` +> Erst verdoppeln, dann 1 dazu: 3 · 2 + 1 = 7. Andersherum käme (3 + 1) · 2 = 8 heraus. + +runde: +frage: Am Ende soll **8** ausgegeben werden. +- \`int zahl = 3\` +- \`zahl = zahl + 1\` +- \`zahl = zahl * 2\` +- \`output: zahl\` +> Dieselben Kästen, andere Reihenfolge, anderes Ergebnis: (3 + 1) · 2 = 8. + +runde: + int a = 3 + int b = 5 +frage: a und b sollen ihre Werte tauschen. +- \`int hilf = a\` +- \`a = b\` +- \`b = hilf\` +- \`output: a + " " + b\` +> Zuerst wird a in hilf gerettet. Sonst ist der alte Wert weg, sobald a den Wert von b bekommt. + +runde: +frage: Ludwig kocht Tee. +- Wasser in den Wasserkocher füllen +- Wasserkocher einschalten +- Warten, bis das Wasser kocht +- Wasser über den Teebeutel gießen +- Tee ziehen lassen +> Jeder Schritt braucht den vorherigen. Genau wie im Struktogramm. +::: + +## 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. + +::: checkliste +- Ich kann erklären, dass eine Sequenz von oben nach unten ausgeführt wird. → Schritt für Schritt +- Ich kann erklären, warum die Reihenfolge der Schritte wichtig ist. → Die Reihenfolge zählt +- Ich kann zwei Werte mit einer Hilfsvariablen tauschen. → Zwei Werte tauschen +- Ich kann eine Sequenz in Java schreiben. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Wie oft wird jeder Kasten einer Sequenz ausgeführt? +→ Schritt für Schritt +- [ ] So oft, bis eine Bedingung falsch ist +- [x] Genau einmal +- [ ] Gar nicht, wenn er leer ist +> In einer Sequenz wird nichts wiederholt und nichts übersprungen. Für Wiederholungen gibt es Schleifen. + +? Am Anfang ist a = 5 und b = 9. Danach wird \`a = b\` und dann \`b = a\` ausgeführt. Was steht am Ende in den Variablen? +→ Zwei Werte tauschen +- [ ] a = 9 und b = 5 +- [x] a = 9 und b = 9 +- [ ] a = 5 und b = 5 +> Nach \`a = b\` ist der alte Wert 5 verloren. \`b = a\` kopiert dann nur die 9 zurück. + +? Wozu brauchst du beim Tauschen eine Hilfsvariable? +→ Zwei Werte tauschen +- [x] Damit ein Wert nicht überschrieben wird, bevor er gebraucht wird +- [ ] Damit das Struktogramm länger wird +- [ ] Weil man Variablen sonst nicht ausgeben kann + +? Was gibt die Sequenz \`int x = 4\`, \`x = x + 1\`, \`x = x * 3\`, \`output: x\` aus? +→ Die Reihenfolge zählt +- [ ] 13 +- [x] 15 +- [ ] 4 +> Erst wird x zu 5, dann zu 15. + +? Womit endet in Java jede Anweisung? +→ Jetzt in Java +- [ ] Mit einem Punkt . +- [x] Mit einem Semikolon ; +- [ ] Mit einem Doppelpunkt : +> Fehlt das Semikolon, zeigt VisuStruct unter dem Code einen Hinweis. +::: +`,vx=`--- +titel: Eingabe und Ausgabe +bereich: Grundlagen +kurz: Werte abfragen, Ergebnisse anzeigen und das EVA-Prinzip anwenden. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- das EVA-Prinzip erklären +- eine Eingabe mit Datentyp, Namen und Frage schreiben +- Text und Variablen in einer Ausgabe mit + verbinden +- ein Ergebnis zuerst ausrechnen und in einer Variablen speichern, dann diese Variable ausgeben, z. B. \`int summe = a + b\`, danach \`output: summe\` +- aus einem Aufgabentext Eingabe, Verarbeitung und Ausgabe herauslesen +- in Java mit dem Scanner Zahlen einlesen +- Kommentare mit \`//\` und \`/* */\` schreiben und damit meinen Code einteilen und erklären +::: + +## Das EVA-Prinzip + +Viele Programme arbeiten in drei Teilen: + +1. **Eingabe:** Das Programm fragt Werte ab, z. B. zwei Zahlen. +2. **Verarbeitung:** Es rechnet mit den Werten. +3. **Ausgabe:** Es zeigt das Ergebnis an. + +Die Anfangsbuchstaben ergeben **EVA**. Bisher standen die Werte fest im Struktogramm. Mit einer Eingabe kann bei jedem Durchlauf ein anderer Wert verwendet werden. + +::: diagramm l06-eva.visustruct +Oben die Eingabe, in der Mitte die Verarbeitung, unten die Ausgabe. Starte die Simulation und probiere verschiedene Zahlen aus. +::: + +## Eingabe mit input: + +Eine Eingabe fragt beim Ausführen einen Wert ab und speichert ihn in einer Variablen. Du schreibst den **Datentyp**, den **Namen** und eine **Frage** in Anführungszeichen: + +\`\`\` +input: int alter "Wie alt bist du?" +input: double preis "Preis in Euro?" +input: String name "Wie heißt du?" +\`\`\` + +Im Editor wählst du bei einer Anweisung oben die Art **Eingabe**. Das Wort \`input:\` steht dann schon davor, und du tippst nur noch \`int alter "Wie alt bist du?"\`. + +> Der Datentyp entscheidet, was eingegeben werden darf. Bei \`int\` meldet die Simulation einen Fehler, wenn jemand 2.5 oder Hallo eintippt. + +## Ausgabe mit output: + +Eine Ausgabe zeigt Text und Werte an. Text steht in Anführungszeichen, Variablen ohne. Mit \`+\` hängst du die Teile **aneinander**: + +\`\`\` +output: "Hallo " + name + "!" +output: "Du bist " + alter + " Jahre alt." +\`\`\` + +Achte auf die Leerzeichen innerhalb der Anführungszeichen. Ohne sie klebt alles zusammen, und du siehst \`HalloMia!\` statt \`Hallo Mia!\`. + +## Übung: Begrüßung + +::: übung l06-begruessung +titel: Begrüßung +auftrag: Frage nach dem Namen und begrüße die Person. Bei der Eingabe Ada soll **Hallo Ada!** ausgegeben werden. +test: Ada -> Hallo Ada! +test: Ben -> Hallo Ben! +braucht: anweisung +tipp: Zuerst kommt eine Eingabe für den Namen, danach eine Ausgabe, die den Namen benutzt. +tipp: Der Name ist Text, die Eingabe braucht also den Typ \`String\`. In der Ausgabe verbindest du \`"Hallo "\`, die Variable und \`"!"\` mit \`+\`. +lösung: l06-begruessung-loesung.visustruct +::: + +## Vorsicht mit + in der Ausgabe + +In einer Ausgabe hängt \`+\` die Teile **immer** aneinander, auch bei Zahlen. Sind \`a\` gleich 3 und \`b\` gleich 4, dann zeigt + +\`\`\` +output: a + b +\`\`\` + +nicht 7, sondern **34**. Rechne deshalb vorher in einer Variablen und gib dann die Variable aus: + +\`\`\` +int summe = a + b +output: "Summe: " + summe +\`\`\` + +Das passt auch zum EVA-Prinzip: Gerechnet wird in der Verarbeitung, nicht in der Ausgabe. + +## Vom Aufgabentext zum Struktogramm + +Bevor du den ersten Kasten ziehst, liest du die Aufgabe genau und zerlegst sie. Das nennt man **Problemanalyse**. Drei Fragen helfen dir dabei: + +1. **Was ist gegeben?** Diese Werte werden zur **Eingabe**. Überlege auch den Datentyp. +2. **Was ist gesucht?** Das wird zur **Ausgabe**. +3. **Wie kommt man vom Gegebenen zum Gesuchten?** Das ist die **Verarbeitung**, oft eine Formel. + +Ein Beispiel: *Eine Kinokarte kostet 9 €. Das Programm fragt, wie viele Karten jemand kauft, und zeigt den Gesamtpreis an.* + +- Gegeben: die Anzahl der Karten → \`input: int anzahl "Wie viele Karten?"\` +- Gesucht: der Gesamtpreis → \`output: "Gesamtpreis: " + gesamt\` +- Weg: Anzahl mal 9 → \`int gesamt = anzahl * 9\` + +Jetzt musst du die drei Teile nur noch in der Reihenfolge E, V, A untereinander setzen. + +> Achte im Aufgabentext auf Signalwörter: *fragt*, *liest ein* oder *gibt ein* deuten auf eine Eingabe. *Zeigt*, *gibt aus* oder *meldet* deuten auf eine Ausgabe. + +## Übung: Rechner + +::: übung l06-rechner +titel: Summe und Produkt +auftrag: Frage zwei ganze Zahlen ab. Gib danach ihre Summe und ihr Produkt aus, jeweils in einer eigenen Zeile. +Bei 3 und 4 sieht das so aus: \`Summe: 7\` und \`Produkt: 12\`. +test: 3, 4 -> Summe: 7 | Produkt: 12 +test: 10, -2 -> Summe: 8 | Produkt: -20 +test: 0, 5 -> Summe: 5 | Produkt: 0 +braucht: anweisung +tipp: Plane die Reihenfolge: erst beide Zahlen einlesen, dann rechnen, dann ausgeben. +tipp: Du brauchst zwei Eingaben, zwei Anweisungen zum Rechnen und zwei Ausgaben. Rechne die Summe in einer eigenen Variablen, sonst hängt \`+\` die Zahlen aneinander. +lösung: l06-rechner-loesung.visustruct +::: + +## Übung: Mittelwert + +::: übung l06-mittelwert +titel: Mittelwert +auftrag: Frage zwei Zahlen ab, die auch Kommazahlen sein dürfen. Gib ihren Mittelwert aus, bei 2 und 3 also \`Mittelwert: 2.5\`. +test: 2, 3 -> Mittelwert: 2.5 +test: 4, 6 -> Mittelwert: 5.0 +test: 1.5, 2 -> Mittelwert: 1.75 +braucht: anweisung +tipp: Den Mittelwert zweier Zahlen bekommst du, wenn du sie addierst und das Ergebnis halbierst. +tipp: Für Kommazahlen nimmst du den Typ \`double\`. Der Mittelwert ist die Summe geteilt durch 2. Denk an die Klammern: \`(x + y) / 2\`. +lösung: l06-mittelwert-loesung.visustruct +::: + +## Jetzt in Java + +So sieht das EVA-Beispiel vom Anfang in Java aus: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Erste Zahl?"); +int a = scanner.nextInt(); +System.out.println("Zweite Zahl?"); +int b = scanner.nextInt(); +int summe = a + b; +System.out.println("Summe: " + summe); +\`\`\` + +- Für Eingaben braucht Java einen **Scanner**. Die ersten beiden Zeilen schreibst du einmal ganz oben, dann kannst du beliebig oft einlesen. +- \`scanner.nextInt()\` liest eine ganze Zahl, \`scanner.nextDouble()\` eine Kommazahl und \`scanner.next()\` ein Wort. +- Die Frage an den Benutzer ist eine normale Ausgabe direkt davor. VisuStruct macht aus beiden Zeilen zusammen einen Eingabe-Kasten. + +::: angeberwissen +Java sollte ursprünglich kleine Geräte steuern, und das tut es heute noch: Auf vielen SIM-Karten im Handy und auf Bankkarten läuft eine Mini-Version namens **Java Card**. Gut möglich, dass du gerade Java in der Hosentasche hast. +::: + +::: übung l06-java-tage +titel: Alter in Tagen +code: java +auftrag: Schreibe ein Java-Programm, das nach dem Alter in Jahren fragt und ausgibt, wie viele Tage das ungefähr sind. Rechne mit 365 Tagen pro Jahr. Bei 2 Jahren erscheint **Das sind etwa 730 Tage.** +test: 2 -> Das sind etwa 730 Tage. +test: 10 -> Das sind etwa 3650 Tage. +test: 1 -> Das sind etwa 365 Tage. +braucht: anweisung +tipp: Erst die beiden Scanner-Zeilen, dann Frage und Eingabe, dann rechnen, dann ausgeben. +tipp: \`int jahre = scanner.nextInt();\` liest ein. \`int tage = jahre * 365;\` rechnet, und \`System.out.println("Das sind etwa " + tage + " Tage.");\` gibt aus. +lösung: l06-java-tage-loesung.visustruct +::: + +## Kommentare im Code + +Im Code darfst du dir Notizen machen. Sie heißen **Kommentare** (englisch *comments*). Java überspringt sie beim Ausführen, das Programm und das Struktogramm bleiben also gleich. Es gibt zwei Arten: + +- \`//\` macht den Rest der Zeile zum Kommentar. Das ist ein **einzeiliger Kommentar**. +- \`/*\` beginnt einen **mehrzeiligen Kommentar**, \`*/\` beendet ihn. Alles dazwischen gehört zum Kommentar, egal wie viele Zeilen. Die Sternchen am Anfang der Zeilen dazwischen braucht Java nicht, sie sehen nur ordentlich aus. + +In fertigen Programmen siehst du manchmal auch \`/** … */\` mit zwei Sternchen am Anfang. Das ist ein **Javadoc-Kommentar**, aus dem Java eine Beschreibung des Programms erzeugen kann. Für dich reichen \`//\` und \`/* */\`. + +So sieht das EVA-Beispiel mit Kommentaren aus: + +\`\`\`java editor +/* + * Aufgabe: Das Programm fragt nach zwei Zahlen + * und gibt ihre Summe aus. + */ +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +// Eingabe +System.out.println("Erste Zahl?"); +int a = scanner.nextInt(); +System.out.println("Zweite Zahl?"); +int b = scanner.nextInt(); + +// Verarbeitung +int summe = a + b; // die beiden Zahlen addieren + +// Ausgabe +System.out.println("Summe: " + summe); // bei 3 und 4 erwarte ich: Summe: 7 + +// Nächstes Mal: auch Kommazahlen erlauben +\`\`\` + +Wofür Kommentare gut sind: + +- **Aufgabenstellung:** Oben im mehrzeiligen Kommentar steht, was das Programm können soll. +- **Einteilung:** \`// Eingabe\`, \`// Verarbeitung\` und \`// Ausgabe\` teilen den Code nach dem EVA-Prinzip ein. +- **Erklärung:** Ein Kommentar hinter einer Zeile sagt, was dein Algorithmus dort macht. +- **Erwartung:** Schreib auf, welche Ausgabe du erwartest. Beim Testen vergleichst du dann. +- **Klammern zuordnen:** Später kommen Blöcke in geschweiften Klammern \`{ }\` dazu. Dann zeigt z. B. \`} // Ende for\`, welche Klammer was schließt. +- **Gedanken festhalten:** Woran musst du denken, wenn du nächstes Mal weiterarbeitest? + +Klicke auf **Im Editor öffnen**, ändere einen Kommentar oder schreib einen neuen dazu. Das Struktogramm bleibt gleich, und VisuStruct behält deine Kommentare. + +> Schreib nicht hinter jede Zeile einen Kommentar. Erkläre, was dein Algorithmus macht und warum, nicht jedes einzelne Zeichen. + +::: angeberwissen +Beide Arten sind viel älter als Java: \`/* … */\` stammt aus der Sprache PL/I von 1964, \`//\` aus BCPL von 1967. Java hat sie über C und C++ geerbt. +::: + +## Lückentext: Kommentare + +::: lückentext +titel: Kommentare ergänzen +auftrag: Ergänze die Zeichen, damit oben ein mehrzeiliger Kommentar mit der Aufgabe steht und die anderen beiden Notizen einzeilige Kommentare sind. +\`\`\`java +[[/*]] + * Aufgabe: Das Programm rechnet Euro in Cent um. + [[*/]] +int euro = 3; +[[//]] Verarbeitung +int cent = euro * 100; +[[//]] Ausgabe, erwartet: 300 +System.out.println(cent); +\`\`\` +erklärung: \`/*\` öffnet den mehrzeiligen Kommentar und \`*/\` schließt ihn. \`//\` gilt nur bis zum Ende der Zeile, darum braucht jede Notiz ihr eigenes \`//\`. +::: + +## Lückentext: Eingabe + +::: lückentext +titel: Name und Alter einlesen +auftrag: Ergänze die fehlenden Wörter, damit das Programm einen Namen und ein Alter einliest. +\`\`\`java +import java.util.[[Scanner]]; +Scanner scanner = [[new]] Scanner(System.[[in]]); + +System.out.println("Wie heißt du?"); +[[String]] name = scanner.[[next]](); +System.out.println("Wie alt bist du?"); +int alter = scanner.[[nextInt]](); +System.out.println("Hallo " + name + ", nächstes Jahr bist du " + [[(alter + 1)]] + "."); +\`\`\` +erklärung: \`scanner.next()\` liest ein Wort, \`scanner.nextInt()\` eine ganze Zahl. Die Klammern um \`alter + 1\` sind wichtig: Ohne sie hängt Java erst \`alter\` und dann \`1\` an den Text an, aus 14 würde **141**. +::: + +## Fehler finden: Summe + +::: übung l06-java-fehler +titel: Summe reparieren +code: java +auftrag: Das Programm liest zwei Zahlen ein und soll ihre Summe ausgeben. Bei 3 und 4 erscheint aber **Summe: 34** statt **Summe: 7**. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l06-java-fehler-start.visustruct +test: 3, 4 -> Summe: 7 +test: 10, 5 -> Summe: 15 +test: 0, 9 -> Summe: 9 +braucht: anweisung +tipp: Lies die Ausgabe von links nach rechts: Was ergibt \`"Summe: " + a\`? Und was passiert, wenn danach noch \`+ b\` kommt? +tipp: Setze Klammern, damit Java zuerst rechnet: \`System.out.println("Summe: " + (a + b));\` +lösung: l06-java-fehler-loesung.visustruct +::: + +## Spiel: Was wird ausgegeben? + +::: spiel frage +titel: Spiel: Was wird ausgegeben? +intro: Ludwig hat Ein- und Ausgaben gebaut. Sag vorher, was passiert. Sieben Runden. + +runde: + int a = 3 + int b = 4 + output: a + b +frage: Was wird ausgegeben? +- 7 +- [x] 34 +- a + b +> In einer Ausgabe hängt \`+\` die Teile immer aneinander, auch bei Zahlen. + +runde: + int a = 3 + int b = 4 + int summe = a + b + output: "Summe: " + summe +frage: Was wird ausgegeben? +- [x] Summe: 7 +- Summe: 34 +- Summe: summe +> Gerechnet wird vorher in einer Variablen. Die Ausgabe hängt nur noch Text und Ergebnis aneinander. + +runde: + input: String name "Wie heißt du?" + output: "Hallo" + name + "!" +frage: Du tippst Mia. Was wird ausgegeben? +- Hallo Mia! +- [x] HalloMia! +- Hallo name! +> Im Text \`"Hallo"\` fehlt das Leerzeichen am Ende. Darum klebt alles zusammen. + +runde: + input: int alter "Wie alt bist du?" +frage: Du tippst 2.5. Was passiert? +- alter ist 2. +- alter ist 2.5. +- [x] Die Simulation meldet einen Fehler. +> Der Datentyp \`int\` erlaubt nur ganze Zahlen. + +runde: + input: double preis "Preis in Euro?" +frage: Zu welchem Teil von EVA gehört dieser Kasten? +- [x] Eingabe +- Verarbeitung +- Ausgabe +> \`input:\` fragt einen Wert ab. Das ist die Eingabe. + +runde: + double mittel = (a + b) / 2.0 +frage: Zu welchem Teil von EVA gehört dieser Kasten? +- Eingabe +- [x] Verarbeitung +- Ausgabe +> Hier wird gerechnet. Das ist die Verarbeitung. + +runde: + output: "Mittelwert: " + mittel +frage: Zu welchem Teil von EVA gehört dieser Kasten? +- Eingabe +- Verarbeitung +- [x] Ausgabe +> \`output:\` zeigt das Ergebnis an. Das ist die Ausgabe. +::: + +## 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. + +::: checkliste +- Ich kann das EVA-Prinzip erklären. → Das EVA-Prinzip +- Ich kann eine Eingabe mit Datentyp, Namen und Frage schreiben. → Eingabe mit input: +- Ich kann Text und Variablen in einer Ausgabe mit + verbinden. → Vorsicht mit + in der Ausgabe +- Ich kann ein Ergebnis zuerst ausrechnen und in einer Variablen speichern, dann diese Variable ausgeben, z. B. \`int summe = a + b\`, danach \`output: summe\`. → Vorsicht mit + in der Ausgabe +- Ich kann aus einem Aufgabentext Eingabe, Verarbeitung und Ausgabe herauslesen. → Vom Aufgabentext zum Struktogramm +- Ich kann in Java mit dem Scanner Zahlen einlesen. → Jetzt in Java +- Ich kann Kommentare mit \`//\` und \`/* */\` schreiben und damit meinen Code einteilen und erklären. → Kommentare im Code +::: + +## Wissenstest + +::: quiz +? Wofür steht EVA? +→ Das EVA-Prinzip +- [x] Eingabe, Verarbeitung, Ausgabe +- [ ] Eingabe, Variable, Anweisung +- [ ] Erst Variablen anlegen +> Viele Programme fragen erst Werte ab, verarbeiten sie und zeigen dann das Ergebnis. + +? Die Variablen a und b haben die Werte 3 und 4. Was zeigt \`output: a + b\`? +→ Vorsicht mit + in der Ausgabe +- [ ] 7 +- [x] 34 +- [ ] a + b +> In der Ausgabe hängt + die Teile aneinander. Rechne die Summe vorher in einer Variablen aus. + +? Welche Eingabe passt, wenn ein Preis wie 4.99 eingegeben werden soll? +→ Eingabe mit input: +- [ ] input: int preis "Preis?" +- [x] input: double preis "Preis?" +- [ ] input: String "Preis?" +> 4.99 ist eine Kommazahl, also double. Außerdem braucht jede Eingabe einen Variablennamen. + +? Was zeigt \`output: "Alter: " + alter\`, wenn alter den Wert 12 hat? +→ Vorsicht mit + in der Ausgabe +- [x] Alter: 12 +- [ ] "Alter: " + 12 +- [ ] Alter: alter + +? Aufgabe: *Das Programm fragt nach dem Radius eines Kreises und zeigt seinen Umfang an.* Ordne jedem Teil des Textes zu, wohin er im EVA-Prinzip gehört. +→ Vom Aufgabentext zum Struktogramm += fragt nach dem Radius -> Eingabe += Umfang = 2 * 3.14 * Radius -> Verarbeitung += zeigt seinen Umfang an -> Ausgabe +> Gegeben ist der Radius, gesucht der Umfang. Die Formel verbindet beides. + +? Was liest \`scanner.nextInt()\` ein? +→ Jetzt in Java +- [x] Eine ganze Zahl +- [ ] Eine Kommazahl +- [ ] Einen ganzen Satz +> Für Kommazahlen gibt es \`scanner.nextDouble()\`, für ein Wort \`scanner.next()\`. + +? Was macht Java mit einem Kommentar? +→ Kommentare im Code +- [ ] Es gibt ihn als Text aus. +- [x] Es überspringt ihn. +- [ ] Es meldet einen Fehler. +> Kommentare sind Notizen für Menschen. Das Programm läuft mit und ohne sie genau gleich. + +? Wo endet ein Kommentar, der mit \`/*\` beginnt? +→ Kommentare im Code +- [x] Bei \`*/\` +- [ ] Am Ende der Zeile +- [ ] Bei der nächsten Leerzeile +> Darum kann ein Kommentar mit \`/*\` über mehrere Zeilen gehen. Ein Kommentar mit \`//\` endet dagegen am Zeilenende. +::: +`,yx=`--- +titel: Simulation und Schreibtischtest +bereich: Grundlagen +kurz: Ein Struktogramm Schritt für Schritt ausführen, von Hand nachrechnen und Fehler finden. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- die Simulation starten, anhalten, einzelne Schritte ausführen und stoppen +- während der Simulation Variablen, Ausgabe und den letzten Schritt ablesen +- einen Schreibtischtest als Tabelle von Hand durchführen +- einen Fehler finden, indem ich die Werte mit meiner Erwartung vergleiche +- Java-Code mit dem Einzelschritt und Haltepunkten verfolgen +::: + +## Die Simulation starten + +Bevor es mit Verzweigungen und Schleifen weitergeht, lernst du dein wichtigstes Werkzeug kennen. Mit der Simulation prüfst du ab jetzt jede Übung selbst. + +Mit dem Knopf [▶︎ Simulation starten](#zeige-simulation) rechts bei den Werkzeugen führt VisuStruct dein Struktogramm aus. Solange die Simulation läuft, kannst du das Diagramm nicht bearbeiten. Derselbe Knopf heißt dann **■ Simulation beenden**, damit kehrst du zum Bearbeiten zurück. + +Rechts erscheint die **Steuerung**: + +- **Start** führt das Diagramm automatisch Schritt für Schritt aus. Wie lange zwischen zwei Schritten gewartet wird, stellst du bei **Pause pro Schritt** ein. +- **Pause** hält an. Danach geht es mit Start oder Schritt weiter. +- **Schritt** führt genau einen Schritt aus. So kannst du in Ruhe zuschauen. +- **Stopp** bricht ab und setzt alles auf den Anfang zurück. + +Öffne das folgende Diagramm im Editor und gehe es mit **Schritt** durch: + +::: diagramm sim-tausch.visustruct +Die Werte von a und b werden vertauscht. Die Variable hilf merkt sich dabei einen Wert. +::: + +## Was die Simulation anzeigt + +- **Markierung:** Ein Kasten im Diagramm ist farbig hervorgehoben. Bei **Letzter Schritt** ist es der Kasten, der gerade ausgeführt wurde. Bei **Nächster Schritt** ist es der Kasten, der als Nächstes drankommt. +- **Eingabe:** Fragt das Diagramm nach einem Wert, tippst du ihn hier ein und bestätigst mit **OK**. +- **Letzter Schritt:** Hier steht, was gerade passiert ist, z. B. \`a = 5 -> 5\` nach dem Kasten \`a = b\`. Links sind die Variablen schon durch ihre Werte ersetzt, rechts vom Pfeil steht das Ergebnis. +- **Variablen:** Alle Variablen mit ihren aktuellen Werten. +- **Ausgabe:** Alles, was mit \`output:\` ausgegeben wurde. + +Ist rechts der Bereich [Code](#zeige-codelive) geöffnet, läuft dort zusätzlich die [Konsole](#zeige-konsole) mit. Sie wird beim Start geleert und zeigt dann die Ausgaben und Eingaben so, wie sie auch beim echten Programm erscheinen würden. + +Am Ende erscheint **Simulation beendet**. Geht etwas schief, bleibt die Simulation auf dem fehlerhaften Kasten stehen und zeigt eine Meldung, z. B. **Unbekannte Variable: gesamt**. + +## Der Schreibtischtest + +Beim **Schreibtischtest** spielst du selbst den Computer. Du gehst das Struktogramm mit Stift und Papier durch und schreibst nach jedem Schritt die Werte der Variablen auf. Am besten machst du eine Tabelle: eine Spalte für den Schritt, eine für jede Variable und eine für die Ausgabe. + +Für das Diagramm oben sieht die Tabelle so aus: + +| Schritt | a | b | hilf | Ausgabe | +|---|---|---|---|---| +| \`int a = 3\` | 3 | – | – | | +| \`int b = 5\` | 3 | 5 | – | | +| \`int hilf = a\` | 3 | 5 | 3 | | +| \`a = b\` | 5 | 5 | 3 | | +| \`b = hilf\` | 5 | 3 | 3 | | +| \`output: "a = " + a\` | 5 | 3 | 3 | a = 5 | +| \`output: "b = " + b\` | 5 | 3 | 3 | b = 3 | + +Vergleiche danach deine Tabelle mit der Simulation. Stimmen die Werte unter **Variablen** nach jedem Schritt mit deiner Zeile überein? + +> Der Schreibtischtest lohnt sich besonders in Prüfungen. Dort hast du keinen Computer, aber du kannst trotzdem zeigen, was dein Struktogramm tut. + +## Fehler finden + +Gibt ein Struktogramm etwas Falsches aus, gehst du so vor: + +1. **Erwartung aufschreiben:** Was soll bei einer bestimmten Eingabe herauskommen? +2. **Schritt für Schritt ausführen:** Starte die Simulation mit **Schritt** und beobachte die Variablen. +3. **Die Stelle finden:** Wo weicht ein Wert zum ersten Mal von deiner Erwartung ab? Genau dort steckt der Fehler. + +Häufige Fehler in einer Sequenz sind: + +- Die **Reihenfolge** stimmt nicht: Eine Variable wird benutzt, bevor sie einen Wert hat. +- Ein Wert wird **überschrieben**, bevor er gebraucht wird. +- **Klammern** fehlen: \`a + b / 2\` ist etwas anderes als \`(a + b) / 2\`. +- Zwei ganze Zahlen werden geteilt: \`7 / 2\` ergibt \`3\`, weil bei \`int\` die Nachkommastellen wegfallen. + +> Später kommen Verzweigungen und Schleifen dazu. Dann zeigt dir die Simulation auch, welcher Weg genommen wird und wie oft eine Schleife läuft. + +::: angeberwissen +Am 9. September 1947 fand das Team von Grace Hopper im Rechner Harvard Mark II eine echte Motte, die zwischen zwei Kontakten klemmte. Sie klebten sie ins Logbuch und schrieben dazu: „Erster echter Fall, dass ein Bug gefunden wurde.“ Die Motte liegt heute in einem Museum in Washington. +::: + +## Übung: Tauschen reparieren + +::: übung sim-tausch +titel: Tauschen reparieren +auftrag: Das Struktogramm soll zwei Zahlen einlesen und sie vertauscht wieder ausgeben. Bei 3 und 5 soll also erst **5** und dann **3** erscheinen. Es gibt aber zweimal 5 aus. + Mache einen Schreibtischtest oder nutze **Schritt** und repariere den Fehler. +start: sim-tausch-start.visustruct +test: 3, 5 -> 5 | 3 +test: 1, 2 -> 2 | 1 +test: 7, 7 -> 7 | 7 +braucht: anweisung +tipp: Gehe das Diagramm mit **Schritt** durch und schreibe nach jedem Schritt die Werte von a und b auf. Wo verschwindet die 3? +tipp: Schau dir a nach dem Schritt \`a = b\` an. Wo ist der alte Wert von a geblieben? Merke ihn dir vorher in einer Hilfsvariablen, wie im Beispiel oben. +lösung: sim-tausch-loesung.visustruct +::: + +## Übung: Kinokarten reparieren + +::: übung sim-kino +titel: Kinokarten reparieren +auftrag: Eine Kinokarte kostet 8.50 €. Das Struktogramm soll nach der Anzahl fragen und den Gesamtpreis ausgeben, bei 2 Karten also \`Gesamt: 17.0\`. + Starte die Simulation. Sie bleibt mit einer Fehlermeldung stehen. Finde heraus, warum, und repariere das Struktogramm. +start: sim-kino-start.visustruct +test: 2 -> Gesamt: 17.0 +test: 3 -> Gesamt: 25.5 +test: 0 -> Gesamt: 0.0 +braucht: anweisung +tipp: Lies die Fehlermeldung der Simulation genau. Welche Variable kennt sie noch nicht? +tipp: Die Simulation führt die Kästen von oben nach unten aus. Hat gesamt schon einen Wert, wenn die Ausgabe drankommt? Du kannst Kästen mit der Maus verschieben. +lösung: sim-kino-loesung.visustruct +::: + +> Läuft eine Simulation endlos weiter, klicke auf **Stopp**. Beim **Prüfen** einer Übung bricht VisuStruct nach sehr vielen Schritten von selbst ab. + +## Jetzt in Java + +Auch Java-Code kannst du Schritt für Schritt ausführen. Im Bereich [Code](#zeige-codelive) heißt das Werkzeug dafür **Debugger**: + +- Klicke links auf eine Zeilennummer. Ein roter Punkt erscheint, das ist ein **Haltepunkt**. [▶︎ Ausführen](#zeige-ausfuehren) hält vor dieser Zeile an. +- Der Knopf [Einzelschritt](#zeige-einzelschritt) führt genau eine Zeile aus, wie **Schritt** in der Simulation. +- Unter dem Code steht, welchen Wert jede Variable gerade hat. Das ist dein Schreibtischtest, nur dass der Computer mitschreibt. + +::: übung l07-java-pizza +titel: Pizzabestellung reparieren +code: java +auftrag: Eine Pizza kostet 8 Euro, Extra-Käse 2 Euro. Für 3 Pizzen mit Extra-Käse soll das Programm **Gesamt: 30** ausgeben. Es gibt aber 14 aus. + Gehe den Java-Code mit dem Einzelschritt durch und beobachte \`gesamt\`. Finde den Fehler und repariere ihn im Code. +start: l07-java-pizza-start.visustruct +test: - -> Gesamt: 30 +braucht: anweisung +tipp: Welcher Wert steht nach der vierten Zeile in \`gesamt\`? Rechne im Kopf nach, was Java zuerst ausrechnet. +tipp: Wie in Mathe gilt Punkt vor Strich: \`preis + kaese * anzahl\` ist \`8 + 6\`. Setze Klammern: \`(preis + kaese) * anzahl\`. +lösung: l07-java-pizza-loesung.visustruct +::: + +## Lückentext: Schreibtischtest + +::: lückentext +titel: Was steht in den Variablen? +auftrag: Mach einen Schreibtischtest im Kopf. Trage hinter jeder Zeile ein, welchen Wert die Variable danach hat, und in der letzten Zeile, was ausgegeben wird. +\`\`\`java +int a = 5; +int b = 2; +a = a + b; // a ist jetzt [[7]] +b = a * 2; // b ist jetzt [[14]] +a = b - a; // a ist jetzt [[7]] +System.out.println(a + b); // Ausgabe: [[21]] +\`\`\` +erklärung: Jede Zeile rechnet mit den Werten, die gerade in den Variablen stehen: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, Ausgabe 7 + 14 = 21. Mit dem Einzelschritt im Bereich Code kannst du es nachprüfen. +::: + +## Fehler finden: Spielstand + +::: übung l07-java-fehler +titel: Spielstand reparieren +code: java +auftrag: Ludwig bekommt in einem Spiel erst 10 Punkte, dann 5 Punkte, dann verliert er 3 Punkte. Am Ende soll **Punkte: 12** erscheinen. Es erscheint aber **Punkte: 3**. + Gehe den Code mit dem Einzelschritt durch und beobachte \`punkte\`. Repariere die falsche Zeile und klicke auf Prüfen. +start: l07-java-fehler-start.visustruct +test: - -> Punkte: 12 +braucht: anweisung +tipp: Nach welcher Zeile hat \`punkte\` plötzlich den Wert 3? Was soll in dieser Zeile eigentlich passieren? +tipp: Ludwig verliert 3 Punkte, also wird vom alten Wert abgezogen: \`punkte = punkte - 3;\` +lösung: l07-java-fehler-loesung.visustruct +::: + +## Spiel: Bombe entschärfen + +::: spiel bombe +titel: Spiel: Bombe entschärfen +intro: In jedem Programm steckt **genau ein Fehler**, und die Bombe tickt. Mach im Kopf den Schreibtischtest und tippe auf die falsche Zeile, bevor die Zeit abläuft. Die Programme sind in Java, aber jede Zeile ist ein Kasten wie im Struktogramm. Sechs Runden, je 30 Sekunden. +zeit: 30 + +runde: + int a = 3; + int b = 5; + int hilf = a; + a = b; + b = a; +frage: Soll die Werte von a und b tauschen. +fehler: 5 +besser: b = hilf; +> In a steht schon der Wert von b. Der alte Wert von a steckt in hilf. + +runde: + int a = 4; + int b = 6; + double mittel = a + b / 2; + System.out.println(mittel); +frage: Soll den Mittelwert 5.0 ausgeben. +fehler: 3 +besser: double mittel = (a + b) / 2.0; +> Ohne Klammern wird zuerst geteilt: 4 + 6 / 2 = 7. + +runde: + int karten = 3; + double preis = 8.5; + double gesamt = karten + preis; + System.out.println("Gesamt: " + gesamt); +frage: Soll den Preis für 3 Kinokarten zu je 8,50 € ausgeben. +fehler: 3 +besser: double gesamt = karten * preis; +> Für den Gesamtpreis wird malgenommen, nicht addiert. + +runde: + int minuten = 135; + int stunden = minuten / 60; + int rest = minuten / 60; + System.out.println(stunden + " h " + rest + " min"); +frage: Soll 2 h 15 min ausgeben. +fehler: 3 +besser: int rest = minuten % 60; +> Den Rest beim Teilen liefert \`%\`. Mit \`/\` stünde auch in rest eine 2. + +runde: + String name = "Ada"; + System.out.println("Hallo " + "name" + "!"); +frage: Soll „Hallo Ada!“ ausgeben. +fehler: 2 +besser: System.out.println("Hallo " + name + "!"); +> In Anführungszeichen ist name nur ein Text. Die Variable steht ohne Anführungszeichen. + +runde: + double preis = 100; + preis = preis * 0.1; + System.out.println(preis); +frage: Soll den Preis um 10 % erhöhen, also 110.0 ausgeben. +fehler: 2 +besser: preis = preis + preis * 0.1; +> Mal 0.1 ergibt nur die 10 %, also 10.0. Die müssen zum alten Preis dazukommen. +::: + +## 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. + +::: checkliste +- Ich kann die Simulation starten, anhalten, einzelne Schritte ausführen und stoppen. → Die Simulation starten +- Ich kann während der Simulation Variablen, Ausgabe und den letzten Schritt ablesen. → Was die Simulation anzeigt +- Ich kann einen Schreibtischtest als Tabelle von Hand durchführen. → Der Schreibtischtest +- Ich kann einen Fehler finden, indem ich die Werte mit meiner Erwartung vergleiche. → Fehler finden +- Ich kann Java-Code mit dem Einzelschritt und Haltepunkten verfolgen. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Mit welchem Knopf führst du genau einen Schritt aus? +→ Die Simulation starten +- [ ] Start +- [x] Schritt +- [ ] Stopp +> Start läuft automatisch weiter, Schritt führt nur einen Schritt aus. + +? Was schreibst du beim Schreibtischtest nach jedem Schritt auf? +→ Der Schreibtischtest +- [ ] Nur die Ausgabe am Ende +- [x] Die aktuellen Werte aller Variablen +- [ ] Den erzeugten Java-Code +> So siehst du genau, an welcher Stelle ein Wert anders ist als erwartet. + +? Erst \`int a = 3\`, dann \`int b = 5\`, dann \`a = b\`. Welche Werte haben a und b danach? +→ Der Schreibtischtest +- [ ] a = 5 und b = 3 +- [x] a = 5 und b = 5 +- [ ] a = 3 und b = 5 +> Der alte Wert von a ist überschrieben. Darum braucht man beim Tauschen eine Hilfsvariable. + +? Im Feld Letzter Schritt steht \`preis = 4 * 2.5 -> 10.0\`. Was bedeutet das? +→ Was die Simulation anzeigt +- [ ] Die Variable preis hat jetzt den Wert 4. +- [x] 4 * 2.5 wurde ausgerechnet und das Ergebnis 10.0 in preis gespeichert. +- [ ] Die Simulation hat einen Fehler gefunden. + +? Die Simulation meldet **Unbekannte Variable: summe**. Was ist ein wahrscheinlicher Grund? +→ Fehler finden +- [x] summe wird benutzt, bevor sie einen Wert bekommen hat. +- [ ] summe ist zu groß. +- [ ] Das Struktogramm hat zu viele Kästen. + +? Was macht ein roter Punkt vor einer Zeilennummer im Bereich Code? +→ Jetzt in Java +- [ ] Er markiert einen Fehler. +- [x] Das Programm hält vor dieser Zeile an. +- [ ] Die Zeile wird übersprungen. +> Das ist ein Haltepunkt. Mit ▶︎ oder dem Einzelschritt geht es weiter. +::: +`,wx=`--- +titel: Verzweigung +bereich: Grundlagen +kurz: Mit einer Bedingung entscheiden, welcher von zwei Wegen ausgeführt wird. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, dass bei einer Verzweigung genau ein Zweig ausgeführt wird +- die Vergleichsoperatoren == != < <= > >= anwenden +- == und = unterscheiden +- eine Verzweigung mit einem leeren Zweig bauen +- eine Verzweigung mit if und else in Java schreiben +::: + +## Wenn, dann, sonst + +Bisher wurden alle Kästen immer ausgeführt. Oft soll ein Programm aber **entscheiden**: Wenn eine Bedingung erfüllt ist, tue das eine, sonst das andere. + +Dafür gibt es die **Verzweigung**. Oben im Dreieck steht die Bedingung. Darunter teilt sich das Struktogramm in zwei Zweige: + +- **true** (links): wird ausgeführt, wenn die Bedingung wahr ist +- **false** (rechts): wird ausgeführt, wenn die Bedingung falsch ist + +Es wird immer **genau einer** der beiden Zweige ausgeführt. Danach geht es unter der Verzweigung weiter. + +::: diagramm l07-alter-pruefen.visustruct +Je nach eingegebenem Alter erscheint die eine oder die andere Meldung. Probiere in der Simulation 17 und 18 aus. +::: + +## Eine Verzweigung einfügen + +Ziehe die **Verzweigung** aus dem Bereich Elemente ins Struktogramm. Klicke das Dreieck an und schreibe im Objektinspektor die Bedingung, z. B. \`alter >= 18\`. Das Wort \`if\` steht schon davor. + +In jedem Zweig liegt zuerst ein Platzhalter ø. Ziehe dort Anweisungen hinein. In einem Zweig dürfen auch mehrere Kästen untereinander stehen. + +## Vergleichsoperatoren + +Eine Bedingung ist meistens ein **Vergleich**. Sein Ergebnis ist immer \`true\` oder \`false\`. + +- \`==\` gleich, z. B. \`zahl == 0\` +- \`!=\` ungleich, z. B. \`antwort != 42\` +- \`<\` kleiner, \`<=\` kleiner oder gleich +- \`>\` größer, \`>=\` größer oder gleich + +> Verwechsle \`==\` nicht mit \`=\`. Ein einzelnes \`=\` ist eine Zuweisung und speichert einen Wert. Zum Vergleichen brauchst du zwei Gleichheitszeichen. + +Mit \`%\` prüfst du, ob eine Zahl durch eine andere teilbar ist: \`zahl % 2 == 0\` ist wahr, wenn \`zahl\` gerade ist. + +## Übung: Gerade oder ungerade + +::: übung l07-gerade +titel: Gerade oder ungerade +auftrag: Frage eine ganze Zahl ab. Gib **gerade** aus, wenn sie gerade ist, und sonst **ungerade**. +test: 4 -> gerade +test: 7 -> ungerade +test: 0 -> gerade +braucht: verzweigung +tipp: Hier gibt es zwei Möglichkeiten, also brauchst du eine Verzweigung. Woran erkennst du eine gerade Zahl? +tipp: Eine Zahl ist gerade, wenn beim Teilen durch 2 kein Rest bleibt. Die Bedingung lautet \`zahl % 2 == 0\`. +lösung: l07-gerade-loesung.visustruct +::: + +## Übung: Die größere Zahl + +::: übung l07-maximum +titel: Die größere Zahl +auftrag: Frage zwei ganze Zahlen ab und gib nur die größere von beiden aus. Sind beide gleich, gib diese Zahl aus. +test: 3, 8 -> 8 +test: 9, 2 -> 9 +test: 5, 5 -> 5 +braucht: verzweigung +tipp: Eine Verzweigung vergleicht die beiden Zahlen. In jedem Zweig steht genau eine Ausgabe. +tipp: Vergleiche mit \`a > b\`. Im true-Zweig gibst du \`a\` aus, im false-Zweig \`b\`. +lösung: l07-maximum-loesung.visustruct +::: + +## Ein leerer Zweig + +Manchmal soll nur dann etwas passieren, wenn die Bedingung wahr ist, und sonst gar nichts. Dann bleibt der false-Zweig **leer**. Im Struktogramm steht dort der Platzhalter **ø**. + +::: diagramm l07-rabatt.visustruct +Ab 50 Euro gibt es 5 Euro Rabatt. Sonst passiert nichts, der false-Zweig ist leer. Die Ausgabe darunter wird in beiden Fällen ausgeführt. +::: + +## Übung: Betrag + +::: übung l07-betrag +titel: Betrag einer Zahl +auftrag: Frage eine ganze Zahl ab. Ist sie negativ, mache sie positiv. Gib danach die Zahl aus. Aus -5 wird also 5, und 7 bleibt 7. +Nutze eine Verzweigung mit einem leeren Zweig und nur **einer** Ausgabe unter der Verzweigung. +test: -5 -> 5 +test: 7 -> 7 +test: 0 -> 0 +test: -12 -> 12 +braucht: verzweigung +tipp: Nur negative Zahlen müssen verändert werden. Was passiert mit einer Zahl, wenn du sie mal -1 nimmst? +tipp: Die Bedingung ist \`zahl < 0\`. Im true-Zweig drehst du das Vorzeichen um, z. B. mit \`zahl = 0 - zahl\`. Der false-Zweig bleibt leer. +lösung: l07-betrag-loesung.visustruct +::: + +## Jetzt in Java + +So sieht die Altersprüfung vom Anfang dieser Lektion in Java aus: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Wie alt bist du?"); +int alter = scanner.nextInt(); +if (alter >= 18) { + System.out.println("Du bist volljährig."); +} else { + System.out.println("Du bist noch nicht volljährig."); +} +\`\`\` + +- Die Bedingung steht nach \`if\` in **runden Klammern** \`( )\`. +- Der true-Zweig steht in **geschweiften Klammern** \`{ }\`, der false-Zweig folgt nach \`else\` in eigenen geschweiften Klammern. Hinter einer geschweiften Klammer steht kein Semikolon. +- Ist der false-Zweig leer, lässt du \`else { }\` einfach weg. +- Die ersten beiden Zeilen braucht dein Programm einmal, sobald es etwas einliest. Danach liest \`scanner.nextInt()\` eine ganze Zahl ein. Die Frage davor ist eine normale Ausgabe. + +::: angeberwissen +Java hat auch ein Maskottchen: **Duke**, ein kleiner schwarz-weißer Kerl mit großer roter Nase. Er wurde 1992 im Team von Java gezeichnet und winkt seitdem von Konferenzen und T-Shirts. Ludwig findet, ein Geißbock hätte besser gepasst. +::: + +::: übung l08-java-bestanden +titel: Bestanden in Java +code: java +auftrag: Schreibe ein Java-Programm, das nach der Punktzahl fragt. Ab 50 Punkten gibt es **bestanden** aus, sonst **nicht bestanden**. + Tippe den Code im Bereich Code und klicke dann auf Prüfen. +test: 50 -> bestanden +test: 49 -> nicht bestanden +test: 100 -> bestanden +test: 0 -> nicht bestanden +braucht: verzweigung +tipp: Fang mit den beiden Zeilen für den Scanner an. Dann fragst du nach den Punkten, liest sie ein und vergleichst sie mit \`if\`. +tipp: Die Bedingung lautet \`punkte >= 50\`. In den Zweigen steht \`System.out.println("bestanden");\` und nach \`else\` \`System.out.println("nicht bestanden");\`. +lösung: l08-java-bestanden-loesung.visustruct +::: + +## Lückentext: Gerade oder ungerade + +::: lückentext +titel: Gerade oder ungerade +auftrag: Ergänze die fehlenden Wörter und Zeichen. Das Programm soll ausgeben, ob eine Zahl gerade ist. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Welche Zahl?"); +int zahl = scanner.nextInt(); +[[if]] (zahl [[%]] 2 [[==]] 0) [[{]] + System.out.println("gerade"); +[[}]] [[else]] { + System.out.println("ungerade"); +} +\`\`\` +erklärung: \`zahl % 2\` ist der Rest beim Teilen durch 2. Ist er 0, ist die Zahl gerade. Zum Vergleichen brauchst du \`==\`, ein einzelnes \`=\` ist eine Zuweisung. Beide Zweige stehen in geschweiften Klammern. +::: + +## Fehler finden: Eintritt + +::: übung l08-java-fehler +titel: Eintritt reparieren +code: java +auftrag: Im Zoo haben Kinder **unter** 6 Jahren freien Eintritt, alle anderen zahlen 4 Euro. Das Programm lässt aber auch Sechsjährige umsonst hinein. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l08-java-fehler-start.visustruct +test: 5 -> Eintritt frei +test: 6 -> 4 Euro +test: 10 -> 4 Euro +test: 0 -> Eintritt frei +braucht: verzweigung +tipp: Probiere das Programm mit 6 aus. Welcher Vergleichsoperator lässt die 6 noch durch? +tipp: „Unter 6“ heißt \`alter < 6\`. \`<=\` bedeutet „kleiner oder gleich“. +lösung: l08-java-fehler-loesung.visustruct +::: + +## Spiel: Welcher Weg? + +::: spiel frage +titel: Spiel: Welcher Weg? +intro: Ludwig hat Verzweigungen in Java geschrieben. Rechne die Bedingung im Kopf aus und sag vorher, was ausgegeben wird. Sieben Runden. + +runde: + int x = 5; + if (x > 5) { + System.out.println("groß"); + } else { + System.out.println("klein"); + } +frage: Was wird ausgegeben? +- groß +- [x] klein +- nichts +> 5 > 5 ist falsch, denn 5 ist nicht größer als 5. Also der false-Zweig. + +runde: + int x = 5; + if (x >= 5) { + System.out.println("groß"); + } else { + System.out.println("klein"); + } +frage: Was wird ausgegeben? +- [x] groß +- klein +- groß und klein +> \`>=\` heißt „größer oder gleich“. 5 >= 5 ist wahr. + +runde: + int zahl = 7; + if (zahl % 2 == 0) { + System.out.println("gerade"); + } else { + System.out.println("ungerade"); + } +frage: Was wird ausgegeben? +- gerade +- [x] ungerade +- 1 +> 7 % 2 ist der Rest 1, also nicht 0. Die Zahl ist ungerade. + +runde: + int x = -4; + if (x < 0) { + x = -x; + } + System.out.println(x); +frage: Was wird ausgegeben? +- -4 +- [x] 4 +- nichts +> -4 < 0 ist wahr, also wird das Vorzeichen umgedreht. + +runde: + int x = 4; + if (x < 0) { + x = -x; + } + System.out.println(x); +frage: Was wird ausgegeben? +- -4 +- [x] 4 +- nichts +> 4 < 0 ist falsch. Der false-Zweig ist leer, das Programm macht einfach unten weiter. + +runde: + int note = 3; + if (note != 3) { + System.out.println("anders"); + } else { + System.out.println("drei"); + } +frage: Was wird ausgegeben? +- anders +- [x] drei +- nichts +> \`!=\` heißt „ungleich“. 3 != 3 ist falsch. + +runde: + int a = 8; + int b = 12; + if (a > b) { + System.out.println(a); + } else { + System.out.println(b); + } +frage: Was wird ausgegeben? +- 8 +- [x] 12 +- 20 +> Das Programm gibt die größere der beiden Zahlen 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. + +::: checkliste +- Ich kann erklären, dass bei einer Verzweigung genau ein Zweig ausgeführt wird. → Wenn, dann, sonst +- Ich kann die Vergleichsoperatoren == != < <= > >= anwenden. → Vergleichsoperatoren +- Ich kann == und = unterscheiden. → Vergleichsoperatoren +- Ich kann eine Verzweigung mit einem leeren Zweig bauen. → Ein leerer Zweig +- Ich kann eine Verzweigung mit if und else in Java schreiben. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Welcher Zweig wird ausgeführt, wenn die Bedingung falsch ist? +→ Wenn, dann, sonst +- [ ] Der true-Zweig +- [x] Der false-Zweig +- [ ] Beide Zweige +- [ ] Keiner, das Programm endet +> Bei false wird der rechte Zweig ausgeführt. Danach geht es unter der Verzweigung weiter. + +? Mit welcher Bedingung prüfst du, ob alter genau 18 ist? +→ Vergleichsoperatoren +- [ ] alter = 18 +- [x] alter == 18 +- [ ] alter >= 18 +> Ein einzelnes = ist eine Zuweisung. Zum Vergleichen brauchst du ==. + +? Was bedeutet ø in einem Zweig? +→ Ein leerer Zweig +- [x] In diesem Fall passiert nichts. +- [ ] Das Programm endet hier. +- [ ] Die Bedingung ist falsch. + +? Die Bedingung lautet \`punkte >= 50\`. Bei welchem Wert ist sie wahr? +→ Vergleichsoperatoren +- [ ] 49 +- [x] 50 +- [ ] 0 +> >= heißt größer oder gleich. 50 gehört also dazu. + +? In Schulbüchern hat die Verzweigung oft noch einen anderen Namen. Welchen? +→ Wenn, dann, sonst +- [ ] Mehrfachauswahl +- [x] Bedingte Anweisung +- [ ] Wiederholungsstruktur +> Die Anweisungen in einem Zweig werden nur unter einer Bedingung ausgeführt. Darum heißt sie auch bedingte Anweisung. + +? Wo steht in Java die Bedingung einer Verzweigung? +→ Jetzt in Java +- [x] In runden Klammern direkt nach if +- [ ] In geschweiften Klammern nach else +- [ ] Hinter einem Semikolon +> \`if (alter >= 18) { … }\`: Die runden Klammern gehören zur Bedingung, die geschweiften zum Zweig. +::: +`,zx=`--- +titel: Bedingungen verknüpfen +bereich: Grundlagen +kurz: Mehrere Bedingungen mit und, oder und nicht verbinden und Wertebereiche prüfen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, wann eine Verknüpfung mit && wahr ist +- erklären, wann eine Verknüpfung mit || wahr ist +- eine Bedingung mit ! umdrehen +- prüfen, ob ein Wert in einem Bereich wie 1 bis 6 liegt +- die Wahrheitstabelle für &&, || und ! lesen +- das Ergebnis einer Bedingung in einer boolean-Variablen speichern +- zusammengesetzte Bedingungen sicher auswerten +- Bedingungen in Java mit && und || verknüpfen +::: + +## Und: && + +Manchmal reicht ein einzelner Vergleich nicht. Ein Jugendticket gibt es zum Beispiel nur, wenn jemand **mindestens 12 und jünger als 18** ist. + +Mit \`&&\` (und) verbindest du zwei Bedingungen. Das Ergebnis ist nur dann \`true\`, wenn **beide** Bedingungen wahr sind. + +::: diagramm l08-jugendticket.visustruct +Beide Vergleiche müssen stimmen. Probiere in der Simulation 11, 12, 17 und 18 aus. +::: + +## Oder: || + +Mit \`||\` (oder) ist das Ergebnis \`true\`, wenn **mindestens eine** der Bedingungen wahr ist. Es dürfen auch beide wahr sein. + +\`\`\` +tag == 6 || tag == 7 +\`\`\` + +Diese Bedingung ist wahr, wenn \`tag\` den Wert 6 oder den Wert 7 hat, also am Samstag oder Sonntag. + +> Die beiden senkrechten Striche \`|\` tippst du auf vielen Tastaturen mit AltGr und der Taste \`<\`, am Mac mit Option und 7. + +## Übung: Wochenende + +::: übung l08-wochenende +titel: Wochenende +auftrag: Frage einen Wochentag als Zahl ab (1 ist Montag, 7 ist Sonntag). Gib **Wochenende** aus, wenn es Samstag oder Sonntag ist, sonst **Werktag**. +test: 6 -> Wochenende +test: 7 -> Wochenende +test: 1 -> Werktag +test: 5 -> Werktag +braucht: verzweigung +tipp: Wochenende ist, wenn der Tag 6 **oder** 7 ist. Dafür brauchst du zwei Vergleiche in einer Bedingung. +tipp: Samstag ist 6, Sonntag ist 7. Verbinde die beiden Vergleiche mit \`||\`. +lösung: l08-wochenende-loesung.visustruct +::: + +## Wertebereiche prüfen + +Schulnoten gehen von 1 bis 6. Ob eine Note **im Bereich** liegt, prüfst du mit zwei Vergleichen und \`&&\`: + +\`\`\` +note >= 1 && note <= 6 +\`\`\` + +::: grafik l08-zahlenstrahl.svg +Gültig ist der grüne Bereich von 1 bis 6, beide Ränder gehören dazu. +::: + +Umgekehrt ist eine Note **außerhalb** des Bereichs, wenn sie zu klein **oder** zu groß ist: + +::: diagramm l08-note.visustruct +Eine Note kleiner als 1 oder größer als 6 gibt es nicht. +::: + +> Die Schreibweise aus Mathe \`1 <= note <= 6\` funktioniert nicht. Du musst sie in zwei Vergleiche aufteilen und mit \`&&\` verbinden. + +## Übung: Gültige Note + +::: übung l08-note-gueltig +titel: Gültige Note +auftrag: Frage eine Note als ganze Zahl ab. Gib **gültig** aus, wenn sie zwischen 1 und 6 liegt (1 und 6 gehören dazu), sonst **ungültig**. +test: 1 -> gültig +test: 6 -> gültig +test: 3 -> gültig +test: 0 -> ungültig +test: 7 -> ungültig +braucht: verzweigung +tipp: Eine gültige Note muss zwei Dinge gleichzeitig erfüllen: nicht zu klein **und** nicht zu groß. +tipp: Die Note muss größer oder gleich 1 und gleichzeitig kleiner oder gleich 6 sein. +lösung: l08-gueltig-loesung.visustruct +::: + +## Nicht und Klammern + +Mit \`!\` (nicht) drehst du eine Bedingung um: Aus \`true\` wird \`false\` und umgekehrt. + +\`\`\` +!(note >= 1 && note <= 6) +\`\`\` + +Das ist wahr, wenn die Note **nicht** im Bereich liegt, und bedeutet dasselbe wie \`note < 1 || note > 6\`. + +Kommen \`&&\` und \`||\` zusammen vor, wird \`&&\` zuerst ausgewertet, so wie Punkt vor Strich. Setze lieber **Klammern**, dann ist klar, was zusammengehört: + +\`\`\` +(alter >= 12 && alter < 18) || schueler == 1 +\`\`\` + +## Die Wahrheitstabelle + +Eine **Wahrheitstabelle** zeigt auf einen Blick, was bei \`&&\`, \`||\` und \`!\` herauskommt. Links stehen alle vier Möglichkeiten für zwei Bedingungen \`a\` und \`b\`, rechts das Ergebnis: + +::: grafik l09-wahrheitstabelle.svg +Grün ist true, rot ist false. Bei && gibt es nur eine grüne Zeile, bei || nur eine rote. +::: + +Merksätze: + +- \`a && b\` ist nur wahr, wenn **beide** wahr sind. +- \`a || b\` ist nur falsch, wenn **beide** falsch sind. +- \`!a\` dreht den Wert um. + +::: angeberwissen +Der Datentyp \`boolean\` heißt nach **George Boole**. Der Engländer hat schon 1847 gezeigt, dass man mit wahr und falsch rechnen kann wie mit Zahlen, fast hundert Jahre bevor es den ersten Computer gab. Heute steckt seine Logik in jedem Chip. +::: + +## Wahrheitswerte in Variablen + +Das Ergebnis einer Bedingung ist ein **Wahrheitswert** vom Typ \`boolean\`. Du kannst ihn wie eine Zahl in einer Variablen speichern und später benutzen: + +\`\`\` +boolean wochenende = tag == 6 || tag == 7 +\`\`\` + +In der Verzweigung steht dann nur noch \`wochenende\`. Das liest sich fast wie ein Satz: „Wenn Wochenende, dann …“. Schreibe nicht \`wochenende == true\`, denn \`wochenende\` ist ja schon true oder false. + +Mit \`!wochenende\` fragst du nach dem Gegenteil, also nach einem Werktag. + +::: ludwig +Lange Bedingungen werden übersichtlich, wenn du Teile davon in boolean-Variablen mit sprechenden Namen packst, zum Beispiel \`boolean jugendlich = alter >= 12 && alter < 18\`. +::: + +## Spiel: Wahr oder falsch? + +Jetzt bist du dran. Rechne jede Bedingung im Kopf aus. Nach jeder Antwort siehst du, wie VisuStruct sie Schritt für Schritt auswertet. + +::: spiel +alter: 8..20 +tag: 1..7 +note: 0..7 +schueler: boolean +wochenende: boolean +? alter >= 18 +? tag == 6 +? note != 3 +? alter >= 12 && alter < 18 +? tag == 6 || tag == 7 +? schueler && wochenende +? !schueler +? note >= 1 && note <= 6 +? !(alter < 18) +? schueler || alter >= 18 +? (alter >= 12 && alter < 18) || schueler +? !(note >= 1 && note <= 6) +? !wochenende && tag != 3 +? alter >= 12 && alter < 18 && !schueler +::: + +## Übung: Schaltjahr + +::: übung l08-schaltjahr +titel: Schaltjahr +auftrag: Ein Jahr ist ein Schaltjahr, wenn es durch 4 teilbar ist, aber nicht durch 100. Jahre, die durch 400 teilbar sind, sind trotzdem Schaltjahre. +Frage eine Jahreszahl ab und gib **Schaltjahr** oder **kein Schaltjahr** aus. +test: 2024 -> Schaltjahr +test: 2023 -> kein Schaltjahr +test: 1900 -> kein Schaltjahr +test: 2000 -> Schaltjahr +braucht: verzweigung +tipp: Prüfe die Regel zuerst an Beispielen: 2024 ist ein Schaltjahr, 1900 nicht, 2000 schon. Teilbar heißt: Der Rest ist 0. +tipp: Teilbar durch 4 heißt \`jahr % 4 == 0\`, nicht teilbar durch 100 heißt \`jahr % 100 != 0\`. Verbinde diese beiden mit \`&&\`, setze Klammern darum und hänge mit \`||\` den Fall für 400 an. +lösung: l08-schaltjahr-loesung.visustruct +::: + +## Jetzt in Java + +Das Jugendticket vom Anfang sieht in Java so aus: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Wie alt bist du?"); +int alter = scanner.nextInt(); +if (alter >= 12 && alter < 18) { + System.out.println("Jugendticket"); +} else { + System.out.println("Kein Jugendticket"); +} +\`\`\` + +Die Zeichen \`&&\`, \`||\` und \`!\` sind genau die, die du schon im Struktogramm benutzt. Sie kommen aus Java. Die ganze Bedingung steht wie immer in den runden Klammern nach \`if\`. + +::: übung l09-java-schule +titel: Schule oder Freizeit +code: java +auftrag: Schreibe ein Java-Programm, das nach der Stunde fragt (0 bis 23). Von 8 bis einschließlich 15 Uhr gibt es **Schule** aus, sonst **Freizeit**. +test: 8 -> Schule +test: 15 -> Schule +test: 16 -> Freizeit +test: 7 -> Freizeit +braucht: verzweigung +tipp: Die Stunde muss zwei Bedingungen gleichzeitig erfüllen. Welcher Operator heißt „und“? +tipp: \`if (stunde >= 8 && stunde <= 15) { … } else { … }\` +lösung: l09-java-schule-loesung.visustruct +::: + +## Lückentext: Bedingungen + +::: lückentext +titel: Note und Wochenende +auftrag: Ergänze die fehlenden Operatoren und Wörter. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Welche Note?"); +int note = scanner.nextInt(); +if (note >= 1 [[&&]] note [[<=]] 6) { + System.out.println("gültige Note"); +} else { + System.out.println("ungültige Note"); +} +System.out.println("Welcher Tag (1 bis 7)?"); +int tag = scanner.nextInt(); +[[boolean]] wochenende = tag == 6 [[||]] tag == 7; +if ([[!]]wochenende) { + System.out.println("Schultag"); +} +\`\`\` +erklärung: Eine Note ist gültig, wenn **beide** Bedingungen stimmen, also \`&&\`. Wochenende ist, wenn **eine** der beiden stimmt, also \`||\`. Das Ergebnis passt in eine \`boolean\`-Variable, und \`!\` dreht es um. +::: + +## Fehler finden: Schulfrei + +::: übung l09-java-fehler +titel: Schulfrei reparieren +code: java +auftrag: Das Programm soll bei Tag 6 (Samstag) und Tag 7 (Sonntag) **schulfrei** ausgeben, sonst **Schule**. Es gibt aber immer **Schule** aus. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l09-java-fehler-start.visustruct +test: 6 -> schulfrei +test: 7 -> schulfrei +test: 3 -> Schule +test: 1 -> Schule +braucht: verzweigung +tipp: Kann \`tag\` gleichzeitig 6 **und** 7 sein? +tipp: Es reicht, wenn eine der beiden Bedingungen stimmt: \`tag == 6 || tag == 7\`. +lösung: l09-java-fehler-loesung.visustruct +::: + +## 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. + +::: checkliste +- Ich kann erklären, wann eine Verknüpfung mit && wahr ist. → Und: && +- Ich kann erklären, wann eine Verknüpfung mit || wahr ist. → Oder: || +- Ich kann eine Bedingung mit ! umdrehen. → Nicht und Klammern +- Ich kann prüfen, ob ein Wert in einem Bereich wie 1 bis 6 liegt. → Wertebereiche prüfen +- Ich kann die Wahrheitstabelle für &&, || und ! lesen. → Die Wahrheitstabelle +- Ich kann das Ergebnis einer Bedingung in einer boolean-Variablen speichern. → Wahrheitswerte in Variablen +- Ich kann zusammengesetzte Bedingungen sicher auswerten (im Spiel mindestens 8 von 10 richtig). → Spiel: Wahr oder falsch? +- Ich kann Bedingungen in Java mit && und || verknüpfen. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Wann ist \`a && b\` wahr? +→ Und: && +- [ ] Wenn a oder b wahr ist +- [x] Nur wenn a und b beide wahr sind +- [ ] Wenn genau eins von beiden wahr ist +> Bei && müssen beide Teile stimmen. Ist einer falsch, ist das Ganze falsch. + +? Die Variable tag hat den Wert 6. Was ergibt \`tag == 6 || tag == 7\`? +→ Oder: || +- [x] true +- [ ] false +> Bei || reicht es, wenn eine Seite wahr ist. + +? Mit welcher Bedingung prüfst du, ob zahl zwischen 10 und 20 liegt (beide eingeschlossen)? +→ Wertebereiche prüfen +- [ ] 10 <= zahl <= 20 +- [ ] zahl >= 10 || zahl <= 20 +- [x] zahl >= 10 && zahl <= 20 +> Mit || wäre jede Zahl erlaubt, denn jede Zahl ist größer als 10 oder kleiner als 20. + +? Was ergibt \`!(5 > 3)\`? +→ Nicht und Klammern +- [ ] true +- [x] false +> 5 > 3 ist wahr, und ! dreht das um. + +? Wie schreibst du in Java „alter ist mindestens 12 und kleiner als 18“? +→ Jetzt in Java +- [ ] if (12 <= alter < 18) +- [x] if (alter >= 12 && alter < 18) +- [ ] if (alter >= 12 || alter < 18) +> Jeder Vergleich steht für sich, verbunden mit \`&&\`. +::: +`,Ix=`--- +titel: Fallauswahl +bereich: Grundlagen +kurz: Je nach Wert einer Variablen einen von vielen Fällen ausführen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- eine Fallauswahl einfügen, Fälle hinzufügen und Fallnamen ändern +- erklären, wann der Fall default ausgeführt wird +- entscheiden, ob eine Fallauswahl oder eine Verzweigung besser passt +- eine Fallauswahl in Java mit switch schreiben +::: + +## Viele Möglichkeiten, eine Variable + +Ein Getränkeautomat hat drei Tasten: 1 für Wasser, 2 für Saft, 3 für Kakao. Mit Verzweigungen brauchst du dafür drei ineinander geschachtelte Kästen. Das wird schnell breit und unübersichtlich. + +::: diagramm l09-verschachtelt.visustruct +Der Automat mit drei verschachtelten Verzweigungen. Jede Verzweigung prüft wieder dieselbe Variable wahl. +::: + +Immer wenn du **eine Variable** mit **mehreren festen Werten** vergleichst, geht es einfacher: mit der **Fallauswahl**. + +## So ist die Fallauswahl aufgebaut + +Oben im Kasten steht die Variable, nach der ausgewählt wird. Darunter steht für jeden Fall eine eigene Spalte. Über jeder Spalte steht der Wert, zu dem sie gehört. + +::: diagramm l09-automat.visustruct +Derselbe Automat als Fallauswahl. Hat wahl den Wert 2, wird nur die Spalte 2 ausgeführt. +::: + +- Die Simulation sucht den Fall, dessen Name genau zum Wert passt. +- Passt kein Fall, wird **default** ausgeführt. Dieser Fall steht immer ganz rechts. +- Danach geht es unter der Fallauswahl weiter. Es wird immer nur **ein** Fall ausgeführt. + +> Eine neue Fallauswahl hat die Fälle 1, 2 und default. Klicke einen Fall an, um im Objektinspektor seinen **Fallnamen** zu ändern. Mit **Weiteren Fall hinzufügen** bekommst du eine neue Spalte vor default. + +## Fälle mit Texten + +Die Fälle müssen keine Zahlen sein. Du kannst auch nach dem Inhalt einer \`String\`-Variablen auswählen. Als Fallname schreibst du dann den Text, zum Beispiel \`rot\`. + +::: diagramm l09-ampel.visustruct +Eine Ampel: Je nach eingegebener Farbe erscheint ein anderer Hinweis. Probiere in der Simulation auch eine Farbe aus, die es nicht gibt. +::: + +Groß- und Kleinschreibung zählt: \`Rot\` passt nicht zum Fall \`rot\`. + +## Übung: Note in Worten + +::: übung l09-note +titel: Note in Worten +auftrag: Frage eine Note als ganze Zahl ab und gib sie in Worten aus: 1 sehr gut, 2 gut, 3 befriedigend, 4 ausreichend, 5 mangelhaft, 6 ungenügend. + Bei jeder anderen Zahl soll **Keine gültige Note** erscheinen. +test: 1 -> sehr gut +test: 4 -> ausreichend +test: 6 -> ungenügend +test: 9 -> Keine gültige Note +braucht: fallauswahl +tipp: Für viele feste Werte ist die Fallauswahl übersichtlicher als viele Verzweigungen. Jede Note bekommt ihren eigenen Fall. +tipp: Füge mit „Weiteren Fall hinzufügen“ so lange Fälle hinzu, bis du die Fälle 1 bis 6 und default hast. Oben in die Fallauswahl schreibst du \`note\`. +lösung: l09-note-loesung.visustruct +::: + +## Übung: Taschenrechner + +::: übung l09-rechner +titel: Taschenrechner +auftrag: Frage nacheinander eine ganze Zahl \`a\`, ein Rechenzeichen als \`String\` und eine zweite ganze Zahl \`b\` ab. + Bei \`+\`, \`-\` und \`*\` gibst du das Ergebnis aus. Bei jedem anderen Zeichen erscheint **Unbekanntes Rechenzeichen**. +test: 3, +, 4 -> 7 +test: 10, -, 4 -> 6 +test: 6, *, 7 -> 42 +test: 1, x, 2 -> Unbekanntes Rechenzeichen +braucht: fallauswahl +tipp: Lies erst alle drei Werte ein. Danach entscheidet eine Fallauswahl über das Rechenzeichen, was gerechnet wird. +tipp: Lege vor der Fallauswahl \`int ergebnis = 0\` an. In jedem Fall rechnest du zum Beispiel \`ergebnis = a + b\` und gibst danach \`ergebnis\` aus. Die Fallnamen sind einfach \`+\`, \`-\` und \`*\`. +lösung: l09-rechner-loesung.visustruct +::: + +## Fallauswahl oder Verzweigung? + +Die Fallauswahl prüft nur, ob ein Wert **genau gleich** einem Fallnamen ist. Daraus folgt: + +- **Fallauswahl:** eine Variable, mehrere feste Werte. Beispiele: Menüauswahl, Wochentag als Zahl, Noten. +- **Verzweigung:** Bereiche und verknüpfte Bedingungen. Beispiele: \`alter >= 18\`, \`temperatur < 0 || temperatur > 30\`. + +Für „Alter ab 18“ brauchst du also weiter die Verzweigung. Du kannst nicht für jedes mögliche Alter einen eigenen Fall anlegen. + +## Jetzt in Java + +Der Getränkeautomat sieht in Java so aus: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("1 Wasser, 2 Saft, 3 Kakao"); +int wahl = scanner.nextInt(); +switch (wahl) { + case 1 -> { + System.out.println("Hier ist dein Wasser."); + } + case 2 -> { + System.out.println("Hier ist dein Saft."); + } + case 3 -> { + System.out.println("Hier ist dein Kakao."); + } + default -> { + System.out.println("Diese Taste gibt es nicht."); + } +} +\`\`\` + +- Nach \`switch\` steht in runden Klammern die Variable, die verglichen wird. +- Jeder Fall beginnt mit \`case\`, dem Wert und einem Pfeil \`->\`. Dahinter steht in geschweiften Klammern, was passieren soll. +- \`default\` ist der Sonst-Fall. Er läuft, wenn kein Wert passt. + +::: angeberwissen +Den Pfeil \`case 1 ->\` gibt es in Java erst seit 2020 (Java 14). Davor schrieb man \`case 1:\` und musste jeden Fall mit \`break;\` beenden. Wer das vergaß, lief einfach in den nächsten Fall weiter. Der Pfeil hat also sehr vielen Programmierern Ärger erspart. +::: + +::: übung l10-java-wuerfel +titel: Würfel in Worten +code: java +auftrag: Schreibe ein Java-Programm mit \`switch\`, das eine Zahl einliest. Bei 1 gibt es **eins** aus, bei 2 **zwei**, bei 3 **drei** und sonst **kenne ich nicht**. +test: 1 -> eins +test: 2 -> zwei +test: 3 -> drei +test: 7 -> kenne ich nicht +braucht: fallauswahl +tipp: Du brauchst drei \`case\`-Fälle und einen \`default\`-Fall. +tipp: \`switch (zahl) { case 1 -> { System.out.println("eins"); } … default -> { System.out.println("kenne ich nicht"); } }\` +lösung: l10-java-wuerfel-loesung.visustruct +::: + +## Lückentext: switch + +::: lückentext +titel: Monate in Worten +auftrag: Ergänze die fehlenden Wörter und Zeichen der Fallauswahl. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Welcher Monat (1 bis 3)?"); +int monat = scanner.nextInt(); +[[switch]] (monat) { + [[case]] 1 -> { + System.out.println("Januar"); + } + case 2 [[->]] { + System.out.println("Februar"); + } + [[case]] 3 -> { + System.out.println("März"); + } + [[default]] -> { + System.out.println("Kenne ich nicht"); + } +} +\`\`\` +erklärung: Nach \`switch\` steht die Variable in runden Klammern. Jeder Fall beginnt mit \`case\`, dem Wert und dem Pfeil \`->\`. \`default\` läuft, wenn kein Fall passt. +::: + +## Fehler finden: Rechner + +::: übung l10-java-fehler +titel: Rechner reparieren +code: java +auftrag: Der Rechner liest zwei Zahlen und eine Wahl ein: 1 plus, 2 minus, 3 mal. Bei 7, 3 und Wahl 2 soll **4** herauskommen, er rechnet aber **-4**. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l10-java-fehler-start.visustruct +test: 7, 3, 2 -> 4 +test: 7, 3, 1 -> 10 +test: 7, 3, 3 -> 21 +test: 7, 3, 5 -> Gibt es nicht +test: 10, 4, 2 -> 6 +braucht: fallauswahl +tipp: Plus und mal stimmen. Schau dir den Fall \`case 2\` genau an. +tipp: Beim Minus zählt die Reihenfolge: \`a - b\` statt \`b - a\`. +lösung: l10-java-fehler-loesung.visustruct +::: + +## Spiel: Welcher Fall? + +::: spiel frage +titel: Spiel: Welcher Fall? +intro: Ludwig drückt Tasten am Getränkeautomaten und an anderen Fallauswahlen. Was passiert? Sechs Runden. + +runde: + int wahl = 2; + switch (wahl) { + case 1 -> { System.out.println("Wasser"); } + case 2 -> { System.out.println("Saft"); } + case 3 -> { System.out.println("Kakao"); } + default -> { System.out.println("Diese Taste gibt es nicht."); } + } +frage: Was wird ausgegeben? +- Wasser +- [x] Saft +- Diese Taste gibt es nicht. +> wahl ist 2, also läuft genau der Fall \`case 2\`. + +runde: + int wahl = 4; + switch (wahl) { + case 1 -> { System.out.println("Wasser"); } + case 2 -> { System.out.println("Saft"); } + case 3 -> { System.out.println("Kakao"); } + default -> { System.out.println("Diese Taste gibt es nicht."); } + } +frage: Was wird ausgegeben? +- Kakao +- nichts +- [x] Diese Taste gibt es nicht. +> Kein Fall passt zu 4, also läuft \`default\`. + +runde: + String tag = "montag"; + switch (tag) { + case "Montag" -> { System.out.println("Mathe"); } + case "Dienstag" -> { System.out.println("Sport"); } + default -> { System.out.println("frei"); } + } +frage: Was wird ausgegeben? +- Mathe +- Sport +- [x] frei +> Bei Texten zählt jeder Buchstabe: "montag" mit kleinem m ist nicht "Montag". + +runde: + int note = 0; + switch (note) { + case 1 -> { System.out.println("sehr gut"); } + case 2 -> { System.out.println("gut"); } + case 3 -> { System.out.println("befriedigend"); } + } +frage: Was wird ausgegeben? +- sehr gut +- [x] nichts +- befriedigend +> Kein Fall passt, und es gibt kein \`default\`. Dann passiert einfach nichts. + +runde: +frage: Du willst prüfen, ob \`alter >= 18\` ist. Was passt besser? +- [x] eine Verzweigung +- eine Fallauswahl +> Eine Fallauswahl vergleicht nur mit festen Werten. Für „größer oder gleich“ brauchst du eine Verzweigung. + +runde: +frage: Ein Würfel zeigt 1 bis 6, und für jede Zahl soll ein anderes Wort erscheinen. Was passt besser? +- eine Verzweigung +- [x] eine Fallauswahl +> Eine Variable, sechs feste Werte: genau dafür ist die Fallauswahl da. +::: + +## 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. + +::: checkliste +- Ich kann eine Fallauswahl einfügen, Fälle hinzufügen und Fallnamen ändern. → So ist die Fallauswahl aufgebaut +- Ich kann erklären, wann der Fall default ausgeführt wird. → So ist die Fallauswahl aufgebaut +- Ich kann entscheiden, ob eine Fallauswahl oder eine Verzweigung besser passt. → Fallauswahl oder Verzweigung? +- Ich kann eine Fallauswahl in Java mit switch schreiben. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Die Variable tag hat den Wert 5. Es gibt die Fälle 1, 2, 3 und default. Was wird ausgeführt? +→ So ist die Fallauswahl aufgebaut +- [ ] Gar nichts +- [ ] Der Fall 3 +- [x] Der Fall default +> Kein Fallname passt zu 5, deshalb greift default. + +? Wie viele Fälle werden bei einem Durchlauf der Fallauswahl ausgeführt? +→ So ist die Fallauswahl aufgebaut +- [x] Genau einer +- [ ] Alle Fälle ab dem passenden +- [ ] Alle Fälle +> Nach dem passenden Fall geht es direkt unter der Fallauswahl weiter. + +? Wofür ist eine Fallauswahl NICHT geeignet? +→ Fallauswahl oder Verzweigung? +- [ ] Menüpunkt 1, 2 oder 3 auswählen +- [x] Prüfen, ob eine Temperatur über 30 Grad liegt +- [ ] Eine Farbe wie rot, gelb oder grün auswerten +> „Über 30“ ist ein Bereich. Dafür brauchst du eine Verzweigung mit einem Vergleich. + +? Du gibst bei der Ampel \`Rot\` ein, der Fall heißt \`rot\`. Was passiert? +→ So ist die Fallauswahl aufgebaut +- [ ] Der Fall rot wird ausgeführt. +- [x] Der Fall default wird ausgeführt. +- [ ] Die Simulation meldet einen Fehler. +> Groß- und Kleinschreibung zählt. Rot und rot sind verschiedene Texte. + +? Unter welchem Namen findest du die Fallauswahl auch in Schulbüchern? +→ So ist die Fallauswahl aufgebaut +- [ ] Bedingte Anweisung +- [ ] Sequenz +- [x] Mehrfachauswahl +> Aus vielen Fällen wird einer ausgewählt. Darum heißt sie auch Mehrfachauswahl. + +? Wie heißt in Java der Sonst-Fall einer Fallauswahl? +→ Jetzt in Java +- [ ] else +- [x] default +- [ ] case 0 +::: +`,kx=`--- +titel: While-Schleife +bereich: Grundlagen +kurz: Schritte wiederholen, solange eine Bedingung wahr ist. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, dass die While-Schleife ihre Bedingung vor jedem Durchlauf prüft +- eine Zählvariable mit Startwert, Bedingung und Veränderung verwenden +- erkennen, wenn eine Schleife nie endet, und den Fehler beheben +- eine Schleife im Schreibtischtest Durchlauf für Durchlauf verfolgen +- eine While-Schleife in Java schreiben +::: + +## Wiederholen, solange etwas gilt + +Oft soll ein Programm etwas mehrmals tun. Statt denselben Kasten fünfmal hinzuschreiben, nimmst du eine **Schleife**. + +Die **While-Schleife** wiederholt ihren Inhalt, **solange** ihre Bedingung wahr ist. Die Bedingung steht oben im Kopf des Kastens. Der Inhalt steht eingerückt darunter, links von einer Klammer eingefasst. + +::: diagramm l10-countdown.visustruct +Ein Countdown: Solange zahl größer als 0 ist, wird zahl ausgegeben und um 1 kleiner. Danach erscheint Start! +::: + +## Die Bedingung kommt zuerst + +Die While-Schleife ist **kopfgesteuert**. Vor **jedem** Durchlauf wird die Bedingung geprüft: + +1. Bedingung prüfen. +2. Ist sie wahr, den Inhalt einmal ausführen und wieder bei 1 anfangen. +3. Ist sie falsch, geht es unter der Schleife weiter. + +::: grafik l10-kopfgesteuert.svg +Nach jedem Durchlauf geht es zurück zur Bedingung. Erst wenn sie false ist, geht es unter der Schleife weiter. +::: + +Im Countdown wird die Bedingung viermal geprüft: bei 3, 2 und 1 ist sie wahr, bei 0 ist sie falsch. + +> Ist die Bedingung schon beim ersten Prüfen falsch, wird der Inhalt **kein einziges Mal** ausgeführt. Starte den Countdown mit \`int zahl = 0\`, dann erscheint nur Start! + +## Eine Zählvariable + +Viele Schleifen zählen mit. Dafür brauchst du drei Dinge: + +- **Startwert vor der Schleife**, z. B. \`int i = 1\` +- **Bedingung im Kopf**, z. B. \`i <= 5\` +- **Veränderung im Inhalt**, z. B. \`i = i + 1\` (kurz \`i++\`) + +Fehlt einer dieser Teile, zählt die Schleife falsch oder gar nicht. + +::: angeberwissen +Zählschleifen sind uralt! Im Artikel von 1973 haben Nassi und Shneiderman ihre Idee unter anderem an der **Fakultät** gezeigt: 5! = 1 · 2 · 3 · 4 · 5 = 120. Hier ist meine Ziegen-Version davon. Probier sie mit **Schritt** in der Simulation aus und schau zu, wie \`fakultaet\` wächst. Määäh, das geht schnell! +::: + +::: diagramm l10-fakultaet.visustruct +Die Fakultät mit einer Zählvariable \`i\`, nachgebaut nach einem Beispiel aus dem Artikel von 1973. +::: + +## Übung: Zählen bis n + +::: übung l10-bis-n +titel: Zählen bis n +auftrag: Frage eine ganze Zahl \`n\` ab und gib alle Zahlen von 1 bis \`n\` aus, jede in einer eigenen Zeile. +test: 3 -> 1 | 2 | 3 +test: 5 -> 1 | 2 | 3 | 4 | 5 +test: 1 -> 1 +braucht: whileSchleife +tipp: Du brauchst eine Zählvariable, die bei 1 beginnt und in jedem Durchlauf um 1 wächst. +tipp: Lege vor der Schleife \`int i = 1\` an. Die Bedingung ist \`i <= n\`. Im Inhalt gibst du \`i\` aus und erhöhst danach \`i\` um 1. +lösung: l10-bis-n-loesung.visustruct +::: + +## Vorsicht, Endlosschleife + +Wenn sich im Inhalt nichts an der Bedingung ändert, bleibt sie für immer wahr. Die Schleife hört nie auf. Das nennt man **Endlosschleife**. + +::: diagramm l10-endlos.visustruct +Hier fehlt zahl = zahl - 1. Die Schleife gibt immer wieder 3 aus und erreicht Start! nie. +::: + +Frage dich bei jeder Schleife: **Was im Inhalt sorgt dafür, dass die Bedingung irgendwann falsch wird?** Beim Prüfen einer Übung bricht VisuStruct nach sehr vielen Schritten ab und meldet eine mögliche Endlosschleife. + +## Übung: Verdoppeln bis 100 + +::: übung l10-verdoppeln +titel: Verdoppeln bis 100 +auftrag: Frage eine ganze Zahl ab. Verdopple sie so lange, bis sie mindestens 100 ist. + Gib am Ende aus, **wie oft** du verdoppelt hast. +test: 10 -> 4 +test: 30 -> 2 +test: 1 -> 7 +test: 100 -> 0 +braucht: whileSchleife +tipp: Die Schleife läuft, solange die Zahl noch zu klein ist. Zähle nebenbei mit, wie oft sie gelaufen ist. +tipp: Du brauchst eine zweite Variable \`int schritte = 0\`. Die Bedingung lautet \`zahl < 100\`. Im Inhalt verdoppelst du die Zahl mit \`zahl = zahl * 2\` und erhöhst \`schritte\` um 1. Ist die Zahl schon 100, läuft die Schleife gar nicht. +lösung: l10-verdoppeln-loesung.visustruct +::: + +## Schleifen im Schreibtischtest + +Bei einer Schleife wird der **Schreibtischtest** besonders wertvoll. Du siehst genau, wie oft die Schleife läuft und mit welchem Wert sie aufhört. Jede Prüfung der Bedingung bekommt eine eigene Zeile. + +::: diagramm l16-schreibtisch.visustruct +Eine While-Schleife zählt die Zahlen 1, 2 und 3 zusammen. +::: + +| Schritt | summe | i | Ausgabe | +|---|---|---|---| +| \`int summe = 0\` | 0 | – | | +| \`int i = 1\` | 0 | 1 | | +| \`i <= 3\` → wahr | 0 | 1 | | +| \`summe = summe + i\` | 1 | 1 | | +| \`i = i + 1\` | 1 | 2 | | +| \`i <= 3\` → wahr | 1 | 2 | | +| \`summe = summe + i\` | 3 | 2 | | +| \`i = i + 1\` | 3 | 3 | | +| \`i <= 3\` → wahr | 3 | 3 | | +| \`summe = summe + i\` | 6 | 3 | | +| \`i = i + 1\` | 6 | 4 | | +| \`i <= 3\` → falsch | 6 | 4 | | +| \`output: summe\` | 6 | 4 | 6 | + +Häufige Fehler in Schleifen sind: + +- Die Schleife läuft **einmal zu oft oder zu wenig**, z. B. \`<\` statt \`<=\`. +- Eine Variable wird in der Schleife **nicht verändert** oder in die falsche Richtung. Dann endet die Schleife nie. +- Eine Variable bekommt ihren Startwert **in** der Schleife statt davor und wird bei jedem Durchlauf zurückgesetzt. + +## Übung: Countdown reparieren + +::: übung l16-countdown +titel: Countdown reparieren +auftrag: Der Countdown soll vom Startwert herunterzählen und am Ende **Los!** ausgeben. Bei 3 also 3, 2, 1, Los! + Im Startdiagramm stecken zwei Fehler. Finde und behebe beide. +start: l16-countdown-start.visustruct +test: 3 -> 3 | 2 | 1 | Los! +test: 1 -> 1 | Los! +test: 0 -> Los! +tipp: Es gibt zwei Fehler. Einer betrifft das Zählen, der andere die Ausgabe am Ende. +tipp: Starte die Simulation mit Startwert 3 und beobachte i unter Variablen. Wird i kleiner? Vergleiche außerdem die letzte Ausgabe genau mit dem Auftrag. +lösung: l16-countdown-loesung.visustruct +::: + +## Jetzt in Java + +Der Countdown vom Anfang dieser Lektion sieht in Java so aus: + +\`\`\`java +int zahl = 3; +while (zahl > 0) { + System.out.println(zahl); + zahl = zahl - 1; +} +System.out.println("Start!"); +\`\`\` + +- Nach \`while\` steht die Bedingung in runden Klammern, wie bei \`if\`. +- Alles, was wiederholt wird, steht in geschweiften Klammern. Das ist der Rumpf der Schleife. +- Der Rumpf ist eingerückt. So erkennst du wie im Struktogramm, was zur Schleife gehört. + +::: übung l11-java-gerade +titel: Gerade Zahlen in Java +code: java +auftrag: Schreibe ein Java-Programm, das eine ganze Zahl \`n\` einliest und mit einer While-Schleife alle geraden Zahlen von 2 bis höchstens \`n\` ausgibt. Bei 7 also 2, 4 und 6. +test: 7 -> 2 | 4 | 6 +test: 8 -> 2 | 4 | 6 | 8 +test: 2 -> 2 +braucht: whileSchleife +tipp: Du brauchst eine Zählvariable, die bei 2 beginnt. Die Schleife läuft, solange sie nicht größer als \`n\` ist. +tipp: \`int zahl = 2;\` vor der Schleife, dann \`while (zahl <= n) { … }\`. Im Rumpf gibst du \`zahl\` aus und erhöhst sie mit \`zahl = zahl + 2;\`. +lösung: l11-java-gerade-loesung.visustruct +::: + +## Lückentext: while + +::: lückentext +titel: Summe von 1 bis 10 +auftrag: Das Programm soll die Zahlen von 1 bis 10 zusammenzählen. Ergänze die fehlenden Wörter und Zeichen. +\`\`\`java +int summe = 0; +int zahl = 1; +[[while]] (zahl [[<=]] 10) [[{]] + summe = summe + [[zahl]]; + [[zahl]] = zahl + 1; +} +System.out.println("Summe: " + summe); +\`\`\` +erklärung: Die Schleife läuft, solange \`zahl\` höchstens 10 ist. In jedem Durchlauf kommt \`zahl\` zur Summe dazu, danach wird \`zahl\` um 1 größer. Ohne diese Zeile wäre es eine Endlosschleife. Ausgabe: **Summe: 55** +::: + +## Fehler finden: Sparen + +::: übung l11-java-fehler +titel: Sparplan reparieren +code: java +auftrag: Ludwig spart jede Woche 5 Euro. Das Programm fragt nach dem Sparziel und soll ausgeben, nach wie vielen Wochen er es erreicht hat. Bei 50 Euro sind das 10 Wochen, das Programm sagt aber **Wochen: 11**. + Gehe den Code mit dem Einzelschritt durch und beobachte \`geld\` und \`wochen\`. Repariere den Fehler und klicke auf Prüfen. +start: l11-java-fehler-start.visustruct +test: 50 -> Wochen: 10 +test: 12 -> Wochen: 3 +test: 5 -> Wochen: 1 +test: 1 -> Wochen: 1 +braucht: whileSchleife +tipp: Wie viel Geld hat Ludwig, wenn die Schleife zum letzten Mal läuft? Muss er dann wirklich noch eine Woche sparen? +tipp: Gespart wird nur, solange das Ziel noch **nicht erreicht** ist: \`while (geld < ziel)\`. +lösung: l11-java-fehler-loesung.visustruct +::: + +## Spiel: Wie oft? + +::: spiel frage +titel: Spiel: Wie oft? +intro: Ludwig hat While-Schleifen geschrieben. Mach im Kopf den Schreibtischtest. Sechs Runden. + +runde: + int zahl = 3; + while (zahl > 0) { + System.out.println(zahl); + zahl = zahl - 1; + } + System.out.println("Start!"); +frage: Was wird ausgegeben? +- [x] 3\\n2\\n1\\nStart! +- 3\\n2\\n1\\n0\\nStart! +- Start! +> Bei zahl gleich 0 ist \`zahl > 0\` falsch, die 0 wird also nicht mehr ausgegeben. + +runde: + int i = 10; + while (i < 5) { + System.out.println(i); + i = i + 1; + } +frage: Was wird ausgegeben? +- [x] nichts +- 10 +- 10 bis 4 +> Die Bedingung wird zuerst geprüft. 10 < 5 ist falsch, der Rumpf läuft kein einziges Mal. + +runde: + int i = 1; + while (i <= 3) { + System.out.println(i); + } +frage: Was passiert? +- 1, 2 und 3 werden ausgegeben. +- [x] Die Schleife hört nie auf. +- Es wird nichts ausgegeben. +> i wird im Rumpf nie größer. Die Bedingung bleibt immer wahr: eine Endlosschleife. + +runde: + int zahl = 1; + while (zahl < 100) { + zahl = zahl * 2; + } + System.out.println(zahl); +frage: Was wird ausgegeben? +- 64 +- 100 +- [x] 128 +> 1, 2, 4, 8, 16, 32, 64, 128. Erst bei 128 ist \`zahl < 100\` falsch. + +runde: + int i = 0; + while (i < 5) { + i = i + 2; + } + System.out.println(i); +frage: Was wird ausgegeben? +- 4 +- 5 +- [x] 6 +> i läuft 0, 2, 4, 6. Bei 6 ist \`i < 5\` falsch. Die 5 wird übersprungen. + +runde: + int i = 1; + while (i <= 10) { + i = i + 3; + } +frage: Wie oft läuft der Rumpf? +- 3-mal +- [x] 4-mal +- 10-mal +> Der Rumpf läuft bei i = 1, 4, 7 und 10. Danach ist i 13. +::: + +## 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. + +::: checkliste +- Ich kann erklären, dass die While-Schleife ihre Bedingung vor jedem Durchlauf prüft. → Die Bedingung kommt zuerst +- Ich kann eine Zählvariable mit Startwert, Bedingung und Veränderung verwenden. → Eine Zählvariable +- Ich kann erkennen, wenn eine Schleife nie endet, und den Fehler beheben. → Vorsicht, Endlosschleife +- Ich kann eine Schleife im Schreibtischtest Durchlauf für Durchlauf verfolgen. → Schleifen im Schreibtischtest +- Ich kann eine While-Schleife in Java schreiben. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Was bedeutet kopfgesteuert? +→ Die Bedingung kommt zuerst +- [x] Die Bedingung wird vor jedem Durchlauf geprüft. +- [ ] Die Bedingung wird nach jedem Durchlauf geprüft. +- [ ] Die Schleife läuft immer genau einmal. +> Der Kopf mit der Bedingung steht oben und wird zuerst ausgewertet. + +? \`int i = 5\`, danach eine While-Schleife mit der Bedingung \`i < 3\`. Wie oft läuft der Inhalt? +→ Die Bedingung kommt zuerst +- [x] Keinmal +- [ ] Einmal +- [ ] Dreimal +> Schon beim ersten Prüfen ist 5 < 3 falsch. + +? Warum endet eine Schleife mit der Bedingung \`zahl > 0\` nie, wenn im Inhalt nur \`output: zahl\` steht? +→ Vorsicht, Endlosschleife +- [ ] Weil output die Zahl vergrößert +- [x] Weil sich zahl nie ändert und die Bedingung wahr bleibt +- [ ] Weil die Bedingung falsch geschrieben ist +> Im Inhalt muss etwas passieren, das die Bedingung irgendwann falsch macht. + +? Wie nennt man Schleifen in Schulbüchern auch? +→ Die Bedingung kommt zuerst +- [x] Wiederholungsstrukturen +- [ ] Verzweigungen +- [ ] Unterprogramme +> Eine Schleife wiederholt Anweisungen. Darum heißt sie auch Wiederholungsstruktur. + +? Eine Schleife soll von 1 bis 5 zählen, läuft aber nur bis 4. Was ist der wahrscheinliche Fehler? +→ Eine Zählvariable +- [x] In der Bedingung steht i < 5 statt i <= 5. +- [ ] Die Schleife ist eine While-Schleife. +- [ ] Die Variable i heißt falsch. + +? Welche Zeile startet in Java eine While-Schleife richtig? +→ Jetzt in Java +- [ ] while zahl > 0 { +- [x] while (zahl > 0) { +- [ ] while (zahl > 0); +> Die Bedingung steht in runden Klammern, danach öffnet \`{\` den Rumpf. +::: +`,Sx=`--- +titel: Do-while-Schleife +bereich: Grundlagen +kurz: Erst ausführen, dann prüfen: Schleifen mit mindestens einem Durchlauf. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, dass die Do-while-Schleife ihre Bedingung erst nach dem Inhalt prüft +- erklären, warum der Inhalt mindestens einmal ausgeführt wird +- eine Eingabe so lange wiederholen lassen, bis sie gültig ist +- eine Do-while-Schleife in Java schreiben +::: + +## Erst machen, dann prüfen + +Die **Do-while-Schleife** ist **fußgesteuert**. Die Bedingung steht unten im Fuß des Kastens. Der Ablauf ist: + +1. Den Inhalt einmal ausführen. +2. Die Bedingung prüfen. +3. Ist sie wahr, wieder bei 1 anfangen. Ist sie falsch, geht es unter der Schleife weiter. + +::: grafik l11-vergleich.svg +Links prüft die While-Schleife zuerst, rechts führt die Do-while-Schleife zuerst aus. +::: + +Oben im Kasten steht \`do\`, unten im Fuß die Bedingung. Wenn du die Schleife anklickst, steht im Objektinspektor vor dem Textfeld das Wort \`while\`: Die Bedingung bedeutet „wiederhole, solange …“. + +> Die Bedingung sagt wie bei der While-Schleife, **wann wiederholt wird**. Solange sie wahr ist, läuft die Schleife weiter. + +::: angeberwissen +Python hat gar keine Do-while-Schleife. Wer dort „erst machen, dann prüfen“ will, schreibt \`while True:\` und verlässt die Schleife mit \`break\`. Java, C und JavaScript haben \`do … while\` dagegen schon seit Jahrzehnten. +::: + +## Mindestens ein Durchlauf + +Weil die Bedingung erst am Ende geprüft wird, läuft der Inhalt **immer mindestens einmal**. Das ist der wichtigste Unterschied zur While-Schleife. + +::: diagramm l11-einmal.visustruct +i ist 10 und damit nicht kleiner als 5. Trotzdem wird 10 einmal ausgegeben, denn geprüft wird erst danach. +::: + +Mit einer While-Schleife und derselben Bedingung \`i < 5\` würde hier gar nichts ausgegeben. + +## Typisch: Eingabe wiederholen + +Die Do-while-Schleife passt immer dann, wenn etwas zuerst passieren muss, bevor man es prüfen kann. Das beste Beispiel ist eine Eingabe: Erst wenn jemand etwas eingegeben hat, weißt du, ob es gültig ist. + +::: diagramm l11-eingabe-pruefen.visustruct +Die Frage kommt so lange wieder, bis eine Zahl von 1 bis 10 eingegeben wurde. Probiere in der Simulation zuerst 0 und dann 12 aus. +::: + +Die Bedingung beschreibt hier die **ungültige** Eingabe: \`zahl < 1 || zahl > 10\`. Solange die Eingabe ungültig ist, wird noch einmal gefragt. + +## Übung: Gültige Note + +::: übung l11-note +titel: Gültige Note +auftrag: Frage eine Note ab. Ist sie nicht zwischen 1 und 6, frage noch einmal. Ist sie gültig, gib sie aus, zum Beispiel **Deine Note: 3**. +test: 3 -> Deine Note: 3 +test: 0, 7, 2 -> Deine Note: 2 +test: 9, 6 -> Deine Note: 6 +test: -1, 1 -> Deine Note: 1 +braucht: doUntilSchleife +tipp: Die Note wird mindestens einmal abgefragt. Danach entscheidet die Bedingung, ob noch einmal gefragt wird. +tipp: Lege vor der Schleife \`int note = 0\` an. In die Schleife kommt die Eingabe \`input: note "Note von 1 bis 6"\`. Die Bedingung lautet \`note < 1 || note > 6\`. +lösung: l11-note-loesung.visustruct +::: + +## Übung: Summe bis 0 + +::: übung l11-summe +titel: Summe bis 0 +auftrag: Frage so lange Zahlen ab, bis eine 0 eingegeben wird. Gib danach die Summe aller eingegebenen Zahlen aus. +test: 3, 4, 0 -> 7 +test: 10, 0 -> 10 +test: 5, 5, 5, 0 -> 15 +test: 0 -> 0 +braucht: doUntilSchleife +tipp: Du brauchst eine Variable für die Summe, die vor der Schleife bei 0 beginnt. In jedem Durchlauf kommt die neue Zahl dazu. +tipp: Lege vor der Schleife \`int summe = 0\` und \`int zahl = 0\` an. In der Schleife fragst du \`zahl\` ab und rechnest \`summe = summe + zahl\`. Die 0 zu addieren schadet nicht. Die Schleife läuft weiter, solange \`zahl != 0\` ist. +lösung: l11-summe-loesung.visustruct +::: + +## Jetzt in Java + +Die Schleife, die trotzdem einmal läuft, sieht in Java so aus: + +\`\`\`java +int i = 10; +do { + System.out.println(i); + i = i + 1; +} while (i < 5); +\`\`\` + +- Der Rumpf steht zwischen \`do {\` und \`}\`, die Bedingung kommt erst danach. +- Hinter \`while (…)\` steht hier ein **Semikolon**. Das ist anders als bei der While-Schleife. + +::: übung l12-java-verdoppeln +titel: Mindestens einmal verdoppeln +code: java +auftrag: Schreibe ein Java-Programm, das eine Startzahl einliest. Mit einer Do-while-Schleife wird sie verdoppelt und ausgegeben, solange sie kleiner als 100 ist. Auch eine Zahl ab 100 wird mindestens einmal verdoppelt: Aus 200 wird 400. +test: 30 -> 60 | 120 +test: 200 -> 400 +test: 13 -> 26 | 52 | 104 +braucht: doUntilSchleife +tipp: Im Rumpf verdoppelst du die Zahl und gibst sie aus. Die Bedingung steht am Ende. +tipp: \`do { zahl = zahl * 2; System.out.println(zahl); } while (zahl < 100);\` +lösung: l12-java-verdoppeln-loesung.visustruct +::: + +## Lückentext: do-while + +::: lückentext +titel: Verdreifachen +auftrag: Die Zahl wird verdreifacht und ausgegeben, solange sie kleiner als 100 ist. Ergänze die fehlenden Wörter und Zeichen. +\`\`\`java +int zahl = 1; +[[do]] { + zahl = zahl * 3; + System.out.println(zahl); +} [[while]] (zahl [[<]] 100)[[;]] +\`\`\` +erklärung: Der Rumpf steht zwischen \`do {\` und \`}\`, die Bedingung erst danach. Hinter \`while (…)\` steht bei der Do-while-Schleife ein Semikolon. Ausgabe: 3, 9, 27, 81 und 243. +::: + +## Fehler finden: Halbieren + +::: übung l12-java-fehler +titel: Halbieren reparieren +code: java +auftrag: Das Programm liest eine Startzahl ein und teilt sie mit einer Do-while-Schleife immer wieder ganzzahlig durch 2. Jedes Ergebnis wird ausgegeben, bis **0** erreicht ist. Bei 10 also 5, 2, 1 und 0. Die 0 fehlt aber. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l12-java-fehler-start.visustruct +test: 10 -> 5 | 2 | 1 | 0 +test: 1 -> 0 +test: 7 -> 3 | 1 | 0 +test: 20 -> 10 | 5 | 2 | 1 | 0 +braucht: doUntilSchleife +tipp: Welchen Wert hat \`zahl\`, nachdem die 1 ausgegeben wurde? Läuft die Schleife dann noch einmal? +tipp: Die Schleife soll weiterlaufen, solange die Zahl größer als 0 ist: \`while (zahl > 0);\` +lösung: l12-java-fehler-loesung.visustruct +::: + +## Spiel: Mindestens einmal? + +::: spiel frage +titel: Spiel: Mindestens einmal? +intro: While oder do-while? Ludwig zeigt dir Schleifen. Sag vorher, was passiert. Sechs Runden. + +runde: + int i = 10; + do { + System.out.println(i); + i = i + 1; + } while (i < 5); +frage: Was wird ausgegeben? +- nichts +- [x] 10 +- 10 bis 4 +> Erst machen, dann prüfen: Der Rumpf läuft einmal, danach ist 11 < 5 falsch. + +runde: + int i = 10; + while (i < 5) { + System.out.println(i); + i = i + 1; + } +frage: Was wird ausgegeben? +- [x] nichts +- 10 +- 11 +> Bei der While-Schleife kommt die Bedingung zuerst. 10 < 5 ist falsch, also läuft gar nichts. + +runde: + int zahl = 200; + do { + zahl = zahl * 2; + } while (zahl < 100); + System.out.println(zahl); +frage: Was wird ausgegeben? +- 200 +- [x] 400 +- 800 +> Einmal wird auf jeden Fall verdoppelt. Danach ist 400 < 100 falsch. + +runde: + int zahl = 30; + do { + zahl = zahl * 2; + System.out.println(zahl); + } while (zahl < 100); +frage: Was wird ausgegeben? +- 60 +- [x] 60\\n120 +- 60\\n120\\n240 +> Nach 60 ist 60 < 100 wahr, es geht weiter. Nach 120 ist Schluss. + +runde: +frage: Welche Zeile beendet eine Do-while-Schleife in Java richtig? +- [x] \`} while (i < 5);\` +- \`} while (i < 5)\` +- \`while (i < 5) {\` +> Hinter dem \`while (…)\` der Do-while-Schleife steht ein Semikolon. + +runde: +frage: Wofür nimmt man typischerweise eine Do-while-Schleife? +- [x] eine Eingabe wiederholen, bis sie gültig ist +- von 1 bis 10 zählen +- zwei Werte tauschen +> Gefragt wird mindestens einmal. Erst danach weiß man, ob die Eingabe gültig war. +::: + +## 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. + +::: checkliste +- Ich kann erklären, dass die Do-while-Schleife ihre Bedingung erst nach dem Inhalt prüft. → Erst machen, dann prüfen +- Ich kann erklären, warum der Inhalt mindestens einmal ausgeführt wird. → Mindestens ein Durchlauf +- Ich kann eine Eingabe so lange wiederholen lassen, bis sie gültig ist. → Typisch: Eingabe wiederholen +- Ich kann eine Do-while-Schleife in Java schreiben. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Was bedeutet fußgesteuert? +→ Erst machen, dann prüfen +- [ ] Die Bedingung wird vor jedem Durchlauf geprüft. +- [x] Die Bedingung wird nach jedem Durchlauf geprüft. +- [ ] Die Schleife hat keine Bedingung. +> Die Bedingung steht im Fuß, also unten, und wird nach dem Inhalt ausgewertet. + +? Die Bedingung einer Do-while-Schleife ist von Anfang an falsch. Wie oft läuft der Inhalt? +→ Mindestens ein Durchlauf +- [ ] Keinmal +- [x] Genau einmal +- [ ] Endlos +> Der Inhalt läuft zuerst. Erst danach merkt die Schleife, dass sie aufhören soll. + +? Du willst eine Zahl von 1 bis 10 abfragen. Welche Bedingung gehört in den Fuß? +→ Typisch: Eingabe wiederholen +- [ ] \`zahl >= 1 && zahl <= 10\` +- [x] \`zahl < 1 || zahl > 10\` +- [ ] \`zahl == 10\` +> Wiederholt wird, solange die Eingabe ungültig ist, also kleiner als 1 oder größer als 10. + +? Wann ist eine Do-while-Schleife besser als eine While-Schleife? +→ Mindestens ein Durchlauf +- [x] Wenn der Inhalt auf jeden Fall einmal laufen muss, z. B. bei einer Eingabe +- [ ] Wenn die Schleife vielleicht gar nicht laufen soll +- [ ] Wenn man genau bis 10 zählen will + +? Was steht in Java am Ende einer Do-while-Schleife? +→ Jetzt in Java +- [ ] } while (bedingung) { +- [x] } while (bedingung); +- [ ] } until (bedingung); +> Nach der Bedingung kommt ein Semikolon. +::: +`,Tx=`--- +titel: For-Schleife +bereich: Grundlagen +kurz: Mit Start, Bedingung und Schritt eine feste Anzahl von Durchläufen zählen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- die drei Teile Start, Bedingung und Schritt der For-Schleife benennen +- erklären, in welcher Reihenfolge die drei Teile ausgeführt werden +- mit einer For-Schleife vorwärts, rückwärts und in größeren Schritten zählen +- eine For-Schleife in Java schreiben und ihre drei Felder erklären +::: + +## Zählen mit festem Plan + +In der While-Schleife hast du schon mitgezählt: Startwert vor der Schleife, Bedingung im Kopf, Veränderung im Inhalt. Die **For-Schleife** schreibt diese drei Teile zusammen in den Kopf. So siehst du auf einen Blick, wie gezählt wird. + +Wenn du eine For-Schleife anklickst, hat sie rechts drei Felder: + +- **Start:** \`int i = 1\` legt die Zählvariable an. +- **Bedingung:** \`i <= 5\` sagt, wie lange gezählt wird. +- **Schritt:** \`i++\` erhöht \`i\` nach jedem Durchlauf um 1. + +::: diagramm l12-eins-bis-fuenf.visustruct +Eine For-Schleife, die die Zahlen von 1 bis 5 ausgibt. +::: + +::: angeberwissen +Warum heißt die Zählvariable fast immer \`i\`? In der Mathematik steht \`i\` schon lange für einen Index. Und in FORTRAN, einer der ersten Programmiersprachen von 1957, waren alle Variablen, die mit I bis N anfingen, automatisch ganze Zahlen. Programmierer haben sich das bis heute nicht abgewöhnt. +::: + +## In welcher Reihenfolge? + +Die drei Teile kommen zu unterschiedlichen Zeiten dran: + +1. **Start** wird genau einmal ausgeführt, ganz am Anfang. +2. **Bedingung** wird vor jedem Durchlauf geprüft. Ist sie falsch, ist die Schleife fertig. +3. Nach dem Inhalt kommt der **Schritt**, dann wieder die Bedingung. + +::: grafik l12-for-ablauf.svg +Der Start kommt nur einmal dran. Danach wiederholen sich Bedingung, Inhalt und Schritt. +::: + +Die For-Schleife ist also kopfgesteuert wie die While-Schleife. Gehe das Beispiel in der Simulation mit **Schritt** durch und beobachte, wie sich \`i\` verändert. + +> Nimm die For-Schleife, wenn du schon vorher weißt, wie oft etwas passieren soll. Hängt das Ende von etwas ab, das erst während der Schleife passiert, zum Beispiel einer Eingabe, ist die While- oder Do-while-Schleife besser. + +## Beispiel: Summe von 1 bis n + +Eine For-Schleife eignet sich gut, um Zahlen aufzusummieren. Vor der Schleife steht \`int summe = 0\`. In jedem Durchlauf kommt die aktuelle Zahl \`i\` dazu. + +::: diagramm l12-summe.visustruct +Bei n = 4 rechnet die Schleife 0 + 1 + 2 + 3 + 4. Am Ende wird 10 ausgegeben. +::: + +## Andere Schritte + +Der Schritt muss nicht immer \`i++\` sein: + +- \`i--\` zählt rückwärts, zum Beispiel mit Start \`int i = 10\` und Bedingung \`i >= 1\`. +- \`i = i + 2\` springt in Zweierschritten, zum Beispiel 0, 2, 4, 6. + +Achte darauf, dass Start, Bedingung und Schritt zusammenpassen. Mit Start \`int i = 1\`, Bedingung \`i >= 1\` und Schritt \`i++\` wird die Bedingung nie falsch. + +::: übung l12-countdown +titel: Countdown +auftrag: Frage eine ganze Zahl \`n\` ab. Zähle mit einer For-Schleife von \`n\` rückwärts bis 1 und gib jede Zahl aus. Gib danach **Los!** aus. +test: 3 -> 3 | 2 | 1 | Los! +test: 5 -> 5 | 4 | 3 | 2 | 1 | Los! +test: 1 -> 1 | Los! +braucht: forSchleife +tipp: Diesmal zählt die For-Schleife rückwärts. Überlege, wo sie beginnt, wann sie aufhört und wie sie zählt. +tipp: Start ist \`int i = n\`, die Bedingung \`i >= 1\` und der Schritt \`i--\`. Die Ausgabe Los! steht unter der Schleife, nicht darin. +lösung: l12-countdown-loesung.visustruct +::: + +## Übung: Einmaleins + +::: übung l12-einmaleins +titel: Einmaleins +auftrag: Frage eine Zahl ab und gib ihre Einmaleins-Reihe von 1 bis 10 aus. Jede Zeile sieht so aus: **3 x 1 = 3**, **3 x 2 = 6** und so weiter. +test: 3 -> 3 x 1 = 3 | 3 x 2 = 6 | 3 x 3 = 9 | 3 x 4 = 12 | 3 x 5 = 15 | 3 x 6 = 18 | 3 x 7 = 21 | 3 x 8 = 24 | 3 x 9 = 27 | 3 x 10 = 30 +test: 7 -> 7 x 1 = 7 | 7 x 2 = 14 | 7 x 3 = 21 | 7 x 4 = 28 | 7 x 5 = 35 | 7 x 6 = 42 | 7 x 7 = 49 | 7 x 8 = 56 | 7 x 9 = 63 | 7 x 10 = 70 +braucht: forSchleife +tipp: Die Schleife zählt von 1 bis 10. In jedem Durchlauf gibst du eine Zeile der Reihe aus. +tipp: Rechne im Inhalt zuerst \`int produkt = zahl * i\`. Danach gibst du \`zahl + " x " + i + " = " + produkt\` aus. Denk an die Leerzeichen innerhalb der Anführungszeichen. +lösung: l12-einmaleins-loesung.visustruct +::: + +## Übung: Summe reparieren + +::: übung l16-summe +titel: Summe reparieren +auftrag: Das Struktogramm soll alle Zahlen von 1 bis n zusammenzählen. Bei n = 4 soll also 1 + 2 + 3 + 4 = **10** herauskommen. Es gibt aber 6 aus. + Mache einen Schreibtischtest oder nutze **Schritt** und repariere den Fehler. +start: l16-summe-start.visustruct +test: 4 -> 10 +test: 1 -> 1 +test: 5 -> 15 +braucht: forSchleife +tipp: Gehe die Schleife mit n = 4 im Kopf oder mit **Schritt** durch. Welche Zahlen werden wirklich addiert? +tipp: Schau, mit welchem Wert von i die Schleife zuletzt läuft. Bei n = 4 muss auch i = 4 noch dazugezählt werden. +lösung: l16-summe-loesung.visustruct +::: + +## Jetzt in Java + +Die Summe von 1 bis n sieht in Java so aus: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Bis zu welcher Zahl?"); +int n = scanner.nextInt(); +int summe = 0; +for (int i = 1; i <= n; i++) { + summe = summe + i; +} +System.out.println(summe); +\`\`\` + +In den runden Klammern nach \`for\` stehen die drei Felder der For-Schleife, getrennt durch Semikolons: + +| Feld | In Java | Bedeutung | +|---|---|---| +| Startwert | \`int i = 1\` | \`i\` beginnt bei 1. | +| Bedingung | \`i <= n\` | Die Schleife läuft, solange das gilt. | +| Schritt | \`i++\` | Nach jedem Durchlauf wird \`i\` um 1 größer. | + +\`i++\` ist die Kurzform von \`i = i + 1\`. Rückwärts zählst du mit \`i--\`. + +::: übung l13-java-quadrate +titel: Quadratzahlen in Java +code: java +auftrag: Schreibe ein Java-Programm, das eine ganze Zahl \`n\` einliest und mit einer For-Schleife die Quadratzahlen von 1 bis \`n\` ausgibt, jede in einer eigenen Zeile. Bei 3 also 1, 4 und 9. +test: 3 -> 1 | 4 | 9 +test: 5 -> 1 | 4 | 9 | 16 | 25 +test: 1 -> 1 +braucht: forSchleife +tipp: Die Schleife zählt \`i\` von 1 bis \`n\`. Die Quadratzahl von \`i\` ist \`i * i\`. +tipp: \`for (int i = 1; i <= n; i++) { … }\` und im Rumpf \`System.out.println(i * i);\`. +lösung: l13-java-quadrate-loesung.visustruct +::: + +## Lückentext: for + +::: lückentext +titel: Hoch- und runterzählen +auftrag: Die erste Schleife zählt die Zahlen von 1 bis 5 zusammen, die zweite zählt von 10 bis 0 rückwärts. Ergänze die fehlenden Wörter und Zeichen. +\`\`\`java +int summe = 0; +[[for]] ([[int]] i = 1; i [[<=]] 5; [[i++ | i += 1 | i = i + 1]]) { + summe = summe + i; +} +System.out.println("Summe: " + summe); +for (int i = 10; i [[>=]] 0; [[i-- | i -= 1 | i = i - 1]]) { + System.out.println(i); +} +\`\`\` +erklärung: In den runden Klammern stehen Startwert, Bedingung und Schritt, getrennt durch Semikolons. \`i++\` zählt hoch, \`i--\` zählt runter. Beim Rückwärtszählen bis 0 heißt die Bedingung \`i >= 0\`. +::: + +## Fehler finden: Einmaleins + +::: übung l13-java-fehler +titel: Einmaleins reparieren +code: java +auftrag: Das Programm fragt nach einer Reihe und soll sie vom 1-fachen bis zum 10-fachen ausgeben, bei 7 also 7, 14, … bis 70. Die 70 fehlt aber. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l13-java-fehler-start.visustruct +test: 7 -> 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 +test: 3 -> 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 +braucht: forSchleife +tipp: Wie oft läuft die Schleife? Zähle nach, welche Werte \`i\` annimmt. +tipp: \`i\` soll auch den Wert 10 annehmen: \`i <= 10\` statt \`i < 10\`. +lösung: l13-java-fehler-loesung.visustruct +::: + +## Spiel: Bombe entschärfen + +::: spiel bombe +titel: Spiel: Bombe entschärfen +intro: In jedem Programm steckt **genau ein Fehler**, und die Bombe tickt. Lies, was das Programm tun soll, und tippe auf die falsche Zeile, bevor die Zeit abläuft. Acht Runden, je 25 Sekunden. +zeit: 25 + +runde: + for (int i = 1; i <= 3; i++) { + System.out.println(i) + } +frage: Soll 1, 2 und 3 ausgeben. +fehler: 2 +besser: System.out.println(i); +> Am Ende der Anweisung fehlt das Semikolon. + +runde: + for (int i = 1, i <= 5, i++) { + System.out.println(i); + } +frage: Soll 1 bis 5 ausgeben. +fehler: 1 +besser: for (int i = 1; i <= 5; i++) { +> Die drei Felder der For-Schleife werden mit Semikolons getrennt, nicht mit Kommas. + +runde: + for (int i = 10; i >= 1; i++) { + System.out.println(i); + } +frage: Soll von 10 bis 1 rückwärts zählen. +fehler: 1 +besser: for (int i = 10; i >= 1; i--) { +> Mit \`i++\` wird \`i\` immer größer, die Bedingung \`i >= 1\` bleibt wahr: eine Endlosschleife. Rückwärts zählst du mit \`i--\`. + +runde: + int summe = 0; + for (int i = 1; i <= 4; i++) { + summe = i; + } + System.out.println(summe); +frage: Soll die Summe 1 + 2 + 3 + 4 = 10 ausgeben. +fehler: 3 +besser: summe = summe + i; +> \`summe = i\` überschreibt die Summe in jedem Durchlauf. Am Ende steht dort nur 4. + +runde: + for (int i = 0; i <= 5; i++) { + System.out.println("Määäh"); + } +frage: Soll genau fünfmal Määäh ausgeben. +fehler: 1 +besser: for (int i = 0; i < 5; i++) { +> Von 0 bis einschließlich 5 sind es sechs Durchläufe. Wer bei 0 anfängt, nimmt \`<\`. + +runde: + for (int i = 1; i <= 3; i++) { + system.out.println(i); + } +frage: Soll 1, 2 und 3 ausgeben. +fehler: 2 +besser: System.out.println(i); +> Java unterscheidet Groß- und Kleinbuchstaben: \`System\` schreibt man mit großem S. + +runde: + int zahl = 7; + for (int i = 1; i <= 10; i++) { + System.out.println(zahl + " x " + i + " = " + zahl * zahl); + } +frage: Soll die Siebenerreihe ausgeben: 7 x 1 = 7, 7 x 2 = 14 und so weiter. +fehler: 3 +besser: System.out.println(zahl + " x " + i + " = " + zahl * i); +> \`zahl * zahl\` ist immer 49. Gerechnet werden muss \`zahl * i\`. + +runde: + for (int i = 2; i <= 10; i + 2) { + System.out.println(i); + } +frage: Soll die geraden Zahlen 2, 4, 6, 8 und 10 ausgeben. +fehler: 1 +besser: for (int i = 2; i <= 10; i = i + 2) { +> \`i + 2\` rechnet nur, speichert aber nichts. Damit \`i\` wirklich wächst, braucht es \`i = i + 2\`. +::: + +## 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. + +::: checkliste +- Ich kann die drei Teile Start, Bedingung und Schritt der For-Schleife benennen. → Zählen mit festem Plan +- Ich kann erklären, in welcher Reihenfolge die drei Teile ausgeführt werden. → In welcher Reihenfolge? +- Ich kann mit einer For-Schleife vorwärts, rückwärts und in größeren Schritten zählen. → Andere Schritte +- Ich kann eine For-Schleife in Java schreiben und ihre drei Felder erklären. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Wie oft wird der Start einer For-Schleife ausgeführt? +→ In welcher Reihenfolge? +- [x] Genau einmal +- [ ] Vor jedem Durchlauf +- [ ] Nach jedem Durchlauf +> Der Start legt die Zählvariable einmal am Anfang an. + +? Start \`int i = 0\`, Bedingung \`i < 3\`, Schritt \`i++\`. Welche Werte hat i im Inhalt? +→ Zählen mit festem Plan +- [ ] 1, 2, 3 +- [x] 0, 1, 2 +- [ ] 0, 1, 2, 3 +> Bei i = 3 ist die Bedingung falsch, deshalb läuft der Inhalt dann nicht mehr. + +? Start \`int i = 2\`, Bedingung \`i <= 10\`, Schritt \`i = i + 2\`. Wie oft läuft der Inhalt? +→ Andere Schritte +- [ ] 4-mal +- [x] 5-mal +- [ ] 10-mal +> i nimmt die Werte 2, 4, 6, 8 und 10 an. + +? Wann passt eine For-Schleife am besten? +→ Zählen mit festem Plan +- [x] Wenn vorher feststeht, wie oft wiederholt wird +- [ ] Wenn so lange gefragt wird, bis eine Eingabe gültig ist +- [ ] Wenn nur ein einziger Wert geprüft wird + +? Was bedeutet \`i++\` in einer For-Schleife? +→ Zählen mit festem Plan +- [ ] i wird verdoppelt. +- [x] i wird um 1 größer. +- [ ] i wird ausgegeben. +> \`i++\` ist die Kurzform von \`i = i + 1\`. +::: +`,_x=`--- +titel: Verschachteln +bereich: Grundlagen +kurz: Verzweigungen in Schleifen und Schleifen in Schleifen kombinieren. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- eine Verzweigung in eine Schleife setzen +- eine Schleife in eine andere Schleife setzen +- erklären, dass die innere Schleife bei jedem Durchlauf der äußeren komplett durchläuft +- verschachtelte Schleifen und Verzweigungen in Java schreiben +::: + +## Bausteine ineinander + +Du kennst jetzt alle wichtigen Bausteine: Sequenz, Verzweigung, Fallauswahl und drei Arten von Schleifen. Richtig stark werden sie erst zusammen. + +Jeder Zweig und jeder Schleifeninhalt ist selbst wieder eine Sequenz. Dort darfst du jedes Element einsetzen, auch weitere Verzweigungen und Schleifen. Das nennt man **Verschachteln**. + +> Ziehe dazu ein Element einfach auf den Platzhalter ø im Inneren einer Schleife oder eines Zweigs. + +## Verzweigung in der Schleife + +Die Schleife geht alle Zahlen durch, die Verzweigung entscheidet bei jeder einzelnen Zahl, ob etwas passiert. So kannst du zum Beispiel zählen, wie viele gerade Zahlen es von 1 bis n gibt. + +::: diagramm l13-gerade-zaehlen.visustruct +Bei jedem Durchlauf prüft die Verzweigung mit i % 2 == 0, ob i gerade ist. Nur dann wird anzahl um 1 erhöht. Der false-Zweig bleibt leer. +::: + +Bei n = 7 sind das die Zahlen 2, 4 und 6, also wird 3 ausgegeben. + +## Übung: Gerade Eingaben zählen + +::: übung l13-gerade-eingaben +titel: Gerade Eingaben zählen +auftrag: Frage nacheinander genau **fünf** ganze Zahlen ab. Gib danach aus, wie viele davon gerade waren. +test: 1, 2, 3, 4, 5 -> 2 +test: 2, 4, 6, 8, 10 -> 5 +test: 1, 3, 5, 7, 9 -> 0 +test: 10, 11, 0, 7, 8 -> 3 +braucht: forSchleife, verzweigung +tipp: Fünfmal dasselbe tun heißt: Schleife. In jedem Durchlauf wird eine Zahl eingelesen und geprüft. +tipp: Eine For-Schleife von 1 bis 5. Im Inhalt steht zuerst die Eingabe \`input: int zahl "Zahl eingeben"\`, darunter eine Verzweigung mit \`zahl % 2 == 0\`. Im true-Zweig erhöhst du \`anzahl\` um 1. +lösung: l13-gerade-eingaben-loesung.visustruct +::: + +## Schleife in der Schleife + +Steht eine Schleife in einer anderen, läuft die **innere Schleife bei jedem Durchlauf der äußeren komplett durch**. Damit kannst du Muster aus Zeilen und Spalten bauen. + +::: diagramm l13-dreieck.visustruct +Die äußere Schleife zählt die Zeilen. Die innere hängt so viele Sterne an den Text, wie die Zeilennummer angibt. Bei n = 3 entsteht ein Dreieck aus 1, 2 und 3 Sternen. +::: + +Mit \`String text = ""\` beginnt jede Zeile leer. \`text = text + "*"\` hängt einen Stern an. Erst wenn die Zeile fertig ist, wird sie ausgegeben. + +## Übung: Rechteck + +::: übung l13-rechteck +titel: Rechteck +auftrag: Frage eine Breite und eine Höhe ab. Gib ein Rechteck aus \`#\` aus: so viele Zeilen wie die Höhe, und in jeder Zeile so viele \`#\` wie die Breite. +test: 3, 2 -> ### | ### +test: 1, 3 -> # | # | # +test: 4, 1 -> #### +test: 2, 2 -> ## | ## +braucht: forSchleife +tipp: Du brauchst zwei Schleifen ineinander: eine für die Zeilen und darin eine für die Zeichen einer Zeile. +tipp: Baue es wie das Dreieck. Der Unterschied: Die innere Schleife zählt immer bis \`breite\`, nicht bis zur Zeilennummer. Die äußere Schleife zählt bis \`hoehe\`. +lösung: l13-rechteck-loesung.visustruct +::: + +## Den Überblick behalten + +Bei verschachtelten Diagrammen hilft dir die Darstellung: Was weiter innen steht, ist eingerückt und von seiner Schleife oder seinem Zweig umschlossen. + +- Lies von außen nach innen: Was wiederholt sich? Was wird bei jedem Durchlauf entschieden? +- Gib Zählvariablen sprechende Namen wie \`zeile\` und \`spalte\`. Zwei Schleifen dürfen nicht dieselbe Zählvariable verändern. +- Gehe ein Beispiel in der Simulation mit **Schritt** durch und beobachte die Variablen. + +::: angeberwissen +Genau dafür wurde das Struktogramm erfunden. Shneiderman fragte sich: Wenn man auf GOTO verzichten soll, warum dann nicht gleich auf die Pfeile im Flussdiagramm? Ergebnis: kein Pfeil-Spaghetti, und jeder Block bleibt brav in seinem Gatter. +::: + +## Jetzt in Java + +Das Zählen der geraden Zahlen sieht in Java so aus: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Bis zu welcher Zahl?"); +int n = scanner.nextInt(); +int anzahl = 0; +for (int i = 1; i <= n; i++) { + if (i % 2 == 0) { + anzahl++; + } // Ende if +} // Ende for +System.out.println(anzahl); +\`\`\` + +Was im Struktogramm ineinander steckt, steht in Java in geschweiften Klammern ineinander. Jede Ebene ist vier Leerzeichen weiter eingerückt. Ist dein Code durcheinander, hilft der Knopf **Einrücken** oben im Bereich Code. + +Bei vielen schließenden Klammern \`}\` verliert man leicht den Überblick: Welche Klammer gehört zu welchem Block? Ein Kommentar dahinter sagt es dir, z. B. \`} // Ende if\` und \`} // Ende for\`. Das hilft dir auch, wenn du später weiterarbeitest. + +\`anzahl++\` ist die Kurzform von \`anzahl = anzahl + 1\`. + +::: übung l14-java-treppe +titel: Treppe aus Sternen +code: java +auftrag: Schreibe ein Java-Programm, das die Anzahl der Stufen einliest und eine Treppe aus Sternchen ausgibt. Bei 3 Stufen also \`*\`, \`**\` und \`***\`, jede Stufe in einer eigenen Zeile. +test: 3 -> * | ** | *** +test: 1 -> * +test: 4 -> * | ** | *** | **** +braucht: forSchleife +tipp: Eine äußere Schleife zählt die Stufen. In jeder Stufe baut eine innere Schleife einen Text aus Sternchen zusammen. +tipp: In der äußeren Schleife: \`String zeile = "";\`, dann \`for (int j = 1; j <= i; j++) { zeile = zeile + "*"; }\` und danach \`System.out.println(zeile);\`. +lösung: l14-java-treppe-loesung.visustruct +::: + +## Lückentext: verschachteln + +::: lückentext +titel: Rechteck aus Sternen +auftrag: Das Programm gibt ein Rechteck aus 3 Zeilen mit je 4 Sternchen aus. Ergänze die fehlenden Wörter und Zeichen. +\`\`\`java +for (int zeile = 1; zeile <= 3; zeile++) { + String text = [[""]]; + [[for]] (int spalte = 1; spalte [[<=]] 4; [[spalte++ | spalte += 1 | spalte = spalte + 1]]) { + text = text [[+]] "*"; + } + System.out.[[println]](text); +[[}]] +\`\`\` +erklärung: Die innere Schleife baut eine Zeile aus 4 Sternchen, die äußere wiederholt das dreimal. Jede Zeile beginnt mit einem leeren Text \`""\`. Die letzte Klammer schließt die äußere Schleife. +::: + +## Fehler finden: durch 3 teilbar + +::: übung l14-java-fehler +titel: Zählen reparieren +code: java +auftrag: Das Programm soll zählen, wie viele Zahlen von 1 bis \`n\` durch 3 teilbar sind, und **einmal** das Ergebnis ausgeben. Bei 10 also nur **Anzahl: 3**. Es gibt aber viel zu viele Zeilen aus. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l14-java-fehler-start.visustruct +test: 10 -> Anzahl: 3 +test: 3 -> Anzahl: 1 +test: 2 -> Anzahl: 0 +braucht: forSchleife, verzweigung +tipp: Achte auf die geschweiften Klammern: Steht die Ausgabe in der Schleife oder dahinter? +tipp: Verschiebe die Zeile \`System.out.println("Anzahl: " + anzahl);\` hinter die schließende Klammer der Schleife. +lösung: l14-java-fehler-loesung.visustruct +::: + +## Spiel: Innen und außen + +::: spiel frage +titel: Spiel: Innen und außen +intro: Ludwig hat Bausteine ineinander gesteckt. Lies von außen nach innen und sag vorher, was passiert. Sechs Runden. + +runde: + for (int i = 1; i <= 3; i++) { + for (int j = 1; j <= 2; j++) { + System.out.println("*"); + } + } +frage: Wie viele Sterne werden ausgegeben? +- 3 +- 5 +- [x] 6 +> Die innere Schleife läuft bei jedem der 3 Durchläufe der äußeren komplett durch: 3 · 2 = 6. + +runde: + for (int i = 1; i <= 2; i++) { + for (int j = 1; j <= 3; j++) { + System.out.println(i + " " + j); + } + } +frage: Welche Zeile wird als vierte ausgegeben? +- 1 4 +- [x] 2 1 +- 2 2 +> Erst läuft j für i = 1 durch: 1 1, 1 2, 1 3. Danach beginnt j wieder bei 1, jetzt mit i = 2. + +runde: + int anzahl = 0; + for (int i = 1; i <= 10; i++) { + if (i % 3 == 0) { + anzahl++; + } + } + System.out.println(anzahl); +frage: Was wird ausgegeben? +- [x] 3 +- 10 +- 4 +> Die Verzweigung zählt nur 3, 6 und 9 mit. + +runde: + for (int i = 1; i <= 4; i++) { + if (i % 2 == 0) { + System.out.println("gerade"); + } else { + System.out.println(i); + } + } +frage: Was wird ausgegeben? +- 1\\n2\\n3\\n4 +- [x] 1\\ngerade\\n3\\ngerade +- gerade\\ngerade +> Bei jeder Zahl entscheidet die Verzweigung neu: ungerade Zahlen selbst, gerade als Wort. + +runde: + for (int i = 1; i <= 3; i++) { + String zeile = ""; + for (int j = 1; j <= i; j++) { + zeile = zeile + "*"; + } + System.out.println(zeile); + } +frage: Was wird ausgegeben? +- ***\\n***\\n*** +- [x] *\\n**\\n*** +- ***\\n**\\n* +> Die innere Schleife läuft bis i. Darum wird jede Zeile einen Stern länger. + +runde: + for (int i = 1; i <= 3; i++) { + for (int i = 1; i <= 3; i++) { + System.out.println(i); + } + } +frage: Was passiert? +- 1 bis 3 wird dreimal ausgegeben. +- 1 bis 3 wird einmal ausgegeben. +- [x] Java meldet einen Fehler. +> Zwei Schleifen ineinander brauchen zwei verschiedene Zählvariablen, zum Beispiel \`zeile\` und \`spalte\`. +::: + +## 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. + +::: checkliste +- Ich kann eine Verzweigung in eine Schleife setzen. → Verzweigung in der Schleife +- Ich kann eine Schleife in eine andere Schleife setzen. → Schleife in der Schleife +- Ich kann erklären, dass die innere Schleife bei jedem Durchlauf der äußeren komplett durchläuft. → Schleife in der Schleife +- Ich kann verschachtelte Schleifen und Verzweigungen in Java schreiben. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Die äußere Schleife läuft 3-mal, die innere 4-mal. Wie oft wird der Inhalt der inneren Schleife insgesamt ausgeführt? +→ Schleife in der Schleife +- [ ] 7-mal +- [x] 12-mal +- [ ] 4-mal +> Bei jedem der 3 äußeren Durchläufe läuft die innere Schleife 4-mal, also 3 · 4 = 12. + +? Woran erkennst du, ob eine Zahl gerade ist? +→ Verzweigung in der Schleife +- [ ] \`zahl / 2 == 0\` +- [x] \`zahl % 2 == 0\` +- [ ] \`zahl == 2\` +> % liefert den Rest beim Teilen. Bei geraden Zahlen ist der Rest beim Teilen durch 2 null. + +? In einer For-Schleife steht eine Verzweigung. Wie oft wird die Bedingung der Verzweigung geprüft? +→ Verzweigung in der Schleife +- [ ] Einmal +- [x] Einmal pro Durchlauf der Schleife +- [ ] Nur wenn sie wahr ist +> Die Verzweigung gehört zum Inhalt und kommt bei jedem Durchlauf dran. + +? Woran erkennst du in Java, was zu einer Schleife gehört? +→ Jetzt in Java +- [ ] An der Farbe +- [x] An den geschweiften Klammern und der Einrückung +- [ ] An den Semikolons +::: +`,Ax=`--- +titel: Arrays +bereich: Grundlagen +kurz: Viele Werte unter einem Namen speichern, mit dem Index darauf zugreifen und sie mit einer Schleife durchlaufen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- ein Array mit Werten oder mit \`new int[5]\` anlegen +- erklären, dass der Index bei 0 beginnt und der letzte Index \`length - 1\` ist +- ein Array mit einer For-Schleife durchlaufen und füllen +- die Summe und das Maximum eines Arrays berechnen +- in Java ein Array anlegen und mit einer Schleife durchlaufen +::: + +## Viele Werte unter einem Namen + +Stell dir vor, du willst die Punkte von fünf Tests speichern. Mit fünf Variablen \`punkte1\` bis \`punkte5\` wird das schnell unübersichtlich. Ein **Array** ist eine Reihe von Fächern, die alle denselben Namen und denselben Datentyp haben. + +Du legst ein Array mit einer Anweisung an. Hinter den Datentyp schreibst du eckige Klammern \`[]\`: + +\`\`\` +int[] zahlen = {2, 4, 6, 8, 10} +String[] namen = {"Ada", "Ben", "Cem"} +\`\`\` + +Die Werte in den geschweiften Klammern stehen gleich in den Fächern. Du kannst auch ein leeres Array mit einer festen Anzahl von Fächern anlegen: + +\`\`\` +int[] punkte = new int[5] +String[] namen = new String[3] +\`\`\` + +Bei \`new int[5]\` stehen in allen fünf Fächern zuerst Nullen, bei \`new String[3]\` leere Texte. + +## Der Index beginnt bei 0 + +Jedes Fach hat eine Nummer, den **Index**. Gezählt wird ab **0**. Bei \`int[] zahlen = {2, 4, 6, 8, 10}\` gilt also: + +- \`zahlen[0]\` ist 2 +- \`zahlen[1]\` ist 4 +- \`zahlen[4]\` ist 10 + +::: grafik l14-array.svg +Fünf Fächer mit den Indizes 0 bis 4. Der Index steht über dem Fach, der Wert darin. +::: + +**Warum beginnt man bei 0?** In der Informatik ist der Index kein „wievieltes Fach“, sondern der **Abstand vom Anfang**. Das erste Fach liegt direkt am Anfang, also 0 Schritte entfernt. Das zweite liegt 1 Schritt entfernt, das dritte 2 Schritte. Du kennst das aus dem Aufzug: Das Erdgeschoss ist die **0**, der erste Stock liegt eine Etage darüber. + +Daraus folgt eine Regel, die du dir merken solltest: Bei 5 Fächern ist der **letzte Index 4**, also immer eins weniger als die Anzahl. + +::: angeberwissen +Dass ab 0 gezählt wird, ist ziemlich alt. Schon die Programmiersprache C von 1972 rechnet so: Der Computer kennt die Adresse des ersten Fachs und rechnet für \`zahlen[i]\` einfach „Anfang plus i Fächer weiter“. Bei i = 0 bleibt er am Anfang stehen, das spart eine Rechnung. Java, Python und JavaScript haben das übernommen. Ich zähle meine Hörner übrigens auch ab 0: Horn 0 links, Horn 1 rechts. +::: + +Mit dem Index liest du einen Wert oder schreibst einen neuen hinein: + +\`\`\` +output: zahlen[0] +zahlen[1] = 99 +\`\`\` + +> Ein Array mit 5 Fächern hat die Indizes 0 bis 4. \`zahlen[5]\` gibt es nicht. Die Simulation meldet dann einen ungültigen Ausdruck. + +## Die Länge eines Arrays + +Wie viele Fächer ein Array hat, verrät \`zahlen.length\`. Bei fünf Werten ist das 5. Der **letzte** Index ist deshalb immer \`zahlen.length - 1\`: + +\`\`\` +output: zahlen.length +output: zahlen[zahlen.length - 1] +\`\`\` + +Die zweite Zeile gibt den letzten Wert aus, egal wie lang das Array ist. VisuStruct versteht auch die Schreibweise \`zahlen.length()\`. + +::: übung l14-erster-letzter +titel: Erster und letzter Wert +auftrag: Lege das Array \`int[] werte = {4, 8, 15, 16, 23, 42}\` an. Gib danach in drei Zeilen aus: den ersten Wert, den letzten Wert und die Anzahl der Werte. + Für den letzten Wert sollst du die Länge benutzen und nicht einfach den Index 5 hinschreiben. +test: - -> 4 | 42 | 6 +braucht: anweisung +tipp: Gezählt wird ab 0. Das erste Fach hat also den Index 0. Und wie heißt der Index des letzten Fachs? +tipp: Der erste Wert ist \`werte[0]\`. Der letzte ist \`werte[werte.length - 1]\`. Die Anzahl ist \`werte.length\`. +lösung: l14-erster-letzter-loesung.visustruct +::: + +## Ein Array mit der Schleife durchlaufen + +Seine Stärke zeigt ein Array zusammen mit einer **For-Schleife**. Die Zählvariable \`i\` läuft von 0 bis zum letzten Index und dient als Index: + +\`\`\` +int i = 0 +i < zahlen.length +i++ +\`\`\` + +Im ersten Durchlauf ist \`i\` gleich 0, im letzten gleich 4. Weil die Bedingung \`i < zahlen.length\` lautet, passt die Schleife zu jeder Länge. + +::: diagramm l14-array-durchlaufen.visustruct +Die For-Schleife gibt alle fünf Werte nacheinander aus. Schau in der Simulation unter Variablen zu, wie i von 0 bis 4 zählt. +::: + +So füllst du ein leeres Array auch mit Eingaben. Als Ziel der Eingabe schreibst du das Fach \`namen[i]\`: + +::: diagramm l14-namen-eingeben.visustruct +Drei Namen werden abgefragt und in die Fächer 0, 1 und 2 geschrieben. +::: + +::: übung l14-rueckwaerts +titel: Rückwärts ausgeben +auftrag: Lege ein Array für 4 ganze Zahlen an und lies die 4 Zahlen mit einer Schleife ein. Gib sie danach in **umgekehrter** Reihenfolge aus, jede in einer eigenen Zeile. +test: 1, 2, 3, 4 -> 4 | 3 | 2 | 1 +test: 7, 0, 5, 9 -> 9 | 5 | 0 | 7 +braucht: forSchleife +tipp: Du brauchst zwei Schleifen: eine zum Einlesen von vorn nach hinten und eine zum Ausgeben von hinten nach vorn. +tipp: Mit \`int[] zahlen = new int[4]\` legst du das Array an. Die Eingabe lautet \`input: zahlen[i] "Zahl eingeben"\`. Für die zweite Schleife beginnst du bei \`int i = zahlen.length - 1\`, prüfst \`i >= 0\` und zählst mit \`i--\` herunter. +lösung: l14-rueckwaerts-loesung.visustruct +::: + +## Summe und Maximum + +Zwei Aufgaben kommen bei Arrays immer wieder vor: + +- **Summe:** Du beginnst mit \`summe = 0\` und zählst in der Schleife jeden Wert dazu. +- **Maximum:** Du merkst dir zuerst den Wert im Fach 0 als bisher größten. In der Schleife prüfst du jeden Wert. Ist er größer, wird er das neue Maximum. + +::: diagramm l14-summe-maximum.visustruct +Summe und Maximum in einem einzigen Durchlauf. Das Maximum beginnt mit punkte[0] und nicht mit 0, damit es auch bei negativen Zahlen stimmt. +::: + +::: übung l14-summe-max +titel: Summe und Maximum +auftrag: Lies 5 ganze Zahlen in ein Array ein. Gib danach **Summe: …** und in der nächsten Zeile **Maximum: …** aus. +test: 3, 9, 2, 9, 1 -> Summe: 24 | Maximum: 9 +test: 10, 20, 30, 40, 50 -> Summe: 150 | Maximum: 50 +test: -5, -2, -9, -1, -3 -> Summe: -20 | Maximum: -1 +braucht: forSchleife, verzweigung +tipp: Gehe das Array mit einer Schleife durch. Zähle jeden Wert zur Summe und merke dir den größten bisher gesehenen Wert. +tipp: Rechne Summe und Maximum in eigenen Variablen aus und gib sie erst am Ende aus, z. B. mit \`output: "Summe: " + summe\`. Beginnt dein Maximum bei 0, scheitert der dritte Test. +lösung: l14-summe-max-loesung.visustruct +::: + +## Jetzt in Java + +Das Durchlaufen eines Arrays sieht in Java so aus: + +\`\`\`java +int[] zahlen = {2, 4, 6, 8, 10}; +for (int i = 0; i < zahlen.length; i++) { + System.out.println(zahlen[i]); +} +\`\`\` + +- \`int[]\` heißt „Array aus ganzen Zahlen“. Die Werte stehen in geschweiften Klammern. +- Ein leeres Array mit 5 Fächern legst du mit \`new int[5]\` an. +- \`zahlen[i]\` ist das Fach mit dem Index \`i\`, \`zahlen.length\` die Länge. + +::: übung l15-java-noten +titel: Notensumme in Java +code: java +auftrag: Lege in Java das Array \`noten\` mit den Werten 2, 3, 1 und 4 an. Zähle alle Noten mit einer For-Schleife zusammen und gib **Summe: 10** aus. +test: - -> Summe: 10 +braucht: forSchleife +tipp: Lege vor der Schleife \`int summe = 0;\` an. Die Schleife läuft von 0 bis \`noten.length - 1\`. +tipp: \`int[] noten = {2, 3, 1, 4};\`, dann \`for (int i = 0; i < noten.length; i++) { summe = summe + noten[i]; }\` und zum Schluss \`System.out.println("Summe: " + summe);\`. +lösung: l15-java-noten-loesung.visustruct +::: + +## Lückentext: Arrays + +::: lückentext +titel: Das Maximum suchen +auftrag: Das Programm sucht den größten Wert im Array. Ergänze die fehlenden Wörter und Zeichen. +\`\`\`java +[[int]][] werte = {3, 7, 1, 9, 4}; +int max = werte[0]; +[[for]] (int i = 1; i < werte.[[length]]; i++) { + if (werte[i] [[>]] max) { + max = werte[i]; + } +} +System.out.println("Maximum: " + max); +\`\`\` +erklärung: \`int[]\` ist ein Array aus ganzen Zahlen, \`werte.length\` seine Länge. \`max\` beginnt mit dem ersten Wert, die Schleife vergleicht alle weiteren damit. Ausgabe: **Maximum: 9** +::: + +## Fehler finden: Temperaturen + +::: übung l15-java-fehler +titel: Höchste Temperatur reparieren +code: java +auftrag: Im Januar wurden die Temperaturen -5, -2, -8 und -3 Grad gemessen. Das Programm soll die höchste ausgeben, also **Höchste Temperatur: -2**. Es behauptet aber 0 Grad, obwohl es so warm nie war. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l15-java-fehler-start.visustruct +test: - -> Höchste Temperatur: -2 +braucht: forSchleife, verzweigung +tipp: Mit welchem Wert beginnt \`max\`? Ist irgendeine der Temperaturen größer als dieser Startwert? +tipp: \`max\` muss mit einem Wert aus dem Array beginnen: \`int max = temperaturen[0];\` +lösung: l15-java-fehler-loesung.visustruct +::: + +## Spiel: Bombe entschärfen + +::: spiel bombe +titel: Spiel: Bombe entschärfen +intro: In jedem Programm steckt **genau ein Fehler** rund um Arrays, und die Bombe tickt. Tippe auf die falsche Zeile, bevor die Zeit abläuft. Sechs Runden, je 30 Sekunden. +zeit: 30 + +runde: + int[] zahlen = {2, 4, 6, 8, 10}; + for (int i = 0; i <= zahlen.length; i++) { + System.out.println(zahlen[i]); + } +frage: Soll alle fünf Werte ausgeben. +fehler: 2 +besser: for (int i = 0; i < zahlen.length; i++) { +> Mit \`<=\` läuft i bis 5. Das Fach \`zahlen[5]\` gibt es nicht. + +runde: + String[] namen = {"Ada", "Ben", "Cem"}; + System.out.println(namen[1]); +frage: Soll den ersten Namen ausgeben, also Ada. +fehler: 2 +besser: System.out.println(namen[0]); +> Gezählt wird ab 0. \`namen[1]\` ist schon Ben. + +runde: + int[] zahlen = {2, 4, 6, 8, 10}; + System.out.println(zahlen[zahlen.length]); +frage: Soll den letzten Wert ausgeben, also 10. +fehler: 2 +besser: System.out.println(zahlen[zahlen.length - 1]); +> Der letzte Index ist immer eins weniger als die Länge. + +runde: + int[] punkte = {3, 9, 2}; + int summe = 0; + for (int i = 0; i < punkte.length; i++) { + summe = punkte[i]; + } + System.out.println(summe); +frage: Soll die Summe 14 ausgeben. +fehler: 4 +besser: summe = summe + punkte[i]; +> So überschreibt jeder Wert den vorigen, am Ende steht nur 2 in summe. + +runde: + int[] punkte = {-5, -2, -9}; + int max = 0; + for (int i = 0; i < punkte.length; i++) { + if (punkte[i] > max) { + max = punkte[i]; + } + } + System.out.println(max); +frage: Soll das Maximum -2 ausgeben. +fehler: 2 +besser: int max = punkte[0]; +> Keine der Zahlen ist größer als 0, also bliebe max bei 0. Das Maximum beginnt deshalb mit dem ersten Fach. + +runde: + int[] zahlen = {2, 4, 6, 8, 10}; + for (int i = zahlen.length; i >= 0; i--) { + System.out.println(zahlen[i]); + } +frage: Soll die Werte rückwärts ausgeben, von 10 bis 2. +fehler: 2 +besser: for (int i = zahlen.length - 1; i >= 0; i--) { +> Rückwärts beginnt man beim letzten Index, und der ist \`zahlen.length - 1\`. +::: + +## 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. + +::: checkliste +- Ich kann ein Array mit Werten oder mit \`new int[5]\` anlegen. → Viele Werte unter einem Namen +- Ich kann erklären, dass der Index bei 0 beginnt und der letzte Index \`length - 1\` ist. → Der Index beginnt bei 0 +- Ich kann ein Array mit einer For-Schleife durchlaufen und füllen. → Ein Array mit der Schleife durchlaufen +- Ich kann die Summe und das Maximum eines Arrays berechnen. → Summe und Maximum +- Ich kann in Java ein Array anlegen und mit einer Schleife durchlaufen. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Was gibt \`output: zahlen[2]\` bei \`int[] zahlen = {5, 10, 15, 20}\` aus? +→ Der Index beginnt bei 0 +- [ ] 10 +- [x] 15 +- [ ] 20 +> Gezählt wird ab 0: zahlen[0] ist 5, zahlen[1] ist 10, zahlen[2] ist 15. + +? Ein Array hat 8 Fächer. Welcher Index ist der letzte? +→ Der Index beginnt bei 0 +- [ ] 8 +- [x] 7 +- [ ] 9 +> Der letzte Index ist immer length - 1. + +? Welche Bedingung passt in eine For-Schleife, die alle Werte von \`zahlen\` durchläuft und bei \`int i = 0\` beginnt? +→ Ein Array mit der Schleife durchlaufen +- [x] i < zahlen.length +- [ ] i <= zahlen.length +- [ ] i > zahlen.length +> Mit <= würde die Schleife auch zahlen[length] lesen, und dieses Fach gibt es nicht. + +? Womit sollte das Maximum beginnen, bevor die Schleife startet? +→ Summe und Maximum +- [ ] Immer mit 0 +- [x] Mit dem ersten Wert des Arrays +- [ ] Mit der Länge des Arrays +> Beginnt es mit 0, wäre bei lauter negativen Zahlen 0 das Ergebnis, obwohl 0 gar nicht im Array steht. + +? Welches deutsche Wort wird oft für Array benutzt? +→ Viele Werte unter einem Namen +- [ ] Zweig +- [x] Feld +- [ ] Fall +> Ein Array heißt auf Deutsch oft Feld. Gemeint ist dasselbe: viele Fächer unter einem Namen. + +? Welche Zeile legt in Java ein Array mit drei Zahlen an? +→ Jetzt in Java +- [x] int[] zahlen = {1, 2, 3}; +- [ ] int zahlen = [1, 2, 3]; +- [ ] array zahlen = (1, 2, 3); +::: +`,Ox=`--- +titel: Zweidimensionale Arrays +bereich: Grundlagen +kurz: Werte in Zeilen und Spalten speichern, wie die Sitze in einem Kinosaal, und mit zwei verschachtelten Schleifen durchlaufen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- ein 2D-Array anlegen und erklären, was die beiden Zahlen bedeuten +- ein Fach mit Reihe und Platz lesen und schreiben +- \`sitze.length\` und \`sitze[0].length\` unterscheiden +- erklären, in welcher Reihenfolge zwei verschachtelte Schleifen die Fächer besuchen +- in Java ein zweidimensionales Array anlegen und durchlaufen +::: + +## Ein Kinosaal als Tabelle + +Ein Kinosaal hat mehrere **Reihen**, und jede Reihe hat mehrere **Plätze**. Für jeden Sitz wollen wir uns merken, ob die Karte schon verkauft ist. Das ist eine Ja-oder-nein-Frage, also passt der Datentyp \`boolean\`: \`true\` heißt verkauft, \`false\` heißt frei. + +Ein normales Array ist eine einzige Reihe von Fächern. Für den Saal brauchen wir eine **Tabelle** mit Zeilen und Spalten. Das ist ein **zweidimensionales Array**, kurz 2D-Array. Du schreibst dafür zwei Paar eckige Klammern: + +\`\`\` +boolean[][] sitze = new boolean[3][5] +\`\`\` + +Das ergibt 3 Reihen mit je 5 Plätzen, also 15 Fächer. Am Anfang steht in allen Fächern \`false\`: Alle Plätze sind frei. + +::: grafik kino-saal.svg +Der erste Index ist die Reihe, der zweite der Platz. Beide werden ab 0 gezählt. +::: + +## Ein Fach ansprechen + +Für ein Fach brauchst du jetzt **zwei** Indizes: zuerst die Reihe, dann den Platz. + +\`\`\` +sitze[1][2] = true +\`\`\` + +Damit ist in Reihe 1 der Platz 2 verkauft. Gelesen wird genauso: \`sitze[1][2]\` ist jetzt \`true\`. + +Auch die Größe kannst du abfragen: + +- \`sitze.length\` ist die Anzahl der **Reihen**, hier 3. +- \`sitze[0].length\` ist die Anzahl der **Plätze** in Reihe 0, hier 5. + +::: diagramm kino-verkaufen.visustruct +Drei Karten werden verkauft. Danach gibt das Diagramm die Größe des Saals aus und ob Reihe 1, Platz 2 verkauft ist. Schau in der Simulation unter Variablen zu: sitze wird Zeile für Zeile angezeigt. +::: + +> Wie beim normalen Array gibt es kein Fach \`sitze[3][0]\`, denn die Reihen heißen 0, 1 und 2. Die Simulation meldet dann einen ungültigen Ausdruck. + +## Zwei Schleifen ineinander + +Um **alle** Plätze anzusehen, brauchst du zwei For-Schleifen ineinander: + +- Die **äußere Schleife** zählt die Reihe: \`reihe\` läuft von 0 bis 2. +- Die **innere Schleife** zählt den Platz: \`platz\` läuft von 0 bis 4. + +::: grafik kino-schleifen.svg +Blau ist die äußere Schleife, Orange die innere. Die Zahlen zeigen, in welcher Reihenfolge die Plätze drankommen. +::: + +Für jede Reihe läuft die innere Schleife einmal **komplett** durch. Erst wenn \`platz\` alle fünf Plätze besucht hat, zählt die äußere Schleife \`reihe\` um eins weiter. Danach beginnt \`platz\` wieder bei 0. So kommen alle 3 · 5 = 15 Plätze genau einmal dran. + +Die Bedingungen lauten \`reihe < sitze.length\` und \`platz < sitze[reihe].length\`. So passen die Schleifen zu jeder Saalgröße. + +::: diagramm kino-saalplan.visustruct +Der Saalplan: Für jede Reihe wird eine Zeile aus X (verkauft) und O (frei) zusammengesetzt und ausgegeben. Gehe es mit Schritt durch und beobachte, wie platz immer wieder von vorn beginnt, während reihe nur langsam weiterzählt. +::: + +::: angeberwissen +Jedes Handyfoto ist ein 2D-Array! Ein Foto mit 4000 · 3000 Pixeln hat 3000 Zeilen mit je 4000 Fächern, also 12 Millionen Pixel. In jedem Fach steht die Farbe eines Punkts. Wenn du ein Foto heller machst, läuft das Handy mit zwei verschachtelten Schleifen über alle Pixel. Mein Profilbild hat übrigens nur ein Fach: braun. +::: + +## Übung: Freie Plätze zählen + +::: übung kino-frei +titel: Freie Plätze zählen +auftrag: Im Startdiagramm sind schon drei Karten verkauft. Zähle mit zwei verschachtelten Schleifen, wie viele Plätze noch **frei** sind, und gib z. B. \`Frei: 12\` aus. +start: kino-frei-start.visustruct +test: - -> Frei: 12 +braucht: forSchleife, verzweigung +tipp: Du gehst wie beim Saalplan mit zwei Schleifen über alle Plätze. Statt etwas auszugeben, zählst du mit. +tipp: Lege vor den Schleifen \`int frei = 0\` an. Ein Platz ist frei, wenn \`sitze[reihe][platz]\` falsch ist. Die Bedingung dafür lautet \`!sitze[reihe][platz]\`. +lösung: kino-frei-loesung.visustruct +::: + +## Übung: Karte verkaufen + +::: übung kino-karte +titel: Karte verkaufen +auftrag: Das Startdiagramm fragt nach Reihe und Platz. Ist der Platz schon verkauft, gib \`Schon verkauft\` aus. Sonst markiere ihn als verkauft und gib z. B. \`Verkauft: Reihe 0, Platz 4\` aus. +start: kino-karte-start.visustruct +test: 1, 2 -> Schon verkauft +test: 0, 4 -> Verkauft: Reihe 0, Platz 4 +test: 2, 0 -> Verkauft: Reihe 2, Platz 0 +braucht: verzweigung +tipp: Zuerst wird geprüft, ob der Platz verkauft ist. Je nach Antwort passiert etwas anderes. +tipp: Hier brauchst du keine Schleife. Eine Verzweigung mit der Bedingung \`sitze[reihe][platz]\` genügt. Im false-Zweig setzt du das Fach auf \`true\`. +lösung: kino-karte-loesung.visustruct +::: + +## Übung: Einmaleins-Tabelle + +::: übung kino-einmaleins +titel: Einmaleins-Tabelle +auftrag: Lege \`int[][] tabelle = new int[10][10]\` an und fülle sie mit zwei Schleifen mit dem kleinen Einmaleins. Frage danach zwei Zahlen von 1 bis 10 ab und lies das Ergebnis aus der Tabelle, z. B. \`3 · 4 = 12\`. +test: 3, 4 -> 3 · 4 = 12 +test: 7, 8 -> 7 · 8 = 56 +test: 10, 10 -> 10 · 10 = 100 +braucht: forSchleife +tipp: Erst füllen zwei verschachtelte Schleifen die Tabelle, danach liest du nur ein einziges Fach aus. +tipp: Die Indizes laufen von 0 bis 9, die Zahlen aber von 1 bis 10. Darum steht im Fach \`tabelle[i][j]\` der Wert \`(i + 1) * (j + 1)\`, und für 3 · 4 liest du \`tabelle[a - 1][b - 1]\`. +lösung: kino-einmaleins-loesung.visustruct +::: + +## Jetzt in Java + +Der Kinosaal sieht in Java so aus: + +\`\`\`java +boolean[][] sitze = new boolean[3][5]; +sitze[0][2] = true; +sitze[1][1] = true; +sitze[1][2] = true; +System.out.println("Reihen: " + sitze.length); +System.out.println("Plätze pro Reihe: " + sitze[0].length); +System.out.println("Reihe 1, Platz 2 verkauft? " + sitze[1][2]); +\`\`\` + +- Zwei Paar eckige Klammern \`[][]\` stehen für eine Tabelle: erst die Reihe, dann der Platz. +- \`sitze.length\` ist die Zahl der Reihen, \`sitze[0].length\` die Zahl der Plätze in einer Reihe. +- Mit festen Werten schreibst du jede Reihe in eigene geschweifte Klammern: \`int[][] t = {{1, 2}, {3, 4}};\` + +::: übung l16-java-punkte +titel: Punkte zusammenzählen +code: java +auftrag: Drei Spieler haben je zwei Runden gespielt. Lege in Java die Tabelle \`punkte\` mit den Reihen {3, 5}, {4, 1} und {2, 2} an. Zähle mit zwei verschachtelten For-Schleifen alle Punkte zusammen und gib **Summe: 17** aus. +test: - -> Summe: 17 +braucht: forSchleife +tipp: Die äußere Schleife geht durch die Reihen, die innere durch die Plätze einer Reihe. +tipp: \`int[][] punkte = {{3, 5}, {4, 1}, {2, 2}};\` und in der inneren Schleife \`summe = summe + punkte[i][j];\`. Die innere Schleife läuft bis \`punkte[i].length\`. +lösung: l16-java-punkte-loesung.visustruct +::: + +## Lückentext: Tabellen + +::: lückentext +titel: Alle Felder zusammenzählen +auftrag: Das Programm zählt alle Zahlen in der Tabelle zusammen. Ergänze die fehlenden Wörter und Zeichen. +\`\`\`java +[[int]][][] feld = {{1, 2, 3}, {4, 5, 6}}; +int summe = 0; +for (int r = 0; r < feld.[[length]]; r++) { + for (int s = 0; s < feld[r].[[length]]; s++) { + summe = summe [[+]] feld[r][s]; + } +} +System.out.println("Summe: " + summe); +\`\`\` +erklärung: \`int[][]\` ist eine Tabelle. \`feld.length\` ist die Zahl der Reihen (2), \`feld[r].length\` die Zahl der Felder in Reihe \`r\` (3). Ausgabe: **Summe: 21** +::: + +## Fehler finden: Punkte + +::: übung l16-java-fehler +titel: Spieler 2 reparieren +code: java +auftrag: In der Tabelle \`punkte\` steht jede Reihe für einen Spieler. Das Programm soll die Punkte von Spieler 2 (Reihe 1) zusammenzählen, also **Spieler 2: 11**. Stattdessen meldet es einen Fehler. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l16-java-fehler-start.visustruct +test: - -> Spieler 2: 11 +braucht: forSchleife +tipp: Bei \`punkte[a][b]\` ist \`a\` die Reihe und \`b\` der Platz in der Reihe. Welche Zahl steht für die Reihe von Spieler 2? +tipp: Die Indizes sind vertauscht: \`punkte[1][j]\` statt \`punkte[j][1]\`. +lösung: l16-java-fehler-loesung.visustruct +::: + +## Spiel: Welcher Platz? + +::: spiel frage +titel: Spiel: Welcher Platz? +intro: Ludwig verkauft Kinokarten. Erst die Reihe, dann der Platz, beide ab 0. Sieben Runden. + +runde: + boolean[][] sitze = new boolean[3][5]; + System.out.println(sitze.length); +frage: Was wird ausgegeben? +- [x] 3 +- 5 +- 15 +> \`sitze.length\` ist die Anzahl der Reihen. + +runde: + boolean[][] sitze = new boolean[3][5]; + System.out.println(sitze[0].length); +frage: Was wird ausgegeben? +- 3 +- [x] 5 +- 15 +> \`sitze[0]\` ist die Reihe 0. Ihre Länge ist die Anzahl der Plätze in dieser Reihe. + +runde: + int[][] tabelle = new int[4][6]; +frage: Wie viele Fächer hat die Tabelle? +- 10 +- [x] 24 +- 35 +> 4 Reihen mit je 6 Plätzen: 4 · 6 = 24. + +runde: + int[][] t = {{1, 2}, {3, 4}}; + System.out.println(t[1][0]); +frage: Was wird ausgegeben? +- 2 +- [x] 3 +- 4 +> Reihe 1 ist \`{3, 4}\`, darin Platz 0 die 3. + +runde: + boolean[][] sitze = new boolean[3][5]; + sitze[3][0] = true; +frage: Was passiert? +- Der erste Platz in Reihe 3 ist verkauft. +- Der erste Platz in der letzten Reihe ist verkauft. +- [x] Es gibt einen Fehler, denn die Reihen heißen 0, 1 und 2. +> Wie beim normalen Array ist der letzte Index eins weniger als die Länge. + +runde: + int[][] t = {{1, 2, 3}, {4, 5, 6}}; + int summe = 0; + for (int reihe = 0; reihe < t.length; reihe++) { + for (int platz = 0; platz < t[reihe].length; platz++) { + summe = summe + t[reihe][platz]; + } + } + System.out.println(summe); +frage: Was wird ausgegeben? +- 6 +- 15 +- [x] 21 +> Die zwei Schleifen besuchen alle sechs Fächer: 1 + 2 + 3 + 4 + 5 + 6 = 21. + +runde: +frage: Zwei Schleifen gehen den Saal \`new boolean[3][5]\` durch. Welches Fach kommt direkt nach \`sitze[0][4]\`? +- \`sitze[0][5]\` +- [x] \`sitze[1][0]\` +- \`sitze[1][4]\` +> Reihe 0 ist fertig. Die äußere Schleife zählt weiter, und der Platz beginnt wieder bei 0. +::: + +## 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. + +::: checkliste +- Ich kann ein 2D-Array anlegen und erklären, was die beiden Zahlen bedeuten. → Ein Kinosaal als Tabelle +- Ich kann ein Fach mit Reihe und Platz lesen und schreiben. → Ein Fach ansprechen +- Ich kann \`sitze.length\` und \`sitze[0].length\` unterscheiden. → Ein Fach ansprechen +- Ich kann erklären, in welcher Reihenfolge zwei verschachtelte Schleifen die Fächer besuchen. → Zwei Schleifen ineinander +- Ich kann in Java ein zweidimensionales Array anlegen und durchlaufen. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Wie viele Fächer hat \`boolean[][] sitze = new boolean[4][6]\`? +→ Ein Kinosaal als Tabelle +- [ ] 10 +- [x] 24 +- [ ] 46 +> 4 Reihen mit je 6 Plätzen: 4 · 6 = 24. + +? Was steht nach \`new boolean[3][5]\` in allen Fächern? +→ Ein Kinosaal als Tabelle +- [ ] true +- [x] false +- [ ] Nichts, die Fächer sind leer +> Ein neues boolean-Array ist mit false gefüllt. Im Kino heißt das: alle Plätze frei. + +? Zwei verschachtelte Schleifen laufen über 3 Reihen mit 5 Plätzen. Wie oft wird der Inhalt der **inneren** Schleife ausgeführt? +→ Zwei Schleifen ineinander +- [ ] 3-mal +- [ ] 8-mal +- [x] 15-mal +> Für jede der 3 Reihen läuft die innere Schleife 5-mal: 3 · 5 = 15. + +? Ordne zu, was der Ausdruck im Kinosaal bedeutet. +→ Ein Fach ansprechen += sitze.length -> Anzahl der Reihen += sitze[0].length -> Anzahl der Plätze in Reihe 0 += sitze[2][4] -> Reihe 2, Platz 4 += sitze[1][0] = true -> In Reihe 1 ist Platz 0 verkauft + +? Was gibt \`sitze.length\` bei \`new boolean[3][5]\` an? +→ Ein Fach ansprechen +- [x] 3, die Zahl der Reihen +- [ ] 5, die Zahl der Plätze +- [ ] 15, alle Plätze zusammen +::: +`,Cx=`--- +titel: Zeichenketten +bereich: Grundlagen +kurz: Mit Texten arbeiten, also einzelne Zeichen lesen, Teile herausschneiden, suchen, vergleichen und zerlegen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, dass auch die Zeichen eines Strings ab 0 gezählt werden +- mit \`length()\` und \`charAt(i)\` arbeiten +- einen \`char\` von einem String unterscheiden und mit \`(int)\` und \`(char)\` den Zeichencode nutzen +- mit \`substring\` einen Teil aus einem Text schneiden +- \`indexOf\`, \`contains\`, \`toUpperCase\` und \`equals\` anwenden +- einen Text mit einer Schleife Zeichen für Zeichen durchgehen +- einen Text mit \`split\` in ein String-Array zerlegen +- in Java einen Text einlesen und mit \`equals\` vergleichen +- weitere Methoden wie \`lastIndexOf\`, \`replace\`, \`compareTo\` und \`Integer.parseInt\` anwenden +- einen Text aus einer Datei mit \`split("\\n")\` in Zeilen zerlegen +- eine Methode in der Java-API nachschlagen und ihre Beschreibung lesen +::: + +## Text ist eine Reihe von Zeichen + +Einen \`String\` kennst du schon: \`String name = "Ludwig"\`. In der Informatik heißt so ein Text auch **Zeichenkette**, weil die Zeichen wie Perlen an einer Kette hintereinander hängen. Jedes Zeichen hat einen Platz mit einem Index, genau wie bei einem Array. Auch hier wird **ab 0 gezählt**: Das erste Zeichen ist 0 Schritte vom Anfang entfernt. + +::: grafik zk-zeichen.svg +Die acht Zeichen von „Geißbock“ mit ihren Indizes 0 bis 7. +::: + +Ein String bringt **Methoden** mit. Du schreibst den Namen der Variablen, einen Punkt und die Methode: + +- \`wort.length()\` liefert die Anzahl der Zeichen, hier 8. +- \`wort.charAt(0)\` liefert das Zeichen mit dem Index 0, hier \`'G'\`. + +> Bei Strings schreibst du \`length()\` **mit** Klammern, bei Arrays \`length\` **ohne**. Das ist in Java leider so. + +Das letzte Zeichen hat wie beim Array den Index \`length() - 1\`. + +## Ein einzelnes Zeichen: char + +Für ein einzelnes Zeichen hat Java einen eigenen Datentyp: **char**, kurz für englisch *character* (Zeichen). Ein \`char\` steht in **einfachen** Anführungszeichen, ein String in doppelten: + +- \`'C'\` ist ein \`char\`: genau ein Zeichen. +- \`"C"\` ist ein String: ein Text, der nur ein Zeichen lang ist. +- Ein \`char\` hat immer genau ein Zeichen. Einen leeren \`char\` wie \`''\` gibt es nicht, einen leeren String \`""\` schon. + +\`charAt\` liefert dir so ein Zeichen aus einem Text: + +\`\`\` +char erster = wort.charAt(0) +char letzter = wort.charAt(wort.length() - 1) +\`\`\` + +Zwei \`char\` vergleichst du mit \`==\`: \`wort.charAt(0) == 'G'\` ist \`true\`. + +Hinter jedem Zeichen steckt eine Zahl, sein **Zeichencode**. Welche Zahl zu welchem Zeichen gehört, steht in der ASCII-Tabelle: \`'A'\` hat den Code 65, \`'B'\` 66, \`'C'\` 67 und so weiter bis \`'Z'\` mit 90. Mit \`(int)\` bekommst du den Code eines Zeichens, mit \`(char)\` wird aus einem Code wieder ein Zeichen: + +\`\`\` +int code = (int) 'C' +code = code + 1 +char naechstes = (char) code +\`\`\` + +Danach ist \`code\` 68 und \`naechstes\` ist \`'D'\`. So verschiebst du einen Buchstaben im Alphabet, und genau das brauchst du später bei der Caesar-Verschlüsselung. + +## Teile herausschneiden + +Mit \`substring\` schneidest du einen Teil aus dem Text: + +- \`wort.substring(0, 4)\` liefert die Zeichen von Index 0 **bis vor** Index 4, also \`"Geiß"\`. +- \`wort.substring(4)\` liefert alles ab Index 4 bis zum Ende, also \`"bock"\`. + +Das Ende gehört **nicht** mehr dazu. Praktisch ist: \`substring(0, 4)\` liefert genau 4 Zeichen. + +::: diagramm zk-zeichen.visustruct +Alle Methoden aus dieser Lektion an einem Beispiel. Gehe es in der Simulation durch und vergleiche jede Ausgabe mit der Grafik. +::: + +## Suchen und vergleichen + +Weitere Methoden, die du oft brauchst: + +| Methode | Bedeutung | Beispiel mit \`"Geißbock"\` | +|---|---|---| +| \`indexOf("bock")\` | Wo beginnt der Text? | 4 | +| \`indexOf("x")\` | nicht gefunden | -1 | +| \`contains("eiß")\` | Kommt der Text vor? | true | +| \`toUpperCase()\` | alles groß | GEISSBOCK | +| \`toLowerCase()\` | alles klein | geißbock | +| \`equals("Geißbock")\` | gleicher Text? | true | + +> Zwei Strings vergleichst du in Java mit \`equals\`, nicht mit \`==\`. Zwei einzelne Zeichen (\`char\`) vergleichst du dagegen mit \`==\`, z. B. \`wort.charAt(i) == 'e'\`. + +::: angeberwissen +Probier mal \`"Geißbock".toUpperCase()\` aus. Heraus kommt GEISSBOCK, und das Wort ist plötzlich ein Zeichen **länger**! Ein großes ß gab es auf Schreibmaschinen nie, darum wird es zu SS. Erst seit 2017 ist das große ẞ offiziell erlaubt, aber Java bleibt beim SS. In meinem Namen kommt zum Glück kein ß vor, nur im Wort Geißbock. +::: + +## Zeichen für Zeichen + +Mit einer For-Schleife gehst du einen Text Zeichen für Zeichen durch. Der Index \`i\` läuft von 0 bis \`wort.length() - 1\`, genau wie bei einem Array: + +::: diagramm zk-zaehlen.visustruct +Zählt, wie oft der Buchstabe e vorkommt. Probiere in der Simulation „Kaffeebecher“ aus und beobachte i und anzahl. +::: + +## Zerlegen mit split + +Oft stehen mehrere Angaben in einer einzigen Zeile, getrennt durch ein Zeichen, z. B. \`"Ludwig;Geißbock;7"\`. Mit \`split\` zerlegst du die Zeile an diesem Zeichen. Heraus kommt ein **String-Array**: + +\`\`\` +String[] teile = zeile.split(";") +\`\`\` + +Danach ist \`teile[0]\` gleich \`"Ludwig"\`, \`teile[1]\` gleich \`"Geißbock"\` und \`teile[2]\` gleich \`"7"\`. Mit \`teile.length\` erfährst du, wie viele Teile es sind. + +::: diagramm zk-split.visustruct +Die Zeile wird am Semikolon zerlegt und jeder Teil mit seinem Index ausgegeben. +::: + +> So sind auch CSV-Dateien aufgebaut, die du aus Tabellenkalkulationen kennst: eine Zeile pro Datensatz, die Werte durch Semikolon getrennt. + +## Übung: Initialen + +::: übung zk-initialen +titel: Initialen +auftrag: Frage nach Vorname und Nachname und gib die Initialen aus. Bei Ludwig Geißbock also \`L. G.\` +test: Ludwig, Geißbock -> L. G. +test: Ada, Lovelace -> A. L. +test: Ben, Shneiderman -> B. S. +braucht: anweisung +tipp: Die Initiale ist der erste Buchstabe eines Namens. Welche Methode liefert ein Zeichen an einer bestimmten Stelle? +tipp: Den ersten Buchstaben liefert \`vorname.charAt(0)\`. Die Ausgabe ist dann \`vorname.charAt(0) + ". " + nachname.charAt(0) + "."\` +lösung: zk-initialen-loesung.visustruct +::: + +## Übung: Rückwärts + +::: übung zk-rueckwaerts +titel: Rückwärts +auftrag: Frage nach einem Wort und gib es rückwärts aus. Aus Ludwig wird \`giwduL\`. +test: Ludwig -> giwduL +test: Anna -> annA +test: a -> a +braucht: forSchleife +tipp: Gehe das Wort Zeichen für Zeichen durch, aber von hinten nach vorn, und baue dabei einen neuen Text zusammen. +tipp: Lege \`String rueckwaerts = ""\` an. Die Schleife beginnt beim letzten Index \`wort.length() - 1\` und zählt mit \`i--\` bis 0 herunter. In jedem Durchlauf hängst du \`wort.charAt(i)\` hinten an. +lösung: zk-rueckwaerts-loesung.visustruct +::: + +## Übung: Wörter zählen + +::: übung zk-woerter +titel: Wörter zählen +auftrag: Frage nach einem Satz und gib aus, wie viele Wörter er hat, z. B. \`Wörter: 4\` bei „Ludwig ist ein Geißbock“. Die Wörter sind durch genau ein Leerzeichen getrennt. +test: Ludwig ist ein Geißbock -> Wörter: 4 +test: Hallo -> Wörter: 1 +test: Struktogramme machen Spaß -> Wörter: 3 +braucht: anweisung +tipp: Zwischen den Wörtern steht immer ein Leerzeichen. Welche Methode zerlegt einen Text an einem Zeichen? +tipp: Zerlege den Satz mit \`satz.split(" ")\` in ein String-Array. Seine Länge ist die Anzahl der Wörter. +lösung: zk-woerter-loesung.visustruct +::: + +## Jetzt in Java + +Die Methoden in dieser Lektion sind schon Java. Ein ganzes Programm mit einem Text sieht so aus: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Wie heißt du?"); +String name = scanner.next(); +System.out.println("Hallo " + name.toUpperCase() + "!"); +System.out.println("Dein Name hat " + name.length() + " Buchstaben."); +\`\`\` + +- \`scanner.next()\` liest ein Wort, also Text bis zum nächsten Leerzeichen. Für Zahlen nimmst du weiter \`scanner.nextInt()\`. +- Text steht in **doppelten** Anführungszeichen \`"Ludwig"\`, ein einzelnes Zeichen in **einfachen** \`'L'\`. +- Hinter \`length()\`, \`toUpperCase()\` und den anderen Methoden stehen immer runde Klammern, auch wenn nichts darin steht. +- Zwei Texte vergleichst du mit \`equals\`. Dabei zählt jeder Buchstabe: \`"Ludwig".equals("ludwig")\` ist false. + +::: übung l17-java-passwort +titel: Passwort prüfen +code: java +auftrag: Schreibe in Java ein Programm, das nach dem Passwort fragt. Ist es **Ludwig**, gibt es **Willkommen!** aus, sonst **Falsches Passwort**. + Achte auf Groß- und Kleinschreibung: \`ludwig\` ist falsch. +test: Ludwig -> Willkommen! +test: ludwig -> Falsches Passwort +test: Geißbock -> Falsches Passwort +braucht: verzweigung +tipp: Lies das Passwort mit \`scanner.next()\` in eine String-Variable. Dann vergleichst du in einer Verzweigung. +tipp: Die Bedingung heißt \`eingabe.equals("Ludwig")\`. Mit \`==\` klappt der Vergleich von Texten in Java nicht zuverlässig. +lösung: l17-java-passwort-loesung.visustruct +::: + +## Lückentext: Texte + +::: lückentext +titel: Ein Wort untersuchen +auftrag: Ergänze die fehlenden Methoden und Wörter. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Ein Wort?"); +[[String]] wort = scanner.next(); +System.out.println("Länge: " + wort.[[length]]()); +System.out.println("Groß: " + wort.[[toUpperCase]]()); +System.out.println("Erster Buchstabe: " + wort.[[charAt]](0)); +if (wort.[[equals]]("Ludwig")) { + System.out.println("Hallo Ludwig!"); +} +\`\`\` +erklärung: \`length()\` zählt die Zeichen, \`toUpperCase()\` macht alles groß, \`charAt(0)\` liefert das erste Zeichen. Texte vergleichst du mit \`equals\`, nicht mit \`==\`. +::: + +## Fehler finden: Initialen + +::: übung l17-java-fehler +titel: Initialen reparieren +code: java +auftrag: Das Programm liest Vor- und Nachnamen ein und soll die Initialen ausgeben. Bei Ludwig Geißbock also **L. G.** Es gibt aber **u. e.** aus. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l17-java-fehler-start.visustruct +test: Ludwig, Geißbock -> L. G. +test: Mia, Meyer -> M. M. +test: Ada, Lovelace -> A. L. +braucht: anweisung +tipp: Bei welchem Index beginnt Java zu zählen? +tipp: Das erste Zeichen hat den Index 0: \`vorname.charAt(0)\` und \`nachname.charAt(0)\`. +lösung: l17-java-fehler-loesung.visustruct +::: + +## Noch mehr Methoden + +Ein String kann noch viel mehr. Diese Methoden brauchst du auch oft: + +| Methode | Bedeutung | Beispiel | Ergebnis | +|---|---|---|---| +| \`lastIndexOf("e")\` | Wo steht das letzte e? | \`"Ziegenbock".lastIndexOf("e")\` | 4 | +| \`isEmpty()\` | Ist der Text leer? | \`"".isEmpty()\` | true | +| \`equalsIgnoreCase(…)\` | gleicher Text, egal ob groß oder klein? | \`"Ziegenbock".equalsIgnoreCase("ZIEGENBOCK")\` | true | +| \`replace(alt, neu)\` | ersetzt jede Stelle | \`"Ziegenbock".replace("bock", "käse")\` | Ziegenkäse | +| \`repeat(n)\` | den Text n-mal hintereinander | \`"Mäh".repeat(3)\` | MähMähMäh | +| \`concat(…)\` | hängt Text an, wie \`+\` | \`"Ziegen".concat("bock")\` | Ziegenbock | +| \`compareTo(…)\` | Wer kommt im Alphabet zuerst? | \`"Anna".compareTo("Ben")\` | -1 | + +\`compareTo\` liefert eine Zahl: **negativ**, wenn der Text im Alphabet vorher kommt, **0**, wenn beide gleich sind, und **positiv**, wenn er danach kommt. Damit kannst du Namen sortieren. + +Zwei Methoden gehören nicht zu einem Text, sondern zu einer Klasse. Davor steht deshalb der Name der Klasse: + +- \`Integer.parseInt("7")\` macht aus dem Text "7" die Zahl 7. Mit ihr kannst du rechnen. +- \`String.valueOf(7)\` macht aus der Zahl 7 den Text "7". + +::: diagramm zk-mehr.visustruct +Alle neuen Methoden an einem Beispiel. Gehe es in der Simulation durch und vergleiche jede Ausgabe mit der Tabelle. +::: + +## Text aus einer Datei + +Programme bekommen Text oft aus einer **Datei**. Prinzessin Zora hat Ludwig einen Brief geschrieben. Er liegt als Datei \`brief.txt\` bereit: + +::: datei brief.txt +Lieber Ludwig, +der Fuchs hat mich in seinen Turm gesperrt. +Die Tür hat ein Schloss mit einem geheimen Wort. +Das Wort findest du nur mit Java. +Bitte hilf mir! +Deine Prinzessin Zora +::: + +Diese Zeilen lesen die ganze Datei in einen String: + +\`\`\` +import java.nio.file.*; + +String brief = Files.readString(Path.of("brief.txt")); +\`\`\` + +Wie das Lesen genau funktioniert, lernst du später in einer eigenen Lektion über Dateien. Hier reicht: Danach steht der ganze Brief in \`brief\`, mit allen Zeilen. + +Am Ende jeder Zeile steht ein unsichtbares Zeichen für den **Zeilenumbruch**. In Java schreibst du es als \`"\\n"\`. Mit \`brief.split("\\n")\` zerlegst du den Brief deshalb in seine Zeilen. + +::: übung l17-java-brief +titel: Wo steckt der Fuchs? +code: java +auftrag: Im Startcode wird der Brief schon gelesen. Zerlege ihn in Zeilen und gib **Zeilen:** und die Anzahl aus. Suche dann die Zeile, in der **Fuchs** steht, und gib **Fuchs in Zeile** und ihre Nummer aus. Die erste Zeile hat die Nummer 1. +start: l17-java-brief-start.visustruct +test: - -> Zeilen: 6 | Fuchs in Zeile 2 +braucht: forSchleife, verzweigung +tipp: \`String[] zeilen = brief.split("\\n");\` zerlegt den Brief. Mit einer For-Schleife gehst du dann alle Zeilen durch. +tipp: In der Schleife prüfst du \`zeilen[i].contains("Fuchs")\`. Der Index beginnt bei 0, deshalb gibst du \`(i + 1)\` aus. Die Klammern brauchst du, damit Java rechnet und nicht 1 an den Text hängt. +lösung: l17-java-brief-loesung.visustruct +::: + +## Die Java-API + +Niemand kennt alle Methoden auswendig, auch Profis nicht. Sie schlagen nach, in der **Java-API**. API heißt Application Programming Interface. Gemeint ist die Beschreibung von allem, was Java schon mitbringt. + +Alle Methoden von String findest du hier: [String in der Java-API](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/String.html) + +Scrolle dort zur Tabelle **Method Summary**. Jede Zeile beschreibt eine Methode: + +| Spalte | Beispiel | Bedeutung | +|---|---|---| +| Modifier and Type | \`int\` | Was die Methode zurückgibt | +| Method | \`lastIndexOf(String str)\` | Name und Parameter mit ihrem Datentyp | +| Description | Returns the index within this string of the last occurrence … | Was die Methode macht | + +Die API ist auf Englisch. Dein Browser kann die Seite übersetzen. Die Namen der Methoden bleiben englisch, denn so schreibst du sie auch in Java. + +::: ludwig +Die Seite ist sehr lang. Mit Strg+F (am Mac ⌘+F) suchst du nach dem Namen der Methode und bist sofort da. +::: + +Schlag diese Methoden nach. Sie stehen nicht in dieser Lektion: + +::: quiz +? Schlag \`strip()\` nach. Was macht die Methode? +- [ ] Sie entfernt alle Leerzeichen im Text. +- [x] Sie entfernt die Leerzeichen am Anfang und am Ende. +- [ ] Sie schneidet das letzte Zeichen ab. +> Wie \`trim()\`. \`strip()\` kennt aber auch besondere Leerzeichen aus anderen Schriften. + +? Schlag \`isBlank()\` nach. Was liefert \`" ".isBlank()\`? +- [x] true +- [ ] false +- [ ] 3 +> isBlank prüft, ob der Text leer ist oder nur aus Leerzeichen besteht. \`" ".isEmpty()\` wäre dagegen false. + +? Schlag \`toCharArray()\` nach. Welchen Datentyp liefert die Methode? +- [ ] String +- [ ] String[] +- [x] char[] +> Ein Array mit allen Zeichen des Textes, für jedes Zeichen ein Fach. + +? Schlag \`indexOf\` mit zwei Parametern nach. Was liefert \`"Ziegenbock".indexOf("e", 3)\`? +- [ ] 2 +- [x] 4 +- [ ] -1 +> Die Suche beginnt erst bei Index 3. Das erste e ab dort steht bei Index 4. + +? Schlag \`startsWith\` nach. Welchen Datentyp liefert die Methode? +- [x] boolean +- [ ] int +- [ ] String +> In der Spalte „Modifier and Type“ steht boolean: Die Antwort ist true oder false. +::: + +## Spiel: Prinzessin retten + +Jetzt hilfst du Ludwig. Der Fuchs hat Prinzessin Zora in seinen Turm gesperrt, und das Tor öffnet sich nur mit einem geheimen Wort. + +::: spiel prinzessin +titel: Spiel: Prinzessin retten +intro: Auf dem Weg zum Turm kommt Ludwig an **sechs Stationen**. An jeder steht ein Stück Java-Code, und heraus kommt eine Zahl. Mit \`alphabet.charAt(zahl)\` wird aus der Zahl ein Buchstabe, der im **Kreuzworträtsel** landet. Löst du das Rätsel, ergeben die gelben Felder das geheime Wort für das Tor. + +station: Am Burggraben + String name = " Zora "; + int zahl = name.trim().length(); +frage: Welche Zahl steht in \`zahl\`? +zahl: 4 +feld: 5 1 +tipp: \`trim()\` schneidet die Leerzeichen vorne und hinten ab. Zähle danach die Zeichen. +> Nach \`trim()\` bleibt \`"Zora"\` übrig, und das sind 4 Zeichen. + +station: Im Fuchswald + String ort = "Fuchsbau"; + int zahl = ort.length(); +frage: Welche Zahl steht in \`zahl\`? +zahl: 8 +feld: 4 4 +tipp: \`length()\` zählt alle Zeichen. Zähle F-u-c-h-s-b-a-u. +> „Fuchsbau“ hat 8 Zeichen. + +station: Am Ziegenfelsen + String wort = "Ziegenbock"; + int zahl = wort.indexOf("bock"); +frage: Welche Zahl steht in \`zahl\`? +zahl: 6 +feld: 4 6 +tipp: \`indexOf\` gibt die Stelle zurück, an der „bock“ anfängt. Das Z hat den Index 0. +> Z i e g e n hat die Indizes 0 bis 5, also beginnt „bock“ bei Index 6. + +station: Auf der Turmtreppe + String wort = "Prinzessin"; + int zahl = wort.indexOf("s", 7); +frage: Welche Zahl steht in \`zahl\`? Schlag \`indexOf(String str, int fromIndex)\` in der Java-API nach. +zahl: 7 +feld: 6 6 +tipp: Die Suche beginnt bei Index 7, und Index 7 zählt schon mit. Schreib dir die Indizes unter die Buchstaben. +> P r i n z e s s i n hat die Indizes 0 bis 9. Ab Index 7 gesucht, steht das erste „s“ genau bei 7. + +station: Vor der Fuchshöhle + int zahl = "Zora".compareTo("Zoe"); +frage: Welche Zahl steht in \`zahl\`? +zahl: 13 +feld: 1 9 +tipp: \`compareTo\` sucht die erste Stelle, an der sich die Texte unterscheiden, und rechnet die Differenz der Zeichencodes aus. \`'r'\` ist 114, \`'e'\` ist 101. +> „Zo“ ist gleich, dann kommt \`'r'\` gegen \`'e'\`: 114 − 101 = 13. + +station: Am Turmtor + int zahl = Integer.parseInt("1" + "1") / 5; +frage: Welche Zahl steht in \`zahl\`? +zahl: 2 +feld: 6 5 +tipp: Zuerst werden die Texte verbunden, dann wird daraus eine Zahl. Bei \`int\` wird beim Teilen der Rest weggelassen. +> \`"1" + "1"\` ist \`"11"\`, \`parseInt\` macht daraus 11, und 11 / 5 ist bei ganzen Zahlen 2. + +kreuzwort: Die blauen Buchstaben hast du schon. Fülle die anderen Felder mit Fachbegriffen aus Java. Klick auf einen Hinweis, um zum Wort zu springen. +- → 1 3 BOOLEAN: Datentyp für wahr oder falsch +- → 4 1 STRING: Datentyp für Text, also für eine Zeichenkette +- → 6 5 CHAR: Datentyp für ein einzelnes Zeichen +- ↓ 1 6 LENGTH: Methode, die die Zeichen eines Strings zählt +- ↓ 2 1 ELSE: Der „sonst“-Teil einer Verzweigung +- ↓ 3 3 BREAK: Springt sofort aus einer Schleife heraus +lösung: 1 3, 4 3, 2 6, 6 7, 7 3 + +tor: Ludwig steht vor dem Tor. Das Schloss vergleicht dein Wort mit \`equals\`. Trag das geheime Wort ein. + String wort = "___"; + if (wort.equals(geheimesWort)) { + tor.oeffnen(); + } +ende: Zora ist frei, und der Fuchs ist schnell davongelaufen. Das geheime Wort war \`BREAK\`: Mit \`break\` kommt man aus jeder Schleife heraus, und Zora aus dem Turm. +::: + +## 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. + +::: checkliste +- Ich kann erklären, dass auch die Zeichen eines Strings ab 0 gezählt werden. → Text ist eine Reihe von Zeichen +- Ich kann mit \`length()\` und \`charAt(i)\` arbeiten. → Text ist eine Reihe von Zeichen +- Ich kann einen \`char\` von einem String unterscheiden und mit \`(int)\` und \`(char)\` den Zeichencode nutzen. → Ein einzelnes Zeichen: char +- Ich kann mit \`substring\` einen Teil aus einem Text schneiden. → Teile herausschneiden +- Ich kann \`indexOf\`, \`contains\`, \`toUpperCase\` und \`equals\` anwenden. → Suchen und vergleichen +- Ich kann einen Text mit einer Schleife Zeichen für Zeichen durchgehen. → Zeichen für Zeichen +- Ich kann einen Text mit \`split\` in ein String-Array zerlegen. → Zerlegen mit split +- Ich kann in Java einen Text einlesen und mit \`equals\` vergleichen. → Jetzt in Java +- Ich kann weitere Methoden wie \`lastIndexOf\`, \`replace\`, \`compareTo\` und \`Integer.parseInt\` anwenden. → Noch mehr Methoden +- Ich kann einen Text aus einer Datei mit \`split("\\n")\` in Zeilen zerlegen. → Text aus einer Datei +- Ich kann eine Methode in der Java-API nachschlagen und ihre Beschreibung lesen. → Die Java-API +::: + +## Wissenstest + +::: quiz +? Was liefert \`"Ludwig".charAt(1)\`? +→ Text ist eine Reihe von Zeichen +- [ ] L +- [x] u +- [ ] d +> Gezählt wird ab 0: L hat den Index 0, u den Index 1. + +? Was ist \`'C'\`? +→ Ein einzelnes Zeichen: char +- [x] ein \`char\`, also genau ein Zeichen +- [ ] ein String +- [ ] eine Variable mit dem Namen C +> Einfache Anführungszeichen stehen für ein einzelnes Zeichen, also einen \`char\`. \`"C"\` in doppelten wäre ein String. + +? \`'A'\` hat den Zeichencode 65. Was ergibt \`(char) 67\`? +→ Ein einzelnes Zeichen: char +- [ ] 'B' +- [x] 'C' +- [ ] 67 +> 65 ist A, 66 ist B, 67 ist C. Mit \`(char)\` wird aus dem Code wieder ein Zeichen. + +? Was liefert \`"Struktogramm".substring(0, 6)\`? +→ Teile herausschneiden +- [x] Strukt +- [ ] Struktog +- [ ] truktog +> Die Zeichen mit den Indizes 0 bis 5. Das Ende 6 gehört nicht mehr dazu. + +? Ein Wort hat 7 Zeichen. Welchen Index hat das letzte Zeichen? +→ Text ist eine Reihe von Zeichen +- [ ] 7 +- [x] 6 +- [ ] 8 +> Wie beim Array: immer eins weniger als die Länge. + +? Wie vergleichst du in Java zwei Strings auf gleichen Inhalt? +→ Suchen und vergleichen +- [ ] a == b +- [x] a.equals(b) +- [ ] a = b + +? Ordne jeder Methode zu, was sie bei \`"Geißbock"\` liefert. +→ Suchen und vergleichen += length() -> 8 += charAt(0) -> G += indexOf("bock") -> 4 += substring(4) -> bock + +? Welche Bedingung prüft in Java, ob in \`eingabe\` der Text Ludwig steht? +→ Jetzt in Java +- [ ] eingabe = "Ludwig" +- [ ] eingabe == 'Ludwig' +- [x] eingabe.equals("Ludwig") +> Texte vergleichst du mit equals. Einfache Anführungszeichen sind nur für ein einzelnes Zeichen. + +? Was liefert \`Integer.parseInt("12") + 1\`? +→ Noch mehr Methoden +- [ ] "121" +- [x] 13 +- [ ] eine Fehlermeldung +> parseInt macht aus dem Text eine Zahl. Danach rechnet Java ganz normal. +::: +`,jx=`--- +titel: Aufruf und Aussprung +bereich: Grundlagen +kurz: Große Aufgaben in Unterprogramme zerlegen und Schleifen vorzeitig verlassen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- eine große Aufgabe in Teilprobleme zerlegen +- einen Aufruf einfügen und ein Unterprogramm in einem eigenen Reiter bauen +- einem Unterprogramm mit Parametern Werte übergeben +- mit return einen Rückgabewert liefern und ihn beim Aufruf speichern +- erklären, warum ein Unterprogramm eine Zahl nicht verändern kann, ein Array aber schon +- erklären, was ein Aussprung macht und warum er in einer Verzweigung steht +- eine Schleife mit einem Aussprung oder über ihre Bedingung beenden +- in Java eine Methode erkennen und eine Schleife mit \`break\` verlassen +::: + +## Große Aufgaben zerlegen + +Lange Struktogramme werden schnell unübersichtlich. Deshalb zerlegst du eine große Aufgabe in **Teilprobleme**. Jedes Teilproblem bekommt einen eigenen Namen und ein eigenes Struktogramm, ein **Unterprogramm**. + +Ein Quiz besteht zum Beispiel aus drei Teilen: begrüßen, Fragen stellen, Ergebnis zeigen. Das Hauptprogramm nennt nur noch diese drei Teile: + +::: diagramm l15-hauptprogramm.visustruct +Das Hauptprogramm besteht nur aus drei Aufrufen. Was in jedem Teil passiert, steht in einem eigenen Struktogramm. +::: + +So siehst du auf einen Blick, wie das Programm aufgebaut ist. Die Einzelheiten stehen woanders. + +## Der Aufruf + +Ein **Aufruf** ist ein Kasten mit doppelten senkrechten Linien links und rechts. Er bedeutet: Führe hier das Unterprogramm mit diesem Namen aus und mache danach weiter. + +- Du ziehst **Aufruf** aus dem Bereich Elemente und schreibst den Namen hinein, z. B. \`zeigeBegruessung()\`. +- Die runden Klammern am Ende zeigen, dass es ein Unterprogramm ist. So schreibt man es auch in Java, Python und JavaScript. +- Das Unterprogramm selbst baust du als eigenes Struktogramm in einem neuen Reiter. Als Titel trägst du denselben Namen ein. + +::: diagramm l15-unterprogramm.visustruct +Das Unterprogramm zeigeBegruessung() als eigenes Struktogramm. +::: + +> **In der Simulation:** Erreicht die Simulation einen Aufruf, sucht sie unter den offenen Reitern das Struktogramm mit diesem Titel und führt es aus. Danach macht sie im Hauptprogramm weiter. Solange das Unterprogramm läuft, bleibt der Aufruf-Kasten markiert. Ein Unterprogramm wie dieses, nur mit Namen als Titel, teilt sich die Variablen mit dem Hauptprogramm. Wie ein Unterprogramm eigene Variablen bekommt, lernst du gleich. Gibt es keinen passenden Reiter, überspringt die Simulation den Aufruf und zeigt einen Hinweis. + +::: angeberwissen +Warum sagt dein Lehrer bei Java immer „Methode“ und nie „Funktion“ oder „Prozedur“? Weil in Java jedes Unterprogramm zu einer Klasse gehören muss, und Unterprogramme einer Klasse heißen Methoden. Den Unterschied gibt es trotzdem: Liefert eine Methode ein Ergebnis zurück, ist sie eigentlich eine Funktion. Steht \`void\` davor, liefert sie nichts und ist eigentlich eine Prozedur. Java ist da einfach bequem und nennt beide Methode. Ich auch: Meine Methode heißt Fressen. +::: + +## Übung: Aufruf einbauen + +::: übung l15-titel +titel: Begrüßung mit Aufruf +auftrag: Stell dir vor, das Unterprogramm \`zeigeTitel()\` gibt es schon. Baue das Hauptprogramm: Es ruft zuerst \`zeigeTitel()\` auf. Danach fragt es nach dem Namen und gibt **Hallo** und den Namen aus. + Bei der Eingabe Ada erscheint also **Hallo Ada**. +test: Ada -> Hallo Ada +test: Ben -> Hallo Ben +braucht: aufruf +tipp: Das Hauptprogramm hat drei Teile: den Aufruf, die Eingabe und die Ausgabe. +tipp: Ziehe einen Aufruf aus dem Bereich Elemente ganz nach oben und schreibe \`zeigeTitel()\` hinein. Darunter kommen die Eingabe \`input: String name "Wie heißt du?"\` und die Ausgabe. +lösung: l15-titel-loesung.visustruct +::: + +## Werte übergeben: Parameter + +Oft soll ein Unterprogramm mit Werten arbeiten, die erst beim Aufruf feststehen. Dann bekommt es als Titel eine **Kopfzeile**: + +\`\`\` +void zeigeSumme(int a, int b) +\`\`\` + +- \`void\` heißt: Das Unterprogramm liefert kein Ergebnis zurück. +- \`zeigeSumme\` ist der Name. +- In den Klammern stehen die **Parameter**: Variablen mit Datentyp, die beim Aufruf ihre Werte bekommen. Mehrere trennst du mit Komma. + +::: diagramm l15-zeige-summe.visustruct +Das Unterprogramm mit der Kopfzeile als Titel. Es rechnet mit a und b, als wären es normale Variablen. +::: + +Im Aufruf-Kasten schreibst du die Werte in die Klammern, z. B. \`zeigeSumme(3, 4)\`. Der erste Wert kommt in \`a\`, der zweite in \`b\`. Statt Zahlen gehen auch Variablen und Rechnungen wie \`zeigeSumme(x, x + 1)\`. + +::: diagramm l15-zeige-summe-haupt.visustruct +Das Hauptprogramm ruft zeigeSumme zweimal mit anderen Werten auf. Öffne beide Diagramme und starte hier die Simulation. +::: + +> **Lokale Variablen:** Die Parameter und alle Variablen, die im Unterprogramm entstehen, gehören nur dem Unterprogramm. Es bekommt **Kopien** der Werte, mehr dazu weiter unten bei der Wertübergabe (call by value). In der Simulation siehst du während des Aufrufs nur die Variablen des Unterprogramms. + +## Ergebnis zurückgeben: return + +Ein Unterprogramm kann auch ein Ergebnis liefern, den **Rückgabewert**. Dann steht in der Kopfzeile statt \`void\` der Datentyp des Ergebnisses: + +\`\`\` +int quadrat(int x) +\`\`\` + +Die Anweisung \`return ergebnis\` gibt den Wert zurück und beendet das Unterprogramm sofort. Beim Aufruf speicherst du das Ergebnis in einer Variablen: Nach \`int q = quadrat(5)\` steht in \`q\` der Wert 25. + +::: diagramm l15-quadrat.visustruct +Das Unterprogramm quadrat rechnet und gibt das Ergebnis mit return zurück. +::: + +::: diagramm l15-quadrat-haupt.visustruct +Das Hauptprogramm speichert den Rückgabewert in q. Öffne beide Diagramme und probiere die Simulation aus. +::: + +> Ein Unterprogramm mit Rückgabewert muss mit \`return\` enden. Fehlt das return, meldet die Simulation einen Fehler. + +In der **Code-Ansicht** wird aus der Kopfzeile eine Java-Methode (\`public static int quadrat(int x)\`), in Python ein \`def\` und in JavaScript eine \`function\`. Sind die Unterprogramme in anderen Reitern offen, stehen sie beim Hauptprogramm mit im Code. + +## Übung: Fläche berechnen + +::: übung l15-flaeche +titel: Fläche berechnen +auftrag: Baue zwei Diagramme. Das Unterprogramm \`int flaeche(int a, int b)\` gibt die Fläche eines Rechtecks zurück, also a mal b. Das Hauptprogramm fragt nach Länge und Breite, ruft \`flaeche\` auf und gibt **Fläche:** und das Ergebnis aus. + Bei 3 und 4 erscheint **Fläche: 12**. +test: 3, 4 -> Fläche: 12 +test: 5, 5 -> Fläche: 25 +test: 7, 0 -> Fläche: 0 +braucht: aufruf +tipp: Du baust zwei Diagramme: ein Unterprogramm, das nur rechnet und das Ergebnis zurückgibt, und ein Hauptprogramm für Eingabe und Ausgabe. +tipp: Lege mit **+** einen neuen Reiter an und gib ihm den Titel \`int flaeche(int a, int b)\`. Darin reicht eine Anweisung: \`return a * b\`. Im Hauptprogramm schreibst du in den Aufruf-Kasten \`int f = flaeche(laenge, breite)\`. +lösung: l15-flaeche-loesung.visustruct +unterprogramm: l15-flaeche-unterprogramm-loesung.visustruct +::: + +## Kopie oder Original: call by value und call by reference + +Was passiert, wenn ein Unterprogramm seinen Parameter verändert? Das hängt davon ab, **was** übergeben wird. + +**Wertübergabe**, englisch **call by value**: Bei \`int\`, \`double\`, \`boolean\`, \`char\` und \`String\` bekommt das Unterprogramm eine **Kopie** des Werts. Ändert es seinen Parameter, bleibt die Variable des Aufrufers, wie sie war. + +**Referenzübergabe**, englisch **call by reference**: Bei einem **Array** bekommt das Unterprogramm keine Kopie, sondern einen Verweis auf dasselbe Array. Ändert es ein Fach, ist das Fach auch beim Aufrufer geändert. Die Kopfzeile dafür sieht so aus: + +\`\`\` +void leeren(boolean[] plaetze) +\`\`\` + +::: grafik uebergabe.svg +Oben bekommt verdopple eine Kopie von zahl. Unten zeigen reihe und plaetze auf dasselbe Array. +::: + +Probiere beides aus. Öffne die drei Diagramme und starte im Hauptprogramm die Simulation: + +::: diagramm uebergabe-verdopple.visustruct +verdopple ändert nur seine Kopie x. +::: + +::: diagramm uebergabe-leeren.visustruct +leeren setzt alle Plätze auf false, zum Beispiel wenn eine Vorstellung ausfällt. +::: + +::: diagramm uebergabe-haupt.visustruct +zahl ist nach dem Aufruf immer noch 5. Die Plätze in reihe sind nach dem Aufruf dagegen frei. +::: + +> Willst du mit einer Zahl aus einem Unterprogramm etwas zurückbekommen, nimmst du \`return\`, z. B. \`zahl = verdopple(zahl)\` mit der Kopfzeile \`int verdopple(int x)\`. Ein Array dagegen kann das Unterprogramm direkt verändern. + +::: angeberwissen +Ganz genau genommen kennt Java nur die Wertübergabe, also call by value. Bei einem Array wird aber nicht das ganze Array kopiert, sondern nur seine **Adresse** im Speicher. Mit der kopierten Adresse findet das Unterprogramm dasselbe Array. Das ist so, als würde ich dir eine Kopie meines Schließfachschlüssels geben: Der Schlüssel ist kopiert, das Heu im Fach gibt es nur einmal. +::: + +## Übung: Bonuspunkte + +::: übung uebergabe-bonus +titel: Bonuspunkte +auftrag: Das Hauptprogramm ruft \`bonus(punkte)\` auf und gibt danach alle Punkte aus. Baue das Unterprogramm \`void bonus(int[] punkte)\`, das jede Punktzahl im Array um 1 erhöht. Statt 3, 5 und 8 erscheinen dann **4**, **6** und **9**. +start: uebergabe-bonus-start.visustruct +test: - -> 4 | 6 | 9 +braucht: aufruf +tipp: Das Hauptprogramm ist schon fertig. Du baust nur das Unterprogramm in einem neuen Reiter. +tipp: Lege mit **+** einen neuen Reiter mit dem Titel \`void bonus(int[] punkte)\` an. Darin läuft eine For-Schleife über alle Fächer und rechnet \`punkte[i] = punkte[i] + 1\`. Ein return brauchst du nicht, denn das Array wird direkt geändert. +lösung: uebergabe-bonus-loesung.visustruct +unterprogramm: uebergabe-bonus-unterprogramm-loesung.visustruct +::: + +## Der Aussprung + +Manchmal soll eine Schleife **vorzeitig** enden, mitten im Rumpf. Dafür gibt es den **Aussprung**. Er verlässt sofort die Schleife, in der er steht. Das Programm macht mit dem ersten Kasten nach der Schleife weiter. In Java, Python und JavaScript heißt das \`break\`. + +Den Aussprung erkennst du an der Spitze am linken Rand. In den Kasten kannst du einen kurzen Kommentar schreiben, z. B. \`Schleife verlassen\`. Er erscheint im Code als Kommentar hinter \`break\`. + +Ein Aussprung steht fast immer in einer **Verzweigung**: Nur wenn eine Bedingung zutrifft, wird die Schleife verlassen. + +Typisch ist die **Endlosschleife mit Aussprung**. Die Schleife selbst hat keine Bedingung. Sie läuft so lange, bis der Aussprung erreicht wird: + +::: diagramm l15-endlos-aussprung.visustruct +Die Schleife fragt immer wieder nach einer Zahl. Bei 0 springt sie heraus, sonst zählt sie die Zahl zur Summe. +::: + +Ohne Aussprung würde eine Endlosschleife wirklich nie enden. + +## Aussprung in der Simulation + +Die Simulation führt den Aussprung aus wie \`break\`: Sie verlässt die innerste Schleife und macht nach ihr weiter. Steht ein Aussprung außerhalb jeder Schleife, endet das Unterprogramm, im Hauptprogramm das ganze Programm. Dasselbe macht \`return\`. + +Oft geht es auch ganz ohne Aussprung: Du schreibst die Abbruchbedingung direkt in die Schleife. Das ist meist sogar übersichtlicher. + +## Übung: Summe bis 0 + +::: übung l15-bis-null +titel: Summe bis 0 +auftrag: Baue das Programm „Summe bis 0“ **ohne** Aussprung nach. Es fragt so lange nach ganzen Zahlen, bis jemand 0 eingibt. Danach gibt es **Summe:** und die Summe aller eingegebenen Zahlen aus. +test: 3, 4, 0 -> Summe: 7 +test: 0 -> Summe: 0 +test: 10, -2, 5, 0 -> Summe: 13 +tipp: Ohne Aussprung muss die Bedingung der Schleife selbst prüfen, ob die 0 eingegeben wurde. +tipp: Frage die erste Zahl schon vor der Schleife ab. Die While-Schleife läuft mit der Bedingung \`zahl != 0\`. Im Rumpf zählst du die Zahl zur Summe und fragst danach die nächste Zahl ab. Bei der zweiten Eingabe schreibst du nur \`input: zahl "…"\`, weil es \`zahl\` schon gibt. +lösung: l15-bis-null-loesung.visustruct +::: + +## Jetzt in Java + +Ein Unterprogramm heißt in Java **Methode**. Das Quadrat von oben sieht so aus: + +\`\`\`java +public static int quadrat(int x) { + int ergebnis = x * x; + return ergebnis; +} +\`\`\` + +Das Hauptprogramm ruft die Methode mit ihrem Namen auf und gibt ihr den Wert in runden Klammern mit: + +\`\`\`java +int q = quadrat(zahl); +System.out.println("Das Quadrat ist " + q); +\`\`\` + +- In der Kopfzeile steht vor dem Namen, was die Methode zurückgibt (\`int\`). Gibt sie nichts zurück, steht dort \`void\`. +- Die Parameter stehen mit Datentyp in den runden Klammern: \`(int x)\`. Mehrere trennst du mit Komma. +- Im Bereich Code schreibst du jede Methode in einen eigenen Reiter, so wie jedes Unterprogramm ein eigenes Struktogramm hat. +- Der Aussprung heißt in Java \`break\`. Mit \`while (true)\` baust du eine Schleife, die nur durch \`break\` endet. + +::: übung l18-java-kasse +titel: Kasse mit break +code: java +auftrag: Schreibe in Java eine Kasse. Sie fragt immer wieder nach einem Preis in ganzen Euro. Bei 0 verlässt sie die Schleife mit \`break\`. Danach gibt sie aus, wie viele Artikel es waren und was alles zusammen kostet. + Bei 3, 4 und dann 0 erscheint **Artikel: 2** und **Gesamt: 7**. +test: 3, 4, 0 -> Artikel: 2 | Gesamt: 7 +test: 0 -> Artikel: 0 | Gesamt: 0 +test: 10, 2, 5, 0 -> Artikel: 3 | Gesamt: 17 +braucht: endlosschleife, aussprung +tipp: Du brauchst zwei Variablen, die vor der Schleife mit 0 anfangen: eine für die Summe und eine für die Anzahl. +tipp: In \`while (true) { … }\` liest du den Preis ein. Gleich danach prüfst du \`if (preis == 0) { break; }\`. Erst dahinter zählst du den Preis zur Summe und die Anzahl um 1 hoch. +lösung: l18-java-kasse-loesung.visustruct +::: + +## Lückentext: Methoden und break + +::: lückentext +titel: Methode und Aussprung +auftrag: Ergänze die fehlenden Wörter. Oben steht die Methode, die ein Quadrat ausrechnet. Darunter steht das Hauptprogramm, das sie aufruft. Im Bereich Code stehen beide in eigenen Reitern. +\`\`\`java +public static [[int]] quadrat(int x) { + [[return]] x * x; +} +\`\`\` +\`\`\`java +int zahl = 1; +while ([[true]]) { + int q = [[quadrat]](zahl); + if (q > 50) { + [[break]]; + } + System.out.println(q); + zahl = zahl + 1; +} +\`\`\` +erklärung: \`int\` vor dem Methodennamen heißt: Die Methode gibt eine ganze Zahl zurück, und zwar mit \`return\`. Gibt eine Methode nichts zurück, steht dort \`void\`. \`while (true)\` läuft endlos, bis \`break\` die Schleife verlässt. Ausgabe: 1, 4, 9, 16, 25, 36 und 49. +::: + +## Fehler finden: Raten + +::: übung l18-java-fehler +titel: Versuche zählen reparieren +code: java +auftrag: Beim Zahlenraten ist die gesuchte Zahl 7. Das Programm fragt so lange nach einem Tipp, bis die 7 kommt, und gibt dann die Zahl der Versuche aus. Bei 3, 5 und 7 waren es 3 Versuche, das Programm sagt aber **Versuche: 2**. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l18-java-fehler-start.visustruct +test: 3, 5, 7 -> Versuche: 3 +test: 7 -> Versuche: 1 +test: 1, 2, 3, 7 -> Versuche: 4 +braucht: endlosschleife, aussprung +tipp: Was passiert beim richtigen Tipp? Wird er noch mitgezählt, bevor \`break\` die Schleife verlässt? +tipp: Zähle zuerst hoch und prüfe danach: \`versuche = versuche + 1;\` gehört vor das \`if\` mit dem \`break\`. +lösung: l18-java-fehler-loesung.visustruct +::: + +## Spiel: Was kommt zurück? + +::: spiel frage +titel: Spiel: Was kommt zurück? +intro: Ludwig ruft Methoden auf und springt aus Schleifen. Sag vorher, was ausgegeben wird. Sieben Runden. + +runde: + public static int quadrat(int x) { + return x * x; + } + + int q = quadrat(5); + System.out.println(q); +frage: Was wird ausgegeben? +- 5 +- 10 +- [x] 25 +> Der Aufruf gibt 5 in x, return liefert 5 · 5 zurück. + +runde: + public static void zeigeSumme(int a, int b) { + System.out.println(a + b); + } + + int x = 2; + zeigeSumme(x, x + 1); +frage: Was wird ausgegeben? +- [x] 5 +- 23 +- 3 +> Der erste Wert 2 kommt in a, der zweite 3 in b. In Java rechnet \`a + b\` mit Zahlen ganz normal. + +runde: +frage: Was liefert eine Methode zurück, vor deren Namen \`void\` steht? +- eine ganze Zahl +- [x] nichts +- immer 0 +> \`void\` heißt: kein Rückgabewert. Steht dort \`int\`, kommt eine ganze Zahl zurück. + +runde: + public static void verdopple(int x) { + x = x * 2; + } + + int zahl = 5; + verdopple(zahl); + System.out.println(zahl); +frage: Was wird ausgegeben? +- [x] 5 +- 10 +- 0 +> Call by value: verdopple bekommt eine Kopie. zahl bleibt 5. + +runde: + public static void leeren(boolean[] plaetze) { + for (int i = 0; i < plaetze.length; i++) { + plaetze[i] = false; + } + } + + boolean[] reihe = {true, true}; + leeren(reihe); + System.out.println(reihe[0]); +frage: Was wird ausgegeben? +- true +- [x] false +> Bei einem Array zeigen reihe und plaetze auf dasselbe Array. Die Änderung sieht auch der Aufrufer. + +runde: + int summe = 0; + for (int i = 1; i <= 10; i++) { + if (i == 4) { + break; + } + summe = summe + i; + } + System.out.println(summe); +frage: Was wird ausgegeben? +- [x] 6 +- 10 +- 55 +> Bei i = 4 springt \`break\` sofort aus der Schleife. Gezählt sind nur 1 + 2 + 3. + +runde: + int zahl = 1; + while (true) { + zahl = zahl * 3; + if (zahl > 20) { + break; + } + } + System.out.println(zahl); +frage: Was wird ausgegeben? +- 9 +- 20 +- [x] 27 +> 3, 9, 27. Erst 27 ist größer als 20, dann endet die Endlosschleife mit break. +::: + +## 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. + +::: checkliste +- Ich kann eine große Aufgabe in Teilprobleme zerlegen. → Große Aufgaben zerlegen +- Ich kann einen Aufruf einfügen und ein Unterprogramm in einem eigenen Reiter bauen. → Der Aufruf +- Ich kann einem Unterprogramm mit Parametern Werte übergeben. → Werte übergeben: Parameter +- Ich kann mit return einen Rückgabewert liefern und ihn beim Aufruf speichern. → Ergebnis zurückgeben: return +- Ich kann erklären, warum ein Unterprogramm eine Zahl nicht verändern kann, ein Array aber schon. → Kopie oder Original: call by value und call by reference +- Ich kann erklären, was ein Aussprung macht und warum er in einer Verzweigung steht. → Der Aussprung +- Ich kann eine Schleife mit einem Aussprung oder über ihre Bedingung beenden. → Aussprung in der Simulation +- Ich kann in Java eine Methode erkennen und eine Schleife mit \`break\` verlassen. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Was bedeutet ein Aufruf-Kasten mit dem Text \`zeigeErgebnis()\`? +→ Der Aufruf +- [ ] Das Programm endet hier. +- [x] Hier wird das Unterprogramm zeigeErgebnis() ausgeführt, danach geht es weiter. +- [ ] Hier wird das Wort zeigeErgebnis() ausgegeben. + +? Wo geht es nach einem Aussprung weiter? +→ Der Aussprung +- [ ] Am Anfang der Schleife +- [x] Beim ersten Kasten nach der Schleife +- [ ] Ganz am Anfang des Programms +> Der Aussprung verlässt die Schleife, in der er steht. In Java, Python und JavaScript heißt er break. + +? Warum steht ein Aussprung meistens in einer Verzweigung? +→ Der Aussprung +- [x] Damit die Schleife nur verlassen wird, wenn eine Bedingung zutrifft +- [ ] Weil ein Aussprung sonst nicht gespeichert werden kann +- [ ] Weil eine Verzweigung selbst eine Schleife ist +> Ohne Verzweigung würde die Schleife schon im ersten Durchlauf verlassen. + +? Wo findet die Simulation das Unterprogramm zu einem Aufruf \`zeigeErgebnis()\`? +→ Der Aufruf +- [ ] Es muss im selben Struktogramm stehen. +- [x] In einem offenen Reiter mit dem Titel zeigeErgebnis() +- [ ] Die Simulation kann keine Unterprogramme ausführen. +> Baue jedes Unterprogramm in einem eigenen Reiter und gib ihm als Titel den Namen aus dem Aufruf. + +? Das Unterprogramm hat die Kopfzeile \`void zeigeSumme(int a, int b)\`. Welcher Aufruf passt? +→ Werte übergeben: Parameter +- [ ] zeigeSumme() +- [x] zeigeSumme(3, 4) +- [ ] int s = zeigeSumme(3, 4) +> Zwei Parameter brauchen zwei Werte. Und \`void\` heißt: Es kommt nichts zurück, das man speichern könnte. + +? Nach \`int q = quadrat(5)\` steht in q die 25. Was steht im Unterprogramm quadrat am Ende? +→ Ergebnis zurückgeben: return +- [ ] output: x * x +- [x] return x * x +- [ ] q = x * x +> Mit return gibt das Unterprogramm den Wert an den Aufruf zurück. Eine Ausgabe würde ihn nur anzeigen. + +? \`void verdopple(int x)\` rechnet \`x = x * 2\`. Im Hauptprogramm steht \`int zahl = 5\` und dann der Aufruf \`verdopple(zahl)\`. Welchen Wert hat zahl danach? +→ Kopie oder Original: call by value und call by reference +- [x] 5 +- [ ] 10 +- [ ] 0 +> Wertübergabe (call by value): verdopple hat nur eine Kopie von zahl verändert. + +? \`void leeren(boolean[] plaetze)\` setzt alle Fächer auf false. Was gilt nach \`leeren(reihe)\` für das Array reihe im Hauptprogramm? +→ Kopie oder Original: call by value und call by reference +- [ ] Es ist unverändert, weil das Unterprogramm eine Kopie bekommt. +- [x] Alle Fächer sind false, weil plaetze und reihe dasselbe Array sind. +- [ ] Das Array ist gelöscht. +> Referenzübergabe (call by reference): Ein Array wird als Referenz übergeben. Änderungen an den Fächern sieht auch der Aufrufer. + +? Wie heißt ein Unterprogramm in Java? +→ Jetzt in Java +- [ ] Klasse +- [x] Methode +- [ ] Schleife +> In Java ist ein Unterprogramm eine Methode, zum Beispiel die \`main\`-Methode. Je nach Art sagt man auch Prozedur oder Funktion. + +? Viele Bausteine haben in Schulbüchern einen zweiten Namen. Ordne jedem Begriff aus VisuStruct den anderen Namen zu. +→ Jetzt in Java += Verzweigung -> Bedingte Anweisung += Fallauswahl -> Mehrfachauswahl += Schleife -> Wiederholungsstruktur += Array -> Feld += Unterprogramm -> Methode +> Beide Namen meinen dasselbe. Wenn du einen davon kennst, verstehst du auch den anderen. + +? Was steht in Java in der Kopfzeile einer Methode, die nichts zurückgibt? +→ Ergebnis zurückgeben: return +- [ ] int +- [x] void +- [ ] return +> void heißt „leer“: Die Methode macht etwas, gibt aber keinen Wert zurück. +::: +`,Px=`--- +titel: Suchen und Sortieren +bereich: Grundlagen +kurz: Mit Spielkarten verstehen, wie lineare und binäre Suche und Bubblesort arbeiten und warum manche Verfahren viel schneller sind. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, wie die lineare Suche ein Array durchsucht +- eine lineare Suche als Struktogramm bauen +- erklären, warum die binäre Suche nur bei sortierten Werten funktioniert +- begründen, warum die binäre Suche bei vielen Werten viel schneller ist +- einen Durchgang von Bubblesort mit Spielkarten vormachen +- in Java ein Array durchsuchen und Treffer zählen +::: + +## Eine Karte suchen + +Du hast einen Stapel Spielkarten verdeckt in einer Reihe vor dir liegen. Gesucht ist die 9. Was machst du? Du drehst eine Karte nach der anderen um, bis du die 9 findest oder alle Karten umgedreht hast. + +::: grafik ss-lineare-suche.svg +Die Karten liegen durcheinander. Jede umgedrehte Karte ist ein Vergleich: Ist das die 9? +::: + +Genau so arbeitet die **lineare Suche**: Sie geht das Array vom Index 0 bis zum Ende durch und vergleicht jedes Fach mit dem gesuchten Wert. Sie funktioniert immer, auch wenn die Werte durcheinander liegen. + +Im Array stehen unsere Karten als Zahlen. Bube, Dame und König lassen wir weg. + +::: diagramm ss-lineare-suche.visustruct +Die Schleife läuft, bis die Karte gefunden ist oder kein Fach mehr übrig ist. Die Variable vergleiche zählt mit, wie oft verglichen wurde. Suche in der Simulation die 2, die 27 und die 4. +::: + +> Ist die Karte nicht dabei, bleibt \`position\` bei **-1**. Einen Index -1 gibt es nicht, darum bedeutet -1 hier „nicht gefunden“. + +## Übung: Karte suchen + +::: übung ss-karte-suchen +titel: Karte suchen +auftrag: Lege das Array \`int[] karten = {8, 4, 11, 4, 6}\` an und frage nach einer Karte. Gib die Position der **ersten** passenden Karte aus, z. B. \`Position: 1\` bei der 4. Ist die Karte nicht dabei, gib \`Nicht gefunden\` aus. +test: 4 -> Position: 1 +test: 6 -> Position: 4 +test: 8 -> Position: 0 +test: 9 -> Nicht gefunden +braucht: whileSchleife, verzweigung +tipp: Gehe das Array von vorn nach hinten durch und vergleiche jede Karte mit der gesuchten. +tipp: Baue das Beispiel oben nach. Die Variable vergleiche brauchst du hier nicht. Die Schleife muss aufhören, sobald \`position\` nicht mehr -1 ist, sonst findest du bei der 4 die zweite statt der ersten. +lösung: ss-karte-suchen-loesung.visustruct +::: + +## Binäre Suche: sortiert geht es schneller + +Jetzt liegen die Karten **sortiert** vor dir, von klein nach groß. Gesucht ist die 27. Du drehst nicht mehr vorne die erste Karte um, sondern die **mittlere**: + +- Ist sie die gesuchte, bist du fertig. +- Ist sie kleiner, kann die gesuchte Karte nur noch rechts liegen. Die ganze linke Hälfte fällt weg. +- Ist sie größer, fällt die rechte Hälfte weg. + +Mit dem Rest machst du dasselbe noch einmal. Bei jedem Vergleich halbiert sich der Stapel. + +::: grafik ss-binaere-suche.svg +Drei Vergleiche statt vierzehn: Mit jeder Mitte fällt die Hälfte der übrigen Karten weg. +::: + +Im Struktogramm merken sich zwei Variablen den Bereich, in dem noch gesucht wird: \`links\` und \`rechts\`. Die Mitte ist \`(links + rechts) / 2\`. Weil das eine Ganzzahldivision ist, kommt immer ein ganzer Index heraus. + +::: diagramm ss-binaere-suche.visustruct +Dasselbe Array wie bei der linearen Suche. Suche in der Simulation wieder die 27 und vergleiche die Ausgabe Vergleiche mit der linearen Suche. +::: + +> Die binäre Suche funktioniert **nur bei sortierten Werten**. Bei durcheinander liegenden Karten weißt du nach dem Blick auf die Mitte nicht, in welcher Hälfte du weitersuchen musst. + +::: angeberwissen +Ich denke mir eine Zahl von 1 bis 100, du darfst raten und ich sage nur „größer“ oder „kleiner“. Mit der binären Suche brauchst du höchstens **7** Versuche. Bei einer Zahl bis eine Million sind es höchstens 20, bei einer Milliarde 30. Jede Verdopplung kostet nur einen einzigen Versuch mehr. So suchen auch Datenbanken in Millionen von Einträgen in Sekundenbruchteilen. Ich suche übrigens linear: Ich fresse die Wiese von links nach rechts ab. +::: + +## Wie schnell ist das? + +Wie gut ein Verfahren ist, misst man an der Zahl der Vergleiche, die es **im schlimmsten Fall** braucht. Bei der linearen Suche ist das der Fall, dass die Karte ganz hinten liegt oder fehlt. + +::: grafik ss-vergleiche.svg +Bei 100 Karten braucht die lineare Suche bis zu 100 Vergleiche, die binäre höchstens 7. +::: + +| Anzahl Karten | Lineare Suche | Binäre Suche | +|---|---|---| +| 10 | 10 | 4 | +| 100 | 100 | 7 | +| 1 000 | 1 000 | 10 | +| 1 000 000 | 1 000 000 | 20 | + +Die lineare Suche wächst im gleichen Maß wie die Kartenzahl. Bei der binären Suche kommt bei doppelt so vielen Karten nur **ein** Vergleich dazu. + +## Sortieren mit Bubblesort + +Für die binäre Suche müssen die Werte sortiert sein. Eines der einfachsten Sortierverfahren ist **Bubblesort**. Du gehst die Reihe von links nach rechts durch und vergleichst immer **zwei Nachbarn**. Steht die größere Karte links, tauschst du die beiden. + +::: grafik ss-bubblesort.svg +Nach einem Durchgang steht die größte Karte ganz rechts. +::: + +Nach dem ersten Durchgang steht die größte Karte ganz rechts, wie eine Luftblase, die nach oben steigt. Daher kommt der Name. Danach wiederholst du den Durchgang für die übrigen Karten. Bei 5 Karten brauchst du 4 Durchgänge. + +Im Struktogramm stecken zwei For-Schleifen ineinander. Die äußere zählt die Durchgänge, die innere vergleicht die Nachbarn \`karten[i]\` und \`karten[i + 1]\`. Das Tauschen kennst du schon: Es braucht eine **Hilfsvariable**. + +::: diagramm ss-bubblesort.visustruct +Die innere Schleife wird mit jedem Durchgang kürzer, weil rechts schon die größten Karten richtig stehen. Gehe es in der Simulation mit Schritt durch und beobachte das Array unter Variablen. +::: + +Bubblesort ist leicht zu verstehen, aber langsam. Bei n Karten braucht es bis zu n · (n − 1) / 2 Vergleiche: bei 10 Karten 45, bei 100 Karten schon 4 950 und bei 1 000 Karten fast eine halbe Million. Schnellere Verfahren wie Quicksort lernst du vielleicht später kennen. + +## Übung: Absteigend sortieren + +::: übung ss-absteigend +titel: Absteigend sortieren +auftrag: Das Startdiagramm liest 5 Karten ein und sortiert sie mit Bubblesort **aufsteigend**, also von klein nach groß. Ändere es so, dass die Karten **absteigend** ausgegeben werden, die größte zuerst. +start: ss-absteigend-start.visustruct +test: 3, 1, 4, 1, 5 -> 5 | 4 | 3 | 1 | 1 +test: 10, 20, 30, 40, 50 -> 50 | 40 | 30 | 20 | 10 +test: 2, 9, 2, 7, 6 -> 9 | 7 | 6 | 2 | 2 +braucht: forSchleife, verzweigung +tipp: Schau dir die Bedingung in der Verzweigung an. Sie entscheidet, wann zwei Nachbarn getauscht werden. +tipp: Du musst nur ein einziges Zeichen ändern. Wann sollen zwei Nachbarn getauscht werden, wenn die größere Karte nach links soll? +lösung: ss-absteigend-loesung.visustruct +::: + +## Jetzt in Java + +Die lineare Suche aus der Übung sieht in Java so aus: + +\`\`\`java +int[] karten = {8, 4, 11, 4, 6}; +int gesucht = 4; +int position = -1; +int i = 0; +while (position == -1 && i < karten.length) { + if (karten[i] == gesucht) { + position = i; + } + i = i + 1; +} +System.out.println("Position: " + position); +\`\`\` + +- \`&&\` heißt „und“: Die Schleife läuft nur, solange noch nichts gefunden ist **und** es noch Karten gibt. +- Ist der false-Zweig leer, lässt du \`else\` einfach weg. +- Der Tausch beim Bubblesort braucht auch in Java eine Hilfsvariable: \`int hilf = karten[i];\` + +::: übung l19-java-zaehlen +titel: Karten zählen +code: java +auftrag: Die Karten {8, 4, 11, 4, 6} liegen in einem Array. Schreibe in Java ein Programm, das nach einer Karte fragt und zählt, wie oft sie vorkommt. Es gibt **Anzahl:** und die Zahl aus. + Bei 4 erscheint **Anzahl: 2**. +test: 4 -> Anzahl: 2 +test: 8 -> Anzahl: 1 +test: 9 -> Anzahl: 0 +braucht: forSchleife, verzweigung +tipp: Anders als bei der Suche hörst du beim ersten Treffer nicht auf. Eine For-Schleife geht alle Karten durch. +tipp: \`for (int i = 0; i < karten.length; i++)\` und darin \`if (karten[i] == gesucht) { anzahl = anzahl + 1; }\`. \`anzahl\` startet vor der Schleife mit 0. +lösung: l19-java-zaehlen-loesung.visustruct +::: + +## Lückentext: Bubblesort + +::: lückentext +titel: Karten sortieren +auftrag: Das Programm sortiert die Karten mit Bubblesort aufsteigend. Ergänze die fehlenden Wörter und Zeichen. +\`\`\`java +int[] karten = {5, 2, 8, 1}; +for (int runde = 0; runde < karten.[[length]] - 1; runde++) { + for (int i = 0; i < karten.length - 1; i++) { + if (karten[i] [[>]] karten[i + 1]) { + [[int]] hilf = karten[i]; + karten[i] = karten[i + 1]; + karten[i + 1] = [[hilf]]; + } + } +} +for (int i = 0; i < karten.length; i++) { + System.out.println(karten[i]); +} +\`\`\` +erklärung: Ist eine Karte größer als ihre rechte Nachbarin, werden die beiden getauscht, mit einer Hilfsvariablen wie beim Gläsertauschen. Nach \`length - 1\` Runden ist alles sortiert: 1, 2, 5, 8. +::: + +## Fehler finden: Suche + +::: übung l19-java-fehler +titel: Lineare Suche reparieren +code: java +auftrag: Die Karten {8, 4, 11, 4, 6} liegen in einem Array. Das Programm soll die **erste** Position der gesuchten Karte ausgeben, bei 4 also **Position: 1**. Es gibt aber **Position: 3** aus. + „Im Editor öffnen“ zeigt den Code im Bereich Code. Finde den Fehler, repariere ihn und klicke auf Prüfen. +start: l19-java-fehler-start.visustruct +test: 4 -> Position: 1 +test: 6 -> Position: 4 +test: 9 -> Position: -1 +test: 8 -> Position: 0 +braucht: whileSchleife, verzweigung +tipp: Die Schleife läuft immer bis zur letzten Karte. Was passiert, wenn die 4 ein zweites Mal kommt? +tipp: Die Schleife soll aufhören, sobald etwas gefunden ist: \`while (position == -1 && i < karten.length)\`. +lösung: l19-java-fehler-loesung.visustruct +::: + +## Spiel: Suchprofi + +::: spiel frage +titel: Spiel: Suchprofi +intro: Ludwig sucht und sortiert Karten. Wie schnell geht das, und was kommt heraus? Sieben Runden. + +runde: + int[] karten = {8, 4, 11, 4, 6}; + int gesucht = 4; + int position = -1; + int i = 0; + while (position == -1 && i < karten.length) { + if (karten[i] == gesucht) { + position = i; + } + i = i + 1; + } + System.out.println("Position: " + position); +frage: Was wird ausgegeben? +- [x] Position: 1 +- Position: 3 +- Position: 2 +> Die Suche hört bei der ersten 4 auf. Sie liegt im Fach 1, gezählt wird ab 0. + +runde: + int[] karten = {8, 4, 11, 4, 6}; + int gesucht = 7; +frage: Mit derselben linearen Suche: Was steht danach in position? +- 0 +- 5 +- [x] -1 +> Die 7 ist nicht dabei. position bleibt bei -1, das bedeutet „nicht gefunden“. + +runde: +frage: Bei welchen Karten funktioniert die binäre Suche? +- bei allen +- [x] nur bei sortierten +- nur bei weniger als 100 +> Nur wenn die Karten sortiert sind, weißt du nach dem Blick auf die Mitte, in welcher Hälfte du weitersuchen musst. + +runde: +frage: Wie viele Vergleiche braucht die binäre Suche bei 100 Karten höchstens? +- 50 +- [x] 7 +- 100 +> Jeder Vergleich halbiert den Stapel. 7-mal halbieren reicht bis 128 Karten, also auch für 100. + +runde: +frage: Statt 1 000 Karten sind es jetzt 2 000. Wie viele Vergleiche braucht die binäre Suche höchstens mehr? +- [x] einen +- doppelt so viele +- 1 000 +> Der erste Vergleich halbiert 2 000 auf 1 000. Danach geht es weiter wie vorher. + +runde: + int[] karten = {5, 3, 8, 1}; +frage: Ein Durchgang Bubblesort vergleicht von links nach rechts immer zwei Nachbarn. Wie liegen die Karten danach? +- 1, 3, 5, 8 +- [x] 3, 5, 1, 8 +- 3, 5, 8, 1 +> 5 und 3 tauschen, 5 und 8 bleiben, 8 und 1 tauschen. Die größte Karte ist ganz rechts. + +runde: +frage: Bubblesort tauscht \`karten[i]\` und \`karten[i + 1]\`. Was braucht es dafür? +- [x] eine Hilfsvariable +- ein zweites Array +- eine binäre Suche +> Wie beim Tauschen zweier Variablen: \`int hilf = karten[i];\`, sonst geht ein Wert verloren. +::: + +## 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. + +::: checkliste +- Ich kann erklären, wie die lineare Suche ein Array durchsucht. → Eine Karte suchen +- Ich kann eine lineare Suche als Struktogramm bauen. → Übung: Karte suchen +- Ich kann erklären, warum die binäre Suche nur bei sortierten Werten funktioniert. → Binäre Suche: sortiert geht es schneller +- Ich kann begründen, warum die binäre Suche bei vielen Werten viel schneller ist. → Wie schnell ist das? +- Ich kann einen Durchgang von Bubblesort mit Spielkarten vormachen. → Sortieren mit Bubblesort +- Ich kann in Java ein Array durchsuchen und Treffer zählen. → Jetzt in Java +::: + +## Wissenstest + +::: quiz +? Welche Voraussetzung braucht die binäre Suche? +→ Binäre Suche: sortiert geht es schneller +- [ ] Das Array muss genau 100 Fächer haben. +- [x] Die Werte müssen sortiert sein. +- [ ] Der gesuchte Wert muss vorkommen. +> Nur bei sortierten Werten weißt du nach dem Blick auf die Mitte, in welcher Hälfte du weitersuchst. + +? Ein sortiertes Array hat 1 000 Werte. Wie viele Vergleiche braucht die binäre Suche höchstens? +→ Wie schnell ist das? +- [ ] 500 +- [ ] 100 +- [x] 10 +> 1 000 → 500 → 250 → 125 → 63 → 32 → 16 → 8 → 4 → 2 → 1: Nach etwa 10 Halbierungen bleibt ein Wert übrig. + +? Was vergleicht Bubblesort in jedem Schritt? +→ Sortieren mit Bubblesort +- [ ] Die erste und die letzte Karte +- [x] Zwei benachbarte Karten +- [ ] Jede Karte mit der Mitte +> Steht die größere Karte links, werden die Nachbarn getauscht. + +? Wo steht nach dem ersten Durchgang von Bubblesort die größte Karte? +→ Sortieren mit Bubblesort +- [ ] Ganz links +- [ ] In der Mitte +- [x] Ganz rechts +> Sie wird bei jedem Vergleich weitergetauscht und steigt wie eine Blase nach rechts. + +? Was bedeutet \`position = -1\` in der linearen Suche? +→ Eine Karte suchen +- [x] Die Karte wurde (noch) nicht gefunden. +- [ ] Die Karte liegt ganz hinten. +- [ ] Das Array ist leer. + +? Ordne jedem Verfahren die passende Beschreibung zu. +→ Eine Karte suchen += Lineare Suche -> eine Karte nach der anderen ansehen += Binäre Suche -> die Mitte ansehen und eine Hälfte weglassen += Bubblesort -> Nachbarn vergleichen und tauschen + +? Warum nimmst du zum Zählen eine For-Schleife und keine Suche, die beim ersten Treffer aufhört? +→ Jetzt in Java +- [ ] Eine For-Schleife ist immer schneller. +- [x] Du musst jede Karte ansehen, sonst fehlen spätere Treffer. +- [ ] Eine While-Schleife kann keine Arrays durchlaufen. +> Die Karte kann mehrmals vorkommen. Darum gehst du alle Karten bis zum Ende durch. +::: +`,Dx=`--- +titel: Struktogramm und Code +bereich: Vom Struktogramm zum Code +kurz: Alle Elemente in Java auf einen Blick, Code erzeugen, im Bereich Code Java schreiben, ausführen und Fehler suchen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- die Code-Ansicht öffnen und Java als Sprache wählen +- Ausgabe, Eingabe, Verzweigung und Schleifen in Java erkennen +- den Unterschied zwischen Snippet und Class erklären +- ein kurzes Java-Programm als Struktogramm nachbauen +- im Bereich Code Java tippen und das entstehende Struktogramm lesen +- ein Programm mit ▶︎ ausführen und Ein- und Ausgaben in der Konsole nutzen +- Haltepunkte setzen und ein Programm im Einzelschritt verfolgen +::: + +## Die Code-Ansicht + +In den Lektionen 4 bis 19 hast du jedes Element schon einmal in Java geschrieben. Hier siehst du alles auf einen Blick und lernst, wie VisuStruct aus einem ganzen Struktogramm ein Java-Programm macht. + +Ein Struktogramm beschreibt einen Ablauf. Damit ein Computer ihn ausführt, brauchst du ein Programm in einer Programmiersprache. VisuStruct schreibt diesen Code für dich. + +Klicke bei den Werkzeugen auf [Code](#zeige-code) (Symbol mit spitzen Klammern). Rechts erscheint der **Code-Generator**: + +- Oben wählst du die Sprache: **Java**, **Python** oder **JavaScript**. +- Bei Java wählst du zusätzlich **Snippet** (nur die Anweisungen) oder **Class** (eine vollständige Java-Datei). +- **Diagramm-Text als Kommentare** schreibt den Text jedes Kastens als Kommentar über den Code. +- **Kopieren** legt den Code in die Zwischenablage, **Java speichern …** speichert eine \`.java\`-Datei. + +Der Code ändert sich sofort mit, wenn du am Struktogramm etwas änderst. + +::: angeberwissen +Nassi hat später an der Programmiersprache Ada mitgearbeitet und war bei Apple für Software zuständig. Wer Struktogramme erfindet, landet also nicht im Ziegenstall, sondern bei Apple. +::: + +::: diagramm l17-beispiel.visustruct +Ein kleines Programm mit Eingabe, For-Schleife und Verzweigung. Öffne es und schau dir den Java-Code dazu an. +::: + +## So sieht das Beispiel in Java aus + +Für das Diagramm oben erzeugt VisuStruct als **Snippet** diesen Code: + +\`\`\` +// import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Welche Reihe?"); +int zahl = scanner.nextInt(); +for (int i = 1; i <= 3; i++) { + int ergebnis = zahl * i; + System.out.println(i + " mal " + zahl + " = " + ergebnis); +} +if (zahl > 10) { + System.out.println("Das war schwer!"); +} else { + System.out.println("Das war leicht."); +} +\`\`\` + +Jede Anweisung endet in Java mit einem **Semikolon** \`;\`. Was in einem Kasten steht, steht in Java in **geschweiften Klammern** \`{ }\`. Die Einrückung zeigt dir, was zusammengehört. + +## Die Elemente in Java + +| Element | Java | Lektion | +|---|---|---| +| Anweisung | \`int summe = 0;\` | 4, 5 | +| Ausgabe | \`System.out.println(summe);\` | 6 | +| Eingabe | \`int zahl = scanner.nextInt();\` | 6 | +| Verzweigung | \`if (bedingung) { … } else { … }\` | 8, 9 | +| Fallauswahl | \`switch (wert) { case 1 -> { … } default -> { … } }\` | 10 | +| While-Schleife | \`while (bedingung) { … }\` | 11 | +| Do-while-Schleife | \`do { … } while (bedingung);\` | 12 | +| For-Schleife | \`for (int i = 0; i < 5; i++) { … }\` | 13 | +| Endlosschleife | \`while (true) { … }\` | 11, 18 | +| Aussprung | \`break;\` | 18 | +| Aufruf | \`berechne();\` | 18 | +| Array | \`int[] zahlen = new int[5];\` | 15, 16 | +| Text (String) | \`String name = scanner.next();\` | 17 | + +Für Eingaben steht ganz oben einmal \`import java.util.Scanner;\` und \`Scanner scanner = new Scanner(System.in);\`. Vor jeder Eingabe gibt VisuStruct die Frage mit \`System.out.println(…)\` aus. + +Ist der Nein-Zweig einer Verzweigung leer, erzeugt VisuStruct trotzdem einen \`else\`-Teil, in dem nur der Kommentar \`// empty element\` steht. Wenn du **Leeren else-Zweig im Code ausgeben** ausschaltest, fällt der leere \`else\`-Teil weg. + +## Snippet oder Class + +Ein **Snippet** kannst du in ein vorhandenes Java-Programm in die \`main\`-Methode einfügen. Mit **Class** bekommst du eine vollständige Datei, die du sofort übersetzen und starten kannst: + +\`\`\` +import java.util.Scanner; + +public class Einmaleins { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + System.out.println("Welche Reihe?"); + int zahl = scanner.nextInt(); + ... + } // Ende main +} // Ende Klasse +\`\`\` + +Die Kommentare \`// Ende main\` und \`// Ende Klasse\` hinter den letzten beiden Klammern sind nicht nötig, aber sehr hilfreich: So siehst du sofort, welche Klammer was schließt, und vergisst keine. + +Der Name der Klasse kommt aus dem **Titel** des Diagramms. Die Datei muss genauso heißen, hier also \`Einmaleins.java\`. Das erledigt **Java speichern …** für dich. + +> Der erzeugte Code ist ein guter Anfang, aber prüfe ihn. Legst du eine Variable zuerst an und liest sie später mit einer Eingabe neu ein, schreibt VisuStruct trotzdem \`int pin = scanner.nextInt();\`. Java meldet dann, dass es \`pin\` schon gibt. Lösche in dieser Zeile einfach das \`int\`. + +::: angeberwissen +Jede übersetzte Java-Datei (\`.class\`) beginnt mit denselben vier Bytes, in Hexadezimal geschrieben: \`CA FE BA BE\`. Daran erkennt der Computer, dass es Java ist. Das „Kaffee-Baby“ hat sich James Gosling ausgedacht, passend zum Kaffee im Namen. +::: + +## Der Java-Sprachmodus + +Unter dem [Zahnrad](#zeige-einstellungen) oben rechts kannst du **Code-Keywords** einschalten. Dann heißen die Bausteine im Bereich Elemente so wie die Befehle in Java: \`if\`, \`switch\`, \`for\`, \`while\`, \`do\`, \`while(true)\`, \`break\` und \`call\`. Die übrige Oberfläche bleibt in deiner Sprache. + +Das hilft dir, die Kästen und die Java-Befehle einander zuzuordnen. Dein Diagramm selbst bleibt dabei unverändert. + +## Java direkt schreiben + +Bisher hast du zuerst das Struktogramm gezeichnet und dann den Code angesehen. Im Bereich [Code](#zeige-codelive) geht es auch andersherum. Klicke rechts auf die schmale Leiste **Code**. Neben dem Struktogramm erscheint eine Spalte, in die du Java selbst tippst. + +- **Struktogramm zu Code:** Änderst du etwas im Struktogramm, ändert sich der Java-Code sofort mit. +- **Code zu Struktogramm:** Tippst du Java, baut VisuStruct beim Tippen das Struktogramm dazu. Fehlt noch etwas, zum Beispiel eine schließende Klammer \`}\`, steht unter dem Code ein Hinweis. +- **Vorschläge:** Beim Tippen schlägt VisuStruct Vorlagen vor, etwa für \`if\`, \`for\` oder \`while\`. Mit der Eingabetaste übernimmst du eine Vorlage. Grau geschriebene Platzhalter ersetzt du einfach durch deinen Text. +- **Einrücken:** Ist dein Code durcheinandergeraten, klicke oben im Bereich Code auf den Knopf **Einrücken**. Jede Ebene steht dann vier Leerzeichen tiefer, wie in Eclipse oder IntelliJ. Hast du Zeilen markiert, rückt VisuStruct nur diese ein. + +So kannst du beide Wege ausprobieren. Erst das Struktogramm zeichnen ist gut, um einen Ablauf zu planen. Direkt Code schreiben ist schneller, wenn du schon weißt, was du willst. Das Struktogramm hilft dir dann, deinen Code zu kontrollieren. + +## Das Programm ausführen + +Oben im Bereich Code startet [▶︎ Ausführen](#zeige-ausfuehren) dein Programm, **■ Stopp** bricht es ab, zum Beispiel bei einer Endlosschleife. Was dein Programm ausgibt, erscheint unten in der [Konsole](#zeige-konsole). Fragt es nach einer Eingabe, tippst du sie dort ein und drückst die Eingabetaste. + +Die Grenze zwischen Code und Konsole kannst du mit der Maus nach oben oder unten ziehen. + +> Der Bereich Code versteht die Java-Befehle, die es auch als Kasten im Struktogramm gibt. Eigene Klassen und Objekte kennt es noch nicht. Fenster mit Swing gehen trotzdem: Schalte dafür im Zahnrad **Echtes Java (mit Swing)** ein (Lektion „Dein erstes Fenster“). + +::: angeberwissen +Profis nennen ein Programm, in dem man Code schreibt, ausführt und Fehler sucht, eine **IDE** (Integrated Development Environment). Mit dem Bereich Code ist VisuStruct eine kleine IDE mit eingebautem Struktogramm. +::: + +## Fehler suchen mit dem Debugger + +Manchmal läuft ein Programm, rechnet aber falsch. Dann hilft der **Debugger**: Er führt dein Programm langsam aus, und du schaust ihm dabei zu. + +- **Haltepunkt:** Klicke links auf eine Zeilennummer. Ein roter Punkt erscheint. [▶︎ Ausführen](#zeige-ausfuehren) hält vor dieser Zeile an. Ein zweiter Klick nimmt den Punkt wieder weg. +- **Gelbe Zeile:** Sie wird als Nächstes ausgeführt. Im Struktogramm ist der passende Kasten markiert. +- **Variablen:** Unter dem Code steht, welchen Wert jede Variable gerade hat. Was sich seit dem letzten Anhalten geändert hat, leuchtet kurz gelb. +- **Einzelschritt:** Der Knopf [Einzelschritt](#zeige-einzelschritt) neben ▶︎ führt genau eine Zeile aus und hält wieder an. Ohne Haltepunkt startet er das Programm und hält vor der ersten Zeile. +- **Weiter:** ▶︎ läuft bis zum nächsten Haltepunkt oder bis zum Ende. **■ Stopp** bricht ab. + +Probier es mit diesem Programm aus. Setze einen Haltepunkt in Zeile 3 und drücke mehrmals ▶︎. Wie wachsen \`i\` und \`summe\`? + +\`\`\` +int summe = 0; +for (int i = 1; i <= 4; i++) { + summe = summe + i; +} +System.out.println("Summe: " + summe); +\`\`\` + +::: ludwig +Das ist ein Schreibtischtest, nur dass der Computer für dich mitschreibt. Überleg dir vor jedem Schritt, welchen Wert die Variable gleich haben müsste. Stimmt die Tabelle nicht mit deiner Vermutung überein, hast du die Stelle mit dem Fehler gefunden. +::: + +## Übung: Erst Code, dann Struktogramm + +Diesmal zeichnest du nicht. Öffne den Bereich Code und tippe diesen Java-Code ab: + +\`\`\` +System.out.println("Startzahl?"); +int zahl = scanner.nextInt(); +while (zahl > 0) { + System.out.println(zahl); + zahl = zahl - 1; +} +System.out.println("Start!"); +\`\`\` + +::: übung l20-countdown +titel: Countdown +bereich: beide +auftrag: Tippe den Java-Code oben im Bereich Code ab. Führe ihn mit ▶︎ aus und gib in der Konsole eine Startzahl ein. + Sieh dir dann das Struktogramm an, das dabei entstanden ist, und klicke auf Prüfen. +test: 3 -> 3 | 2 | 1 | Start! +test: 1 -> 1 | Start! +test: 0 -> Start! +braucht: whileSchleife +tipp: Öffne den Bereich Code mit der schmalen Leiste ganz rechts und tippe einfach los. +tipp: Achte auf das Semikolon am Ende jeder Anweisung und auf die geschweiften Klammern der While-Schleife. Unter dem Code steht ein Hinweis, wenn noch etwas fehlt. +lösung: l20-countdown-loesung.visustruct +::: + +## Übung: Java als Struktogramm + +Jetzt andersherum: Hier ist ein Stück Java-Code. Baue es als Struktogramm nach. + +\`\`\` +System.out.println("Zahl eingeben"); +int n = scanner.nextInt(); +int fakultaet = 1; +for (int i = 1; i <= n; i++) { + fakultaet = fakultaet * i; +} +System.out.println(fakultaet); +\`\`\` + +::: übung l17-fakultaet +titel: Fakultät aus Java +bereich: beide +auftrag: Baue den Java-Code oben als Struktogramm nach. Das Programm liest eine Zahl n ein und gibt das Produkt 1 · 2 · … · n aus. + Kontrolliere am Ende in der Code-Ansicht, ob dein Java-Code genauso aussieht. +test: 3 -> 6 +test: 5 -> 120 +test: 1 -> 1 +braucht: forSchleife +tipp: Lies den Java-Code Zeile für Zeile und überlege, welcher Kasten zu jeder Zeile passt. +tipp: Die beiden ersten Java-Zeilen sind zusammen eine einzige Eingabe: \`input: int n "Zahl eingeben"\`. Die For-Schleife hat die drei Felder \`int i = 1\`, \`i <= n\` und \`i++\`. +lösung: l17-fakultaet-loesung.visustruct +::: + +## Übung: else if + +In Java schreibt man mehrere Fälle oft als \`else if\`: + +\`\`\` +if (alter < 6) { + System.out.println("Eintritt frei"); +} else if (alter < 18) { + System.out.println("Kinderticket: 4 Euro"); +} else { + System.out.println("Erwachsenenticket: 8 Euro"); +} +\`\`\` + +Im Struktogramm gibt es kein \`else if\`. Dort steckt eine zweite Verzweigung im Nein-Zweig der ersten. Steht im Nein-Zweig nur diese eine Verzweigung, macht VisuStruct beim Erzeugen des Codes daraus wieder \`else if\`, in Python \`elif\`. + +::: übung l17-ticket +titel: Ticketpreis +auftrag: Frage nach dem Alter als ganze Zahl und baue den Java-Code oben als Struktogramm nach. +test: 5 -> Eintritt frei +test: 6 -> Kinderticket: 4 Euro +test: 17 -> Kinderticket: 4 Euro +test: 18 -> Erwachsenenticket: 8 Euro +braucht: verzweigung +tipp: Im Java-Code steckt in einem \`else\` ein weiteres \`if\`. Im Struktogramm ist das eine Verzweigung in einem Zweig. +tipp: Ziehe in den false-Zweig der ersten Verzweigung eine zweite Verzweigung mit der Bedingung \`alter < 18\`. +lösung: l17-ticket-loesung.visustruct +::: + +## Spiel: Welcher Kasten? + +::: spiel frage +titel: Spiel: Welcher Kasten? +intro: Ludwig zeigt dir Java. Welcher Kasten aus dem Struktogramm steckt dahinter? Acht Runden. +frage: Welcher Kasten ist das? + +runde: + do { + zahl = zahl * 2; + } while (zahl < 100); +- While-Schleife +- [x] Do-while-Schleife +- For-Schleife +> Die Bedingung steht unten. Der Rumpf läuft also mindestens einmal. + +runde: + switch (wahl) { + case 1 -> { System.out.println("Wasser"); } + default -> { System.out.println("Gibt es nicht."); } + } +- Verzweigung +- [x] Fallauswahl +- Aufruf +> Eine Variable wird mit festen Werten verglichen: Das ist die Fallauswahl. + +runde: + break; +- Aufruf +- Endlosschleife +- [x] Aussprung +> \`break\` verlässt sofort die Schleife, in der es steht. + +runde: + berechne(); +- [x] Aufruf +- Ausgabe +- Anweisung +> Name mit runden Klammern: Hier wird ein Unterprogramm aufgerufen. + +runde: + int zahl = scanner.nextInt(); +- Ausgabe +- [x] Eingabe +- Aufruf +> Der Scanner liest einen Wert ein. Das ist eine Eingabe. + +runde: + while (true) { + System.out.println("Hallo"); + } +- While-Schleife mit Bedingung +- [x] Endlosschleife +- Do-while-Schleife +> \`while (true)\` hat keine echte Bedingung. Nur ein break könnte sie beenden. + +runde: +frage: Du willst eine vollständige Java-Datei, die du sofort übersetzen und starten kannst. Was wählst du in der Code-Ansicht? +- Snippet +- [x] Class +> Ein Snippet sind nur die Anweisungen für die \`main\`-Methode. Class erzeugt die ganze Datei. + +runde: +frage: Im Debugger ist eine Zeile gelb. Was bedeutet das? +- Sie hat einen Fehler. +- [x] Sie wird als Nächstes ausgeführt. +- Dort steht ein Haltepunkt. +> Gelb ist die nächste Zeile. Ein Haltepunkt ist ein roter Punkt an der Zeilennummer. +::: + +## 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. + +::: checkliste +- Ich kann die Code-Ansicht öffnen und Java als Sprache wählen. → Die Code-Ansicht +- Ich kann Ausgabe, Eingabe, Verzweigung und Schleifen in Java erkennen. → Die Elemente in Java +- Ich kann den Unterschied zwischen Snippet und Class erklären. → Snippet oder Class +- Ich kann ein kurzes Java-Programm als Struktogramm nachbauen. → Übung: Java als Struktogramm +- Ich kann im Bereich Code Java tippen und das entstehende Struktogramm lesen. → Java direkt schreiben +- Ich kann ein Programm mit ▶︎ ausführen und Ein- und Ausgaben in der Konsole nutzen. → Das Programm ausführen +- Ich kann Haltepunkte setzen und ein Programm im Einzelschritt verfolgen. → Fehler suchen mit dem Debugger +::: + +## Wissenstest + +::: quiz +? Wie sieht \`output: "Hallo"\` in Java aus? +→ Die Elemente in Java +- [ ] print("Hallo") +- [x] System.out.println("Hallo"); +- [ ] console.log("Hallo"); +> print ist Python, console.log ist JavaScript. + +? Woher kommt der Klassenname bei Class? +→ Snippet oder Class +- [ ] Er heißt immer Main. +- [x] Aus dem Titel des Diagramms +- [ ] Aus dem ersten Kasten +> Ohne Titel heißt die Klasse Main. + +? Welcher Java-Code gehört zu einer Do-while-Schleife? +→ Die Elemente in Java +- [ ] while (bedingung) { … } +- [x] do { … } while (bedingung); +- [ ] for (;;) { … } +> Bei do-while steht die Bedingung am Ende, deshalb läuft der Rumpf mindestens einmal. + +? Was wird aus einem Aussprung im Java-Code? +→ Die Elemente in Java +- [x] break; +- [ ] return; +- [ ] exit(); + +? Was passiert an einem roten Punkt vor der Zeilennummer? +→ Fehler suchen mit dem Debugger +- [ ] Die Zeile wird übersprungen. +- [x] Das Programm hält vor dieser Zeile an. +- [ ] Die Zeile enthält einen Fehler. +> Das ist ein Haltepunkt. Danach geht es mit ▶︎ oder dem Einzelschritt weiter. +::: +`,Bx=`--- +titel: Python und JavaScript +bereich: Vom Struktogramm zum Code +kurz: Python- und JavaScript-Code aus dem Struktogramm erzeugen und JavaScript direkt im Browser ausführen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- Python und JavaScript in der Code-Ansicht auswählen und vergleichen +- erklären, dass Python Blöcke durch Einrückung bildet und keine Datentypen braucht +- erklären, was VisuStruct beim Übersetzen nach Python anpasst +- JavaScript mit Im Browser testen ausführen +::: + +## Dasselbe Diagramm, drei Sprachen + +In der Code-Ansicht ([Code](#zeige-code) bei den Werkzeugen) wählst du oben die Sprache. Das Struktogramm bleibt gleich, nur die Schreibweise ändert sich. So kannst du die Sprachen gut vergleichen. + +::: diagramm l18-beispiel.visustruct +Eine Zahl wird so lange um 3 verkleinert, bis sie nicht mehr größer als 0 ist. +::: + +## Python + +Für das Diagramm oben erzeugt VisuStruct diesen Python-Code: + +\`\`\` +zahl = int(input("Startwert?")) +while zahl > 0: + print(zahl) + zahl = zahl - 3 +print("Ende") +\`\`\` + +Was in Python anders ist als in Java: + +- Es gibt **keine Semikolons** und **keine geschweiften Klammern**. Was zu einer Schleife oder Verzweigung gehört, erkennt Python allein an der **Einrückung**. Hinter \`while\`, \`if\` und \`else\` steht ein Doppelpunkt. +- Variablen bekommen **keinen Datentyp**: aus \`int zahl = 5\` wird \`zahl = 5\`. +- Die Ausgabe heißt \`print(…)\`, die Eingabe \`input(…)\`. Für eine Zahl steht \`int(…)\` darum herum. +- Arrays heißen in Python **Listen**: aus \`int[] zahlen = {2, 4, 6}\` wird \`zahlen = [2, 4, 6]\`, und aus \`zahlen.length\` wird \`len(zahlen)\`. +- Eine einfache For-Schleife wie \`int i = 0\`, \`i < 5\`, \`i++\` wird zu \`for i in range(5):\`. + +## Worauf du bei Python achten musst + +Python ist an einigen Stellen strenger als Java. VisuStruct übersetzt die Java-Schreibweise beim Export deshalb gleich mit: + +- **Text und Zahl mit +:** \`"Summe: " + summe\` wird zu \`"Summe: " + str(summe)\`. Ohne \`str(…)\` bricht Python ab. +- **i++ gibt es nicht:** daraus wird \`i += 1\`. +- **&&, || und !** heißen in Python \`and\`, \`or\` und \`not\`, \`true\` und \`false\` werden zu \`True\` und \`False\`. +- **Ganzzahlige Division:** In Python ergibt \`7 / 2\` immer 3.5. Teilt das Struktogramm zwei \`int\`-Werte, schreibt VisuStruct deshalb \`7 // 2\`, das ergibt wie in Java 3. +- **For-Schleifen:** Zählschleifen werden zu \`for … in range(…)\`, auch mit \`i <= n\`, Rückwärtszählen oder Schritten wie \`i = i + 2\`. Passt eine Schleife nicht dazu, wird daraus eine \`while\`-Schleife. +- **do-while gibt es nicht:** daraus wird \`while True:\` mit \`if not (…): break\` am Ende. + +Ist ein Diagramm als **Pseudocode** markiert, steht nur ein Hinweis über dem Code. Dann ist der Text eine Skizze und kein lauffähiges Programm. + +## JavaScript + +Dasselbe Diagramm in JavaScript: + +\`\`\` +"use strict"; + +let zahl = parseInt((prompt("Startwert?") ?? "0"), 10); +while (zahl > 0) { + console.log(zahl); + zahl = zahl - 3; +} +console.log("Ende"); +\`\`\` + +JavaScript sieht Java ähnlich: geschweifte Klammern, Semikolons, \`while (…)\` und \`if (…)\`. Die Unterschiede: + +- Variablen werden mit \`let\` angelegt, ohne Datentyp. Konstanten mit \`const\`. +- Die Ausgabe heißt \`console.log(…)\`, die Eingabe \`prompt(…)\`. Mit \`parseInt(…)\` wird aus der Eingabe eine ganze Zahl. +- Arrays stehen in eckigen Klammern: \`let zahlen = [2, 4, 6];\`. +- \`"use strict";\` ganz oben sorgt dafür, dass JavaScript bei Tippfehlern in Variablennamen meckert. +- JavaScript kennt nur einen Zahlentyp. Teilt das Struktogramm zwei \`int\`-Werte, schreibt VisuStruct \`Math.trunc(a / b)\`. Dann fallen die Nachkommastellen wie in Java weg. + +::: angeberwissen +JavaScript hat mit Java fast nichts zu tun. Brendan Eich hat es 1995 in nur zehn Tagen für den Browser Netscape gebaut. Erst hieß es Mocha, dann LiveScript. Weil Java gerade alle begeisterte, wurde es kurz vor dem Start aus Werbegründen in JavaScript umbenannt. Seitdem werden die beiden ständig verwechselt, bis heute. Programmierer sagen dazu: Java und JavaScript haben so viel gemeinsam wie Auto und Autogramm. +::: + +## JavaScript im Browser ausführen + +JavaScript ist die Sprache der Browser. Deshalb kann VisuStruct den Code **sofort ausführen**: + +::: angeberwissen +Warum sind Links im Browser eigentlich blau? Ben Shneidermans Team hat 1985 untersucht, welche Farbe man gut sieht und die beim Lesen nicht stört. Gewonnen hat Hellblau. Rot fiel zwar mehr auf, aber man konnte sich den Text danach schlechter merken. +::: + +1. Wähle in der Code-Ansicht **JavaScript**. +2. Klicke auf **Im Browser testen**. +3. Unter **Ausgabe** erscheint, was \`console.log\` ausgibt. Fragt das Programm mit \`prompt\` nach einem Wert, tippst du ihn ein und klickst auf **OK**. +4. Mit **Stopp** brichst du das Programm ab. + +Eine Endlosschleife \`while (true)\` hält VisuStruct nach 100 000 Durchläufen von selbst an und meldet **Ausführung gestoppt: mögliche Endlosschleife.** + +> Ein **Aufruf** braucht im JavaScript-Code ein Unterprogramm mit diesem Namen, sonst meldet JavaScript einen Fehler. Anders als die Simulation sucht der Browser nicht in den anderen Reitern. + +## Übung: Python als Struktogramm + +Dieses Python-Programm gibt alle geraden Zahlen von 0 bis zu einer Grenze aus: + +\`\`\` +grenze = int(input("Bis wohin?")) +for i in range(0, grenze + 1, 2): + print(i) +\`\`\` + +\`range(0, grenze + 1, 2)\` heißt: bei 0 anfangen, vor \`grenze + 1\` aufhören, in Zweierschritten zählen. + +::: übung l18-python +titel: Gerade Zahlen +auftrag: Baue das Python-Programm oben als Struktogramm mit einer For-Schleife nach. Bei der Grenze 7 gibt es 0, 2, 4 und 6 aus. +test: 7 -> 0 | 2 | 4 | 6 +test: 4 -> 0 | 2 | 4 +test: 0 -> 0 +braucht: forSchleife +tipp: \`range(0, grenze + 1, 2)\` zählt von 0 bis zur Grenze in Zweierschritten. Das ist eine For-Schleife. +tipp: Die drei Felder der For-Schleife sind \`int i = 0\`, \`i <= grenze\` und \`i = i + 2\`. +lösung: l18-python-loesung.visustruct +::: + +## Übung: JavaScript als Struktogramm + +\`\`\` +let alter = parseInt((prompt("Wie alt bist du?") ?? "0"), 10); +if (alter >= 16) { + console.log("Du darfst wählen."); +} else { + let jahre = 16 - alter; + console.log("Noch " + jahre + " Jahre warten."); +} +\`\`\` + +::: übung l18-js +titel: Wählen ab 16 +auftrag: Baue den JavaScript-Code oben als Struktogramm nach. Teste danach in der Code-Ansicht mit **JavaScript** und **Im Browser testen**, ob dein Code dasselbe ausgibt wie die Simulation. +test: 12 -> Noch 4 Jahre warten. +test: 16 -> Du darfst wählen. +test: 13 -> Noch 3 Jahre warten. +test: 40 -> Du darfst wählen. +braucht: verzweigung +tipp: Lies den Code Zeile für Zeile. \`if\` und \`else\` werden zu einer Verzweigung. +tipp: \`prompt\` und \`parseInt\` sind zusammen eine Eingabe: \`input: int alter "Wie alt bist du?"\`. Im false-Zweig stehen zwei Kästen: erst \`int jahre = 16 - alter\`, dann die Ausgabe. +lösung: l18-js-loesung.visustruct +::: + +## Spiel: Welche Sprache? + +::: spiel frage +titel: Spiel: Welche Sprache? +intro: Ludwig hat Zeilen aus drei Sprachen gemischt. Erkennst du, woher jede stammt? Acht Runden. +frage: In welcher Sprache ist das geschrieben? +antworten: Java | Python | JavaScript + +runde: + print(zahl) +richtig: Python +> Die Ausgabe heißt in Python \`print(…)\`, ohne Semikolon. + +runde: + console.log(zahl); +richtig: JavaScript +> \`console.log\` ist die Ausgabe in JavaScript. + +runde: + System.out.println(zahl); +richtig: Java +> Die lange Ausgabe mit \`System.out\` gibt es nur in Java. + +runde: + let zahlen = [2, 4, 6]; +richtig: JavaScript +> \`let\` und eckige Klammern: ein Array in JavaScript. + +runde: + for i in range(5): +richtig: Python +> Doppelpunkt statt geschweifter Klammern und \`range\`: typisch Python. + +runde: + int[] zahlen = {2, 4, 6}; +richtig: Java +> Nur Java schreibt den Datentyp \`int[]\` davor. + +runde: + zahl = int(input("Startwert?")) +richtig: Python +> Kein Datentyp vor der Variablen, kein Semikolon, und \`int(…)\` um die Eingabe. + +runde: + let zahl = parseInt(prompt("Startwert?"), 10); +richtig: JavaScript +> \`prompt\` fragt im Browser nach einem Wert, \`parseInt\` macht eine Zahl daraus. +::: + +## 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. + +::: checkliste +- Ich kann Python und JavaScript in der Code-Ansicht auswählen und vergleichen. → Dasselbe Diagramm, drei Sprachen +- Ich kann erklären, dass Python Blöcke durch Einrückung bildet und keine Datentypen braucht. → Python +- Ich kann erklären, was VisuStruct beim Übersetzen nach Python anpasst. → Worauf du bei Python achten musst +- Ich kann JavaScript mit Im Browser testen ausführen. → JavaScript im Browser ausführen +::: + +## Wissenstest + +::: quiz +? Woran erkennt Python, welche Zeilen zu einer Schleife gehören? +→ Python +- [ ] An den geschweiften Klammern +- [x] An der Einrückung +- [ ] Am Semikolon am Zeilenende + +? Wie heißt \`output: summe\` in JavaScript? +→ Dasselbe Diagramm, drei Sprachen +- [ ] print(summe) +- [ ] System.out.println(summe); +- [x] console.log(summe); + +? Welche Sprache kann VisuStruct direkt im Browser ausführen? +→ JavaScript im Browser ausführen +- [ ] Java +- [ ] Python +- [x] JavaScript +> Jeder Browser kann JavaScript ausführen. Für Java und Python brauchst du ein eigenes Programm. + +? Was passiert in Python bei \`print("Summe: " + summe)\`, wenn summe die Zahl 7 ist? +→ Worauf du bei Python achten musst +- [ ] Es wird Summe: 7 ausgegeben. +- [x] Python meldet einen Fehler, weil Text und Zahl nicht mit + verbunden werden können. +- [ ] Es wird Summe: ausgegeben. +> Mit str(summe) wird aus der Zahl ein Text. +::: +`,Mx=`--- +titel: Wenn das Programm abstürzt: try und catch +bereich: Fehler abfangen +kurz: Mit echtem Java Fehlermeldungen lesen und Abstürze mit try und catch abfangen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- echtes Java im Bereich Code einschalten +- aus einer Fehlermeldung die Exception und die Zeile ablesen +- eine Exception mit try und catch auffangen +- Text mit Integer.parseInt in eine Zahl umwandeln und die NumberFormatException abfangen +- ein Programm schreiben, das sicher teilt, auch durch 0 +::: + +## Abgestürzt! + +Dieses Programm soll drei Noten ausgeben. Tippe es im Bereich [Code](#zeige-codelive) ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): + +\`\`\`java +int[] noten = {2, 3, 1}; +System.out.println("Erste Note: " + noten[0]); +System.out.println("Vierte Note: " + noten[3]); +System.out.println("Fertig!"); +\`\`\` + +Die erste Note erscheint, dann ist Schluss. VisuStruct meldet „Ungültiger Ausdruck: noten[3]“, und „Fertig!“ kommt nie an. Das Array hat nur die Fächer 0, 1 und 2, ein Fach 3 gibt es nicht. + +::: ludwig +Ist dir das auch schon passiert? Ein kleiner Fehler, und das ganze Programm ist weg. Mir ist das so oft passiert, dass ich vor dem Bildschirm geweint habe. Aber es gibt eine Lösung, und die heißt **try** und **catch**. +::: + +::: angeberwissen +1947 fand das Team von Grace Hopper im Rechner Mark II an der Universität Harvard eine Motte, die einen Fehler verursacht hatte. Sie klebten sie ins Logbuch und schrieben dazu: „First actual case of bug being found“. Seitdem heißen Programmfehler **Bugs** (englisch für Käfer). +::: + +## Echtes Java einschalten + +Der Bereich Code rechnet normalerweise mit derselben Simulation wie das Struktogramm. Die hält bei einem Fehler einfach an. Um zu sehen, was echtes Java macht, schaltest du echtes Java ein: + +1. Klicke oben rechts auf das [Zahnrad](#zeige-einstellungen) und wähle als **Programmiersprache** Java. +2. Setze im Abschnitt Java den Haken bei **Echtes Java (mit Swing)**. + +Beim ersten Ausführen lädt VisuStruct einmalig etwa 40 MB. Danach wird dein Code wie in einer richtigen Java-Entwicklungsumgebung übersetzt und ausgeführt. + +> Mit echtem Java funktionieren Eingaben über die Konsole (\`Scanner\`) noch nicht. Unsere Beispiele kommen deshalb ohne Eingabe aus. + +Schreib das Programm jetzt als ganze Klasse, damit die Zeilennummern stimmen, und führe es aus: + +\`\`\`java +public class Noten { + public static void main(String[] args) { + int[] noten = {2, 3, 1}; + System.out.println("Erste Note: " + noten[0]); + System.out.println("Vierte Note: " + noten[3]); + System.out.println("Fertig!"); + } +} +\`\`\` + +In der [Konsole](#zeige-konsole) steht jetzt: + +\`\`\` +Erste Note: 2 +java.lang.ArrayIndexOutOfBoundsException: 3 + at Noten.main(Noten.java:5) +\`\`\` + +## Die Fehlermeldung lesen + +So eine Meldung sieht erst einmal erschreckend aus. Sie verrät dir aber genau, was los ist: + +| Teil | Bedeutung | +|---|---| +| \`ArrayIndexOutOfBoundsException\` | Die Art des Fehlers: Der Index liegt außerhalb des Arrays. | +| \`3\` | Der falsche Index. | +| \`Noten.java:5\` | Die Zeile, in der es passiert ist: Zeile 5. | + +So einen Fehler zur Laufzeit nennt Java eine **Exception** (englisch für Ausnahme). Man sagt: Java *wirft* eine Exception. Fängt sie niemand auf, bricht das Programm ab. Deshalb erscheint „Fertig!“ nicht. + +::: ludwig +Lies Fehlermeldungen immer von oben: Erst der Name der Exception, dann die Zeilennummer. Die Zeilennummern stehen im Bereich Code links neben dem Code. +::: + +## try und catch + +Mit **try** und **catch** fängst du die Exception auf. Ändere die Zeile mit \`noten[3]\` so: + +\`\`\`java +try { + System.out.println("Vierte Note: " + noten[3]); +} catch (ArrayIndexOutOfBoundsException e) { + System.out.println("Diese Note gibt es nicht."); +} +System.out.println("Fertig!"); +\`\`\` + +- \`try\` heißt „versuche“. Java führt den Block in den geschweiften Klammern ganz normal aus. +- Wirft eine Zeile darin eine Exception, springt Java sofort in den \`catch\`-Block. Der Rest des \`try\`-Blocks wird übersprungen. +- In der Klammer hinter \`catch\` steht, welche Exception aufgefangen wird, und ein Name dafür, meistens \`e\`. +- Danach geht das Programm normal weiter. Jetzt erscheint auch „Fertig!“. + +Läuft im \`try\`-Block alles gut, wird der \`catch\`-Block einfach übersprungen. + +::: ludwig +try und catch sind wie das Netz unter dem Trapez im Zirkus: Solange alles klappt, merkst du nichts davon. Fällt jemand, fängt das Netz ihn auf, und die Vorstellung geht weiter. +::: + +> Im Struktogramm gibt es keinen Kasten für try und catch. VisuStruct zeigt den ganzen Block deshalb als eine Anweisung. Ausführen kannst du ihn nur mit echtem Java. + +## Text in eine Zahl umwandeln + +Oft steht eine Zahl zuerst als Text da, zum Beispiel später in einem Textfeld im Fenster. \`Integer.parseInt\` wandelt Text in eine ganze Zahl um: + +\`\`\`java +String eingabe = "zwölf"; +try { + int zahl = Integer.parseInt(eingabe); + System.out.println("Doppelt: " + zahl * 2); +} catch (NumberFormatException e) { + System.out.println("Das ist keine Zahl: " + eingabe); +} +\`\`\` + +„zwölf“ kann Java nicht umwandeln und wirft eine \`NumberFormatException\`. Das Programm gibt „Das ist keine Zahl: zwölf“ aus. Ändere die erste Zeile in \`String eingabe = "12";\` und führe es noch einmal aus: Jetzt erscheint „Doppelt: 24“. + +## Profiwissen: Exceptions sind Objekte + +Das steht nicht im Lehrplan, ist aber praktisch zu wissen. + +::: angeberwissen +Jede Exception ist ein Objekt einer eigenen Klasse, zum Beispiel \`ArithmeticException\` für das Teilen durch 0. \`e.getMessage()\` liefert ihre Meldung, etwa \`/ by zero\`. + +Hinter einem \`try\` dürfen mehrere \`catch\`-Blöcke stehen, für jede Art von Fehler einer. \`catch (Exception e)\` fängt alle Exceptions auf, verrät dir dann aber weniger darüber, was passiert ist. Und ein Block \`finally { … }\` am Ende läuft immer, egal ob es einen Fehler gab oder nicht. +::: + +## Spiel: Fängt das Netz? + +::: spiel frage +titel: Spiel: Fängt das Netz? +intro: Ludwig turnt am Trapez. Fängt try und catch ihn auf, oder stürzt das Programm ab? Sieben Runden. + +runde: + int[] noten = {2, 3, 1}; + System.out.println(noten[3]); + System.out.println("Fertig!"); +frage: Was passiert mit echtem Java? +- Es erscheint 1 und Fertig! +- Es erscheint nur Fertig! +- [x] Das Programm stürzt mit einer ArrayIndexOutOfBoundsException ab. +> Ein Fach 3 gibt es nicht. Niemand fängt die Exception auf, also kommt Fertig! nie an. + +runde: + int[] noten = {2, 3, 1}; + try { + System.out.println(noten[3]); + } catch (ArrayIndexOutOfBoundsException e) { + System.out.println("Diese Note gibt es nicht."); + } + System.out.println("Fertig!"); +frage: Was wird ausgegeben? +- Fertig! +- [x] Diese Note gibt es nicht.\\nFertig! +- Diese Note gibt es nicht. +> Der catch-Block fängt die Exception auf, danach geht das Programm normal weiter. + +runde: + try { + System.out.println("A"); + System.out.println(10 / 0); + System.out.println("B"); + } catch (ArithmeticException e) { + System.out.println("C"); + } +frage: Was wird ausgegeben? +- A\\nB\\nC +- [x] A\\nC +- C +> Bei 10 / 0 springt Java sofort in den catch-Block. Der Rest des try-Blocks, also B, wird übersprungen. + +runde: + String eingabe = "12"; + try { + int zahl = Integer.parseInt(eingabe); + System.out.println("Doppelt: " + zahl * 2); + } catch (NumberFormatException e) { + System.out.println("Das ist keine Zahl: " + eingabe); + } +frage: Was wird ausgegeben? +- [x] Doppelt: 24 +- Das ist keine Zahl: 12 +- Doppelt: 1212 +> „12“ lässt sich umwandeln. Läuft im try-Block alles gut, wird catch übersprungen. + +runde: +frage: Welche Exception wirft \`Integer.parseInt("2.5")\`? +- ArithmeticException +- [x] NumberFormatException +- keine, das Ergebnis ist 2 +> parseInt wandelt nur ganze Zahlen um. Mit Komma oder Punkt ist es kein gültiges Format. + +runde: +frage: Welche Exception wirft \`12 / 0\` mit \`int\`? +- [x] ArithmeticException +- NumberFormatException +- ArrayIndexOutOfBoundsException +> Durch 0 teilen geht mit ganzen Zahlen nicht. Die Meldung lautet \`/ by zero\`. + +runde: + try { + int stuecke = 12 / 0; + } catch (NumberFormatException e) { + System.out.println("Fehler!"); + } + System.out.println("Fertig!"); +frage: Was passiert? +- Es erscheint Fehler! und Fertig! +- Es erscheint nur Fertig! +- [x] Das Programm stürzt ab. +> catch fängt nur die Exception, die in der Klammer steht. Eine ArithmeticException fällt durch das Netz. +::: + +## Aufgabe: Sicher teilen + +Dieses Programm stürzt ab: + +\`\`\`java +int kuchen = 12; +int personen = 0; +System.out.println("Jeder bekommt " + kuchen / personen + " Stücke."); +System.out.println("Guten Appetit!"); +\`\`\` + +1. Führe es mit echtem Java aus und lies die Fehlermeldung. Welche Exception ist es? +2. Fange sie mit try und catch ab. Statt des Absturzes soll „Ohne Personen kann man nicht teilen.“ erscheinen, und „Guten Appetit!“ soll trotzdem kommen. +3. Setze \`personen\` auf 4 und prüfe, dass dann „Jeder bekommt 3 Stücke.“ erscheint. + +::: ludwig +Die Exception heißt \`ArithmeticException\`. Schreib in den \`try\`-Block nur die Zeile, die abstürzen kann. +::: + +## 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. + +::: checkliste +- Ich kann echtes Java im Bereich Code einschalten. → Echtes Java einschalten +- Ich kann aus einer Fehlermeldung die Exception und die Zeile ablesen. → Die Fehlermeldung lesen +- Ich kann eine Exception mit try und catch auffangen. → try und catch +- Ich kann Text mit Integer.parseInt in eine Zahl umwandeln und die NumberFormatException abfangen. → Text in eine Zahl umwandeln +- Ich kann ein Programm schreiben, das sicher teilt, auch durch 0. → Aufgabe: Sicher teilen +::: + +## Wissenstest + +::: quiz +? Was passiert, wenn eine Exception nicht aufgefangen wird? +→ Die Fehlermeldung lesen +- [ ] Java überspringt die Zeile und macht weiter. +- [x] Das Programm bricht ab. +- [ ] Der Computer startet neu. +> Deshalb erscheint im ersten Beispiel „Fertig!“ nicht. + +? Was passiert im try-Block nach der Zeile, die eine Exception wirft? +→ try und catch +- [ ] Die restlichen Zeilen laufen trotzdem. +- [x] Der Rest wird übersprungen, Java springt in den catch-Block. +- [ ] Java beginnt den try-Block von vorne. + +? Welche Exception wirft Integer.parseInt("zwölf")? +→ Text in eine Zahl umwandeln +- [ ] ArithmeticException +- [ ] ArrayIndexOutOfBoundsException +- [x] NumberFormatException +> „zwölf“ hat kein Zahlenformat, das Java versteht. + +? Ordne jeder Exception ihre Ursache zu. +→ Die Fehlermeldung lesen += ArrayIndexOutOfBoundsException -> Index außerhalb des Arrays += ArithmeticException -> Teilen durch 0 += NumberFormatException -> Text ist keine Zahl +::: +`,Zx=`--- +titel: Text einlesen und speichern +bereich: Dateien +kurz: Mit Scanner eine Textdatei Zeile für Zeile lesen und mit PrintWriter eine Datei speichern. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, warum Programme Daten in Dateien speichern +- eine Textdatei mit Scanner, hasNextLine und nextLine Zeile für Zeile lesen +- erklären, warum Java bei Dateien try und catch oder throws verlangt +- mit PrintWriter eine Datei schreiben und sie mit close() abschließen +- eine Datei lesen, ergänzen und nummeriert wieder speichern +::: + +## Warum Dateien? + +Alles, was in Variablen steht, ist weg, sobald das Programm endet. Soll sich ein Programm etwas merken, zum Beispiel einen Spielstand, eine Liste oder Noten, speichert es die Daten in einer **Datei**. Beim nächsten Start liest es die Datei wieder ein. + +Zora ist frei, und Ludwig plant ein Fest. Seine Einkaufsliste liegt als Datei \`einkauf.txt\` bereit: + +::: datei einkauf.txt +Heu +Äpfel +Karotten +Löwenzahn +::: + +Eine Datei mit der Endung \`.txt\` enthält nur Text, Zeile für Zeile. Du kannst sie mit jedem Editor öffnen, zum Beispiel mit dem Editor von Windows oder TextEdit am Mac. + +## Eine Datei lesen mit Scanner + +Den \`Scanner\` kennst du schon: \`new Scanner(System.in)\` liest von der Tastatur. Gibst du ihm statt \`System.in\` eine Datei, liest er aus der Datei: + +\`\`\`java +import java.io.*; +import java.util.Scanner; + +Scanner datei = new Scanner(new File("einkauf.txt")); +while (datei.hasNextLine()) { + String zeile = datei.nextLine(); + System.out.println(zeile); +} +datei.close(); +\`\`\` + +| Methode | Bedeutung | +|---|---| +| \`new File("einkauf.txt")\` | die Datei mit diesem Namen | +| \`hasNextLine()\` | Gibt es noch eine Zeile? \`true\` oder \`false\` | +| \`nextLine()\` | liefert die nächste Zeile und rückt eine Zeile weiter | +| \`close()\` | schließt die Datei, wenn du fertig bist | + +Die Schleife läuft, solange es noch eine Zeile gibt. In jedem Durchlauf holt \`nextLine()\` die nächste Zeile. \`File\` steht im Paket \`java.io\`, deshalb brauchst du \`import java.io.*;\`. + +::: diagramm dt-lesen.visustruct +So sieht das Lesen im Struktogramm aus. Probier es in der Simulation aus. +::: + +::: ludwig +Stell dir den Scanner wie einen Finger vor, der auf eine Zeile zeigt. \`nextLine()\` liest die Zeile unter dem Finger und schiebt ihn eine Zeile weiter. Ist der Finger unter der letzten Zeile, liefert \`hasNextLine()\` \`false\`. +::: + +## Was, wenn die Datei fehlt? + +Gibt es die Datei nicht, kann Java sie nicht lesen und wirft eine \`FileNotFoundException\`. Java verlangt, dass dein Programm damit rechnet. Entweder du fängst sie mit try und catch auf, wie in Lektion 22: + +\`\`\`java +try { + Scanner datei = new Scanner(new File("einkauf.txt")); + // ... lesen ... + datei.close(); +} catch (FileNotFoundException e) { + System.out.println("Die Datei einkauf.txt fehlt!"); +} +\`\`\` + +Oder du schreibst hinter \`main\` den Zusatz \`throws Exception\`. Das heißt: „Diese Methode kann eine Exception werfen, ich kümmere mich nicht darum.“ Dann bricht das Programm ab, wenn die Datei fehlt. + +\`\`\`java +public static void main(String[] args) throws Exception { +\`\`\` + +> VisuStruct schreibt \`throws Exception\` automatisch hinter \`main\`, sobald dein Programm mit Dateien arbeitet. In der Simulation meldet VisuStruct eine fehlende Datei mit „Es gibt keine Datei …“. + +## Übung: Einkaufsliste nummerieren + +::: übung l23-java-nummern +titel: Einkaufsliste nummerieren +code: java +auftrag: Lies \`einkauf.txt\` Zeile für Zeile und gib jede Zeile mit ihrer Nummer aus: **1. Heu**, **2. Äpfel** und so weiter. +start: l23-java-nummern-start.visustruct +test: - -> 1. Heu | 2. Äpfel | 3. Karotten | 4. Löwenzahn +braucht: whileSchleife +tipp: Lege vor der Schleife \`int nummer = 1;\` an und erhöhe die Nummer am Ende jedes Durchlaufs. +tipp: Die Ausgabe ist \`System.out.println(nummer + ". " + zeile);\` +lösung: l23-java-nummern-loesung.visustruct +::: + +## In eine Datei schreiben mit PrintWriter + +Zum Schreiben gibt es den \`PrintWriter\`. Seine Methoden heißen wie bei \`System.out\`: + +\`\`\`java +PrintWriter aus = new PrintWriter("gruss.txt"); +aus.println("Hallo Zora!"); +aus.println("Bis morgen, Ludwig"); +aus.close(); +\`\`\` + +Danach steht in \`gruss.txt\`: + +\`\`\` +Hallo Zora! +Bis morgen, Ludwig +\`\`\` + +- \`println\` schreibt den Text und beginnt danach eine neue Zeile, \`print\` schreibt ohne neue Zeile. +- Gibt es die Datei schon, wird sie **überschrieben**. Der alte Inhalt ist dann weg. +- Nach dem Lauf zeigt VisuStruct unter der Ausgabe, was in der Datei gespeichert wurde. + +::: ludwig +Vergiss \`close()\` nicht! Der PrintWriter sammelt den Text erst in einem Zwischenspeicher und schreibt ihn beim Schließen in die Datei. Ohne \`close()\` bleibt die Datei leer. Mir ist so schon eine ganze Geschichte verloren gegangen. +::: + +## Übung: Einkaufsliste ergänzen + +::: übung l23-java-ergaenzen +titel: Einkaufsliste ergänzen +code: java +auftrag: Ludwig braucht noch Kuchen. Lies \`einkauf.txt\` und schreibe jede Zeile in die neue Datei \`einkauf-neu.txt\`. Schreibe danach **Kuchen** als letzte Zeile dazu. Gib am Ende aus, wie viele Zeilen gespeichert wurden: **5 Zeilen gespeichert**. +start: l23-java-ergaenzen-start.visustruct +test: - -> 5 Zeilen gespeichert +datei: einkauf-neu.txt -> Heu | Äpfel | Karotten | Löwenzahn | Kuchen +braucht: whileSchleife +tipp: In der Schleife liest du eine Zeile mit \`datei.nextLine()\` und schreibst sie mit \`aus.println(zeile)\` gleich wieder hinaus. +tipp: Nach der Schleife kommt \`aus.println("Kuchen");\`. Schließe beide Dateien mit \`close()\`, sonst bleibt \`einkauf-neu.txt\` leer. +lösung: l23-java-ergaenzen-loesung.visustruct +::: + +## Spiel: Was steht in der Datei? + +::: spiel frage +titel: Spiel: Was steht in der Datei? +intro: Ludwig schreibt Dateien mit dem PrintWriter. Lies den Code und sag voraus, was danach in der Datei steht. Sechs Runden. +frage: Was steht danach in der Datei? + +runde: + PrintWriter aus = new PrintWriter("gruss.txt"); + aus.println("Hallo"); + aus.println("Zora"); + aus.close(); +- [x] Hallo\\nZora +- HalloZora +- Zora +> \`println\` beginnt nach jedem Text eine neue Zeile. + +runde: + PrintWriter aus = new PrintWriter("wort.txt"); + aus.print("Ha"); + aus.print("llo"); + aus.println("!"); + aus.close(); +- Ha\\nllo\\n! +- [x] Hallo! +- Ha llo ! +> \`print\` schreibt ohne neue Zeile weiter, die Teile hängen direkt aneinander. + +runde: + PrintWriter aus = new PrintWriter("geheim.txt"); + aus.println("Der Schatz liegt im Turm"); +- Der Schatz liegt im Turm +- [x] Nichts, die Datei bleibt leer. +- Java meldet einen Fehler. +> Ohne \`close()\` landet der Text nie in der Datei. Er bleibt im Zwischenspeicher. + +runde: + // In notiz.txt steht vorher: Alt + PrintWriter aus = new PrintWriter("notiz.txt"); + aus.println("Neu"); + aus.close(); +- Alt\\nNeu +- [x] Neu +- Neu\\nAlt +> Ein neuer PrintWriter überschreibt die Datei. Der alte Inhalt ist weg. + +runde: + PrintWriter aus = new PrintWriter("zahlen.txt"); + for (int i = 1; i <= 3; i++) { + aus.println(i * 2); + } + aus.close(); +- 1\\n2\\n3 +- 246 +- [x] 2\\n4\\n6 +> Die Schleife schreibt 2, 4 und 6, jede Zahl in eine eigene Zeile. + +runde: + // In einkauf.txt steht: Heu, Äpfel (je eine Zeile) + Scanner datei = new Scanner(new File("einkauf.txt")); + PrintWriter aus = new PrintWriter("gross.txt"); + while (datei.hasNextLine()) { + aus.println(datei.nextLine().toUpperCase()); + } + datei.close(); + aus.close(); +- Heu\\nÄpfel +- [x] HEU\\nÄPFEL +- HEUÄPFEL +> Jede Zeile wird gelesen, in Großbuchstaben verwandelt und in eine eigene Zeile geschrieben. +::: + +## 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. + +::: checkliste +- Ich kann erklären, warum Programme Daten in Dateien speichern. → Warum Dateien? +- Ich kann eine Textdatei mit Scanner, hasNextLine und nextLine Zeile für Zeile lesen. → Eine Datei lesen mit Scanner +- Ich kann erklären, warum Java bei Dateien try und catch oder throws verlangt. → Was, wenn die Datei fehlt? +- Ich kann mit PrintWriter eine Datei schreiben und sie mit close() abschließen. → In eine Datei schreiben mit PrintWriter +- Ich kann eine Datei lesen, ergänzen und nummeriert wieder speichern. → Übung: Einkaufsliste ergänzen +::: + +## Wissenstest + +::: quiz +? Was liefert hasNextLine()? +→ Eine Datei lesen mit Scanner +- [ ] die nächste Zeile +- [x] true, wenn es noch eine Zeile gibt, sonst false +- [ ] die Anzahl der Zeilen +> Mit hasNextLine() prüft die Schleife, ob es weitergeht. + +? Was passiert, wenn du new PrintWriter("liste.txt") für eine Datei aufrufst, die es schon gibt? +→ In eine Datei schreiben mit PrintWriter +- [ ] Der neue Text wird hinten angehängt. +- [x] Die Datei wird überschrieben. +- [ ] Java meldet einen Fehler. + +? Warum bleibt eine Datei leer, obwohl println aufgerufen wurde? +→ In eine Datei schreiben mit PrintWriter +- [ ] Weil println nur in die Konsole schreibt. +- [x] Weil close() fehlt. +- [ ] Weil der Dateiname auf .txt endet. +> Erst close() schreibt den Zwischenspeicher in die Datei. + +? Ordne jeder Methode ihre Aufgabe zu. +→ Eine Datei lesen mit Scanner += nextLine() -> liest die nächste Zeile += println(text) -> schreibt eine Zeile += close() -> schließt die Datei +::: +`,Lx=`--- +titel: Zeile für Zeile mit BufferedReader +bereich: Dateien +kurz: Mit BufferedReader und readLine lesen, bis null kommt, und mit Files eine ganze Datei auf einmal lesen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- eine Datei mit BufferedReader und readLine lesen +- das Dateiende erkennen, weil readLine dort null liefert +- zählen, wie oft ein Wort in einer Datei vorkommt +- eine ganze Datei mit Files.readString lesen und mit split in Zeilen zerlegen +- den längsten Eintrag einer Datei finden +::: + +## Der Kuchen ist weg! + +Am Morgen nach dem Fest ist Ludwigs Kuchen verschwunden. Zum Glück führt die Burg ein Logbuch. Jede Zeile beginnt mit dem Tag und der Uhrzeit: + +::: datei logbuch.txt +Mo 08:15 Ludwig füttert die Ziegen +Mo 12:30 Zora liest im Turm +Mo 18:00 Fuchs schleicht am Tor vorbei +Di 09:00 Ludwig backt einen Kuchen +Di 14:45 Hase bringt Karotten +Di 16:20 Fuchs fragt nach dem Rezept +Di 23:55 Der Kuchen ist weg +Mi 07:00 Zora findet Krümel vor dem Fuchsbau +::: + +Mit dem Scanner aus Lektion 23 könntest du es schon lesen. Profis nehmen für Dateien aber oft den **BufferedReader**. + +## Lesen mit BufferedReader + +\`\`\`java +import java.io.*; + +BufferedReader leser = new BufferedReader(new FileReader("logbuch.txt")); +String zeile = leser.readLine(); +while (zeile != null) { + System.out.println(zeile); + zeile = leser.readLine(); +} +leser.close(); +\`\`\` + +- \`new FileReader("logbuch.txt")\` öffnet die Datei, \`new BufferedReader(…)\` legt einen Puffer drumherum. Er holt die Datei in großen Stücken und ist deshalb bei langen Dateien schneller. +- \`readLine()\` liefert die nächste Zeile. Gibt es keine Zeile mehr, liefert es **null**. +- Die Schleife läuft deshalb, solange \`zeile != null\` ist. Am Ende jedes Durchlaufs liest sie die nächste Zeile. + +::: diagramm dt-buffered.visustruct +Erst eine Zeile lesen, dann prüfen, dann am Ende des Durchlaufs die nächste lesen. +::: + +**null** heißt „gar nichts“. Es ist nicht der leere Text \`""\`, sondern kein Text. Eine Variable mit \`null\` hat keine Methoden: \`zeile.length()\` bricht dann mit einer \`NullPointerException\` ab. Prüfe deshalb immer zuerst \`zeile != null\`. + +| | Scanner | BufferedReader | +|---|---|---| +| Anlegen | \`new Scanner(new File(…))\` | \`new BufferedReader(new FileReader(…))\` | +| Gibt es noch eine Zeile? | \`hasNextLine()\` | \`readLine()\` liefert \`null\` | +| Nächste Zeile | \`nextLine()\` | \`readLine()\` | +| Stärke | kann auch Zahlen lesen (\`nextInt()\`) | schnell, auch bei großen Dateien | + +::: ludwig +Die Schleife sieht anders aus als beim Scanner: Die erste Zeile wird **vor** der Schleife gelesen, jede weitere **am Ende** des Durchlaufs. Vergisst du das Lesen am Ende, liest das Programm immer wieder dieselbe Zeile und hört nie auf. +::: + +::: angeberwissen +Wo eine Zeile endet, ist nicht überall gleich: Windows schreibt zwei unsichtbare Zeichen, „Wagenrücklauf“ und „Zeilenvorschub“, Linux und macOS nur den Zeilenvorschub. Die Namen stammen von der Schreibmaschine, bei der der Papierwagen zurückfuhr und das Papier eine Zeile weiterrückte. \`readLine()\` kommt mit beidem klar. +::: + +## Übung: Wie oft kommt der Fuchs vor? + +::: übung l24-java-fuchs +titel: Wie oft kommt der Fuchs vor? +code: java +auftrag: Lies das Logbuch mit dem BufferedReader und zähle die Zeilen, in denen **Fuchs** vorkommt. Gib am Ende **Fuchs:** und die Anzahl aus. +start: l24-java-fuchs-start.visustruct +test: - -> Fuchs: 3 +braucht: whileSchleife, verzweigung +tipp: Lege vor der Schleife \`int anzahl = 0;\` an. In der Schleife prüfst du \`zeile.contains("Fuchs")\`. +tipp: Das \`zeile = leser.readLine();\` gehört ans Ende der Schleife, nach dem if. +lösung: l24-java-fuchs-loesung.visustruct +::: + +## Automatisch schließen + +Damit \`close()\` auch nach einer Exception nicht vergessen wird, gibt es eine Kurzform von try: Was in den runden Klammern hinter \`try\` angelegt wird, schließt Java am Ende von selbst. + +\`\`\`java +try (BufferedReader leser = new BufferedReader(new FileReader("logbuch.txt"))) { + String zeile = leser.readLine(); + while (zeile != null) { + System.out.println(zeile); + zeile = leser.readLine(); + } +} catch (IOException e) { + System.out.println("Das Logbuch fehlt."); +} +\`\`\` + +Das heißt **try-with-resources**. \`IOException\` fängt alle Fehler beim Lesen und Schreiben auf, auch eine fehlende Datei. + +> Wie try und catch läuft auch try-with-resources nur mit echtem Java (Lektion 22). In der Simulation schreibst du \`close()\` selbst. + +## Die Abkürzung: Files + +Seit Java 11 geht es noch kürzer. \`Files.readString\` liest die ganze Datei auf einmal, das kennst du aus Lektion 17. Mit \`split("\\n")\` zerlegst du den Text in ein Array von Zeilen: + +\`\`\`java +import java.nio.file.*; + +String text = Files.readString(Path.of("logbuch.txt")); +String[] zeilen = text.split("\\n"); +for (int i = 0; i < zeilen.length; i++) { + System.out.println(zeilen[i]); +} +\`\`\` + +Jetzt stehen alle Zeilen im Array. Du kannst sie in beliebiger Reihenfolge ansehen, zum Beispiel rückwärts oder nur jede zweite. + +| Weg | Gut für | +|---|---| +| \`Scanner\` | kleine Dateien, Zahlen und Wörter lesen | +| \`BufferedReader\` | große Dateien, Zeile für Zeile | +| \`Files.readString\` | kleine Dateien, die ganz ins Programm passen | + +::: ludwig +Eine Datei mit einer Million Zeilen liest du besser mit dem BufferedReader Zeile für Zeile. Mit \`Files.readString\` müsste die ganze Datei auf einmal in den Speicher. +::: + +## Übung: Der längste Eintrag + +::: übung l24-java-laengster +titel: Der längste Eintrag +code: java +auftrag: Im Startcode stehen die Zeilen des Logbuchs schon im Array \`zeilen\`. Finde die längste Zeile und gib sie so aus: **Längster Eintrag:** und dann die Zeile. +start: l24-java-laengster-start.visustruct +test: - -> Längster Eintrag: Mi 07:00 Zora findet Krümel vor dem Fuchsbau +braucht: forSchleife, verzweigung +tipp: Merke dir die bisher längste Zeile in \`String laengster = zeilen[0];\` und gehe die anderen Zeilen mit einer for-Schleife durch. +tipp: Ist \`zeilen[i].length() > laengster.length()\`, wird \`zeilen[i]\` der neue Längste. +lösung: l24-java-laengster-loesung.visustruct +::: + +## Spiel: Datei-Detektiv + +::: spiel frage +titel: Spiel: Datei-Detektiv +intro: Wer hat den Kuchen genommen? Jedes Programm durchsucht das **Logbuch** von oben. Sag voraus, was es ausgibt, und sammle so die Hinweise. Fünf Runden. +frage: Was gibt das Programm aus? + +runde: + String zeile = leser.readLine(); + zeile = leser.readLine(); + System.out.println(zeile.substring(9)); +- Ludwig füttert die Ziegen +- [x] Zora liest im Turm +- Mo 12:30 Zora liest im Turm +> Das zweite \`readLine()\` liefert die zweite Zeile. Ab Index 9 beginnt der Text nach der Uhrzeit. + +runde: + int n = 0; + String zeile = leser.readLine(); + while (zeile != null) { + if (zeile.startsWith("Di")) n++; + zeile = leser.readLine(); + } + System.out.println(n); +- 3 +- [x] 4 +- 8 +> Vier Einträge stammen vom Dienstag. + +runde: + String zeile = leser.readLine(); + while (zeile != null) { + if (zeile.contains("Kuchen")) { + System.out.println(zeile.substring(3, 8)); + } + zeile = leser.readLine(); + } +- [x] 09:00\\n23:55 +- 09:00 +- Di\\nDi +> Zwei Zeilen enthalten „Kuchen“. \`substring(3, 8)\` schneidet die Uhrzeit heraus. + +runde: + String zeile = leser.readLine(); + String letzte = ""; + while (zeile != null) { + if (zeile.contains("Fuchs")) letzte = zeile; + zeile = leser.readLine(); + } + System.out.println(letzte); +- Di 16:20 Fuchs fragt nach dem Rezept +- [x] Mi 07:00 Zora findet Krümel vor dem Fuchsbau +- Mo 18:00 Fuchs schleicht am Tor vorbei +> \`letzte\` wird bei jedem Treffer überschrieben. Am Ende steht der letzte Treffer darin. „Fuchsbau“ enthält auch „Fuchs“. + +runde: + String zeile = leser.readLine(); + while (zeile != null) { + if (zeile.contains("Krümel")) { + int bei = zeile.indexOf("vor dem "); + System.out.println(zeile.substring(bei + 8)); + } + zeile = leser.readLine(); + } +- [x] Fuchsbau +- vor dem Fuchsbau +- Krümel +> Die Krümel liegen vor dem Fuchsbau. Der Fuchs hat nach dem Rezept gefragt, und um 23:55 war der Kuchen weg. Fall gelöst! +::: + +## 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. + +::: checkliste +- Ich kann eine Datei mit BufferedReader und readLine lesen. → Lesen mit BufferedReader +- Ich kann das Dateiende erkennen, weil readLine dort null liefert (zeile != null). → Lesen mit BufferedReader +- Ich kann zählen, wie oft ein Wort in einer Datei vorkommt. → Übung: Wie oft kommt der Fuchs vor? +- Ich kann eine ganze Datei mit Files.readString lesen und mit split in Zeilen zerlegen. → Die Abkürzung: Files +- Ich kann den längsten Eintrag einer Datei finden. → Übung: Der längste Eintrag +::: + +## Wissenstest + +::: quiz +? Was liefert readLine(), wenn die Datei zu Ende ist? +→ Lesen mit BufferedReader +- [ ] "" +- [x] null +- [ ] -1 +> null heißt: Es gibt keinen Text mehr. + +? Warum steht in der Schleife am Ende noch einmal zeile = leser.readLine()? +→ Lesen mit BufferedReader +- [ ] Damit die Datei geschlossen wird. +- [x] Sonst bleibt zeile immer gleich, und die Schleife hört nie auf. +- [ ] Damit die erste Zeile doppelt ausgegeben wird. + +? Was macht try-with-resources? +→ Lesen mit BufferedReader +- [ ] Es liest die Datei schneller. +- [x] Es schließt die Datei am Ende von selbst. +- [ ] Es verhindert jede Exception. + +? Ordne jedem Weg zu, wofür er gut ist. +→ Die Abkürzung: Files += BufferedReader -> große Dateien, Zeile für Zeile += Files.readString -> kleine Dateien auf einmal += Scanner -> Zahlen und Wörter lesen +::: +`,Ex=`--- +titel: Tabellen als CSV +bereich: Dateien +kurz: Eine Tabelle als CSV-Datei lesen, jede Zeile mit split zerlegen und mit den Zahlen rechnen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- den Aufbau einer CSV-Datei erklären: Kopfzeile, Datensätze, Trennzeichen +- eine Zeile mit split zerlegen und mit Integer.parseInt eine Zahl daraus machen +- die Kopfzeile überspringen, bevor ich rechne +- einen Durchschnitt aus einer Spalte einer CSV-Datei berechnen +- den besten Wert in einer Spalte einer CSV-Datei finden +- eine Stärke und eine Schwäche von CSV nennen +::: + +## Eine Tabelle in einer Textdatei + +Frau Ziege, die Lehrerin der Burgschule, hat die Noten ihrer Klasse als Tabelle gespeichert: + +| Name | Mathe | Deutsch | Englisch | +|---|---|---|---| +| Ludwig | 2 | 3 | 1 | +| Zora | 1 | 2 | 2 | +| Fuchs | 4 | 3 | 5 | +| Hase | 2 | 1 | 3 | + +In der Datei sieht die Tabelle so aus: + +::: datei klasse.csv +Name;Mathe;Deutsch;Englisch +Ludwig;2;3;1 +Zora;1;2;2 +Fuchs;4;3;5 +Hase;2;1;3 +::: + +Das ist eine **CSV-Datei**. CSV heißt „Comma-Separated Values“, also „durch Kommas getrennte Werte“. Jede Zeile ist eine Zeile der Tabelle, die Spalten sind durch ein Trennzeichen getrennt. In Deutschland nimmt man meist das **Semikolon** \`;\`, weil das Komma schon in Zahlen wie \`2,5\` steckt. + +- Die erste Zeile ist die **Kopfzeile**. Sie sagt, was in den Spalten steht. +- Jede weitere Zeile ist ein **Datensatz**, hier eine Schülerin oder ein Schüler. +- Excel, LibreOffice und Numbers öffnen CSV-Dateien direkt als Tabelle. + +## Eine Zeile zerlegen mit split + +\`split(";")\` kennst du aus Lektion 17. Es zerlegt einen Text an jedem Semikolon und liefert ein Array: + +\`\`\`java +String zeile = "Zora;1;2;2"; +String[] teile = zeile.split(";"); +// teile[0] ist "Zora", teile[1] ist "1", teile[2] ist "2", teile[3] ist "2" +\`\`\` + +Die Noten sind danach noch **Text**. Rechnen kannst du erst, wenn du sie mit \`Integer.parseInt\` in eine Zahl verwandelst: + +\`\`\`java +int mathe = Integer.parseInt(teile[1]); +\`\`\` + +::: diagramm dt-csv.visustruct +Eine CSV-Zeile zerlegen und die Mathenote als Zahl lesen. +::: + +## Die ganze Datei lesen + +Für die ganze Datei kombinierst du den BufferedReader aus Lektion 24 mit \`split\`. Die Kopfzeile enthält keine Noten, deshalb liest du sie vor der Schleife und überspringst sie: + +\`\`\`java +BufferedReader leser = new BufferedReader(new FileReader("klasse.csv")); +String zeile = leser.readLine(); // Kopfzeile +zeile = leser.readLine(); // erster Datensatz +while (zeile != null) { + String[] teile = zeile.split(";"); + System.out.println(teile[0] + ": Mathe " + teile[1]); + zeile = leser.readLine(); +} +leser.close(); +\`\`\` + +::: ludwig +Ohne das zweite \`readLine()\` vor der Schleife landet die Kopfzeile in der Schleife. Dann versucht \`Integer.parseInt("Mathe")\` aus dem Wort eine Zahl zu machen, und Java bricht mit einer \`NumberFormatException\` ab. +::: + +## Übung: Notenschnitt in Mathe + +::: übung l25-java-schnitt +titel: Notenschnitt in Mathe +code: java +auftrag: Berechne den Notenschnitt in Mathe. Überspringe die Kopfzeile, addiere die Mathenoten (Spalte 1) und teile durch die Anzahl der Datensätze. Gib **Schnitt Mathe:** und den Schnitt aus. +start: l25-java-schnitt-start.visustruct +test: - -> Schnitt Mathe: 2.25 +braucht: whileSchleife +tipp: Lege vor der Schleife \`double summe = 0;\` und \`int anzahl = 0;\` an. Mit \`double\` wird beim Teilen nichts abgeschnitten. +tipp: In der Schleife: \`String[] teile = zeile.split(";");\`, dann \`summe = summe + Integer.parseInt(teile[1]);\` und \`anzahl++;\`. +lösung: l25-java-schnitt-loesung.visustruct +::: + +## Übung: Beste Note in Englisch + +::: übung l25-java-beste +titel: Beste Note in Englisch +code: java +auftrag: Wer hat die beste Note in Englisch (Spalte 3)? Gib **Beste Note in Englisch:**, den Namen und in Klammern die Note aus. +start: l25-java-beste-start.visustruct +test: - -> Beste Note in Englisch: Ludwig (1) +braucht: whileSchleife, verzweigung +tipp: Merke dir die bisher beste Note in \`int besteNote = 7;\` und den Namen in \`String besterName = "";\`. Jede echte Note ist besser als 7. +tipp: Ist \`note < besteNote\`, merkst du dir die neue Note und \`teile[0]\` als Namen. +lösung: l25-java-beste-loesung.visustruct +::: + +## Stärken und Schwächen von CSV + +| Gut | Schwierig | +|---|---| +| Tabellen brauchen wenig Platz. | Steht das Trennzeichen im Text, zum Beispiel \`Hase;sehr gut; fleißig\`, zerfällt die Zeile in zu viele Teile. | +| Excel und andere Programme öffnen die Datei direkt. | Alles ist eine flache Tabelle. Hat ein Tier mehrere Lieblingsessen, passt das nicht gut in eine Zelle. | +| Jedes Programm kann sie mit \`split\` lesen. | Die Datei sagt nicht, ob \`1\` eine Zahl oder ein Text ist. | + +::: ludwig +Excel speichert CSV-Dateien in Deutschland mit Semikolon, in England und den USA mit Komma. Wer eine Datei aus dem Ausland öffnet, sieht deshalb manchmal alles in einer einzigen Spalte. +::: + +## Spiel: Kaputte Zeile + +::: spiel bombe +titel: Spiel: Kaputte Zeile +intro: In jeder CSV-Datei ist **genau eine Zeile kaputt**, und die Bombe tickt. Vergleiche jede Zeile mit der Kopfzeile und tippe auf die kaputte Zeile, bevor die Zeit abläuft. Fünf Runden, je 20 Sekunden. +zeit: 20 +daten: csv + +runde: + Name;Mathe;Deutsch;Englisch + Ludwig;2;3;1 + Zora;1 + Fuchs;4;3;5 +frage: Jede Zeile braucht vier Spalten. +fehler: 3 +besser: Zora;1;2;2 +> Bei Zora fehlen zwei Noten. \`teile[3]\` gibt es dann nicht, und Java bricht mit einer \`ArrayIndexOutOfBoundsException\` ab. + +runde: + Name;Note;Bemerkung + Ludwig;2;arbeitet gut mit + Hase;1;sehr gut; fleißig + Zora;1;liest viel +frage: Jede Zeile braucht drei Spalten. +fehler: 3 +besser: Hase;1;sehr gut, fleißig +> Das Semikolon in der Bemerkung trennt eine vierte Spalte ab. Im Text darf das Trennzeichen nicht vorkommen. + +runde: + Name;Mathe;Deutsch;Englisch + Ludwig;2;3;1 + Zora;1;2;2 + Fuchs,4,3,5 +frage: Getrennt wird mit Semikolon. +fehler: 4 +besser: Fuchs;4;3;5 +> Hier stehen Kommas statt Semikolons. \`split(";")\` findet kein Semikolon und liefert die ganze Zeile als ein einziges Teil. + +runde: + Name;Mathe;Deutsch;Englisch + Hase;2;1;3 + Fuchs;vier;3;5 + Ludwig;2;3;1 +frage: Noten sind Zahlen. +fehler: 3 +besser: Fuchs;4;3;5 +> \`Integer.parseInt("vier")\` kann aus dem Wort keine Zahl machen und wirft eine \`NumberFormatException\`. + +runde: + Name;Mathe;Deutsch;Englisch + Zora;1;2;2 + Hase;2;1;3 + Ludwig;2;;1 +frage: Kein Feld darf leer sein. +fehler: 4 +besser: Ludwig;2;3;1 +> Zwischen den beiden Semikolons steht nichts. \`Integer.parseInt("")\` wirft eine \`NumberFormatException\`. +::: + +## 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. + +::: checkliste +- Ich kann den Aufbau einer CSV-Datei erklären: Kopfzeile, Datensätze, Trennzeichen. → Eine Tabelle in einer Textdatei +- Ich kann eine Zeile mit split zerlegen und mit Integer.parseInt eine Zahl daraus machen. → Eine Zeile zerlegen mit split +- Ich kann die Kopfzeile überspringen, bevor ich rechne. → Die ganze Datei lesen +- Ich kann einen Durchschnitt aus einer Spalte einer CSV-Datei berechnen. → Übung: Notenschnitt in Mathe +- Ich kann den besten Wert in einer Spalte einer CSV-Datei finden. → Übung: Beste Note in Englisch +- Ich kann eine Stärke und eine Schwäche von CSV nennen. → Stärken und Schwächen von CSV +::: + +## Wissenstest + +::: quiz +? Was liefert "Hase;2;1;3".split(";")[2]? +→ Eine Zeile zerlegen mit split +- [ ] "2" +- [x] "1" +- [ ] 1 +> Die Zählung beginnt bei 0. Und das Ergebnis ist ein Text, keine Zahl. + +? Warum liest das Programm vor der Schleife zweimal readLine()? +→ Die ganze Datei lesen +- [ ] Damit die Datei schneller gelesen wird. +- [x] Die erste Zeile ist die Kopfzeile ohne Noten. Sie wird übersprungen. +- [ ] Weil readLine immer zwei Zeilen braucht. + +? Was passiert bei Integer.parseInt("Mathe")? +→ Eine Zeile zerlegen mit split +- [ ] Es liefert 0. +- [x] Java wirft eine NumberFormatException. +- [ ] Es liefert die Länge des Wortes. + +? Ordne zu. +→ Stärken und Schwächen von CSV += Kopfzeile -> sagt, was in den Spalten steht += Datensatz -> eine Zeile mit Werten += Trennzeichen -> trennt die Spalten, meist ; +::: +`,Wx=`--- +titel: Daten als JSON +bereich: Dateien +kurz: JSON-Dateien verstehen, Werte mit indexOf und substring herausholen und selbst JSON schreiben. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- Objekte, Schlüssel, Werte und Listen in JSON erkennen +- mit indexOf und substring einen Wert aus einer JSON-Zeile holen +- alle Werte zu einem Schlüssel aus einer JSON-Datei ausgeben +- mit + und \\" einen JSON-Eintrag bauen und speichern +- Daten als JSON-Datei speichern +- eine Stärke und eine Schwäche von JSON nennen +::: + +## Daten mit Namen + +Der Burgzoo speichert seine Tiere in einer Datei \`zoo.json\`: + +::: datei zoo.json +{ + "zoo": "Burgzoo", + "tiere": [ + {"name": "Ludwig", "art": "Geißbock", "alter": 7}, + {"name": "Zora", "art": "Ziege", "alter": 6}, + {"name": "Fuchs", "art": "Rotfuchs", "alter": 4}, + {"name": "Hase", "art": "Feldhase", "alter": 2} + ] +} +::: + +Das ist **JSON**, die „JavaScript Object Notation“. Fast jede Web-App und jedes Spiel schickt und speichert Daten so. Anders als in einer CSV-Datei steht vor jedem Wert sein **Name**, der **Schlüssel**. + +| Zeichen | Bedeutung | Beispiel | +|---|---|---| +| \`{ … }\` | ein **Objekt**: Paare aus Schlüssel und Wert | \`{"name": "Zora", "alter": 6}\` | +| \`"schlüssel": wert\` | ein Paar, getrennt durch einen Doppelpunkt | \`"alter": 6\` | +| \`[ … ]\` | eine **Liste** von Werten, wie ein Array | \`"tiere": [ … ]\` | +| \`,\` | trennt die Paare und die Einträge einer Liste | | +| \`"…"\` | ein Text. Zahlen und \`true\`/\`false\` stehen ohne Anführungszeichen. | \`"Ziege"\`, \`6\` | + +Objekte und Listen lassen sich **verschachteln**: Das ganze Zoo-Objekt enthält die Liste \`tiere\`, und jedes Tier ist wieder ein Objekt. Wie bei Arrays zählt die Liste ab 0: \`tiere[1].name\` ist \`"Zora"\`. + +::: angeberwissen +JSON hat Douglas Crockford Anfang der 2000er bekannt gemacht. In die Lizenz seines JSON-Programms schrieb er: „Die Software soll für Gutes verwendet werden, nicht für Böses.“ Die Firma IBM fragte deshalb nach, ob sie es trotzdem benutzen darf. Er antwortete, IBM und seine Kunden dürften es auch für Böses verwenden. +::: + +## Einen Wert herausholen + +Profis lesen JSON mit einer Bibliothek, zum Beispiel **Gson**. Sie gehört nicht zu Java und muss erst eingebunden werden. Für unsere Zoo-Datei reichen die String-Methoden aus Lektion 17, denn jedes Tier steht in einer eigenen Zeile. + +Ein Anführungszeichen im Text schreibst du in Java als \`\\"\`. Der Text \`"\\"name\\": \\""\` ist also \`"name": "\`, genau das, was vor jedem Namen steht. + +\`\`\`java +String zeile = "{\\"name\\": \\"Zora\\", \\"art\\": \\"Ziege\\", \\"alter\\": 6},"; +int start = zeile.indexOf("\\"name\\": \\"") + 9; +int ende = zeile.indexOf("\\"", start); +String name = zeile.substring(start, ende); +\`\`\` + +- \`indexOf("\\"name\\": \\"")\` findet den Anfang von \`"name": "\`. Das sind 9 Zeichen, also beginnt der Name 9 Zeichen weiter. +- \`indexOf("\\"", start)\` sucht **ab** \`start\` das nächste Anführungszeichen. Dort endet der Name. +- \`substring(start, ende)\` schneidet den Namen heraus: \`Zora\`. + +::: diagramm dt-json.visustruct +Den Namen aus einer JSON-Zeile holen. +::: + +## Übung: Alle Namen aus dem Zoo + +::: übung l26-java-namen +titel: Alle Namen aus dem Zoo +code: java +auftrag: Lies \`zoo.json\` Zeile für Zeile. Gib in jeder Zeile, die \`"name"\` enthält, nur den Namen aus. +start: l26-java-namen-start.visustruct +test: - -> Ludwig | Zora | Fuchs | Hase +braucht: whileSchleife, verzweigung +tipp: Prüfe mit \`zeile.contains("\\"name\\"")\`, ob in der Zeile ein Name steht. Die anderen Zeilen überspringst du. +tipp: Im if: \`int start = zeile.indexOf("\\"name\\": \\"") + 9;\`, dann \`int ende = zeile.indexOf("\\"", start);\` und \`System.out.println(zeile.substring(start, ende));\`. +lösung: l26-java-namen-loesung.visustruct +::: + +## JSON schreiben + +Zum Schreiben setzt du den Text mit \`+\` zusammen und schreibst ihn mit dem PrintWriter aus Lektion 23 in die Datei. Texte im JSON brauchen Anführungszeichen, also \`\\"\` im Java-Text, Zahlen nicht: + +\`\`\`java +String name = "Zora"; +int punkte = 15; +String eintrag = "{\\"name\\": \\"" + name + "\\", \\"punkte\\": " + punkte + "}"; +// eintrag ist {"name": "Zora", "punkte": 15} +\`\`\` + +Bei einer Liste steht zwischen den Einträgen ein Komma, hinter dem letzten aber **keins**. Das prüfst du mit einem if. + +::: ludwig +Ein einziges vergessenes Anführungszeichen oder ein Komma zu viel, und kein Programm kann die Datei mehr lesen. JSON ist streng. Darum benutzen Profis zum Schreiben auch eine Bibliothek. +::: + +## Übung: Punkte als JSON speichern + +::: übung l26-java-schreiben +titel: Punkte als JSON speichern +code: java +auftrag: Speichere die Punkte aus dem Quiz-Turnier als Liste in \`punkte.json\`. Jede Zeile enthält ein Objekt mit **name** und **punkte**, zwischen den Objekten steht ein Komma. Gib am Ende **3 Einträge gespeichert** aus. +start: l26-java-schreiben-start.visustruct +test: - -> 3 Einträge gespeichert +datei: punkte.json -> [ | {"name": "Ludwig", "punkte": 12}, | {"name": "Zora", "punkte": 15}, | {"name": "Fuchs", "punkte": 9} | ] +braucht: forSchleife, verzweigung +tipp: Gehe mit \`for (int i = 0; i < namen.length; i++)\` durch die Arrays. Baue den Eintrag mit \`" {\\"name\\": \\"" + namen[i] + "\\", \\"punkte\\": " + punkte[i] + "}"\`. +tipp: Ist \`i < namen.length - 1\`, hängst du noch \`","\` an. Schreibe nach der Schleife \`"]"\` und schließe die Datei. +lösung: l26-java-schreiben-loesung.visustruct +::: + +## Stärken und Schwächen von JSON + +| Gut | Schwierig | +|---|---| +| Jeder Wert hat einen Namen. Man sieht sofort, was \`6\` bedeutet. | Die Datei ist länger als eine CSV-Datei, weil die Schlüssel in jeder Zeile stehen. | +| Daten lassen sich verschachteln, zum Beispiel eine Liste in einem Objekt. | Java kann JSON nicht von selbst lesen. Man braucht eine Bibliothek wie Gson. | +| JSON ist der Standard im Web. Fast jede Programmiersprache kennt es. | Ein Zeichen zu viel oder zu wenig macht die ganze Datei unlesbar. | + +## Spiel: Welcher Schlüssel? + +::: spiel frage +titel: Spiel: Welcher Schlüssel? +intro: Ludwig sucht Werte in JSON-Dateien. Lies die Datei und sag, welcher Wert gemeint ist. Fünf Runden. + +runde: + {"name": "Zora", "art": "Ziege", "alter": 6} +frage: Was ist der Wert von **alter**? +- "alter" +- [x] 6 +- "Ziege" +> Vor dem Doppelpunkt steht der Schlüssel, dahinter der Wert. Zahlen stehen ohne Anführungszeichen. + +runde: + { + "tiere": [ + {"name": "Ludwig", "alter": 7}, + {"name": "Zora", "alter": 6}, + {"name": "Fuchs", "alter": 4} + ] + } +frage: Was ist **tiere[1].name**? +- Ludwig +- [x] Zora +- Fuchs +> Die Liste zählt wie ein Array ab 0. \`tiere[1]\` ist das zweite Tier. + +runde: + { + "zoo": "Burgzoo", + "chef": {"name": "Ludwig", "art": "Geißbock"} + } +frage: Wie kommst du an **Geißbock**? +- [x] chef.art +- art +- zoo.chef.art +> \`art\` steckt im Objekt \`chef\`. Darum geht der Weg über \`chef\`. + +runde: + { + "name": "Hase", + "lieblingsessen": ["Karotten", "Klee", "Löwenzahn"] + } +frage: Was ist **lieblingsessen[2]**? +- Klee +- Karotten +- [x] Löwenzahn +> Index 0 ist Karotten, 1 ist Klee, 2 ist Löwenzahn. So etwas passt in CSV nur schwer in eine Zelle. + +runde: + {"name": "Fuchs", "alter": 4, "hungrig": true} +frage: Welcher Schlüssel hat einen Wahrheitswert? +- name +- alter +- [x] hungrig +> \`true\` und \`false\` stehen wie Zahlen ohne Anführungszeichen. In Java wäre das ein \`boolean\`. +::: + +## 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. + +::: checkliste +- Ich kann Objekte, Schlüssel, Werte und Listen in JSON erkennen. → Daten mit Namen +- Ich kann mit indexOf und substring einen Wert aus einer JSON-Zeile holen. → Einen Wert herausholen +- Ich kann alle Werte zu einem Schlüssel aus einer JSON-Datei ausgeben. → Übung: Alle Namen aus dem Zoo +- Ich kann mit + und \\" einen JSON-Eintrag bauen und speichern. → JSON schreiben +- Ich kann Daten als JSON-Datei speichern. → Übung: Punkte als JSON speichern +- Ich kann eine Stärke und eine Schwäche von JSON nennen. → Stärken und Schwächen von JSON +::: + +## Wissenstest + +::: quiz +? Was steht in JSON vor jedem Wert? +→ Daten mit Namen +- [ ] seine Zeilennummer +- [x] sein Schlüssel, zum Beispiel "name" +- [ ] ein Semikolon +> Schlüssel und Wert werden durch einen Doppelpunkt getrennt. + +? Wie schreibst du ein Anführungszeichen in einem Java-Text? +→ JSON schreiben +- [ ] "" +- [x] \\" +- [ ] '"' + +? Was ist bei {"tiere": [{"name": "Ludwig"}, {"name": "Zora"}]} der Wert von tiere[0].name? +→ Daten mit Namen +- [x] Ludwig +- [ ] Zora +- [ ] tiere +> Die Liste zählt ab 0. + +? Ordne zu. +→ Stärken und Schwächen von JSON += { } -> ein Objekt mit Schlüsseln und Werten += [ ] -> eine Liste += : -> trennt Schlüssel und Wert +::: +`,Nx=`--- +titel: Formate im Vergleich +bereich: Dateien +kurz: Dieselben Daten als txt, CSV und JSON vergleichen, das passende Format wählen und eine Datei in ein anderes Format umwandeln. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- dieselben Daten als txt, CSV und JSON erkennen +- Stärken und Schwächen von txt, CSV und JSON vergleichen +- eine CSV-Datei in Sätze umwandeln +- eine CSV-Datei in JSON umwandeln +::: + +## Dreimal dieselben Tiere + +Ludwig hat die Tiere der Burg in drei Dateien gespeichert. In allen steht dasselbe, nur anders aufgeschrieben. + +Als Text, so wie man es einem Menschen schreiben würde: + +::: datei tiere.txt +Ludwig (Geißbock) ist 7 Jahre alt. +Zora (Ziege) ist 6 Jahre alt. +Fuchs (Rotfuchs) ist 4 Jahre alt. +::: + +Als Tabelle in CSV: + +::: datei tiere.csv +Name;Art;Alter +Ludwig;Geißbock;7 +Zora;Ziege;6 +Fuchs;Rotfuchs;4 +::: + +Als JSON: + +::: datei tiere.json +[ + {"name": "Ludwig", "art": "Geißbock", "alter": 7}, + {"name": "Zora", "art": "Ziege", "alter": 6}, + {"name": "Fuchs", "art": "Rotfuchs", "alter": 4} +] +::: + +## Was kann welches Format? + +| | txt | CSV | JSON | +|---|---|---|---| +| Für Menschen gut lesbar | ja | geht so | geht so | +| Feste Ordnung für Programme | nein | ja, Spalten | ja, Schlüssel | +| Was bedeutet ein Wert? | steht im Satz | steht in der Kopfzeile | steht direkt davor | +| Verschachteln (Liste in einem Eintrag) | nein | schwer | ja | +| Öffnen in Excel | nein | ja | nein | +| Lesen in Java | Scanner, BufferedReader | dazu \`split\` | String-Methoden oder eine Bibliothek | +| Größe | klein | am kleinsten | am größten | + +Kurz gesagt: + +- **txt** für Texte, die Menschen lesen: Briefe, Notizen, ein Logbuch. +- **CSV** für Tabellen: Noten, Messwerte, eine Bestenliste. Jede Zeile hat dieselben Spalten. +- **JSON** für Daten mit Struktur: Spielstände, Einstellungen, alles, was zwischen Programmen und im Web hin- und hergeht. + +::: ludwig +Wenn deine Wetter-App die Temperatur holt, kommt die Antwort fast immer als JSON. Und wenn die Lehrkraft die Noten aus dem Schulprogramm exportiert, bekommt sie oft eine CSV-Datei. +::: + +## Übung: Aus CSV werden Sätze + +::: übung l27-java-saetze +titel: Aus CSV werden Sätze +code: java +auftrag: Wandle \`tiere.csv\` in Text um. Schreibe für jedes Tier einen Satz wie **Ludwig (Geißbock) ist 7 Jahre alt.** in die Datei \`saetze.txt\`. Gib am Ende **3 Sätze gespeichert** aus. +start: l27-java-saetze-start.visustruct +test: - -> 3 Sätze gespeichert +datei: saetze.txt -> Ludwig (Geißbock) ist 7 Jahre alt. | Zora (Ziege) ist 6 Jahre alt. | Fuchs (Rotfuchs) ist 4 Jahre alt. +braucht: whileSchleife +tipp: Die Kopfzeile ist im Startcode schon übersprungen. Zerlege jede Zeile mit \`String[] teile = zeile.split(";");\`. +tipp: Der Satz ist \`teile[0] + " (" + teile[1] + ") ist " + teile[2] + " Jahre alt."\`. Zähle mit \`anzahl++\` mit und lies am Ende der Schleife die nächste Zeile. +lösung: l27-java-saetze-loesung.visustruct +::: + +## Übung: Aus CSV wird JSON + +::: übung l27-java-json +titel: Aus CSV wird JSON +code: java +auftrag: Wandle \`tiere.csv\` in JSON um und speichere es in \`tiere-neu.json\`, genau wie \`tiere.json\` oben. Gib am Ende **3 Tiere gespeichert** aus. +start: l27-java-json-start.visustruct +test: - -> 3 Tiere gespeichert +datei: tiere-neu.json -> [ | {"name": "Ludwig", "art": "Geißbock", "alter": 7}, | {"name": "Zora", "art": "Ziege", "alter": 6}, | {"name": "Fuchs", "art": "Rotfuchs", "alter": 4} | ] +braucht: forSchleife, verzweigung +tipp: \`zeilen[0]\` ist die Kopfzeile. Beginne die for-Schleife deshalb bei \`i = 1\` und zerlege \`zeilen[i]\` mit \`split(";")\`. +tipp: Baue den Eintrag wie in Lektion 26 mit \`\\"\`. Das Alter ist eine Zahl und steht ohne Anführungszeichen. Ein Komma hängst du nur an, wenn \`i < zeilen.length - 1\` ist. +lösung: l27-java-json-loesung.visustruct +::: + +## Spiel: Welches Format passt? + +::: spiel frage +titel: Spiel: Welches Format passt? +intro: Ludwig will Daten speichern und weiß nicht, welches Format er nehmen soll. Hilf ihm. Sechs Runden. +antworten: txt | CSV | JSON + +runde: +frage: Die Noten der ganzen Klasse sollen in Excel geöffnet werden. +richtig: CSV +> Noten sind eine Tabelle, und Excel öffnet CSV-Dateien direkt. + +runde: +frage: Ludwig schreibt Zora einen Brief. +richtig: txt +> Ein Brief ist Text für Menschen. Er braucht keine Spalten und keine Schlüssel. + +runde: +frage: Ein Spielstand mit Name, Level und einer Liste aller gesammelten Schlüssel. +richtig: JSON +> Eine Liste in einem Eintrag lässt sich in JSON verschachteln. In CSV passt sie nur schwer in eine Zelle. + +runde: +frage: Ein Messgerät speichert jede Minute Uhrzeit und Temperatur, ein ganzes Jahr lang. +richtig: CSV +> Viele gleiche Zeilen mit denselben Spalten: CSV ist dafür am kleinsten. JSON würde die Schlüssel in jeder Zeile wiederholen. + +runde: +frage: Eine Wetter-App holt die Vorhersage von einem Server im Internet. +richtig: JSON +> JSON ist der Standard im Web. Fast jede App bekommt ihre Daten so. + +runde: +frage: Das Logbuch der Burg, in dem jeder Eintrag ein kurzer Satz ist. +richtig: txt +> Jede Zeile ist ein Satz für Menschen. Gelesen wird sie Zeile für Zeile, wie in Lektion 24. +::: + +## 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. + +::: checkliste +- Ich kann dieselben Daten als txt, CSV und JSON erkennen. → Dreimal dieselben Tiere +- Ich kann Stärken und Schwächen von txt, CSV und JSON vergleichen. → Was kann welches Format? +- Ich kann eine CSV-Datei in Sätze umwandeln. → Übung: Aus CSV werden Sätze +- Ich kann eine CSV-Datei in JSON umwandeln. → Übung: Aus CSV wird JSON +::: + +## Wissenstest + +::: quiz +? Welches Format öffnet Excel direkt als Tabelle? +→ Was kann welches Format? +- [ ] txt +- [x] CSV +- [ ] JSON + +? Warum ist eine JSON-Datei meist größer als eine CSV-Datei mit denselben Daten? +→ Was kann welches Format? +- [ ] Weil JSON mehr Zahlen speichert. +- [x] Weil die Schlüssel in jedem Eintrag wiederholt werden. +- [ ] Weil JSON keine Kommas benutzt. + +? In welchem Format sagt jeder Wert selbst, was er bedeutet? +→ Was kann welches Format? +- [ ] txt +- [ ] CSV +- [x] JSON +> In JSON steht der Schlüssel direkt vor dem Wert, zum Beispiel "alter": 7. + +? Ordne jedem Zweck ein Format zu. +→ Was kann welches Format? += ein Brief an Zora -> txt += die Notenliste der Klasse -> CSV += ein Spielstand mit Listen -> JSON +::: +`,Fx=`--- +titel: Dein erstes Fenster +bereich: Fenster mit Swing +kurz: Mit Java und Swing ein eigenes Fenster öffnen, Zeile für Zeile erklärt. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- im Bereich Code „Echtes Java“ einschalten +- ein Fenster mit Titel und Größe öffnen +- erklären, was jede Zeile des Fensterprogramms macht +- erklären, warum setVisible(true) am Ende steht +::: + +## Programme mit Fenstern + +Bisher haben deine Programme Text in die Konsole geschrieben. Die meisten Programme, die du kennst, haben aber **Fenster** mit Knöpfen und Textfeldern. Das nennt man eine grafische Oberfläche. + +Java bringt dafür einen Werkzeugkasten mit: **Swing**. In VisuStruct schaltest du ihn so ein: + +1. Öffne rechts den Bereich [Code](#zeige-codelive). +2. Klicke oben rechts auf das [Zahnrad](#zeige-einstellungen) und wähle als **Programmiersprache** Java. +3. Setze darunter im Abschnitt Java den Haken bei **Echtes Java (mit Swing)**. + +Beim ersten [▶︎ Ausführen](#zeige-ausfuehren) lädt VisuStruct einmalig etwa 40 MB, das dauert einen Moment. Danach läuft dein Code als echtes Java, und deine Fenster erscheinen im Bereich Code im Feld **Java-Fenster** über der Konsole. + +> Mit „Echtes Java“ funktionieren Eingaben über die Konsole (\`Scanner\`) noch nicht. Für Programme mit Eingabe schaltest du den Haken wieder aus. + +::: angeberwissen +Swing gibt es seit 1998. Davor hatte Java nur das ältere AWT mit einer Klasse \`Frame\`. Damit man die neuen Bausteine nicht verwechselt, beginnen in Swing fast alle Namen mit **J**: \`JFrame\`, \`JButton\`, \`JLabel\`. Am J erkennst du Swing also sofort. +::: + +## Das ganze Programm + +So sieht das kleinste Programm aus, das ein Fenster öffnet. Tippe es im Bereich Code ab und klicke auf [▶︎ Ausführen](#zeige-ausfuehren): + +\`\`\`java +import javax.swing.*; + +public class MeinFenster { + public static void main(String[] args) { + JFrame fenster = new JFrame("Mein erstes Fenster"); + fenster.setSize(300, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setVisible(true); + } +} +\`\`\` + +Ein leeres graues Fenster mit dem Titel „Mein erstes Fenster“ erscheint. Mehr nicht, aber es ist dein eigenes Fenster! + +Den Rahmen mit \`public class\` und \`main\` kennst du schon aus der Lektion Java. Neu sind die erste Zeile und die vier Zeilen in \`main\`. Die schauen wir uns jetzt einzeln an. + +::: ludwig +Schau dir das Struktogramm neben dem Code an: Jede Zeile in \`main\` ist ein Kasten, alle untereinander. Ein Fensterprogramm ist am Anfang also nur eine Sequenz. +::: + +## Zeile für Zeile + +| Zeile | Was sie macht | +|---|---| +| \`import javax.swing.*;\` | Holt den Werkzeugkasten Swing ins Programm. Ohne diese Zeile kennt Java \`JFrame\` nicht. | +| \`JFrame fenster = new JFrame("Mein erstes Fenster");\` | Baut ein neues Fenster. Der Text in Klammern ist der Titel oben im Fensterrahmen. Über die Variable \`fenster\` sprichst du es danach an. | +| \`fenster.setSize(300, 200);\` | Das Fenster wird 300 Pixel breit und 200 Pixel hoch. | +| \`fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\` | Schließt jemand das Fenster, endet auch das Programm. | +| \`fenster.setVisible(true);\` | Jetzt erst wird das Fenster sichtbar. | + +Der Punkt in \`fenster.setSize(…)\` bedeutet: „Fenster, mach das!“ Vor dem Punkt steht, wer etwas tun soll, dahinter, was es tun soll. + +> Ohne \`setDefaultCloseOperation\` versteckt Java das Fenster beim Schließen nur. Das Programm läuft dann unsichtbar weiter. + +## Warum setVisible am Ende steht + +\`setVisible(true)\` zeigt das Fenster so, wie es in diesem Moment ist. Deshalb richtest du zuerst alles ein: Titel, Größe, später auch Knöpfe. Erst ganz am Ende machst du das Fenster sichtbar. + +Was du erst nach \`setVisible(true)\` ins Fenster legst, erscheint oft nicht. Java zeichnet das Fenster nämlich nicht von selbst neu. Manchmal taucht es erst auf, wenn man die Größe des Fensters ändert. Solche Fehler sind schwer zu finden. + +::: ludwig +Erst einrichten, dann zeigen. Wie im Theater: Der Vorhang geht erst auf, wenn die Bühne fertig aufgebaut ist. +::: + +Probier es aus: Lösche die Zeile mit \`setVisible(true)\` und führe das Programm noch einmal aus. Das Programm läuft, aber du siehst kein Fenster. + +## Profiwissen: Klassen und Objekte + +Das steht nicht im Lehrplan, hilft dir aber, Swing zu verstehen. + +::: angeberwissen +Java ist eigentlich eine **objektorientierte** Sprache. \`JFrame\` ist eine Klasse, also ein Bauplan für Fenster. Mit \`new JFrame(…)\` baut Java nach diesem Bauplan ein echtes Fenster, ein **Objekt**. Du könntest mit zwei \`new\` auch zwei Fenster bauen, beide nach demselben Bauplan. + +\`setSize\` und \`setVisible\` sind Methoden, die jedes Fenster-Objekt kann. Deshalb schreibst du \`fenster.setSize(…)\`: Das Objekt \`fenster\` führt seine Methode aus. Auch dein Programm selbst ist eine Klasse, nämlich \`MeinFenster\`. +::: + +## Spiel: Was passiert? + +::: spiel frage +titel: Spiel: Was passiert? +intro: Ludwig hat am Fensterprogramm herumgebastelt. Lies die Zeilen und sag vorher, was passiert. Sechs Runden. + +runde: + JFrame fenster = new JFrame("Hallo"); + fenster.setSize(300, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); +frage: Was siehst du nach dem Ausführen? +- ein Fenster mit dem Titel „Hallo“ +- [x] gar kein Fenster +- eine Fehlermeldung +> \`setVisible(true)\` fehlt. Das Fenster ist gebaut, bleibt aber unsichtbar. + +runde: + JFrame fenster = new JFrame("Hallo"); + fenster.setSize(200, 300); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setVisible(true); +frage: Wie sieht das Fenster aus? +- breiter als hoch +- [x] höher als breit +- quadratisch +> Die erste Zahl ist die Breite, die zweite die Höhe: 200 breit, 300 hoch. + +runde: + JFrame fenster = new JFrame("Hallo"); + fenster.setSize(300, 200); + fenster.setVisible(true); +frage: Du schließt das Fenster. Was passiert mit dem Programm? +- Es endet. +- [x] Es läuft unsichtbar weiter. +- Das Fenster geht sofort wieder auf. +> Ohne \`setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)\` versteckt Java das Fenster nur. + +runde: + JFrame fenster = new JFrame(); + fenster.setSize(300, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setVisible(true); +frage: Was steht oben im Fensterrahmen? +- fenster +- JFrame +- [x] nichts, der Titel ist leer +> Ohne Text in den Klammern hat das Fenster keinen Titel. Der Variablenname \`fenster\` erscheint nie im Fenster. + +runde: + public class Test { + public static void main(String[] args) { + JFrame fenster = new JFrame("Test"); + fenster.setVisible(true); + } + } +frage: Was meldet javac? +- [x] cannot find symbol: class JFrame +- nichts, das Fenster erscheint +- missing return statement +> Die Zeile \`import javax.swing.*;\` fehlt. Ohne sie kennt Java \`JFrame\` nicht. + +runde: + JFrame a = new JFrame("Eins"); + JFrame b = new JFrame("Zwei"); + a.setSize(300, 200); + b.setSize(300, 200); + a.setVisible(true); +frage: Was siehst du? +- [x] ein Fenster mit dem Titel „Eins“ +- zwei Fenster +- ein Fenster mit dem Titel „Zwei“ +> Zwei Fenster nach demselben Bauplan, aber nur \`a\` wird sichtbar gemacht. +::: + +## Aufgabe: Dein eigenes Fenster + +Ändere das Programm so, dass + +- im Titel „Hallo“ und dein Name steht, +- das Fenster 400 Pixel breit und 300 Pixel hoch ist, +- das Programm endet, wenn du das Fenster schließt. + +Führe es aus und prüfe alle drei Punkte. + +::: ludwig +Du willst nicht so viel tippen? Mit „Echtes Java“ darfst du im Bereich Code auch nur die vier Zeilen aus \`main\` schreiben. VisuStruct packt sie dann selbst in eine Klasse und ergänzt die \`import\`-Zeilen. In einer richtigen Java-Entwicklungsumgebung brauchst du aber das ganze Programm. +::: + +## 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. + +::: checkliste +- Ich kann im Bereich Code „Echtes Java“ einschalten. → Programme mit Fenstern +- Ich kann ein Fenster mit Titel und Größe öffnen. → Das ganze Programm +- Ich kann erklären, was jede Zeile des Fensterprogramms macht. → Zeile für Zeile +- Ich kann erklären, warum setVisible(true) am Ende steht. → Warum setVisible am Ende steht +::: + +## Wissenstest + +::: quiz +? Welche Zeile macht das Fenster sichtbar? +→ Warum setVisible am Ende steht +- [ ] fenster.setSize(300, 200); +- [x] fenster.setVisible(true); +- [ ] new JFrame("Hallo"); +> Ohne setVisible(true) bleibt das Fenster unsichtbar. + +? Wo steht fenster.setVisible(true) am besten? +→ Warum setVisible am Ende steht +- [ ] Ganz am Anfang von main +- [x] Am Ende, wenn das Fenster fertig eingerichtet ist +- [ ] Das ist egal. +> Was nach setVisible(true) dazukommt, erscheint oft nicht. + +? Was bewirkt setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)? +→ Zeile für Zeile +- [ ] Das Fenster schließt sich sofort. +- [x] Schließt man das Fenster, endet das Programm. +- [ ] Das Fenster lässt sich nicht mehr schließen. + +? Woran erkennst du Bausteine aus Swing? +→ Zeile für Zeile +- [x] Ihr Name beginnt mit J, z. B. JFrame. +- [ ] Sie stehen in geschweiften Klammern. +- [ ] Sie enden mit Window. +::: +`,Jx=`--- +titel: Ein Knopf im Fenster +bereich: Fenster mit Swing +kurz: Einen Knopf ins Fenster legen und mit einem Layout ordentlich anordnen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- einen Knopf bauen und mit add ins Fenster legen +- erklären, warum der Knopf vor setVisible(true) hineinkommt +- mit FlowLayout dafür sorgen, dass der Knopf normal groß ist +- ein Fenster mit einem Knopf bauen, den man drücken kann +::: + +## Einen Knopf bauen + +Ein leeres Fenster ist langweilig. Jetzt kommt ein Knopf hinein. In Swing heißt ein Knopf **JButton** (button ist englisch für Knopf). + +Zwei neue Zeilen brauchst du dafür: + +\`\`\`java +JButton knopf = new JButton("Klick mich"); +fenster.add(knopf); +\`\`\` + +- \`new JButton("Klick mich")\` baut einen Knopf. Der Text in Klammern steht später auf dem Knopf. +- \`fenster.add(knopf)\` legt den Knopf ins Fenster. Ohne \`add\` gibt es den Knopf zwar, aber er liegt nirgends und du siehst ihn nicht. + +## Das ganze Programm + +Beide Zeilen kommen **vor** \`setVisible(true)\`, denn das Fenster soll erst fertig eingerichtet und dann gezeigt werden: + +\`\`\`java +import javax.swing.*; + +public class KnopfFenster { + public static void main(String[] args) { + JFrame fenster = new JFrame("Knopf"); + fenster.setSize(300, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JButton knopf = new JButton("Klick mich"); + fenster.add(knopf); + + fenster.setVisible(true); + } +} +\`\`\` + +Führe das Programm aus. Überraschung: Der Knopf ist riesig und füllt das ganze Fenster! + +::: ludwig +Die Reihenfolge ist wie beim ersten Fenster: einrichten, Knopf bauen, Knopf hineinlegen und ganz zum Schluss zeigen. Die Leerzeilen im Code helfen dir, diese Teile zu sehen. +::: + +## Der Riesenknopf + +Wie ein Fenster seine Teile anordnet, bestimmt sein **Layout**. Ein \`JFrame\` legt ohne weitere Angabe alles in die Mitte und macht es so groß wie das ganze Fenster. + +Mit einem anderen Layout bekommt der Knopf seine normale Größe. Das **FlowLayout** stellt alles wie Wörter in einer Zeile nebeneinander, so groß wie nötig: + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class KnopfFenster { + public static void main(String[] args) { + JFrame fenster = new JFrame("Knopf"); + fenster.setSize(300, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new FlowLayout()); + + JButton knopf = new JButton("Klick mich"); + fenster.add(knopf); + + fenster.setVisible(true); + } +} +\`\`\` + +\`FlowLayout\` gehört zum älteren Werkzeugkasten AWT. Deshalb steht oben eine zweite Zeile: \`import java.awt.*;\`. + +::: angeberwissen +Beim FlowLayout fließen die Bausteine wie Text: Passt ein Knopf nicht mehr in die Zeile, rutscht er in die nächste. Mach das Fenster schmal und schau zu, wie die Knöpfe umbrechen. Flow ist englisch für Fluss. +::: + +## Klicken geht, aber nichts passiert + +Klicke auf den Knopf. Er wird kurz dunkler, wenn du ihn drückst. Swing zeigt also, dass er gedrückt wurde. Sonst passiert aber nichts. + +Das ist kein Fehler: Du hast dem Programm noch nicht gesagt, **was** beim Klick passieren soll. Das lernst du in der nächsten Lektion. + +## Spiel: Bombe entschärfen + +::: spiel bombe +titel: Spiel: Bombe entschärfen +intro: In jedem Fensterprogramm steckt **genau ein Fehler**, und die Bombe tickt. Lies, was das Programm tun soll, und tippe auf die falsche Zeile, bevor die Zeit abläuft. Sechs Runden, je 25 Sekunden. +zeit: 25 + +runde: + JFrame fenster = new JFrame("Knopf"); + fenster.setSize(300, 200); + JButton knopf = new JButton(Klick mich); + fenster.add(knopf); + fenster.setVisible(true); +frage: Soll einen Knopf „Klick mich“ zeigen. +fehler: 3 +besser: JButton knopf = new JButton("Klick mich"); +> Die Beschriftung ist ein Text und braucht Anführungszeichen. + +runde: + JFrame fenster = new JFrame("Knopf"); + fenster.setSize(300, 200); + JButton knopf = new JButton("OK"); + fenster.add(fenster); + fenster.setVisible(true); +frage: Soll den Knopf „OK“ ins Fenster legen. +fehler: 4 +besser: fenster.add(knopf); +> Ins Fenster gehört der Knopf, nicht das Fenster selbst. + +runde: + import java.swing.*; + import java.awt.*; +frage: Soll Swing und das FlowLayout ins Programm holen. +fehler: 1 +besser: import javax.swing.*; +> Swing liegt in \`javax.swing\`, mit x. Das FlowLayout kommt aus \`java.awt\`, ohne x. + +runde: + JFrame fenster = new JFrame("Knopf"); + fenster.setSize(300, 200); + fenster.setLayout(new FlowLayout); + fenster.add(new JButton("OK")); + fenster.setVisible(true); +frage: Soll den Knopf in normaler Größe zeigen. +fehler: 3 +besser: fenster.setLayout(new FlowLayout()); +> Nach \`new\` und dem Namen kommen immer runde Klammern, auch wenn nichts darin steht. + +runde: + JFrame fenster = new JFrame("Knopf"); + fenster.setSize(300, 200); + fenster.setLayout(new FlowLayout()); + JButton knopf = new Jbutton("OK"); + fenster.add(knopf); + fenster.setVisible(true); +frage: Soll einen Knopf „OK“ zeigen. +fehler: 4 +besser: JButton knopf = new JButton("OK"); +> Java unterscheidet Groß- und Kleinschreibung: \`JButton\` mit großem B. + +runde: + JFrame fenster = new JFrame("Knopf"); + fenster.setSize(300, 200); + fenster.setLayout(new FlowLayout()); + fenster.add(new JButton("OK")); + fenster.setVisible(false); +frage: Soll das Fenster mit dem Knopf zeigen. +fehler: 5 +besser: fenster.setVisible(true); +> Mit \`false\` bleibt das Fenster unsichtbar. +::: + +## Aufgabe: Klick mich + +Baue ein Fenster mit dem Titel „Knopf-Test“, 300 mal 200 Pixel groß, mit einem Knopf „Klick mich“ in normaler Größe. Der Knopf soll sich drücken lassen, auch wenn noch nichts passiert. + +Zusatz: Lege einen zweiten Knopf „Ich auch“ daneben. In welcher Reihenfolge stehen die Knöpfe? Tausche die beiden \`add\`-Zeilen und probiere es noch einmal. + +::: ludwig +Jeder Knopf braucht eine eigene Variable, zum Beispiel \`knopf\` und \`knopf2\`, und ein eigenes \`add\`. Das FlowLayout stellt die Knöpfe in der Reihenfolge der \`add\`-Zeilen auf. +::: + +## 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. + +::: checkliste +- Ich kann einen Knopf bauen und mit add ins Fenster legen. → Einen Knopf bauen +- Ich kann erklären, warum der Knopf vor setVisible(true) hineinkommt. → Das ganze Programm +- Ich kann mit FlowLayout dafür sorgen, dass der Knopf normal groß ist. → Der Riesenknopf +- Ich kann ein Fenster mit einem Knopf bauen, den man drücken kann. → Aufgabe: Klick mich +::: + +## Wissenstest + +::: quiz +? Was macht fenster.add(knopf)? +→ Einen Knopf bauen +- [ ] Es baut einen neuen Knopf. +- [x] Es legt den Knopf ins Fenster. +- [ ] Es macht den Knopf klickbar. +> Gebaut wird der Knopf mit new JButton(…). + +? Warum füllt der Knopf ohne FlowLayout das ganze Fenster? +→ Der Riesenknopf +- [ ] Weil der Text zu lang ist +- [x] Weil das Fenster ohne eigenes Layout alles so groß wie das Fenster macht +- [ ] Weil setSize fehlt + +? Welche import-Zeile brauchst du für FlowLayout? +→ Der Riesenknopf +- [ ] import javax.swing.*; +- [x] import java.awt.*; +- [ ] import java.util.*; +> FlowLayout stammt aus dem älteren AWT. + +? Was passiert beim Klick auf den Knopf in dieser Lektion? +→ Aufgabe: Klick mich +- [ ] Das Programm endet. +- [x] Der Knopf wird kurz dunkler, sonst passiert nichts. +- [ ] Auf dem Knopf steht „Ich wurde geklickt“. +> Was beim Klick passieren soll, lernst du in der nächsten Lektion. +::: +`,Rx=`--- +titel: Der Knopf reagiert +bereich: Fenster mit Swing +kurz: Mit einem ActionListener festlegen, was beim Klick passiert. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, was ein Ereignis ist +- mit addActionListener festlegen, was beim Klick passiert +- beim Klick mehrere Anweisungen ausführen +- einen Knopf bauen, der nach dem Klick seinen Text ändert +::: + +## Ein Klick ist ein Ereignis + +In der letzten Lektion ließ sich der Knopf drücken, aber nichts geschah. Bei einem Fensterprogramm bestimmt nämlich der Mensch, wann etwas passiert: Er klickt, tippt oder schließt ein Fenster. Jede solche Aktion heißt **Ereignis**. + +Dein Programm muss deshalb auf den Klick warten und ihn bemerken. Dafür meldest du beim Knopf einen Zuhörer an, einen **ActionListener** (englisch für „Aktions-Zuhörer“). Bei jedem Klick ruft der Knopf seinen Zuhörer, und der führt deinen Code aus. + +::: ludwig +Bisher lief dein Programm von oben nach unten durch, wie im Struktogramm. Der Code im Zuhörer läuft dagegen erst später, nämlich immer dann, wenn jemand klickt. Wie oft das ist, weiß vorher niemand. +::: + +## Die Zeile mit dem Pfeil + +So meldest du den Zuhörer an: + +\`\`\`java +knopf.addActionListener(e -> knopf.setText("Ich wurde geklickt")); +\`\`\` + +Von außen nach innen gelesen: + +- \`knopf.addActionListener( … )\` meldet beim Knopf einen Zuhörer an. +- \`e\` ist das Ereignis. Darin steht zum Beispiel, wann geklickt wurde. Hier brauchst du es nicht, aber der Name muss dastehen. +- \`->\` liest du als „dann mach“. +- \`knopf.setText("Ich wurde geklickt")\` ist das, was beim Klick passiert: Der Knopf bekommt eine neue Beschriftung. + +Die Zeile steht nach \`new JButton(…)\`, denn den Knopf muss es schon geben. Und wie alles andere kommt sie vor \`setVisible(true)\`. + +## Das ganze Programm + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class KlickMich { + public static void main(String[] args) { + JFrame fenster = new JFrame("Klick mich"); + fenster.setSize(300, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new FlowLayout()); + + JButton knopf = new JButton("Klick mich"); + knopf.addActionListener(e -> knopf.setText("Ich wurde geklickt")); + fenster.add(knopf); + + fenster.setVisible(true); + } +} +\`\`\` + +Führe es aus und klicke auf den Knopf. Jetzt steht darauf „Ich wurde geklickt“. + +> Ist der neue Text länger als der alte, macht das FlowLayout den Knopf von selbst breiter. + +## Mehrere Anweisungen beim Klick + +Soll beim Klick mehr als eine Sache passieren, setzt du hinter den Pfeil geschweifte Klammern. Darin steht jede Anweisung mit Semikolon, wie in einem Schleifenrumpf: + +\`\`\`java +knopf.addActionListener(e -> { + knopf.setText("Ich wurde geklickt"); + fenster.setTitle("Danke!"); + System.out.println("Klick!"); +}); +\`\`\` + +\`System.out.println\` schreibt wie gewohnt in die [Konsole](#zeige-konsole). Klicke mehrmals: Bei jedem Klick erscheint eine neue Zeile „Klick!“. So siehst du, dass der Code im Zuhörer wirklich bei jedem Klick läuft. + +::: ludwig +Achte auf das Ende: Erst schließt \`}\` den Block, dann \`)\` die Klammer von \`addActionListener\`, dann kommt das Semikolon. Also \`});\`. Fehlt etwas davon, steht unter dem Code ein Hinweis. +::: + +## Spiel: Wer hört zu? + +::: spiel zuhoerer +titel: Spiel: Wer hört zu? +intro: Ludwig zeigt dir Code und das Fenster dazu. Darunter steht, welche Knöpfe nacheinander geklickt werden. Was passiert? Nach deiner Antwort spielt Ludwig die Klicks ab: Du siehst, welcher Zuhörer das Ereignis hört und welche Zeilen dann laufen. +frage: Was steht nach den Klicks in der Beschriftung? + +runde: + JFrame fenster = new JFrame("Gruß"); + JLabel text = new JLabel("Start"); + JButton knopf = new JButton("Hallo"); + knopf.addActionListener(e -> text.setText("Hallo Welt")); +klicks: Hallo +- Start +- [x] Hallo Welt +- Hallo +> Der Knopf hat einen Zuhörer. Beim Klick führt er \`text.setText("Hallo Welt")\` aus, und die Beschriftung zeigt „Hallo Welt“. + +runde: + JFrame fenster = new JFrame("Obst"); + JLabel text = new JLabel("?"); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + a.addActionListener(e -> text.setText("Apfel")); + b.addActionListener(e -> text.setText("Birne")); +klicks: A, B +- Apfel +- [x] Birne +- Apfel Birne +> Jeder Knopf hat seinen eigenen Zuhörer. Erst schreibt A „Apfel“ hinein, dann überschreibt B das mit „Birne“. \`setText\` ersetzt den alten Text, es hängt nichts an. + +runde: + JFrame fenster = new JFrame("Obst"); + JLabel text = new JLabel("?"); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + a.addActionListener(e -> text.setText("Apfel")); +klicks: B +- Apfel +- Birne +- [x] ? +> Beim Knopf B hat sich niemand angemeldet: Es gibt kein \`b.addActionListener\`. Der Klick ist ein Ereignis, aber niemand hört zu. Deshalb bleibt das Fragezeichen stehen. + +runde: + JFrame fenster = new JFrame("Farben"); + JLabel text = new JLabel("keine"); + JButton rot = new JButton("Rot"); + JButton blau = new JButton("Blau"); + rot.addActionListener(e -> text.setText("Blau")); + blau.addActionListener(e -> text.setText("Rot")); +klicks: Rot +- Rot +- [x] Blau +- keine +> Aufgepasst: Was passiert, entscheidet der Code im Zuhörer, nicht die Beschriftung des Knopfs. Der Zuhörer am Knopf „Rot“ schreibt „Blau“ hinein. + +runde: + JFrame fenster = new JFrame("Knopf"); + JLabel text = new JLabel("Bitte klicken"); + JButton knopf = new JButton("Klick mich"); + knopf.addActionListener(e -> { + knopf.setText("Danke!"); + text.setText("Geklickt"); + }); +klicks: Klick mich +frage: Was steht nach dem Klick auf dem Knopf? +- Klick mich +- [x] Danke! +- Geklickt +> Im Block hinter dem Pfeil stehen zwei Anweisungen. Beide laufen beim Klick nacheinander: Der Knopf bekommt „Danke!“, die Beschriftung „Geklickt“. + +runde: + JFrame fenster = new JFrame("Konsole"); + JButton knopf = new JButton("Los"); + knopf.addActionListener(e -> System.out.println("Klick!")); +klicks: Los, Los, Los +frage: Wie viele Zeilen „Klick!“ stehen danach in der Konsole? +- 1 +- [x] 3 +- 0 +> Der Zuhörer läuft bei **jedem** Klick, nicht nur beim ersten. Drei Klicks, drei Zeilen. +::: + +## Profiwissen: ActionListener ist ein Interface + +Das steht nicht im Lehrplan. Wenn du wissen willst, was hinter dem Pfeil steckt, lies weiter. + +::: angeberwissen +\`ActionListener\` ist ein **Interface**, eine Art Vertrag. Darin steht: Wer ein ActionListener sein will, muss eine Methode \`actionPerformed(ActionEvent e)\` haben. Der Knopf ruft bei jedem Klick genau diese Methode auf. +::: + +Die Zeile mit dem Pfeil kennst du schon aus Schritt 3: + +\`\`\`java +knopf.addActionListener(e -> knopf.setText("Ich wurde geklickt")); +\`\`\` + +Ohne Pfeil schreibt man den Zuhörer als Klasse ohne Namen, die den Vertrag erfüllt (eine anonyme Klasse): + +\`\`\`java +knopf.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + knopf.setText("Ich wurde geklickt"); + } +}); +\`\`\` + +Dafür brauchst du oben noch \`import java.awt.event.*;\`. Beide Schreibweisen machen genau dasselbe. Der Pfeil \`e -> …\` ist die Kurzform (ein Lambda-Ausdruck, seit Java 8): \`e\` ist der Parameter von \`actionPerformed\`, und hinter dem Pfeil steht ihr Rumpf. Die Kurzform geht, weil das Interface nur eine einzige Methode hat. Java weiß also, welche Methode gemeint ist. + +## Spiel: Vertrag erfüllt? + +::: spiel vertrag +titel: Spiel: Vertrag erfüllt? +intro: Der Vertrag \`ActionListener\` verlangt genau eine Methode: \`public void actionPerformed(ActionEvent e)\`. Ludwig zeigt dir Code. Erfüllt er den Vertrag, sodass man ihn beim Knopf anmelden kann? Jede Antwort hat Ludwig mit dem echten Java-Compiler geprüft. +frage: Erfüllt das den Vertrag ActionListener? +antworten: erfüllt | nicht erfüllt + +runde: + class Gruss implements ActionListener { + public void actionPerformed(ActionEvent e) { + System.out.println("Hallo"); + } + } +richtig: erfüllt +> Alles da: \`implements ActionListener\` unterschreibt den Vertrag, und die Methode heißt genau \`actionPerformed\`, ist \`public\`, gibt nichts zurück (\`void\`) und bekommt ein \`ActionEvent\`. + +runde: + class Gruss implements ActionListener { + public void actionPerfomed(ActionEvent e) { + System.out.println("Hallo"); + } + } +richtig: nicht erfüllt +> Schau genau hin: \`actionPerfomed\` statt \`actionPerformed\`, ein r fehlt. Für Java ist das eine ganz andere Methode. Der Compiler meldet, dass \`actionPerformed\` fehlt. + +runde: + class Gruss implements ActionListener { + public void actionPerformed() { + System.out.println("Hallo"); + } + } +richtig: nicht erfüllt +> Der Parameter fehlt. Der Vertrag verlangt \`actionPerformed(ActionEvent e)\`, denn der Knopf übergibt beim Klick das Ereignis. + +runde: + class Gruss implements ActionListener { + public void actionPerformed(ActionEvent ereignis) { + System.out.println("Hallo"); + } + } +richtig: erfüllt +> Der Name des Parameters ist frei wählbar. Wichtig ist nur der Typ \`ActionEvent\`. Statt \`e\` darf er also auch \`ereignis\` heißen. + +runde: + class Gruss implements ActionListener { + void actionPerformed(ActionEvent e) { + System.out.println("Hallo"); + } + } +richtig: nicht erfüllt +> Das \`public\` fehlt. Alle Methoden eines Interfaces sind öffentlich, denn der Knopf muss sie von außen aufrufen können. Ohne \`public\` meldet der Compiler einen Fehler. + +runde: + class Gruss implements ActionListener { + public int actionPerformed(ActionEvent e) { + return 0; + } + } +richtig: nicht erfüllt +> Der Vertrag sagt \`void\`: Die Methode gibt nichts zurück. Mit \`int\` als Rückgabetyp passt sie nicht mehr. + +runde: + class Gruss implements ActionListener { + public void actionPerformed(ActionEvent e) { + sagHallo(); + } + void sagHallo() { + System.out.println("Hallo"); + } + } +richtig: erfüllt +> Zusätzliche Methoden sind erlaubt. Der Vertrag verlangt nur, dass \`actionPerformed\` da ist, nicht, dass sonst nichts da ist. + +runde: + class Gruss { + public void actionPerformed(ActionEvent e) { + System.out.println("Hallo"); + } + } + knopf.addActionListener(new Gruss()); +richtig: nicht erfüllt +> Die Methode stimmt, aber der Vertrag ist nicht unterschrieben: Es fehlt \`implements ActionListener\`. Java nimmt beim Knopf nur Objekte an, die den Vertrag offiziell erfüllen. + +runde: + knopf.addActionListener(e -> System.out.println("Hallo")); +richtig: erfüllt +> Der Pfeil ist die Kurzform. Weil der Vertrag nur eine Methode hat, weiß Java: \`e\` ist der Parameter von \`actionPerformed\`, und hinter dem Pfeil steht ihr Rumpf. + +runde: + knopf.addActionListener((a, b) -> System.out.println("Hallo")); +richtig: nicht erfüllt +> Hier hat der Pfeil zwei Parameter. \`actionPerformed\` bekommt aber genau einen, das Ereignis. Darum passt diese Kurzform nicht zum Vertrag. +::: + +## Aufgabe: Ich wurde geklickt + +Jetzt machst du die Aufgabe fertig: Baue ein Fenster mit einem Knopf „Klick mich“ in normaler Größe. Nach dem Klick steht auf dem Knopf „Ich wurde geklickt“. + +Zusatz: Baue zwei Knöpfe „Rot“ und „Blau“. Ein Klick auf einen Knopf schreibt seinen Namen in den Titel des Fensters, zum Beispiel „Du hast Rot gewählt“. + +::: ludwig +Jeder Knopf bekommt seinen eigenen Zuhörer mit eigenem \`addActionListener\`. Den Titel änderst du mit \`fenster.setTitle(…)\`. +::: + +## 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. + +::: checkliste +- Ich kann erklären, was ein Ereignis ist. → Ein Klick ist ein Ereignis +- Ich kann mit addActionListener festlegen, was beim Klick passiert. → Die Zeile mit dem Pfeil +- Ich kann beim Klick mehrere Anweisungen ausführen. → Mehrere Anweisungen beim Klick +- Ich kann einen Knopf bauen, der nach dem Klick seinen Text ändert. → Aufgabe: Ich wurde geklickt +::: + +## Wissenstest + +::: quiz +? Was ist ein ActionListener? +→ Ein Klick ist ein Ereignis +- [ ] Ein Knopf mit Text +- [x] Ein Zuhörer, der bei jedem Klick deinen Code ausführt +- [ ] Ein Layout für Fenster +> Du meldest ihn mit addActionListener beim Knopf an. + +? Wann läuft knopf.setText("Ich wurde geklickt") im Zuhörer? +→ Die Zeile mit dem Pfeil +- [ ] Sofort beim Start des Programms +- [x] Jedes Mal, wenn jemand auf den Knopf klickt +- [ ] Nur beim ersten Klick +> Der Code im Zuhörer läuft erst, wenn das Ereignis eintritt. + +? Wie endet ein Zuhörer mit geschweiften Klammern? +→ Die Zeile mit dem Pfeil +- [ ] };) +- [x] }); +- [ ] );} +> Erst schließt der Block, dann die Klammer von addActionListener, dann das Semikolon. + +? Ordne jedem Teil seine Aufgabe zu. +→ Die Zeile mit dem Pfeil += JButton -> ein Knopf += addActionListener -> Zuhörer anmelden += setText -> Beschriftung ändern += setVisible(true) -> Fenster zeigen +::: +`,Gx=`--- +titel: Zahl verdoppeln im Fenster +bereich: Fenster mit Swing +kurz: Beschriftung, Textfeld und Knopf mit einem GridLayout anordnen und mit dem Text im Textfeld rechnen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- JLabel und JTextField ins Fenster legen +- erklären, warum ohne Layout nur der letzte Baustein zu sehen ist +- mit GridLayout(0, 1) alles untereinander anordnen +- mit getText, Integer.parseInt und setText rechnen +- ein Programm schreiben, das bei „abc“ nicht abstürzt +::: + +## Das Ziel + +Wir bauen ein kleines Rechenprogramm mit Fenster: Oben steht eine Beschriftung, darunter ein Textfeld und ein Knopf **Berechne**. Gibst du 2 ein und klickst, steht im Textfeld 4. Klickst du noch einmal, wird daraus 8, dann 16 und so weiter. + +Dafür brauchst du zwei neue Bausteine: + +- **JLabel**: eine Beschriftung, also einfacher Text im Fenster. +- **JTextField**: ein Textfeld, in das man etwas tippen kann. + +Schalte wie in den letzten Lektionen im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Drei Bausteine ins Fenster + +Wir legen alle drei Bausteine ins Fenster, genau wie den Knopf in Lektion 29: + +\`\`\`java +import javax.swing.*; + +public class Verdoppeln { + public static void main(String[] args) { + JFrame fenster = new JFrame("Zahl verdoppeln"); + fenster.setSize(250, 150); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JLabel beschriftung = new JLabel("Gib eine Zahl ein:"); + JTextField feld = new JTextField(); + JButton knopf = new JButton("Berechne"); + fenster.add(beschriftung); + fenster.add(feld); + fenster.add(knopf); + + fenster.setVisible(true); + } +} +\`\`\` + +Führe das Programm aus. Hoppla: Man sieht nur den riesigen Knopf. Wo sind die Beschriftung und das Textfeld? + +## Warum nur der Knopf zu sehen ist + +::: ludwig +Erinnerst du dich an den Riesenknopf? Ein \`JFrame\` hat ohne eigenes Layout nur **einen** Platz: die Mitte. Jedes \`add\` legt den neuen Baustein genau dorthin, so groß wie das ganze Fenster. Die drei Bausteine landen also übereinander auf demselben Platz, und das Fenster zeigt nur den zuletzt hineingelegten: den Knopf. Benutzen kannst du das Programm so nicht. +::: + +Die Lösung ist wieder ein Layout. Diesmal nehmen wir das **GridLayout**. Es teilt das Fenster in gleich große Zellen wie ein Gitter: + +\`\`\`java +fenster.setLayout(new GridLayout(0, 1)); +\`\`\` + +Die beiden Zahlen sind Zeilen und Spalten. \`0\` Zeilen heißt „so viele wie nötig“, \`1\` Spalte heißt: alles untereinander. Für \`GridLayout\` brauchst du oben außerdem \`import java.awt.*;\`. + +| Layout | So ordnet es an | +|---|---| +| ohne Layout | alles in die Mitte, übereinander | +| \`FlowLayout\` | nebeneinander wie Wörter, Zeilenumbruch wenn nötig | +| \`GridLayout(0, 1)\` | untereinander, jede Zeile gleich hoch | + +## Das Fenster mit GridLayout + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Verdoppeln { + public static void main(String[] args) { + JFrame fenster = new JFrame("Zahl verdoppeln"); + fenster.setSize(250, 150); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new GridLayout(0, 1)); + + JLabel beschriftung = new JLabel("Gib eine Zahl ein:"); + JTextField feld = new JTextField(); + JButton knopf = new JButton("Berechne"); + fenster.add(beschriftung); + fenster.add(feld); + fenster.add(knopf); + + fenster.setVisible(true); + } +} +\`\`\` + +Jetzt stehen alle drei untereinander. Du kannst ins Textfeld tippen und den Knopf drücken. Rechnen tut das Programm aber noch nicht. + +::: angeberwissen +Mit \`new GridLayout(2, 3)\` bekommst du 2 Zeilen mit je 3 Spalten, also 6 gleich große Zellen. So baut man zum Beispiel die Tasten eines Taschenrechners. Die Bausteine füllen die Zellen in der Reihenfolge der \`add\`-Zeilen, Zeile für Zeile von links nach rechts. +::: + +## Mit dem Text im Textfeld rechnen + +Beim Klick soll das Programm die Zahl aus dem Textfeld holen, verdoppeln und wieder hineinschreiben. Das machen drei Methoden: + +- \`feld.getText()\` liefert den Text im Textfeld, zum Beispiel \`"2"\`. +- \`Integer.parseInt(…)\` macht daraus die Zahl 2. Das kennst du aus Lektion 22. +- \`feld.setText(…)\` schreibt einen neuen Text ins Textfeld. + +Zusammen mit dem ActionListener aus Lektion 30 sieht das so aus: + +\`\`\`java +knopf.addActionListener(e -> { + int zahl = Integer.parseInt(feld.getText()); + feld.setText("" + zahl * 2); +}); +\`\`\` + +\`setText\` braucht einen Text. \`"" + zahl * 2\` hängt das Ergebnis an einen leeren Text und macht so aus der Zahl einen Text. + +## Keine Zahl? Kein Absturz! + +Tippe „abc“ ins Textfeld und klicke auf Berechne. Das Fenster bleibt, aber es passiert nichts, und in der [Konsole](#zeige-konsole) steht eine \`NumberFormatException\`. Aus Lektion 22 weißt du, was zu tun ist: + +\`\`\`java +knopf.addActionListener(e -> { + try { + int zahl = Integer.parseInt(feld.getText()); + feld.setText("" + zahl * 2); + } catch (NumberFormatException fehler) { + beschriftung.setText("Bitte eine ganze Zahl eingeben!"); + } +}); +\`\`\` + +Statt eines Fehlers in der Konsole sieht man jetzt einen Hinweis im Fenster. + +::: ludwig +Der Pfeil hat schon ein \`e\` für das Ereignis. Deshalb braucht die Exception im \`catch\` einen anderen Namen, hier \`fehler\`. Zwei Variablen mit demselben Namen erlaubt Java nicht. +::: + +## Spiel: Was steht danach im Fenster? + +::: spiel frage +titel: Spiel: Was steht danach im Fenster? +intro: Ludwig tippt etwas ins Textfeld und klickt auf Berechne. Lies den Zuhörer und sag vorher, was danach im Fenster steht. Sechs Runden. + +runde: + knopf.addActionListener(e -> { + int zahl = Integer.parseInt(feld.getText()); + feld.setText("" + zahl * 2); + }); +frage: Im Textfeld steht 21. Was steht nach dem Klick darin? +- 2121 +- [x] 42 +- 21 +> \`parseInt\` macht aus dem Text die Zahl 21. Das Doppelte ist 42. + +runde: + knopf.addActionListener(e -> { + int zahl = Integer.parseInt(feld.getText()); + feld.setText("" + zahl * 2); + }); +frage: Im Textfeld steht 21. Du klickst zweimal. Was steht danach darin? +- 42 +- [x] 84 +- 4242 +> Jeder Klick verdoppelt, was gerade im Feld steht: 21, 42, 84. + +runde: + knopf.addActionListener(e -> { + feld.setText(feld.getText() + feld.getText()); + }); +frage: Im Textfeld steht 21. Was steht nach dem Klick darin? +- 42 +- [x] 2121 +- 21 +> Ohne \`parseInt\` bleibt es ein Text, und \`+\` hängt Texte aneinander. + +runde: + knopf.addActionListener(e -> { + try { + int zahl = Integer.parseInt(feld.getText()); + feld.setText("" + zahl * 2); + } catch (NumberFormatException fehler) { + beschriftung.setText("Bitte eine ganze Zahl eingeben!"); + } + }); +frage: Im Textfeld steht abc. Was passiert beim Klick? +- [x] Die Beschriftung zeigt „Bitte eine ganze Zahl eingeben!“ +- Im Textfeld steht abcabc. +- Das Fenster stürzt ab. +> \`parseInt\` wirft eine NumberFormatException, und \`catch\` fängt sie ab. + +runde: + knopf.addActionListener(e -> { + try { + int zahl = Integer.parseInt(feld.getText()); + feld.setText("" + zahl * 2); + } catch (NumberFormatException fehler) { + beschriftung.setText("Bitte eine ganze Zahl eingeben!"); + } + }); +frage: Im Textfeld steht 2.5. Was passiert beim Klick? +- Im Textfeld steht 5.0. +- Im Textfeld steht 5. +- [x] Die Beschriftung zeigt „Bitte eine ganze Zahl eingeben!“ +> \`Integer.parseInt\` kennt nur ganze Zahlen. 2.5 ist für ihn keine Zahl. + +runde: + knopf.addActionListener(e -> { + int zahl = Integer.parseInt(feld.getText()); + feld.setText("" + zahl + zahl); + }); +frage: Im Textfeld steht 5. Was steht nach dem Klick darin? +- 10 +- [x] 55 +- 5 +> \`"" + zahl\` ist schon ein Text, und das zweite \`+\` hängt die 5 noch einmal an. Mit \`"" + (zahl + zahl)\` wird zuerst gerechnet. +::: + +## Aufgabe: Zahl verdoppeln + +Baue das ganze Programm zusammen: + +- ein Fenster mit dem Titel „Zahl verdoppeln“, 250 Pixel breit und 150 Pixel hoch, +- untereinander eine Beschriftung, ein Textfeld und ein Knopf „Berechne“, +- jeder Klick verdoppelt die Zahl im Textfeld: 2, 4, 8, 16, … +- bei „abc“ erscheint in der Beschriftung ein Hinweis statt eines Absturzes. + +Zusatz: Ein zweiter Knopf „Halbieren“ teilt die Zahl durch 2. Was passiert bei 5? + +::: ludwig +Der Knopf „Halbieren“ kommt als vierte Zeile ins GridLayout und bekommt seinen eigenen ActionListener. Bei \`int\` schneidet Java beim Teilen die Nachkommastellen ab. +::: + +## 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. + +::: checkliste +- Ich kann JLabel und JTextField ins Fenster legen. → Drei Bausteine ins Fenster +- Ich kann erklären, warum ohne Layout nur der letzte Baustein zu sehen ist. → Warum nur der Knopf zu sehen ist +- Ich kann mit GridLayout(0, 1) alles untereinander anordnen. → Das Fenster mit GridLayout +- Ich kann mit getText, Integer.parseInt und setText rechnen. → Mit dem Text im Textfeld rechnen +- Ich kann ein Programm schreiben, das bei „abc“ nicht abstürzt. → Keine Zahl? Kein Absturz! +::: + +## Wissenstest + +::: quiz +? Warum ist ohne Layout nur der Knopf zu sehen? +→ Warum nur der Knopf zu sehen ist +- [ ] Weil Beschriftung und Textfeld fehlen +- [x] Weil alle Bausteine in der Mitte übereinander liegen und der letzte die anderen verdeckt +- [ ] Weil das Fenster zu klein ist + +? Was bedeutet new GridLayout(0, 1)? +→ Das Fenster mit GridLayout +- [ ] Keine Zeile und eine Spalte, also ist das Fenster leer +- [x] So viele Zeilen wie nötig in einer Spalte, also alles untereinander +- [ ] Eine Zeile, alles nebeneinander + +? Was liefert feld.getText()? +→ Mit dem Text im Textfeld rechnen +- [ ] Immer eine Zahl +- [x] Den Text im Textfeld +- [ ] Den Titel des Fensters +> Für eine Zahl brauchst du noch Integer.parseInt. + +? Ordne jedem Baustein seine Aufgabe zu. +→ Drei Bausteine ins Fenster += JLabel -> Beschriftung += JTextField -> Textfeld zum Tippen += JButton -> Knopf += GridLayout -> Anordnung im Gitter +::: +`,Hx=`--- +titel: Klickzähler mit Reset +bereich: Fenster mit Swing +kurz: Zwei Knöpfe ändern dieselbe Zahl: eine Variable für die ganze Klasse anlegen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, warum ein Zuhörer eine Variable aus main nicht ändern darf +- eine static-Variable in der Klasse anlegen +- zwei Knöpfe dieselbe Zahl ändern lassen +- einen Zähler mit −1 bauen, der nie unter 0 fällt +::: + +## Das Ziel + +Ein Fenster zählt Klicks: Oben steht die Zahl, darunter zwei Knöpfe. **+1** zählt eins hoch, **Reset** setzt die Zahl wieder auf 0. + +Neu ist diesmal: Zwei Knöpfe arbeiten mit **derselben** Zahl. Dafür brauchst du eine Variable, die beide Zuhörer kennen. + +Schalte im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Der erste Versuch + +Naheliegend wäre, die Zahl wie gewohnt in \`main\` anzulegen und im Zuhörer hochzuzählen: + +\`\`\`java +int anzahl = 0; +knopf.addActionListener(e -> { + anzahl++; + zahl.setText("" + anzahl); +}); +\`\`\` + +Führst du das mit echtem Java aus, meldet der Compiler einen Fehler: + +\`\`\` +local variables referenced from a lambda expression must be final or effectively final +\`\`\` + +::: ludwig +Der Zuhörer läuft erst später, bei jedem Klick, wenn \`main\` längst fertig ist. Deshalb darf er die Variablen aus \`main\` zwar lesen, aber nicht verändern. Java besteht darauf: Eine Variable aus \`main\`, die im Pfeil vorkommt, muss gleich bleiben. Für eine Zahl, die sich bei jedem Klick ändert, brauchen wir einen anderen Platz. +::: + +## Eine Variable für die ganze Klasse + +Die Lösung: Die Variable kommt **nicht** in \`main\`, sondern direkt in die Klasse, über \`main\`. Dann gehört sie der ganzen Klasse, und jeder Zuhörer darf sie ändern: + +\`\`\`java +public class Zaehler { + static int anzahl = 0; + + public static void main(String[] args) { + // hier wie gewohnt das Fenster + } +} +\`\`\` + +- \`static\` heißt: Die Variable gehört zur Klasse selbst. Weil \`main\` auch \`static\` ist, braucht es das hier. +- Eine solche Variable nennt man **Attribut** der Klasse. Sie lebt so lange wie das Programm, nicht nur so lange wie \`main\`. + +## Das ganze Programm + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Zaehler { + static int anzahl = 0; + + public static void main(String[] args) { + JFrame fenster = new JFrame("Klickzähler"); + fenster.setSize(250, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new GridLayout(0, 1)); + + JLabel zahl = new JLabel("0", SwingConstants.CENTER); + JButton plus = new JButton("+1"); + JButton reset = new JButton("Reset"); + + plus.addActionListener(e -> { + anzahl++; + zahl.setText("" + anzahl); + }); + reset.addActionListener(e -> { + anzahl = 0; + zahl.setText("0"); + }); + + fenster.add(zahl); + fenster.add(plus); + fenster.add(reset); + fenster.setVisible(true); + } +} +\`\`\` + +\`SwingConstants.CENTER\` setzt den Text der Beschriftung in die Mitte. Klicke ein paarmal auf +1 und dann auf Reset. + +::: angeberwissen +Mit \`zahl.setFont(new Font("SansSerif", Font.BOLD, 48));\` wird die Zahl groß und fett. \`Font\` kommt aus \`java.awt\`, das du schon importiert hast. +::: + +## Spiel: Wer zählt mit? + +::: spiel zuhoerer +titel: Spiel: Wer zählt mit? +intro: Jetzt rechnen die Zuhörer mit der Variable aus der Klasse. Ludwig zeigt dir Code, Fenster und die Klicks. Welche Zahl steht am Ende da? Danach spielt Ludwig die Klicks ab. +frage: Was steht nach den Klicks in der Beschriftung? + +runde: + static int anzahl = 0; + JLabel zahl = new JLabel("0"); + JButton plus = new JButton("+1"); + plus.addActionListener(e -> { + anzahl++; + zahl.setText("" + anzahl); + }); +klicks: +1, +1, +1 +- 1 +- [x] 3 +- 0 +> Die Variable steht in der Klasse und behält ihren Wert zwischen den Klicks. Jeder Klick zählt eins hoch: 1, 2, 3. + +runde: + static int anzahl = 0; + JLabel zahl = new JLabel("0"); + JButton plus = new JButton("+1"); + JButton reset = new JButton("Reset"); + plus.addActionListener(e -> { + anzahl++; + zahl.setText("" + anzahl); + }); + reset.addActionListener(e -> { + anzahl = 0; + zahl.setText("0"); + }); +klicks: +1, +1, Reset, +1 +- 3 +- 0 +- [x] 1 +> Nach zwei Klicks steht 2 da. Reset setzt die Variable auf 0, und der letzte Klick zählt wieder auf 1. + +runde: + static int anzahl = 0; + JLabel zahl = new JLabel("0"); + JButton plus = new JButton("+1"); + plus.addActionListener(e -> anzahl++); +klicks: +1, +1 +- 2 +- [x] 0 +- 1 +> Die Variable ist danach 2, aber niemand schreibt sie in die Beschriftung. Ohne \`zahl.setText(…)\` zeigt das Fenster weiter 0. Rechnen und Anzeigen sind zwei verschiedene Dinge. + +runde: + static int anzahl = 0; + JLabel zahl = new JLabel("Klicks: 0"); + JButton plus = new JButton("+1"); + plus.addActionListener(e -> { + anzahl++; + zahl.setText("Klicks: " + anzahl + 1); + }); +klicks: +1 +- Klicks: 2 +- Klicks: 1 +- [x] Klicks: 11 +> Die Klammerfalle: Java rechnet von links nach rechts. \`"Klicks: " + anzahl\` ergibt den Text „Klicks: 1“, und \`+ 1\` hängt eine weitere 1 an. + +runde: + static int anzahl = 0; + JLabel zahl = new JLabel("0"); + JButton eins = new JButton("+1"); + JButton zehn = new JButton("+10"); + eins.addActionListener(e -> { + anzahl++; + zahl.setText("" + anzahl); + }); + zehn.addActionListener(e -> { + anzahl += 10; + zahl.setText("" + anzahl); + }); +klicks: +10, +1, +10 +- 12 +- [x] 21 +- 111 +> Beide Zuhörer ändern dieselbe Variable: 10, dann 11, dann 21. \`anzahl += 10\` ist die Kurzform von \`anzahl = anzahl + 10\`. +::: + +## Aufgabe: Klickzähler + +Baue den Klickzähler nach und erweitere ihn: + +- ein Knopf **−1**, der eins herunterzählt, +- die Zahl soll nie unter 0 fallen. Steht sie auf 0, passiert bei −1 nichts. + +::: ludwig +Für „nie unter 0“ brauchst du im Zuhörer von −1 ein \`if\`: Nur wenn \`anzahl > 0\` ist, wird heruntergezählt. +::: + +## 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. + +::: checkliste +- Ich kann erklären, warum ein Zuhörer eine Variable aus main nicht ändern darf. → Der erste Versuch +- Ich kann eine static-Variable in der Klasse anlegen. → Eine Variable für die ganze Klasse +- Ich kann zwei Knöpfe dieselbe Zahl ändern lassen. → Das ganze Programm +- Ich kann einen Zähler mit −1 bauen, der nie unter 0 fällt. → Aufgabe: Klickzähler +::: + +## Wissenstest + +::: quiz +? Warum darf der Zuhörer die Variable anzahl aus main nicht verändern? +→ Der erste Versuch +- [ ] Weil Zahlen in Swing nicht erlaubt sind +- [x] Weil der Zuhörer erst später läuft und Java Variablen aus main im Pfeil nicht verändern lässt +- [ ] Weil anzahl zu groß wird + +? Wo steht static int anzahl = 0;? +→ Eine Variable für die ganze Klasse +- [ ] In main, ganz oben +- [x] In der Klasse, außerhalb von main +- [ ] Im Zuhörer + +? Was macht SwingConstants.CENTER bei new JLabel("0", SwingConstants.CENTER)? +→ Das ganze Programm +- [x] Es setzt den Text in die Mitte der Beschriftung. +- [ ] Es setzt das Fenster in die Mitte des Bildschirms. +- [ ] Es macht die Schrift größer. +::: +`,Vx=`--- +titel: Eine Ampel mit Farben +bereich: Fenster mit Swing +kurz: Hintergrundfarben setzen und mit einer Zustandsvariable eine Ampel weiterschalten. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- mit setOpaque und setBackground eine Beschriftung färben +- mir mit einer static-Variable einen Zustand merken +- mit BorderLayout etwas groß in die Mitte und etwas schmal nach unten setzen +- erklären, wofür FlowLayout, GridLayout und BorderLayout gut sind +- eine Ampel mit vier Phasen programmieren +::: + +## Das Ziel + +Wir bauen eine Ampel: Eine große Fläche leuchtet rot. Bei jedem Klick auf **Weiter** schaltet sie um: Rot, Grün, Gelb und wieder Rot. + +Neu sind diesmal **Farben** und ein **Zustand**: Das Programm muss sich merken, welche Farbe gerade dran ist. + +Schalte im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Farben in Swing + +Farben stehen in der Klasse \`Color\` aus \`java.awt\`. Fertige Farben sind zum Beispiel \`Color.RED\`, \`Color.GREEN\`, \`Color.YELLOW\`, \`Color.ORANGE\` und \`Color.WHITE\`. + +Eine Beschriftung färbst du so: + +\`\`\`java +JLabel licht = new JLabel("", SwingConstants.CENTER); +licht.setOpaque(true); +licht.setBackground(Color.RED); +\`\`\` + +- \`setBackground(…)\` legt die Hintergrundfarbe fest. +- \`setOpaque(true)\` braucht ein \`JLabel\` dazu. Ohne diese Zeile ist der Hintergrund durchsichtig, und die Farbe bleibt unsichtbar. + +::: ludwig +\`opaque\` ist englisch für „undurchsichtig“. Eine Beschriftung ist normalerweise durchsichtig wie Schrift auf einer Glasscheibe. Erst mit \`setOpaque(true)\` bekommt sie eine eigene Fläche, die man anmalen kann. +::: + +## Sich die Farbe merken + +Damit die Ampel weiß, was als Nächstes kommt, merkt sie sich ihren Zustand in einer Zahl: 0 heißt Rot, 1 heißt Grün, 2 heißt Gelb. Wie beim Klickzähler aus Lektion 32 steht die Variable in der Klasse, damit der Zuhörer sie ändern darf: + +\`\`\`java +static int phase = 0; +\`\`\` + +Bei jedem Klick geht die Phase eins weiter. Nach Gelb (2) kommt wieder Rot (0): + +\`\`\`java +weiter.addActionListener(e -> { + phase++; + if (phase > 2) { + phase = 0; + } + if (phase == 0) { + licht.setBackground(Color.RED); + } else if (phase == 1) { + licht.setBackground(Color.GREEN); + } else { + licht.setBackground(Color.YELLOW); + } +}); +\`\`\` + +## Das ganze Programm + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Ampel { + static int phase = 0; + + public static void main(String[] args) { + JFrame fenster = new JFrame("Ampel"); + fenster.setSize(200, 300); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new BorderLayout()); + + JLabel licht = new JLabel("", SwingConstants.CENTER); + licht.setOpaque(true); + licht.setBackground(Color.RED); + JButton weiter = new JButton("Weiter"); + + weiter.addActionListener(e -> { + phase++; + if (phase > 2) { + phase = 0; + } + if (phase == 0) { + licht.setBackground(Color.RED); + } else if (phase == 1) { + licht.setBackground(Color.GREEN); + } else { + licht.setBackground(Color.YELLOW); + } + }); + + fenster.add(licht, BorderLayout.CENTER); + fenster.add(weiter, BorderLayout.SOUTH); + fenster.setVisible(true); + } +} +\`\`\` + +Hier kommt ein neues Layout zum Einsatz, das **BorderLayout**. Es hat fünf Plätze: \`NORTH\` (oben), \`SOUTH\` (unten), \`WEST\` (links), \`EAST\` (rechts) und \`CENTER\` (Mitte). Die Mitte bekommt allen Platz, der übrig bleibt. So wird das Licht groß, und der Knopf bleibt unten schmal. + +::: angeberwissen +Das BorderLayout ist das Layout, das ein \`JFrame\` ohne eigenes Layout benutzt. Ein \`add\` ohne Platzangabe landet in \`CENTER\`. Deshalb lagen in Lektion 31 alle Bausteine übereinander. +::: + +::: angeberwissen +Profis schreiben das Weiterschalten in einer Zeile: \`phase = (phase + 1) % 3;\`. Der Rest-Operator \`%\` liefert den Rest beim Teilen. 3 % 3 ist 0, also beginnt es nach 2 wieder bei 0. +::: + +## Welches Layout wofür? + +Du kennst jetzt drei Layouts. Jedes ordnet die Bausteine anders an: + +| Layout | So ordnet es an | Gut für | +|---|---|---| +| \`FlowLayout\` (Lektion 29) | nebeneinander wie Wörter in einer Zeile, jeder Baustein so groß wie nötig | ein paar Knöpfe in einer Reihe | +| \`GridLayout\` (Lektion 31) | ein Gitter aus gleich großen Zellen, Zeile für Zeile gefüllt | Formulare, Tastenfelder wie beim Taschenrechner | +| \`BorderLayout\` (diese Lektion) | fünf Plätze: oben, unten, links, rechts und die Mitte, die den Rest bekommt | etwas Großes in der Mitte, z. B. ein Bild oder eine Anzeige, mit Knöpfen am Rand | + +Ohne \`setLayout\` benutzt ein Fenster das BorderLayout. Darum landet dann alles in der Mitte. + +::: ludwig +Frag dich beim Planen: Sollen alle Teile gleich groß sein? Dann GridLayout. Soll ein Teil groß sein und der Rest schmal am Rand? Dann BorderLayout. Sollen die Teile einfach ihre normale Größe behalten? Dann FlowLayout. +::: + +## Spiel: Wo landet der Knopf? + +::: spiel layout +titel: Spiel: Wo landet der Knopf? +intro: Du kennst jetzt drei Layouts und das Fenster ganz ohne Layout. Ludwig zeigt dir Code mit den Knöpfen A, B, C … Wie sieht das Fenster aus? Tippe auf das richtige Bild. +frage: Wie sieht das Fenster aus? + +runde: + fenster.add(new JButton("A")); + fenster.add(new JButton("B")); + fenster.add(new JButton("C")); +- flow: A B C +- grid: A / B / C +- [x] border: C=C +> Ohne eigenes Layout landet jedes \`add\` in der Mitte, so groß wie das Fenster. Die drei liegen übereinander, man sieht nur den letzten: C. + +runde: + fenster.setLayout(new FlowLayout()); + fenster.add(new JButton("A")); + fenster.add(new JButton("B")); + fenster.add(new JButton("C")); +- [x] flow: A B C +- grid: A B C +- border: C=C +> FlowLayout setzt die Knöpfe in normaler Größe nebeneinander, wie Wörter in einer Zeile, und zentriert sie. + +runde: + fenster.setLayout(new GridLayout(0, 1)); + fenster.add(new JButton("A")); + fenster.add(new JButton("B")); + fenster.add(new JButton("C")); +- flow: A B C +- [x] grid: A / B / C +- grid: A B C +> Eine Spalte, so viele Zeilen wie nötig: alles untereinander, jede Zeile gleich hoch und so breit wie das Fenster. + +runde: + fenster.setLayout(new GridLayout(0, 2)); + fenster.add(new JButton("A")); + fenster.add(new JButton("B")); + fenster.add(new JButton("C")); + fenster.add(new JButton("D")); +- grid: A C / B D +- [x] grid: A B / C D +- grid: A / B / C / D +> Zwei Spalten. Die Zellen werden Zeile für Zeile gefüllt, immer erst links, dann rechts: A B, dann C D. + +runde: + fenster.setLayout(new GridLayout(2, 3)); + fenster.add(new JButton("A")); + fenster.add(new JButton("B")); + fenster.add(new JButton("C")); + fenster.add(new JButton("D")); + fenster.add(new JButton("E")); + fenster.add(new JButton("F")); +- grid: A B / C D / E F +- [x] grid: A B C / D E F +- flow: A B C D E F +> Erst kommen die Zeilen, dann die Spalten: 2 Zeilen mit je 3 Spalten. + +runde: + fenster.setLayout(new GridLayout(0, 2)); + fenster.add(new JButton("A")); + fenster.add(new JButton("B")); + fenster.add(new JButton("C")); +- [x] grid: A B / C +- grid: A B C +- grid: A / B C +> Zwei Spalten, drei Knöpfe: Die erste Zeile ist voll, in der zweiten steht C links, und rechts bleibt die Zelle leer. + +runde: + fenster.setLayout(new BorderLayout()); + fenster.add(new JButton("A"), BorderLayout.NORTH); + fenster.add(new JButton("B"), BorderLayout.CENTER); + fenster.add(new JButton("C"), BorderLayout.SOUTH); +- grid: A / B / C +- [x] border: N=A C=B S=C +- border: N=C C=B S=A +> NORTH ist oben, SOUTH unten. Die Mitte bekommt den ganzen übrigen Platz, darum ist B groß. + +runde: + fenster.setLayout(new BorderLayout()); + fenster.add(new JButton("A"), BorderLayout.WEST); + fenster.add(new JButton("B")); + fenster.add(new JButton("C"), BorderLayout.EAST); +- flow: A B C +- border: N=A C=B S=C +- [x] border: W=A C=B E=C +> WEST ist links, EAST rechts. B hat keine Platzangabe und landet deshalb in CENTER. +::: + +## Aufgabe: Ampel + +Baue die Ampel nach und mach sie echter. In Deutschland leuchten nach Rot kurz Rot und Gelb zusammen. Nimm deshalb eine vierte Phase dazu: + +- 0: Rot +- 1: Rot-Gelb (nimm dafür \`Color.ORANGE\`) +- 2: Grün +- 3: Gelb + +Zusatz: Schreib in jeder Phase zusätzlich mit \`licht.setText(…)\`, was die Ampel bedeutet, zum Beispiel „Stehen“ oder „Gehen“. + +::: ludwig +Mit vier Phasen kommt nach 3 wieder 0. Pass also die Zahl in \`if (phase > 2)\` an. +::: + +## 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. + +::: checkliste +- Ich kann mit setOpaque und setBackground eine Beschriftung färben. → Farben in Swing +- Ich kann mir mit einer static-Variable einen Zustand merken. → Sich die Farbe merken +- Ich kann mit BorderLayout etwas groß in die Mitte und etwas schmal nach unten setzen. → Das ganze Programm +- Ich kann erklären, wofür FlowLayout, GridLayout und BorderLayout gut sind. → Welches Layout wofür? +- Ich kann eine Ampel mit vier Phasen programmieren. → Aufgabe: Ampel +::: + +## Wissenstest + +::: quiz +? Warum bleibt die Farbe ohne setOpaque(true) unsichtbar? +→ Farben in Swing +- [ ] Weil Color.RED nicht existiert +- [x] Weil eine Beschriftung sonst durchsichtig ist +- [ ] Weil das Fenster zu klein ist + +? Welcher Platz im BorderLayout bekommt den übrigen Platz? +→ Das ganze Programm +- [ ] NORTH +- [ ] SOUTH +- [x] CENTER + +? phase ist 2 und der Zuhörer führt phase++ und dann if (phase > 2) { phase = 0; } aus. Welchen Wert hat phase danach? +→ Sich die Farbe merken +- [x] 0 +- [ ] 2 +- [ ] 3 +> Nach phase++ ist sie 3, das ist größer als 2, also wird sie 0. +::: +`,qx=`--- +titel: Notenrechner im Fenster +bereich: Fenster mit Swing +kurz: Punkte eingeben, mit else if die Note bestimmen und falsche Eingaben abfangen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- mit else if Punkte in eine Note umrechnen +- die Note im Fenster anzeigen +- „abc“ und Punkte außerhalb von 0 bis 100 abfangen und melden +- ein Programm an den Grenzen testen, zum Beispiel mit 92 und 91 +::: + +## Das Ziel + +Ein Fenster rechnet Punkte in eine Note um: Du tippst die Punkte einer Klassenarbeit ein (0 bis 100), klickst auf **Note berechnen**, und unten steht die Note. + +Diesmal kommt kein neuer Swing-Baustein dazu. Neu ist, dass du alles Bisherige kombinierst: Textfeld, Knopf, \`else if\` aus Lektion 20 und try/catch aus Lektion 22. + +Schalte im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Der Notenschlüssel + +Wir nehmen den Notenschlüssel der IHK-Prüfungen: + +| Punkte | Note | +|---|---| +| 92 bis 100 | 1 | +| 81 bis 91 | 2 | +| 67 bis 80 | 3 | +| 50 bis 66 | 4 | +| 30 bis 49 | 5 | +| 0 bis 29 | 6 | + +Mit \`else if\` prüfst du von oben nach unten. Die erste Bedingung, die zutrifft, gewinnt: + +\`\`\`java +int note; +if (punkte >= 92) { + note = 1; +} else if (punkte >= 81) { + note = 2; +} else if (punkte >= 67) { + note = 3; +} else if (punkte >= 50) { + note = 4; +} else if (punkte >= 30) { + note = 5; +} else { + note = 6; +} +\`\`\` + +::: ludwig +Bei 85 Punkten ist \`punkte >= 92\` falsch, aber \`punkte >= 81\` wahr. Also Note 2, und die restlichen Bedingungen werden gar nicht mehr geprüft. Deshalb reicht jeweils die untere Grenze. +::: + +Du kannst diesen Teil ohne Fenster im Bereich [Code](#zeige-codelive) ausprobieren. Schreib \`int punkte = 85;\` davor und \`System.out.println("Note: " + note);\` dahinter. Das Struktogramm zeigt dir die verschachtelten Verzweigungen. + +## Das Fenster + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Notenrechner { + public static void main(String[] args) { + JFrame fenster = new JFrame("Notenrechner"); + fenster.setSize(260, 180); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new GridLayout(0, 1)); + + JLabel frage = new JLabel("Punkte (0 bis 100):"); + JTextField feld = new JTextField(); + JButton knopf = new JButton("Note berechnen"); + JLabel ergebnis = new JLabel("Note: ?"); + + knopf.addActionListener(e -> { + int punkte = Integer.parseInt(feld.getText()); + int note; + if (punkte >= 92) { + note = 1; + } else if (punkte >= 81) { + note = 2; + } else if (punkte >= 67) { + note = 3; + } else if (punkte >= 50) { + note = 4; + } else if (punkte >= 30) { + note = 5; + } else { + note = 6; + } + ergebnis.setText("Note: " + note); + }); + + fenster.add(frage); + fenster.add(feld); + fenster.add(knopf); + fenster.add(ergebnis); + fenster.setVisible(true); + } +} +\`\`\` + +Probiere 100, 85, 50 und 12 aus. + +## Falsche Eingaben abfangen + +Zwei Dinge können noch schiefgehen: + +1. Jemand tippt „abc“. Dann wirft \`Integer.parseInt\` eine \`NumberFormatException\`. +2. Jemand tippt 150 oder −5. Das ist zwar eine Zahl, aber keine gültige Punktzahl. + +Den ersten Fall fängst du mit try/catch ab, den zweiten mit einem \`if\` vor der Notenberechnung: + +\`\`\`java +knopf.addActionListener(e -> { + try { + int punkte = Integer.parseInt(feld.getText()); + if (punkte < 0 || punkte > 100) { + ergebnis.setText("Bitte 0 bis 100 eingeben."); + } else { + // hier die Notenberechnung von oben + } + } catch (NumberFormatException fehler) { + ergebnis.setText("Das ist keine Zahl."); + } +}); +\`\`\` + +::: ludwig +\`||\` heißt „oder“ (Lektion 9). Die Bedingung ist wahr, wenn die Punkte zu klein **oder** zu groß sind. +::: + +## Spiel: Welche Note? + +::: spiel frage +titel: Spiel: Welche Note? +intro: Ludwig hat Notenrechner gebaut, aber nicht alle sind richtig. Rechne nach, welche Note herauskommt. Sechs Runden. + +runde: + if (punkte >= 92) { + note = 1; + } else if (punkte >= 81) { + note = 2; + } else if (punkte >= 67) { + note = 3; + } else { + note = 4; + } +frage: punkte ist 81. Welche Note kommt heraus? +- 1 +- [x] 2 +- 3 +> 81 >= 92 ist falsch, 81 >= 81 ist wahr. Die Grenze gehört noch zur 2. + +runde: + if (punkte >= 92) { + note = 1; + } else if (punkte >= 81) { + note = 2; + } else if (punkte >= 67) { + note = 3; + } else if (punkte >= 50) { + note = 4; + } else { + note = 5; + } +frage: punkte ist 66. Welche Note kommt heraus? +- 3 +- [x] 4 +- 5 +> 66 >= 67 ist knapp falsch, 66 >= 50 ist wahr. Also Note 4. + +runde: + if (punkte >= 50) { + note = 4; + } else if (punkte >= 92) { + note = 1; + } else { + note = 6; + } +frage: punkte ist 95. Welche Note kommt heraus? +- 1 +- [x] 4 +- 6 +> Die erste wahre Bedingung gewinnt. 95 >= 50 ist schon wahr, die 1 wird nie erreicht. Deshalb prüft man von den hohen Punkten nach unten. + +runde: + note = 6; + if (punkte >= 30) { + note = 5; + } + if (punkte >= 50) { + note = 4; + } +frage: punkte ist 70. Welche Note steht danach in note? +- 6 +- 5 +- [x] 4 +> Ohne \`else\` wird jedes \`if\` geprüft. Beide sind wahr, das letzte setzt die Note 4. + +runde: + // note ist schon berechnet + if (punkte < 0 || punkte > 100) { + ergebnis.setText("Bitte 0 bis 100 eingeben."); + } else { + ergebnis.setText("Note: " + note); + } +frage: Im Textfeld steht 100. Was zeigt das Fenster? +- [x] Note: 1 +- Bitte 0 bis 100 eingeben. +- Das ist keine Zahl. +> 100 > 100 ist falsch. 100 Punkte sind also gültig und ergeben die Note 1. + +runde: + // note ist schon berechnet + if (punkte < 0 && punkte > 100) { + ergebnis.setText("Bitte 0 bis 100 eingeben."); + } else { + ergebnis.setText("Note: " + note); + } +frage: Im Textfeld steht 150. Was zeigt das Fenster? +- Bitte 0 bis 100 eingeben. +- [x] eine Note, obwohl 150 ungültig ist +- Das ist keine Zahl. +> Mit \`&&\` müssten die Punkte gleichzeitig unter 0 und über 100 sein. Das geht nie, also warnt das Programm nie. Richtig ist \`||\`. +::: + +## Aufgabe: Notenrechner + +Baue den Notenrechner zusammen, mit beiden Prüfungen aus dem letzten Schritt. Teste ihn mit 92, 91, 0, 100, 101 und „zehn“. + +Zusatz: Schreib die Note zusätzlich als Wort hin, zum Beispiel „Note: 2 (gut)“. Die Wörter sind sehr gut, gut, befriedigend, ausreichend, mangelhaft und ungenügend. + +::: ludwig +Teste immer die Grenzen: 92 muss eine 1 sein, 91 eine 2. An den Grenzen stecken die meisten Fehler, zum Beispiel \`>\` statt \`>=\`. +::: + +## 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. + +::: checkliste +- Ich kann mit else if Punkte in eine Note umrechnen. → Der Notenschlüssel +- Ich kann die Note im Fenster anzeigen. → Das Fenster +- Ich kann „abc“ und Punkte außerhalb von 0 bis 100 abfangen und melden. → Falsche Eingaben abfangen +- Ich kann ein Programm an den Grenzen testen, zum Beispiel mit 92 und 91. → Aufgabe: Notenrechner +::: + +## Wissenstest + +::: quiz +? Welche Note ergibt der Schlüssel bei 67 Punkten? +→ Der Notenschlüssel +- [ ] 2 +- [x] 3 +- [ ] 4 +> 67 ist die untere Grenze für die 3. + +? Warum reicht in jeder Bedingung die untere Grenze? +→ Der Notenschlüssel +- [x] Weil else if die oberen Fälle schon vorher aussortiert hat +- [ ] Weil Java obere Grenzen nicht kennt +- [ ] Weil die Punkte immer 100 sind + +? Welche Bedingung erkennt ungültige Punkte? +→ Falsche Eingaben abfangen +- [ ] punkte < 0 && punkte > 100 +- [x] punkte < 0 || punkte > 100 +- [ ] punkte >= 0 || punkte <= 100 +> Eine Zahl kann nicht gleichzeitig kleiner als 0 und größer als 100 sein, deshalb braucht es oder. +::: +`,Qx=`--- +titel: Ein Taschenrechner +bereich: Fenster mit Swing +kurz: Zwei Spalten mit GridLayout, vier Rechenknöpfe und die Division durch 0 abfangen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- mit GridLayout(0, 2) zwei Spalten bauen +- erklären, warum "" + (a + b) Klammern braucht +- alle vier Rechenknöpfe programmieren +- einen Rechner bauen, der bei 0 und bei „abc“ nicht abstürzt +::: + +## Das Ziel + +Wir bauen einen kleinen Taschenrechner: zwei Textfelder für die Zahlen, vier Knöpfe **+**, **-**, **\\*** und **/** und eine Zeile für das Ergebnis. + +Neu sind diesmal **zwei Spalten** im GridLayout und **mehrere Knöpfe**, die alle mit denselben Textfeldern rechnen. + +Schalte im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Zwei Spalten + +Bisher stand mit \`GridLayout(0, 1)\` alles untereinander. Mit \`GridLayout(0, 2)\` gibt es zwei Spalten. Die Bausteine füllen die Zellen in der Reihenfolge der \`add\`-Zeilen, immer erst links, dann rechts: + +| links | rechts | +|---|---| +| Erste Zahl: | Textfeld | +| Zweite Zahl: | Textfeld | +| + | - | +| \\* | / | +| Ergebnis: | ? | + +Die Beschriftungen links brauchst du später nicht mehr. Du kannst sie deshalb direkt in \`add\` bauen, ohne Variable: + +\`\`\`java +fenster.add(new JLabel("Erste Zahl:")); +fenster.add(feld1); +\`\`\` + +## Das Fenster mit dem ersten Knopf + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Rechner { + public static void main(String[] args) { + JFrame fenster = new JFrame("Rechner"); + fenster.setSize(280, 220); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new GridLayout(0, 2)); + + JTextField feld1 = new JTextField(); + JTextField feld2 = new JTextField(); + JButton plus = new JButton("+"); + JButton minus = new JButton("-"); + JButton mal = new JButton("*"); + JButton geteilt = new JButton("/"); + JLabel ergebnis = new JLabel("?"); + + plus.addActionListener(e -> { + int a = Integer.parseInt(feld1.getText()); + int b = Integer.parseInt(feld2.getText()); + ergebnis.setText("" + (a + b)); + }); + + fenster.add(new JLabel("Erste Zahl:")); + fenster.add(feld1); + fenster.add(new JLabel("Zweite Zahl:")); + fenster.add(feld2); + fenster.add(plus); + fenster.add(minus); + fenster.add(mal); + fenster.add(geteilt); + fenster.add(new JLabel("Ergebnis:")); + fenster.add(ergebnis); + fenster.setVisible(true); + } +} +\`\`\` + +Tippe 3 und 4 ein und klicke auf +. Unten steht 7. + +::: ludwig +Achte auf die Klammern in \`"" + (a + b)\`. Ohne sie rechnet Java von links nach rechts: \`"" + a\` ergibt den Text „3“, und \`"3" + b\` hängt die 4 hinten an. Heraus kommt „34“ statt 7. Die Klammer sorgt dafür, dass zuerst gerechnet wird. +::: + +## Die anderen drei Knöpfe + +Die Knöpfe -, \\* und / funktionieren genauso. Nur das Rechenzeichen in der letzten Zeile ändert sich: + +\`\`\`java +minus.addActionListener(e -> { + int a = Integer.parseInt(feld1.getText()); + int b = Integer.parseInt(feld2.getText()); + ergebnis.setText("" + (a - b)); +}); +\`\`\` + +Bei / gibt es zwei Besonderheiten: + +- Mit \`int\` schneidet Java beim Teilen die Nachkommastellen ab. 7 / 2 ergibt 3. +- Bei 0 als zweiter Zahl wirft Java eine \`ArithmeticException\`, wie bei der Aufgabe „Sicher teilen“ in Lektion 22. + +## Division durch 0 abfangen + +\`\`\`java +geteilt.addActionListener(e -> { + int a = Integer.parseInt(feld1.getText()); + int b = Integer.parseInt(feld2.getText()); + try { + ergebnis.setText("" + (a / b)); + } catch (ArithmeticException fehler) { + ergebnis.setText("Nicht durch 0!"); + } +}); +\`\`\` + +::: angeberwissen +Mit \`double\` und \`Double.parseDouble(…)\` gibt es Nachkommastellen: 7 / 2 ergibt 3.5. Dafür wirft Java bei Kommazahlen keine Exception beim Teilen durch 0. Das Ergebnis heißt dann \`Infinity\`, also „unendlich“. +::: + +## Profiwissen: eine eigene Methode + +Das steht nicht im Lehrplan, macht den Code aber kürzer. + +::: angeberwissen +Jeder Zuhörer liest dieselben zwei Felder. Diese Wiederholung kannst du in eine eigene Methode auslagern, ein Unterprogramm wie in Lektion 18. Sie steht in der Klasse neben \`main\`: + +\`static int zahl(JTextField feld) { return Integer.parseInt(feld.getText()); }\` + +Im Zuhörer heißt es dann nur noch \`ergebnis.setText("" + (zahl(feld1) + zahl(feld2)));\`. +::: + +## Spiel: Was zeigt der Rechner? + +::: spiel frage +titel: Spiel: Was zeigt der Rechner? +intro: Ludwig hat am Taschenrechner geschraubt. Lies den Zuhörer und sag vorher, was im Ergebnis steht. Sechs Runden. + +runde: + plus.addActionListener(e -> { + int a = Integer.parseInt(feld1.getText()); + int b = Integer.parseInt(feld2.getText()); + ergebnis.setText("" + a + b); + }); +frage: Du tippst 3 und 4 und klickst auf +. Was steht im Ergebnis? +- 7 +- [x] 34 +- 12 +> Ohne Klammern rechnet Java von links nach rechts: \`"" + 3\` ist der Text „3“, und \`+ 4\` hängt die 4 an. + +runde: + mal.addActionListener(e -> { + int a = Integer.parseInt(feld1.getText()); + int b = Integer.parseInt(feld2.getText()); + ergebnis.setText("" + a * b); + }); +frage: Du tippst 3 und 4 und klickst auf *. Was steht im Ergebnis? +- 34 +- [x] 12 +- 7 +> Punkt vor Strich gilt auch hier: Erst rechnet Java 3 * 4, dann hängt es die 12 an den Text. Beim Plus fehlt dieser Vorrang, darum braucht es dort die Klammern. + +runde: + geteilt.addActionListener(e -> { + int a = Integer.parseInt(feld1.getText()); + int b = Integer.parseInt(feld2.getText()); + ergebnis.setText("" + (a / b)); + }); +frage: Du tippst 7 und 2 und klickst auf /. Was steht im Ergebnis? +- 3.5 +- [x] 3 +- 4 +> Mit \`int\` schneidet Java die Nachkommastellen ab. Es wird nicht gerundet. + +runde: + geteilt.addActionListener(e -> { + int a = Integer.parseInt(feld1.getText()); + int b = Integer.parseInt(feld2.getText()); + try { + ergebnis.setText("" + (a / b)); + } catch (ArithmeticException fehler) { + ergebnis.setText("Nicht durch 0!"); + } + }); +frage: Du tippst 8 und 0 und klickst auf /. Was steht im Ergebnis? +- 0 +- [x] Nicht durch 0! +- Infinity +> Bei \`int\` wirft das Teilen durch 0 eine ArithmeticException, und \`catch\` schreibt den Hinweis. + +runde: + geteilt.addActionListener(e -> { + double a = Double.parseDouble(feld1.getText()); + double b = Double.parseDouble(feld2.getText()); + ergebnis.setText("" + (a / b)); + }); +frage: Du tippst 7 und 2 und klickst auf /. Was steht im Ergebnis? +- 3 +- [x] 3.5 +- 3.0 +> Mit \`double\` bleiben die Nachkommastellen erhalten. + +runde: + geteilt.addActionListener(e -> { + double a = Double.parseDouble(feld1.getText()); + double b = Double.parseDouble(feld2.getText()); + try { + ergebnis.setText("" + (a / b)); + } catch (ArithmeticException fehler) { + ergebnis.setText("Nicht durch 0!"); + } + }); +frage: Du tippst 8 und 0 und klickst auf /. Was steht im Ergebnis? +- Nicht durch 0! +- [x] Infinity +- 0.0 +> Bei \`double\` gibt es keine Exception. Das Ergebnis ist \`Infinity\`, also „unendlich“, und das \`catch\` kommt nie dran. +::: + +## Aufgabe: Taschenrechner + +Baue den Rechner fertig: + +- alle vier Knöpfe rechnen, +- / meldet „Nicht durch 0!“ statt abzustürzen, +- steht in einem Feld „abc“ oder nichts, erscheint „Bitte zwei Zahlen eingeben“. + +Zusatz: Ein fünfter Knopf **C** leert beide Felder und setzt das Ergebnis wieder auf „?“. + +::: ludwig +Für „abc“ brauchst du in jedem Zuhörer ein try/catch mit \`NumberFormatException\`. Hinter einem \`try\` dürfen auch zwei \`catch\` stehen, einer für \`NumberFormatException\` und einer für \`ArithmeticException\`. Ein leeres Feld liefert übrigens den Text \`""\`, und auch der ist keine Zahl. +::: + +## 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. + +::: checkliste +- Ich kann mit GridLayout(0, 2) zwei Spalten bauen. → Zwei Spalten +- Ich kann erklären, warum "" + (a + b) Klammern braucht. → Das Fenster mit dem ersten Knopf +- Ich kann alle vier Rechenknöpfe programmieren. → Die anderen drei Knöpfe +- Ich kann einen Rechner bauen, der bei 0 und bei „abc“ nicht abstürzt. → Aufgabe: Taschenrechner +::: + +## Wissenstest + +::: quiz +? a ist 3 und b ist 4. Was ergibt "" + a + b? +→ Das Fenster mit dem ersten Knopf +- [ ] 7 +- [x] 34 +- [ ] Einen Fehler +> Java rechnet von links nach rechts: Erst entsteht der Text "3", dann wird die 4 angehängt. + +? Was ergibt 7 / 2 mit int? +→ Die anderen drei Knöpfe +- [ ] 3.5 +- [x] 3 +- [ ] 4 + +? In welcher Reihenfolge füllt GridLayout(0, 2) die Zellen? +→ Zwei Spalten +- [x] Zeile für Zeile, jeweils erst links, dann rechts +- [ ] Spalte für Spalte, erst ganz links von oben nach unten +- [ ] Zufällig +::: +`,Ux=`--- +titel: Zahlenraten +bereich: Fenster mit Swing +kurz: Ein Spiel mit Zufallszahl, Versuchszähler und einem Knopf, der sich am Ende abschaltet. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- mit Math.random eine ganze Zufallszahl von 1 bis 100 erzeugen +- entscheiden, welche Variablen in die Klasse gehören +- einen Knopf mit setEnabled abschalten +- ein Ratespiel mit einem Knopf „Neues Spiel“ bauen +::: + +## Das Ziel + +Jetzt wird gespielt: Der Computer denkt sich eine Zahl von 1 bis 100 aus. Du rätst, und das Fenster sagt dir „zu klein“ oder „zu groß“. Hast du sie gefunden, verrät es dir, wie viele Versuche du gebraucht hast. + +Neu sind diesmal **Zufallszahlen** und ein Knopf, der sich am Ende **abschaltet**. + +Schalte im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Eine Zufallszahl + +\`Math.random()\` liefert eine zufällige Kommazahl von 0 bis knapp unter 1, zum Beispiel 0.4173. Daraus wird in drei Schritten eine ganze Zahl von 1 bis 100: + +\`\`\`java +int geheim = (int) (Math.random() * 100) + 1; +\`\`\` + +| Schritt | Beispiel | +|---|---| +| \`Math.random()\` | 0.4173 | +| \`* 100\` | 41.73 | +| \`(int)\` schneidet die Nachkommastellen ab | 41 | +| \`+ 1\` | 42 | + +Ohne \`+ 1\` käme 0 bis 99 heraus. + +Probiere es im Bereich [Code](#zeige-codelive) aus: \`int geheim = (int) (Math.random() * 100) + 1;\` und \`System.out.println(geheim);\`. Jedes Ausführen liefert eine andere Zahl. + +::: angeberwissen +Computer können eigentlich gar nicht würfeln. \`Math.random()\` rechnet mit einer Formel eine lange Folge von Zahlen aus, die nur zufällig **aussehen**. Man nennt sie Pseudozufallszahlen. Für Spiele reicht das völlig. +::: + +## Was sich das Spiel merkt + +Zwei Dinge muss sich das Spiel über alle Klicks hinweg merken: die geheime Zahl und die Zahl der Versuche. Wie beim Klickzähler aus Lektion 32 stehen beide in der Klasse: + +\`\`\`java +static int geheim = (int) (Math.random() * 100) + 1; +static int versuche = 0; +\`\`\` + +## Das ganze Programm + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Zahlenraten { + static int geheim = (int) (Math.random() * 100) + 1; + static int versuche = 0; + + public static void main(String[] args) { + JFrame fenster = new JFrame("Zahlenraten"); + fenster.setSize(320, 180); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new GridLayout(0, 1)); + + JLabel hinweis = new JLabel("Ich denke mir eine Zahl von 1 bis 100."); + JTextField feld = new JTextField(); + JButton knopf = new JButton("Raten"); + + knopf.addActionListener(e -> { + int tipp = Integer.parseInt(feld.getText()); + versuche++; + if (tipp < geheim) { + hinweis.setText(tipp + " ist zu klein."); + } else if (tipp > geheim) { + hinweis.setText(tipp + " ist zu groß."); + } else { + hinweis.setText("Richtig! Du hast " + versuche + " Versuche gebraucht."); + knopf.setEnabled(false); + } + feld.setText(""); + }); + + fenster.add(hinweis); + fenster.add(feld); + fenster.add(knopf); + fenster.setVisible(true); + } +} +\`\`\` + +- \`feld.setText("")\` leert das Textfeld nach jedem Tipp, damit du gleich den nächsten eintippen kannst. +- \`knopf.setEnabled(false)\` schaltet den Knopf ab. Er wird grau und lässt sich nicht mehr klicken. Das Spiel ist vorbei. + +::: ludwig +Mit \`setEnabled(true)\` schaltest du einen Knopf wieder ein. So kannst du zum Beispiel einen Knopf erst freigeben, wenn etwas eingegeben wurde. +::: + +## Profiwissen: mit 7 Versuchen gewinnen + +::: angeberwissen +Wer geschickt rät, braucht nie mehr als 7 Versuche. Rate immer die Mitte des Bereichs, der noch übrig ist: erst 50, dann 25 oder 75 und so weiter. Jeder Tipp halbiert den Bereich: 100, 50, 25, 13, 7, 4, 2, 1. Das ist die **binäre Suche** aus Lektion 19. Weil 2 hoch 7 = 128 größer als 100 ist, reichen 7 Tipps. +::: + +## Aufgabe: Zahlenraten + +Baue das Spiel nach und mach es besser: + +- Eine Eingabe wie „abc“ zählt nicht als Versuch und bringt den Hinweis „Bitte eine Zahl eingeben“. +- Ein zweiter Knopf **Neues Spiel** denkt sich eine neue Zahl aus, setzt die Versuche auf 0, schaltet den Knopf Raten wieder ein und setzt den Hinweis zurück. + +Zusatz: Nach 7 Fehlversuchen ist das Spiel verloren. Das Fenster verrät dann die geheime Zahl. + +::: ludwig +Für „zählt nicht als Versuch“ muss \`versuche++\` **hinter** \`Integer.parseInt\` stehen, beides im \`try\`-Block. Wirft \`parseInt\` eine Exception, wird die Zeile mit \`versuche++\` übersprungen. +::: + +## 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. + +::: checkliste +- Ich kann mit Math.random eine ganze Zufallszahl von 1 bis 100 erzeugen. → Eine Zufallszahl +- Ich kann entscheiden, welche Variablen in die Klasse gehören. → Was sich das Spiel merkt +- Ich kann einen Knopf mit setEnabled abschalten. → Das ganze Programm +- Ich kann ein Ratespiel mit einem Knopf „Neues Spiel“ bauen. → Aufgabe: Zahlenraten +::: + +## Wissenstest + +::: quiz +? Welche Zahlen liefert (int) (Math.random() * 100) + 1? +→ Eine Zufallszahl +- [ ] 0 bis 100 +- [x] 1 bis 100 +- [ ] 1 bis 101 + +? Was macht knopf.setEnabled(false)? +→ Das ganze Programm +- [ ] Es löscht den Knopf aus dem Fenster. +- [x] Der Knopf wird grau und lässt sich nicht mehr klicken. +- [ ] Es ändert die Beschriftung des Knopfs. + +? Wie viele Versuche braucht man mit der binären Suche höchstens bei 1 bis 100? +→ Aufgabe: Zahlenraten +- [ ] 50 +- [ ] 10 +- [x] 7 +> Jeder Tipp halbiert den Bereich, und 2 hoch 7 = 128 ist größer als 100. +::: +`,$x=`--- +titel: Viele Knöpfe, ein Zuhörer +bereich: Fenster mit Swing +kurz: Ein Zuhörer für viele Knöpfe, mit getActionCommand und getSource herausfinden, welcher Knopf geklickt wurde. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- einen Zuhörer in einer Variable vom Typ ActionListener speichern und bei mehreren Knöpfen anmelden +- erklären, was getActionCommand und getSource liefern +- Knöpfe in einer Schleife auf ein JPanel setzen +- ein Zahlenschloss bauen, das sich nur mit dem richtigen Code öffnet +::: + +## Das Ziel + +Seit der Sache mit dem Kuchen will Ludwig seinen Stall abschließen. Er baut ein **Zahlenschloss**: neun Zifferntasten, eine Null, **C** zum Löschen und **OK** zum Prüfen. Nur wer 1234 eintippt, bekommt „Tor offen!“. + +Das sind zwölf Knöpfe. Bisher hatte jeder Knopf seinen eigenen Zuhörer, wie beim Taschenrechner in Lektion 35. Heute lernst du, wie **ein** Zuhörer für alle Knöpfe reicht. + +Schalte im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Neun fast gleiche Zuhörer + +So sähe es mit einem Zuhörer pro Taste aus: + +\`\`\`java +eins.addActionListener(e -> anzeige.setText(anzeige.getText() + "1")); +zwei.addActionListener(e -> anzeige.setText(anzeige.getText() + "2")); +drei.addActionListener(e -> anzeige.setText(anzeige.getText() + "3")); +// ... und so weiter bis 9 +\`\`\` + +Die Zeilen unterscheiden sich nur in der Ziffer. Wer eine Kleinigkeit ändern will, muss es neunmal tun und vergisst bestimmt eine Zeile. + +## Ein Zuhörer als Variable + +Ein Zuhörer kann auch in einer **Variable** stehen. Ihr Datentyp ist \`ActionListener\`, der Vertrag aus Lektion 30. Danach meldest du denselben Zuhörer bei mehreren Knöpfen an: + +\`\`\`java +ActionListener ziffer = e -> anzeige.setText(anzeige.getText() + e.getActionCommand()); + +eins.addActionListener(ziffer); +zwei.addActionListener(ziffer); +drei.addActionListener(ziffer); +\`\`\` + +\`ActionListener\` steht im Paket \`java.awt.event\`. Du brauchst deshalb oben \`import java.awt.event.*;\`. + +Jetzt gibt es den Code nur einmal. Aber woher weiß der Zuhörer, welche Ziffer er anhängen soll? + +## Wer hat geklickt? + +Das \`e\` vor dem Pfeil ist das **Ereignis**, ein Objekt vom Typ \`ActionEvent\`. Der Knopf gibt es bei jedem Klick mit, und darin steht, was passiert ist: + +| Aufruf | Liefert | Beispiel | +|---|---|---| +| \`e.getActionCommand()\` | die Beschriftung des geklickten Knopfs, als Text | \`"7"\` | +| \`e.getSource()\` | den geklickten Knopf selbst | der Knopf \`ok\` | + +- \`getActionCommand()\` ist praktisch, wenn die Beschriftung schon sagt, was zu tun ist, wie bei den Ziffern. +- \`getSource()\` vergleichst du mit \`==\` mit einem Knopf: \`if (e.getSource() == ok)\`. Hier ist \`==\` richtig, denn es geht um genau dieses eine Objekt, nicht um einen Text. + +::: ludwig +Texte vergleichst du mit \`equals\`, Knöpfe mit \`==\`. Willst du über die Beschriftung entscheiden, schreibst du \`e.getActionCommand().equals("OK")\`. Das geht auch, bricht aber, sobald jemand die Beschriftung in „Öffnen“ ändert. \`e.getSource() == ok\` bleibt richtig. +::: + +## Knöpfe in einer Schleife + +Mit einem gemeinsamen Zuhörer kannst du die Zifferntasten sogar in einer Schleife bauen. Damit sie ordentlich im Raster stehen, kommen sie auf ein **JPanel**. Ein JPanel ist eine Fläche im Fenster mit einem eigenen Layout: + +\`\`\`java +JPanel tasten = new JPanel(new GridLayout(0, 3)); +for (int i = 1; i <= 9; i++) { + JButton ziffer = new JButton("" + i); + ziffer.addActionListener(taste); + tasten.add(ziffer); +} +\`\`\` + +- \`"" + i\` macht aus der Zahl \`i\` den Text für die Beschriftung. +- In jedem Durchlauf entsteht ein neuer Knopf. Alle bekommen denselben Zuhörer \`taste\`. +- \`fenster.add(tasten, BorderLayout.CENTER)\` setzt die ganze Fläche mit allen Tasten ins Fenster. + +## Das ganze Programm + +\`\`\`java +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class Zahlenschloss { + public static void main(String[] args) { + JFrame fenster = new JFrame("Zahlenschloss"); + fenster.setSize(240, 300); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new BorderLayout()); + + JLabel anzeige = new JLabel("", SwingConstants.CENTER); + JPanel tasten = new JPanel(new GridLayout(0, 3)); + JButton loeschen = new JButton("C"); + JButton ok = new JButton("OK"); + + ActionListener taste = e -> { + if (e.getSource() == loeschen) { + anzeige.setText(""); + } else if (e.getSource() == ok) { + if (anzeige.getText().equals("1234")) { + anzeige.setText("Tor offen!"); + } else { + anzeige.setText("Falsch"); + } + } else { + anzeige.setText(anzeige.getText() + e.getActionCommand()); + } + }; + + for (int i = 1; i <= 9; i++) { + JButton ziffer = new JButton("" + i); + ziffer.addActionListener(taste); + tasten.add(ziffer); + } + JButton nullTaste = new JButton("0"); + nullTaste.addActionListener(taste); + loeschen.addActionListener(taste); + ok.addActionListener(taste); + tasten.add(loeschen); + tasten.add(nullTaste); + tasten.add(ok); + + fenster.add(anzeige, BorderLayout.NORTH); + fenster.add(tasten, BorderLayout.CENTER); + fenster.setVisible(true); + } +} +\`\`\` + +- \`loeschen\` und \`ok\` werden **vor** dem Zuhörer angelegt, denn der Zuhörer vergleicht mit ihnen. +- Der Zuhörer prüft erst die beiden besonderen Knöpfe. Alle anderen sind Ziffern und hängen ihre Beschriftung an. +- Die Null heißt \`nullTaste\`, weil \`null\` in Java schon ein Wort mit fester Bedeutung ist. + +::: angeberwissen +Das Zahlenfeld am Telefon hat die 1 oben links, das am Taschenrechner und an der Computertastatur hat die 7 oben links. Warum? Als die Tastentelefone kamen, gab es Tests mit Leuten, die damit wählen sollten. Mit der 1 oben ging es schneller, und Rechenmaschinen hatten ihre Anordnung da schon längst. Ludwigs Schloss macht es wie das Telefon. +::: + +## Spiel: Wer hat geklickt? + +::: spiel zuhoerer +titel: Spiel: Wer hat geklickt? +intro: In jeder Runde hört **ein** Zuhörer an mehreren Knöpfen. Ludwig zeigt dir Code, Fenster und die Klicks. Was steht am Ende in der Anzeige? Danach spielt Ludwig die Klicks ab. +frage: Was steht nach den Klicks in der Anzeige? + +runde: + JFrame fenster = new JFrame("Buchstaben"); + JLabel anzeige = new JLabel(""); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + ActionListener z = e -> anzeige.setText(anzeige.getText() + e.getActionCommand()); + a.addActionListener(z); + b.addActionListener(z); +klicks: A, B, A +- A +- AB +- [x] ABA +> Ein Zuhörer, zwei Knöpfe. \`e.getActionCommand()\` liefert jedes Mal die Beschriftung des geklickten Knopfs, und sie wird hinten angehängt. + +runde: + JFrame fenster = new JFrame("Zähler"); + static int zahl = 0; + JLabel anzeige = new JLabel("0"); + JButton plus = new JButton("+"); + JButton minus = new JButton("-"); + ActionListener z = e -> { + if (e.getSource() == plus) { + zahl++; + } else { + zahl--; + } + anzeige.setText("" + zahl); + }; + plus.addActionListener(z); + minus.addActionListener(z); +klicks: +, +, - +- 3 +- [x] 1 +- -1 +> \`e.getSource()\` sagt, welcher Knopf es war. Zweimal plus, einmal minus: 0 + 1 + 1 - 1 = 1. + +runde: + JFrame fenster = new JFrame("Buchstaben"); + JLabel anzeige = new JLabel(""); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + JButton c = new JButton("C"); + ActionListener z = e -> anzeige.setText(anzeige.getText() + e.getActionCommand()); + a.addActionListener(z); + b.addActionListener(z); +klicks: A, C, B +- ACB +- [x] AB +- A +> Der Zuhörer ist nur bei A und B angemeldet. Beim Klick auf C hört niemand zu. + +runde: + JFrame fenster = new JFrame("Tasten"); + JLabel anzeige = new JLabel(""); + JButton eins = new JButton("1"); + JButton zwei = new JButton("2"); + JButton weg = new JButton("C"); + ActionListener z = e -> { + if (e.getActionCommand().equals("C")) { + anzeige.setText(""); + } else { + anzeige.setText(anzeige.getText() + e.getActionCommand()); + } + }; + eins.addActionListener(z); + zwei.addActionListener(z); + weg.addActionListener(z); +klicks: 1, 2, C, 1 +- 121 +- 12 +- [x] 1 +> Nach 1 und 2 steht „12“ da. C löscht alles, und die letzte 1 steht allein. + +runde: + JFrame fenster = new JFrame("Schloss"); + JLabel anzeige = new JLabel(""); + JButton vier = new JButton("4"); + JButton zwei = new JButton("2"); + JButton ok = new JButton("OK"); + ActionListener z = e -> { + if (e.getSource() == ok) { + if (anzeige.getText().equals("42")) { + anzeige.setText("Tor offen!"); + } else { + anzeige.setText("Falsch"); + } + } else { + anzeige.setText(anzeige.getText() + e.getActionCommand()); + } + }; + vier.addActionListener(z); + zwei.addActionListener(z); + ok.addActionListener(z); +klicks: 2, 4, OK +- Tor offen! +- [x] Falsch +- 24OK +> Eingetippt ist „24“, das Geheimnis ist aber „42“. Die Reihenfolge der Klicks zählt. +::: + +## Aufgabe: Zahlenschloss + +Baue das Zahlenschloss nach und probiere es aus. + +Dann mach es besser: + +- Nach drei falschen Versuchen schaltet sich **OK** ab, wie der Knopf beim Zahlenraten in Lektion 36. Zähle die Versuche in einer \`static int\`-Variable in der Klasse. +- Zusatz: Die Anzeige zeigt \`*\` statt der Ziffern. Merke dir die echte Eingabe in einer \`static String eingabe = "";\` und hänge an die Anzeige nur einen Stern an. + +::: ludwig +Auch beim Taschenrechner aus Lektion 35 reicht ein Zuhörer für +, -, \\* und /. Prüfe darin mit \`e.getActionCommand().equals("+")\`, welches Rechenzeichen geklickt wurde. +::: + +## 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. + +::: checkliste +- Ich kann einen Zuhörer in einer Variable vom Typ ActionListener speichern und bei mehreren Knöpfen anmelden. → Ein Zuhörer als Variable +- Ich kann erklären, was getActionCommand und getSource liefern. → Wer hat geklickt? +- Ich kann Knöpfe in einer Schleife auf ein JPanel setzen. → Knöpfe in einer Schleife +- Ich kann ein Zahlenschloss bauen, das sich nur mit dem richtigen Code öffnet. → Aufgabe: Zahlenschloss +::: + +## Wissenstest + +::: quiz +? Was liefert e.getActionCommand() bei einem Klick auf den Knopf new JButton("7")? +→ Wer hat geklickt? +- [ ] die Zahl 7 +- [x] den Text "7" +- [ ] den Knopf selbst + +? Wie prüfst du, ob der Knopf ok geklickt wurde? +→ Wer hat geklickt? +- [x] e.getSource() == ok +- [ ] e.getSource().equals("ok") +- [ ] ok.getActionCommand() +> getSource liefert den Knopf selbst, und den vergleichst du mit ==. + +? Warum steht ein Zuhörer in einer Variable? +→ Ein Zuhörer als Variable +- [ ] Damit er schneller läuft. +- [x] Damit man ihn bei mehreren Knöpfen anmelden kann und den Code nur einmal schreibt. +- [ ] Weil Lambdas sonst nicht erlaubt sind. + +? Ordne zu. +→ Wer hat geklickt? += ActionListener -> Datentyp eines Zuhörers += ActionEvent -> das Ereignis e mit den Infos zum Klick += JPanel -> eine Fläche mit eigenem Layout +::: +`,Yx=`--- +titel: Innere Klassen +bereich: Fenster mit Swing +kurz: Einen Zuhörer als benannte innere Klasse, als anonyme Klasse und als Lambda schreiben und wissen, wer was sehen darf. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- einen Zuhörer als benannte innere Klasse schreiben +- einen Zuhörer als anonyme Klasse schreiben +- erklären, was beim Lambda weggelassen wird +- erklären, welche Schreibweise welche Variablen sieht +- einen Zähler mit drei Knöpfen in drei Schreibweisen bauen +::: + +## Das Ziel + +Den Klickzähler aus Lektion 32 kennst du schon. Heute schreibst du seinen Zuhörer auf **drei Arten**, die alle genau dasselbe tun: + +1. als **benannte innere Klasse**, wie man es vor Java 8 meistens gemacht hat, +2. als **anonyme Klasse**, die du aus dem Profiwissen in Lektion 30 kennst, +3. als **Lambda** mit dem Pfeil, so wie bisher. + +In fremdem Code, in Büchern und im Internet triffst du alle drei Schreibweisen. Nach dieser Lektion erkennst du sie. + +Schalte im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Erinnerung: der Vertrag + +Ein Zuhörer ist alles, was den Vertrag \`ActionListener\` erfüllt. Darin steht genau eine Methode: + +\`\`\` +public void actionPerformed(ActionEvent e) +\`\`\` + +Der Knopf ruft sie bei jedem Klick auf. Die drei Schreibweisen sind drei Wege, diese eine Methode zu liefern. + +## 1. Die benannte innere Klasse + +Eine **innere Klasse** steht innerhalb einer anderen Klasse. Sie hat einen Namen, hier \`Plus\`, und erfüllt den Vertrag mit \`implements ActionListener\`: + +\`\`\`java +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class Zaehler { + static int anzahl = 0; + static JLabel zahl = new JLabel("0", SwingConstants.CENTER); + + static class Plus implements ActionListener { + public void actionPerformed(ActionEvent e) { + anzahl++; + zahl.setText("" + anzahl); + } + } + + public static void main(String[] args) { + JFrame fenster = new JFrame("Klickzähler"); + fenster.setSize(250, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new GridLayout(0, 1)); + + JButton plus = new JButton("+1"); + JButton nochmal = new JButton("Auch +1"); + plus.addActionListener(new Plus()); + nochmal.addActionListener(new Plus()); + + fenster.add(zahl); + fenster.add(plus); + fenster.add(nochmal); + fenster.setVisible(true); + } +} +\`\`\` + +- \`new Plus()\` erzeugt ein Objekt der Klasse \`Plus\`. Das ist der Zuhörer, den der Knopf bekommt. +- Weil die Klasse einen Namen hat, kannst du sie bei mehreren Knöpfen benutzen, hier bei \`plus\` und \`nochmal\`. +- Die Klasse steht **außerhalb** von \`main\`. Darum sieht sie nur, was in der Klasse \`Zaehler\` steht: \`anzahl\` und \`zahl\`. Deshalb ist \`zahl\` diesmal eine Variable der Klasse und nicht von \`main\`. +- \`static class\` brauchst du, weil \`main\` static ist. Ohne \`static\` meldet javac „non-static variable this cannot be referenced from a static context“. + +## 2. Die anonyme Klasse + +Brauchst du den Zuhörer nur an einer Stelle, kannst du die Klasse direkt dort schreiben, wo das Objekt gebraucht wird. Sie bekommt dann keinen Namen: + +\`\`\`java +plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + anzahl++; + zahl.setText("" + anzahl); + } +}); +\`\`\` + +- \`new ActionListener() { … }\` heißt: „ein neues Objekt, das den Vertrag ActionListener erfüllt, und zwar so: …“. +- Am Ende steht \`});\`: die geschweifte Klammer schließt die Klasse, die runde den Aufruf von \`addActionListener\`. +- Die anonyme Klasse steht **in** \`main\`. Sie sieht deshalb auch die Variablen von \`main\`, solange diese sich nicht mehr ändern. + +## 3. Das Lambda + +Das Lambda ist die Kurzform der anonymen Klasse, seit Java 8: + +\`\`\`java +plus.addActionListener(e -> { + anzahl++; + zahl.setText("" + anzahl); +}); +\`\`\` + +Weggelassen wird alles, was Java sowieso weiß: \`new ActionListener()\`, der Name \`actionPerformed\`, \`public void\` und der Typ \`ActionEvent\`. Übrig bleiben der Parameter \`e\`, der Pfeil und der Rumpf. Das geht nur, weil der Vertrag genau **eine** Methode hat. + +## Die drei im Vergleich + +| | benannte innere Klasse | anonyme Klasse | Lambda | +|---|---|---|---| +| hat einen Namen | ja, z. B. \`Plus\` | nein | nein | +| steht | in der Klasse, außerhalb von \`main\` | direkt beim Knopf | direkt beim Knopf | +| für mehrere Knöpfe | ja, \`new Plus()\` | nein | ja, in einer Variable (Lektion 37) | +| sieht Variablen von \`main\` | nein | ja, wenn sie sich nicht ändern | ja, wenn sie sich nicht ändern | +| Länge | am längsten | mittel | am kürzesten | + +::: ludwig +Wenn sich eine Variable von \`main\` im Zuhörer ändern soll, wie \`anzahl++\`, muss sie in die Klasse, egal welche Schreibweise du nimmst. Das war das Problem aus Lektion 32. +::: + +::: angeberwissen +Schau nach dem Übersetzen in den Ordner mit den \`.class\`-Dateien. Für jede Klasse legt javac eine Datei an: \`Zaehler.class\`, für die innere Klasse \`Zaehler$Plus.class\` und für die anonyme Klasse \`Zaehler$1.class\`. Weil sie keinen Namen hat, bekommt sie eine Nummer. Für ein Lambda gibt es keine eigene Datei, Java baut es erst beim Start. +::: + +## Spiel: Welche Schreibweise? + +::: spiel frage +titel: Spiel: Welche Schreibweise? +intro: Ludwig zeigt dir Zuhörer aus fremden Programmen. Welche Schreibweise ist das? Sechs Runden. +frage: Welche Schreibweise ist das? +antworten: benannte innere Klasse | anonyme Klasse | Lambda + +runde: + knopf.addActionListener(e -> text.setText("Hallo")); +richtig: Lambda +> Der Pfeil \`->\` verrät das Lambda. + +runde: + knopf.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + text.setText("Hallo"); + } + }); +richtig: anonyme Klasse +> \`new ActionListener() {\` und dahinter eine ganze Methode: Hier wird eine Klasse ohne Namen geschrieben. + +runde: + static class Gruss implements ActionListener { + public void actionPerformed(ActionEvent e) { + text.setText("Hallo"); + } + } +richtig: benannte innere Klasse +> Die Klasse heißt \`Gruss\` und erfüllt den Vertrag mit \`implements ActionListener\`. + +runde: + knopf.addActionListener(new Gruss()); +richtig: benannte innere Klasse +> \`new Gruss()\` erzeugt ein Objekt der Klasse \`Gruss\`. Die Klasse selbst steht woanders, sie hat einen Namen. + +runde: + ActionListener taste = e -> { + anzeige.setText(anzeige.getText() + e.getActionCommand()); + }; +richtig: Lambda +> Ein Lambda in einer Variable, wie beim Zahlenschloss in Lektion 37. Der Pfeil verrät es. + +runde: + ActionListener taste = new ActionListener() { + public void actionPerformed(ActionEvent e) { + anzeige.setText(anzeige.getText() + e.getActionCommand()); + } + }; +richtig: anonyme Klasse +> Auch eine anonyme Klasse kann in einer Variable stehen. Dann kann man sie wie das Lambda bei mehreren Knöpfen anmelden. +::: + +## Aufgabe: Ein Zähler, drei Schreibweisen + +Baue den Klickzähler mit drei Knöpfen: + +- **+1** bekommt die benannte innere Klasse \`Plus\`. +- **-1** bekommt eine anonyme Klasse. +- **Reset** bekommt ein Lambda. + +Probiere aus, ob alle drei Knöpfe wie erwartet zählen. Lass dann bei der Klasse \`Plus\` das \`static\` weg und lies die Fehlermeldung von javac. + +## 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. + +::: checkliste +- Ich kann einen Zuhörer als benannte innere Klasse schreiben. → 1. Die benannte innere Klasse +- Ich kann einen Zuhörer als anonyme Klasse schreiben. → 2. Die anonyme Klasse +- Ich kann erklären, was beim Lambda weggelassen wird. → 3. Das Lambda +- Ich kann erklären, welche Schreibweise welche Variablen sieht. → Die drei im Vergleich +- Ich kann einen Zähler mit drei Knöpfen in drei Schreibweisen bauen. → Aufgabe: Ein Zähler, drei Schreibweisen +::: + +## Wissenstest + +::: quiz +? Warum geht die Kurzform mit dem Pfeil bei ActionListener? +→ 3. Das Lambda +- [ ] Weil ActionListener eine Klasse ist. +- [x] Weil der Vertrag genau eine Methode hat. +- [ ] Weil der Knopf es so verlangt. + +? Welche Schreibweise kannst du mit new Plus() bei mehreren Knöpfen benutzen, ohne sie in eine Variable zu speichern? +→ 1. Die benannte innere Klasse +- [x] die benannte innere Klasse +- [ ] die anonyme Klasse +- [ ] das Lambda + +? Warum steht static vor class Plus? +→ 1. Die benannte innere Klasse +- [ ] Damit die Klasse schneller ist. +- [x] Weil main static ist und sonst kein Objekt von Plus erzeugen kann. +- [ ] Weil jede Klasse static sein muss. + +? Ordne zu. +→ Die drei im Vergleich += class Plus implements ActionListener -> benannte innere Klasse += new ActionListener() { … } -> anonyme Klasse += der Pfeil hinter e -> Lambda +::: +`,Xx=`--- +titel: Zwei Reiter +bereich: Fenster mit Swing +kurz: Ein Fenster mit zwei Reitern bauen, Daten von einem Reiter zum anderen bringen und die Liste als Textdatei speichern. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- ein Fenster mit zwei Reitern bauen +- mit append Zeilen an eine JTextArea anhängen +- erklären, warum ein Zuhörer Bausteine auf beiden Reitern benutzen kann +- im Zuhörer mit try und catch eine Datei speichern +- eine Einkaufsliste bauen, die mitzählt, wie viele Dinge darauf stehen +::: + +## Das Ziel + +Ludwigs Einkaufsliste aus Lektion 23 bekommt ein Fenster. Es hat zwei **Reiter**, wie die Tabs im Browser: + +- Im Reiter **Eingabe** tippst du ein, was du brauchst, und klickst auf **Hinzufügen**. +- Im Reiter **Liste** steht alles, was du eingegeben hast. Ein Knopf **Speichern** schreibt die Liste in eine Textdatei. + +Neu sind die Reiter (\`JTabbedPane\`), ein Textbereich mit mehreren Zeilen (\`JTextArea\`) und das Speichern aus einem Zuhörer heraus. + +Schalte im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Reiter mit JTabbedPane + +Jeder Reiter zeigt eine eigene Fläche. Die Flächen sind JPanels, wie das Tastenfeld beim Zahlenschloss in Lektion 37: + +\`\`\`java +JTabbedPane reiter = new JTabbedPane(); +JPanel eingabe = new JPanel(new GridLayout(0, 1)); +JPanel liste = new JPanel(new BorderLayout()); + +reiter.addTab("Eingabe", eingabe); +reiter.addTab("Liste", liste); +fenster.add(reiter); +\`\`\` + +| Aufruf | Bedeutung | +|---|---| +| \`addTab("Eingabe", eingabe)\` | neuer Reiter mit der Beschriftung „Eingabe“, er zeigt das JPanel \`eingabe\` | +| \`setSelectedIndex(1)\` | wechselt zum zweiten Reiter, gezählt wird ab 0 | +| \`setTitleAt(1, "Liste (3)")\` | ändert die Beschriftung des zweiten Reiters | + +Beim Start ist der Reiter offen, der zuerst hinzugefügt wurde. + +## Ein Textbereich mit mehreren Zeilen + +Ein \`JTextField\` hat nur eine Zeile. Für die Liste brauchst du eine \`JTextArea\`: + +\`\`\`java +JTextArea bereich = new JTextArea(); +bereich.setEditable(false); +bereich.append("Heu\\n"); +\`\`\` + +- \`append\` hängt Text hinten an. Das \`"\\n"\` beginnt danach eine neue Zeile, wie beim Zerlegen mit \`split("\\n")\` in Lektion 24. +- \`setEditable(false)\` verhindert, dass man in der Liste selbst herumtippt. +- \`getText()\` liefert den ganzen Text mit allen Zeilen. + +## Von einem Reiter zum anderen + +Der Knopf **Hinzufügen** steht im Reiter Eingabe, der Textbereich im Reiter Liste. Trotzdem kann der Zuhörer beide benutzen. Alle Bausteine sind Variablen in \`main\`, und das Lambda sieht sie alle, egal auf welchem Reiter sie später angezeigt werden: + +\`\`\`java +hinzufuegen.addActionListener(e -> { + bereich.append(feld.getText() + "\\n"); + info.setText(feld.getText() + " steht auf der Liste."); + feld.setText(""); +}); +\`\`\` + +::: ludwig +Ein Baustein kann nur auf **einer** Fläche liegen. Fügst du denselben Knopf erst zu \`eingabe\` und dann zu \`liste\` hinzu, nimmt Swing ihn bei \`eingabe\` wieder weg. Er erscheint nur im Reiter Liste. +::: + +## Speichern im Zuhörer + +Zum Speichern nimmst du den \`PrintWriter\` aus Lektion 23. Im Zuhörer gibt es aber einen Haken: Den Ausweg \`throws Exception\` aus Lektion 23 gibt es hier nicht. Das Lambda ist eine eigene Methode, \`actionPerformed\`, und die darf laut Vertrag keine \`FileNotFoundException\` weiterwerfen. Darum steht das Speichern in try und catch: + +\`\`\`java +speichern.addActionListener(e -> { + try { + PrintWriter aus = new PrintWriter("einkaufsliste.txt"); + aus.print(bereich.getText()); + aus.close(); + info.setText("Gespeichert in einkaufsliste.txt"); + reiter.setSelectedIndex(0); + } catch (FileNotFoundException ex) { + info.setText("Speichern ging nicht."); + } +}); +\`\`\` + +- Die Exception heißt hier \`ex\`, weil der Name \`e\` schon für das Ereignis vergeben ist. +- Nach dem Speichern springt das Fenster mit \`setSelectedIndex(0)\` zurück zum Reiter Eingabe, wo die Meldung steht. +- VisuStruct zeigt die gespeicherte Datei unter der Konsole, sobald du auf Speichern geklickt hast. + +## Das ganze Programm + +\`\`\`java +import javax.swing.*; +import java.awt.*; +import java.io.*; + +public class Einkaufsliste { + public static void main(String[] args) { + JFrame fenster = new JFrame("Einkaufsliste"); + fenster.setSize(300, 250); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JTabbedPane reiter = new JTabbedPane(); + + JPanel eingabe = new JPanel(new GridLayout(0, 1)); + JTextField feld = new JTextField(); + JButton hinzufuegen = new JButton("Hinzufügen"); + JLabel info = new JLabel("Noch nichts auf der Liste."); + eingabe.add(new JLabel("Was brauchst du?")); + eingabe.add(feld); + eingabe.add(hinzufuegen); + eingabe.add(info); + + JPanel liste = new JPanel(new BorderLayout()); + JTextArea bereich = new JTextArea(); + bereich.setEditable(false); + JButton speichern = new JButton("Speichern"); + liste.add(bereich, BorderLayout.CENTER); + liste.add(speichern, BorderLayout.SOUTH); + + reiter.addTab("Eingabe", eingabe); + reiter.addTab("Liste", liste); + + hinzufuegen.addActionListener(e -> { + bereich.append(feld.getText() + "\\n"); + info.setText(feld.getText() + " steht auf der Liste."); + feld.setText(""); + }); + + speichern.addActionListener(e -> { + try { + PrintWriter aus = new PrintWriter("einkaufsliste.txt"); + aus.print(bereich.getText()); + aus.close(); + info.setText("Gespeichert in einkaufsliste.txt"); + reiter.setSelectedIndex(0); + } catch (FileNotFoundException ex) { + info.setText("Speichern ging nicht."); + } + }); + + fenster.add(reiter); + fenster.setVisible(true); + } +} +\`\`\` + +Tippe Heu ein, klicke auf Hinzufügen, dann Äpfel und noch einmal Hinzufügen. Wechsle zum Reiter Liste und klicke auf Speichern. + +## Spiel: Wo landet es? + +::: spiel frage +titel: Spiel: Wo landet es? +intro: Ludwig baut Fenster mit Reitern. Lies den Code und sag voraus, was du siehst. Sechs Runden. + +runde: + reiter.addTab("Eingabe", eingabe); + reiter.addTab("Liste", liste); +frage: Welcher Reiter ist beim Start offen? +- [x] Eingabe +- Liste +- keiner +> Beim Start ist der Reiter offen, der zuerst hinzugefügt wurde. + +runde: + reiter.addTab("Liste", liste); + reiter.addTab("Eingabe", eingabe); +frage: Welcher Reiter ist beim Start offen? +- Eingabe +- [x] Liste +- beide +> Diesmal kommt Liste zuerst. Die Reihenfolge von \`addTab\` bestimmt die Reihenfolge der Reiter. + +runde: + reiter.addTab("Eingabe", eingabe); + reiter.addTab("Liste", liste); + reiter.addTab("Hilfe", hilfe); + reiter.setSelectedIndex(1); +frage: Welcher Reiter ist offen? +- Eingabe +- [x] Liste +- Hilfe +> Gezählt wird ab 0: 0 ist Eingabe, 1 ist Liste, 2 ist Hilfe. + +runde: + hinzufuegen.addActionListener(e -> { + bereich.append(feld.getText() + "\\n"); + feld.setText(""); + }); + // Du tippst Heu, klickst Hinzufügen, tippst Äpfel, klickst Hinzufügen. +frage: Was steht danach im Reiter Liste? +- Äpfel +- HeuÄpfel +- [x] Heu\\nÄpfel +> \`append\` hängt an, und jedes \`"\\n"\` beginnt eine neue Zeile. + +runde: + JButton knopf = new JButton("OK"); + eingabe.add(knopf); + liste.add(knopf); +frage: Wo erscheint der Knopf OK? +- in beiden Reitern +- nur im Reiter Eingabe +- [x] nur im Reiter Liste +> Ein Baustein kann nur auf einer Fläche liegen. Beim zweiten \`add\` nimmt Swing ihn von \`eingabe\` weg. + +runde: + speichern.addActionListener(e -> { + bereich.setText(""); + reiter.setTitleAt(1, "Liste (leer)"); + reiter.setSelectedIndex(0); + }); + // Der Knopf speichern liegt im Reiter Liste. +frage: Was siehst du nach dem Klick? +- den leeren Reiter Liste +- [x] den Reiter Eingabe, und der zweite Reiter heißt „Liste (leer)“ +- den Reiter Eingabe, der zweite Reiter heißt weiter „Liste“ +> Der Zuhörer leert den Bereich, benennt den Reiter um und wechselt zu Reiter 0. Alles passiert bei einem Klick. +::: + +## Aufgabe: Einkaufsliste mit Reitern + +Baue das Programm nach und probiere es aus. + +Dann mach es besser: + +- Leere Eingaben kommen nicht auf die Liste. Prüfe vorher \`feld.getText().isEmpty()\` (Lektion 17). +- Der Reiter Liste zeigt in seinem Titel, wie viele Dinge auf der Liste stehen: „Liste (3)“. Zähle in einer \`static int\`-Variable mit und benutze \`setTitleAt\`. +- Zusatz: Ein dritter Reiter **Hilfe** mit einem JLabel, das erklärt, wie das Programm geht. + +## 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. + +::: checkliste +- Ich kann ein Fenster mit zwei Reitern bauen. → Reiter mit JTabbedPane +- Ich kann mit append Zeilen an eine JTextArea anhängen. → Ein Textbereich mit mehreren Zeilen +- Ich kann erklären, warum ein Zuhörer Bausteine auf beiden Reitern benutzen kann. → Von einem Reiter zum anderen +- Ich kann im Zuhörer mit try und catch eine Datei speichern. → Speichern im Zuhörer +- Ich kann eine Einkaufsliste bauen, die mitzählt, wie viele Dinge darauf stehen. → Aufgabe: Einkaufsliste mit Reitern +::: + +## Wissenstest + +::: quiz +? Welcher Reiter ist nach reiter.setSelectedIndex(0) offen? +→ Reiter mit JTabbedPane +- [x] der erste +- [ ] der zweite +- [ ] keiner + +? Warum steht das Speichern im Zuhörer in try und catch? +→ Speichern im Zuhörer +- [ ] Weil PrintWriter nur in try funktioniert. +- [x] Weil actionPerformed keine FileNotFoundException weiterwerfen darf. +- [ ] Weil main kein throws hat. + +? Was ist der Unterschied zwischen JTextField und JTextArea? +→ Ein Textbereich mit mehreren Zeilen +- [ ] Es gibt keinen. +- [x] JTextArea kann mehrere Zeilen zeigen. +- [ ] JTextField kann man nicht beschreiben. + +? Ordne zu. +→ Reiter mit JTabbedPane += JTabbedPane -> eine Fläche mit Reitern += JPanel -> die Fläche eines Reiters += JTextArea -> ein Textbereich mit mehreren Zeilen +::: +`,Kx=`--- +titel: Model View Controller +bereich: Fenster mit Swing +kurz: Den Klickzähler in Model, View und Controller zerlegen und verstehen, wer mit wem redet. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- sagen, was Model, View und Controller jeweils tun +- ein Model ohne Swing schreiben und ohne Fenster testen +- erklären, was new Zaehler() baut und warum dort kein static steht +- die vier Nachrichten nach einem Klick nennen +- eine zweite View dazubauen, ohne das Model zu ändern +- einen Zähler mit −1, Reset und Grenzen im Model bauen +::: + +## Das Ziel + +Große Programme mit Fenstern haben fast immer denselben Aufbau. Er heißt **Model View Controller**, kurz **MVC**: + +- Das **Model** hält die Daten und kennt ihre Regeln. +- Die **View** zeigt die Daten nur an. +- Der **Controller** reagiert auf Klicks und gibt Bescheid. + +Du lernst MVC am Klickzähler aus Lektion 32. Er wird Schritt für Schritt in drei Teile zerlegt. Am Ende zeigt er denselben Zählerstand zweimal an: als Zahl und als Balken. + +Schalte im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** ein. + +## Alles in einer Klasse + +So sah der Klickzähler bisher aus, alles steckt in \`main\` und einer Variable der Klasse: + +\`\`\`java +static int anzahl = 0; + +public static void main(String[] args) { + // ... Fenster bauen ... + JLabel zahl = new JLabel("0", SwingConstants.CENTER); + JButton plus = new JButton("+1"); + plus.addActionListener(e -> { + anzahl++; + zahl.setText("" + anzahl); + }); +} +\`\`\` + +Das läuft. Aber stell dir vor, der Zählerstand soll zusätzlich als Balken erscheinen, später noch in einem zweiten Fenster und in einer Datei. Dann muss jeder Zuhörer an alle Anzeigen denken. Rechnen und Anzeigen sind ineinander verknotet, und mit jeder Anzeige wird der Knoten größer. + +MVC löst den Knoten: Jede Aufgabe bekommt ihre eigene Klasse. + +## Das Model + +Das Model ist der Zähler selbst, ganz ohne Swing: + +\`\`\`java +class Zaehler { + int wert = 0; + + void erhoehen() { + wert++; + } + + int getWert() { + return wert; + } +} +\`\`\` + +- Diesmal steht vor \`wert\` und den Methoden kein \`static\`. Dann gehören sie zu einem **Objekt**: \`new Zaehler()\` baut einen Zähler mit eigenem \`wert\`, so wie \`new JButton("+1")\` einen Knopf mit eigener Beschriftung baut. +- \`model.erhoehen()\` ruft die Methode dieses einen Zählers auf, genau wie \`knopf.setText(…)\`. +- Wer den Wert wissen will, fragt mit \`getWert()\`. Ändern geht nur über \`erhoehen()\`. + +Weil das Model kein Fenster braucht, kannst du es ganz ohne Fenster ausprobieren: + +\`\`\`java +public class ZaehlerTest { + public static void main(String[] args) { + Zaehler model = new Zaehler(); + model.erhoehen(); + model.erhoehen(); + System.out.println(model.getWert()); + } +} + +class Zaehler { + int wert = 0; + + void erhoehen() { + wert++; + } + + int getWert() { + return wert; + } +} +\`\`\` + +Die Ausgabe ist 2. Mehrere Klassen dürfen in einer Datei stehen. Nur eine davon ist \`public\`, und die enthält \`main\`. + +## Die View + +Die View zeigt den Wert an und macht sonst nichts. Sie rechnet nicht und weiß nicht, woher die Zahl kommt: + +\`\`\`java +class ZahlAnzeige { + JLabel zahl = new JLabel("0", SwingConstants.CENTER); + + void aktualisieren(int wert) { + zahl.setText("" + wert); + } +} +\`\`\` + +- Die View bekommt den Wert mit \`aktualisieren(int wert)\` geliefert und schreibt ihn in ihr JLabel. +- Fenster und Knopf baust du wie immer in \`main\`. Mit \`fenster.add(view.zahl)\` kommt das JLabel der View ins Fenster. + +## Der Controller + +Der Controller ist der Zuhörer am Knopf. Er verbindet Model und View: + +\`\`\`java +Zaehler model = new Zaehler(); +ZahlAnzeige view = new ZahlAnzeige(); + +plus.addActionListener(e -> { + model.erhoehen(); + view.aktualisieren(model.getWert()); +}); +\`\`\` + +- Erst ändert er das Model, dann holt er den neuen Wert und gibt ihn der View. +- Das Problem aus Lektion 32 ist weg: Die Variable \`model\` ändert sich nie, sie zeigt immer auf denselben Zähler. Nur der \`wert\` darin ändert sich. Deshalb darf das Lambda \`model\` benutzen, ganz ohne \`static\`. + +## Wer redet mit wem? + +Bei jedem Klick laufen vier Nachrichten, immer in derselben Reihenfolge: + +::: grafik mvc-klick.svg +Die Pfeile leuchten der Reihe nach auf. Das Model zählt beim zweiten Pfeil hoch, die Anzeige erst beim vierten. +::: + +1. Der Knopf meldet den Klick an den Controller (\`actionPerformed\`). +2. Der Controller sagt dem Model: \`erhoehen()\`. +3. Der Controller fragt das Model nach dem neuen Wert: \`getWert()\`. +4. Der Controller gibt den Wert an die View: \`aktualisieren(wert)\`. + +Das Model redet mit niemandem. Es wartet, bis es gefragt wird. + +::: ludwig +Merk dir: Das Model weiß nichts von Fenstern. In \`Zaehler\` steht kein einziges \`JLabel\` und kein \`import javax.swing\`. Wenn du dort Swing brauchst, gehört der Code in die View. +::: + +## Der Gewinn: eine zweite View + +Jetzt soll der Zählerstand zusätzlich als Balken erscheinen. Dafür kommt eine zweite View dazu. Ein \`JProgressBar\` ist ein Balken, der sich füllt, hier von 0 bis 10: + +\`\`\`java +class BalkenAnzeige { + JProgressBar balken = new JProgressBar(0, 10); + + void aktualisieren(int wert) { + balken.setValue(wert); + } +} +\`\`\` + +Der Controller bekommt eine Zeile mehr. Das Model bleibt genau, wie es war: + +\`\`\`java +plus.addActionListener(e -> { + model.erhoehen(); + view.aktualisieren(model.getWert()); + balken.aktualisieren(model.getWert()); +}); +\`\`\` + +Genau das ist der Gewinn von MVC: Du kannst Anzeigen dazubauen oder austauschen, ohne das Model anzufassen. + +## Das ganze Programm + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +class Zaehler { + int wert = 0; + + void erhoehen() { + wert++; + } + + int getWert() { + return wert; + } +} + +class ZahlAnzeige { + JLabel zahl = new JLabel("0", SwingConstants.CENTER); + + void aktualisieren(int wert) { + zahl.setText("" + wert); + } +} + +class BalkenAnzeige { + JProgressBar balken = new JProgressBar(0, 10); + + void aktualisieren(int wert) { + balken.setValue(wert); + } +} + +public class KlickZaehler { + public static void main(String[] args) { + Zaehler model = new Zaehler(); + ZahlAnzeige view = new ZahlAnzeige(); + BalkenAnzeige balken = new BalkenAnzeige(); + + JFrame fenster = new JFrame("Klickzähler"); + fenster.setSize(250, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new GridLayout(0, 1)); + + JButton plus = new JButton("+1"); + plus.addActionListener(e -> { + model.erhoehen(); + view.aktualisieren(model.getWert()); + balken.aktualisieren(model.getWert()); + }); + + fenster.add(view.zahl); + fenster.add(balken.balken); + fenster.add(plus); + fenster.setVisible(true); + } +} +\`\`\` + +Klick ein paar Mal auf +1 und sieh zu, wie Zahl und Balken gemeinsam wachsen. + +::: angeberwissen +MVC hat sich der Norweger Trygve Reenskaug 1979 ausgedacht, im Forschungszentrum Xerox PARC in Kalifornien. Dort standen damals schon Computer mit Fenstern und Maus. Im selben Jahr besuchte Steve Jobs das Labor und war so begeistert, dass Apple danach Computer mit Fenstern und Maus baute. +::: + +## Spiel: Wohin gehört der Code? + +::: spiel frage +titel: Spiel: Wohin gehört der Code? +intro: Ludwig hat Code aus einem MVC-Programm auf einen Haufen geworfen. Sortier jedes Stück ein. Acht Runden. +frage: Wohin gehört dieser Code? +antworten: Model | View | Controller + +runde: + int wert = 0; +richtig: Model +> Der Zählerstand sind die Daten. Daten wohnen im Model. + +runde: + zahl.setText("" + wert); +richtig: View +> Etwas auf dem Bildschirm anzeigen ist die Aufgabe der View. + +runde: + plus.addActionListener(e -> model.erhoehen()); +richtig: Controller +> Auf einen Klick reagieren und dem Model Bescheid geben: Das macht der Controller. + +runde: + void erhoehen() { + wert++; + } +richtig: Model +> Das Model weiß selbst, wie es seine Daten ändert. + +runde: + balken.setValue(wert); +richtig: View +> Ein Balken, der sich füllt, zeigt nur an. Also View. + +runde: + void erhoehen() { + if (wert < 10) { + wert++; + } + } +richtig: Model +> „Höchstens 10“ ist eine Regel für die Daten. Regeln gehören ins Model, dann gelten sie für jeden Knopf und jede View. + +runde: + view.aktualisieren(model.getWert()); +richtig: Controller +> Den Wert beim Model abholen und der View geben: Das ist der Controller in der Mitte. + +runde: + JLabel zahl = new JLabel("0", SwingConstants.CENTER); +richtig: View +> Ein JLabel ist ein Baustein der Oberfläche. Im Model steht kein Swing. +::: + +## Spiel: Wer ist dran? + +::: spiel reihenfolge +titel: Spiel: Wer ist dran? +intro: Nach einem Klick reden Model, View und Controller miteinander, aber nur in einer Reihenfolge funktioniert es. Bring die Schritte in die richtige Reihenfolge. Fünf Runden. + +runde: +frage: Du klickst im Klickzähler auf +1. Was passiert der Reihe nach? +- Du klickst auf +1. +- Der Controller bekommt \`actionPerformed\`. +- Der Controller ruft \`model.erhoehen()\` auf. +- Das Model zählt \`wert\` hoch. +- Der Controller holt \`model.getWert()\`. +- Die View zeigt die neue Zahl. +> Klick, Controller, Model ändern, Wert holen, anzeigen. Das sind die vier Pfeile aus der Grafik, mit dem Hochzählen in der Mitte. + +runde: + plus.addActionListener(e -> { + model.erhoehen(); + view.aktualisieren(model.getWert()); + balken.aktualisieren(model.getWert()); + }); +frage: Was passiert nach einem Klick auf +1 der Reihe nach? +- Der Klick auf +1 +- \`model.erhoehen()\` +- Die Zahl zeigt den neuen Wert. +- Der Balken wächst. +> Der Zuhörer arbeitet seine Zeilen von oben nach unten ab: erst das Model, dann die Zahl, dann der Balken. + +runde: +frage: Bring den Controller in die richtige Reihenfolge, damit die View die neue Zahl zeigt. +- \`plus.addActionListener(e -> {\` +- \`model.erhoehen();\` +- \`view.aktualisieren(model.getWert());\` +- \`});\` +> Erst ändern, dann anzeigen. Andersherum zeigt die View noch den alten Wert. + +runde: + reset.addActionListener(e -> { + model.zuruecksetzen(); + view.aktualisieren(model.getWert()); + }); +frage: Der Zähler steht auf 5. Du klickst auf Reset. Was passiert der Reihe nach? +- Du klickst auf Reset. +- Das Model setzt \`wert\` auf 0. +- \`model.getWert()\` liefert 0. +- Die View zeigt 0. +> Auch Reset läuft über den Controller ins Model. Die View erfährt den neuen Wert erst ganz am Schluss. + +runde: +frage: Ein Test ohne Fenster soll 1 ausgeben. In welcher Reihenfolge stehen die Zeilen in main? +- \`Zaehler model = new Zaehler();\` +- \`model.erhoehen();\` +- \`System.out.println(model.getWert());\` +> Erst das Objekt bauen, dann damit arbeiten, zum Schluss nachsehen. Das Model lässt sich ganz ohne Fenster testen. +::: + +## Aufgabe: Ein Zähler mit Grenzen + +Baue das ganze Programm und probier es aus. + +Dann mach es besser: + +- Ein Knopf **−1** zählt herunter. Das Model bekommt dafür eine Methode \`verringern()\`, der Controller einen zweiten Zuhörer. +- Ein Knopf **Reset** setzt den Zähler mit \`zuruecksetzen()\` auf 0. +- Das Model achtet selbst auf die Grenzen: nie unter 0 und nie über 10, denn dann ist der Balken voll. +- Extra: eine dritte View \`KonsolenAnzeige\`, deren \`aktualisieren\` mit \`System.out.println\` „Neuer Wert: 3“ ausgibt. Eine View muss kein Fenster sein. + +## 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. + +::: checkliste +- Ich kann sagen, was Model, View und Controller jeweils tun. → Das Ziel +- Ich kann ein Model ohne Swing schreiben und ohne Fenster testen. → Das Model +- Ich kann erklären, was new Zaehler() baut und warum dort kein static steht. → Das Model +- Ich kann die vier Nachrichten nach einem Klick nennen. → Wer redet mit wem? +- Ich kann eine zweite View dazubauen, ohne das Model zu ändern. → Der Gewinn: eine zweite View +- Ich kann einen Zähler mit −1, Reset und Grenzen im Model bauen. → Aufgabe: Ein Zähler mit Grenzen +::: + +## Wissenstest + +::: quiz +? Wo steht die Regel „Der Zähler geht nie über 10“? +→ Das Model +- [x] im Model +- [ ] in der View +- [ ] im Controller +> Regeln über die Daten gehören ins Model. Dann gelten sie, egal welcher Knopf drückt. + +? Was macht die View? +→ Das Ziel +- [ ] Sie rechnet den neuen Wert aus. +- [x] Sie zeigt den Wert an, den sie bekommt. +- [ ] Sie hört auf Klicks. + +? Warum darf das Lambda model benutzen, obwohl model eine Variable von main ist? +→ Wer redet mit wem? +- [ ] Weil Zaehler public ist. +- [x] Weil model immer auf denselben Zähler zeigt; nur der wert darin ändert sich. +- [ ] Weil Lambdas alle Variablen ändern dürfen. + +? Was musst du am Model ändern, wenn eine zweite View dazukommt? +→ Der Gewinn: eine zweite View +- [x] nichts +- [ ] eine zweite Methode erhoehen +- [ ] ein zweites JLabel + +? Ordne zu. +→ Das Ziel += Zaehler mit wert und erhoehen() -> Model += ZahlAnzeige mit aktualisieren(int wert) -> View += der Zuhörer am Knopf -> Controller +::: +`,e4=`Fachbegriffe für den Lernbereich. Kommt ein Begriff in einem Schritt vor, wird er dort einmal markiert und zeigt beim +Hovern oder Antippen seine Erklärung. Steht er im Schritt fett, wird er gerade erklärt und deshalb nicht markiert. +\`auch:\` nennt weitere Formen, die ebenfalls erkannt werden. Groß- und Kleinschreibung zählt. + +### Algorithmus +auch: Algorithmen +Eine genaue Schritt-für-Schritt-Anleitung, mit der man eine Aufgabe löst. Jeder Schritt ist eindeutig. + +### Struktogramm +auch: Struktogramme, Struktogramms, Struktogrammen +Ein Algorithmus als Bild aus Kästen. Es wird von oben nach unten gelesen. + +### Programmablaufplan +auch: PAP, Programmablaufpläne, Programmablaufplans +Ein Algorithmus als Bild aus Symbolen, die mit Pfeilen verbunden sind (DIN 66001). Eine Raute ist eine Verzweigung. + +### Pseudocode +Ein Algorithmus als Text in normaler Sprache mit festen Wörtern wie WENN und SOLANGE. Die Einrückung zeigt, was zusammengehört. + +### Anweisung +auch: Anweisungen +Ein einzelner Schritt im Struktogramm, zum Beispiel eine Rechnung, eine Eingabe oder eine Ausgabe. + +### Sequenz +auch: Sequenzen +Schritte, die nacheinander von oben nach unten ausgeführt werden, jeder genau einmal. + +### Verzweigung +auch: Verzweigungen, bedingte Anweisung, bedingte Anweisungen +Ein Baustein, der mit einer Bedingung entscheidet, welcher von zwei Wegen ausgeführt wird. Im Lehrplan heißt sie auch bedingte Anweisung. + +### Zweig +auch: Zweige, Zweigen +Einer der beiden Wege einer Verzweigung: links für true, rechts für false. + +### Schleife +auch: Schleifen, Wiederholung, Wiederholungen, Wiederholungsstruktur, Wiederholungsstrukturen +Ein Baustein, der Schritte wiederholt, solange eine Bedingung gilt. Im Lehrplan heißt sie auch Wiederholungsstruktur. + +### Rumpf +Der Inhalt einer Schleife, also die Schritte, die wiederholt werden. + +### Durchlauf +auch: Durchläufe, Durchlaufs, Durchläufen +Ein einmaliges Ausführen des Inhalts einer Schleife. + +### Bedingung +auch: Bedingungen +Eine Frage, die nur mit ja (true) oder nein (false) beantwortet wird, zum Beispiel alter >= 18. + +### Platzhalter +Ein leerer Kasten mit dem Zeichen ø. Ziehst du ein Element darauf, wird er ersetzt. + +### Objektinspektor +Der Bereich unter dem Diagramm. Hier bearbeitest du Text und Einstellungen des Kastens, den du gerade angeklickt hast. + +### Simulation +Führt dein Struktogramm im Editor aus, auf Wunsch Schritt für Schritt. So siehst du, was passiert. + +### Variable +auch: Variablen +Eine beschriftete Kiste für einen Wert. Sie hat einen Namen, einen Datentyp und einen Wert. + +### CamelCase +auch: camelCase +Schreibweise für Namen aus mehreren Wörtern: zusammengeschrieben, jedes weitere Wort beginnt groß, z. B. \`preisMitSteuer\`. + +### Konstante +auch: Konstanten +Eine Variable, deren Wert nach dem Festlegen gleich bleibt. Man schreibt \`const\` davor, z. B. \`const double MWST = 0.19\`. + +### Datentyp +auch: Datentypen, Datentyps +Legt fest, welche Art von Wert in eine Variable passt: int (ganze Zahl), double (Kommazahl), String (Text), boolean (true oder false) oder char (ein einzelnes Zeichen). + +### Zuweisung +auch: Zuweisungen +Das Zeichen =. Es rechnet die rechte Seite aus und speichert das Ergebnis in der Variablen links. + +### Hilfsvariable +auch: Hilfsvariablen +Eine zusätzliche Variable, die einen Wert kurz aufbewahrt, zum Beispiel beim Tauschen. + +### EVA-Prinzip +Eingabe, Verarbeitung, Ausgabe: erst Werte abfragen, dann rechnen, dann das Ergebnis anzeigen. + +### Problemanalyse +Du liest eine Aufgabe genau und klärst, was gegeben ist, was gesucht ist und wie man vom einen zum anderen kommt. + +### Vergleichsoperator +auch: Vergleichsoperatoren +Ein Zeichen, das zwei Werte vergleicht, zum Beispiel == oder <. Das Ergebnis ist true oder false. + +### Fallauswahl +auch: Mehrfachauswahl +Ein Baustein, der je nach Wert einer Variablen genau einen von mehreren Fällen ausführt. Im Lehrplan heißt sie auch Mehrfachauswahl. + +### kopfgesteuert +auch: kopfgesteuerte, kopfgesteuerten +Die Schleife prüft ihre Bedingung vor jedem Durchlauf. Ist sie gleich zu Beginn falsch, läuft die Schleife kein einziges Mal. + +### fußgesteuert +auch: fußgesteuerte, fußgesteuerten +Die Schleife prüft ihre Bedingung erst nach jedem Durchlauf. Sie läuft also mindestens einmal. + +### Zählvariable +auch: Zählvariablen +Eine Variable, die in einer Schleife mitzählt, meistens i. + +### Endlosschleife +auch: Endlosschleifen +Eine Schleife, deren Bedingung nie falsch wird. Sie hört nie von selbst auf. + +### Array +auch: Arrays +Eine Reihe von Fächern mit einem gemeinsamen Namen und demselben Datentyp. Im Lehrplan heißt es auch Feld. + +### Index +Die Nummer eines Fachs in einem Array. Gezählt wird ab 0. + +### char +Der Datentyp für ein einzelnes Zeichen. Er steht in einfachen Anführungszeichen, z. B. 'C'. "C" mit doppelten Anführungszeichen ist dagegen ein String. + +### Zeichencode +auch: Zeichencodes, ASCII-Code, ASCII-Tabelle +Die Zahl, die hinter einem Zeichen steckt. In der ASCII-Tabelle hat A den Code 65, B 66 und so weiter. In Java wird mit (int) aus einem Zeichen sein Code und mit (char) aus einem Code das Zeichen. + +### Zeichenkette +auch: Zeichenketten +Ein Text, also eine Reihe von Zeichen. In Java heißt der Datentyp String. Die Zeichen werden ab 0 gezählt. + +### 2D-Array +auch: 2D-Arrays, zweidimensionales Array, zweidimensionale Arrays +Ein Array mit Zeilen und Spalten, wie eine Tabelle. Ein Fach braucht zwei Indizes, z. B. \`sitze[1][2]\`. + +### Unterprogramm +auch: Unterprogramme, Unterprogramms, Unterprogrammen, Methode, Methoden, Prozedur, Prozeduren, Funktion, Funktionen +Ein eigenes Struktogramm für eine Teilaufgabe. Es wird mit einem Aufruf ausgeführt. Im Lehrplan und in Java heißt es auch Methode, je nach Art auch Prozedur oder Funktion. + +### Parameter +auch: Parametern +Eine Variable in der Kopfzeile eines Unterprogramms. Beim Aufruf bekommt sie den Wert aus den Klammern. + +### Spaghetticode +Ein Programm, das so kreuz und quer springt, dass man den Ablauf kaum noch verfolgen kann. Struktogramme verhindern das. + +### Wertübergabe +auch: call by value +Englisch call by value. Ein Unterprogramm bekommt eine Kopie des Werts. Ändert es seinen Parameter, bleibt die Variable des Aufrufers unverändert. + +### Referenzübergabe +auch: call by reference +Englisch call by reference. Ein Unterprogramm bekommt einen Verweis auf dieselben Daten, z. B. auf ein Array. Ändert es ein Fach, sieht auch der Aufrufer die Änderung. + +### Rückgabewert +auch: Rückgabewerte +Das Ergebnis, das ein Unterprogramm mit return an den Aufruf zurückgibt. + +### Aussprung +Verlässt sofort die Schleife, in der er steht. Danach geht es unter der Schleife weiter. + +### Schreibtischtest +auch: Schreibtischtests +Du führst ein Struktogramm auf Papier aus und notierst nach jedem Schritt die Werte der Variablen. + +### lineare Suche +auch: Lineare Suche +Ein Suchverfahren, das alle Werte der Reihe nach mit dem gesuchten Wert vergleicht. Es funktioniert auch bei unsortierten Werten. + +### binäre Suche +auch: Binäre Suche +Ein Suchverfahren für sortierte Werte. Es sieht sich die Mitte an und sucht nur in der passenden Hälfte weiter. + +### Bubblesort +Ein einfaches Sortierverfahren. Es vergleicht immer zwei Nachbarn und tauscht sie, wenn sie falsch herum stehen. + +### Ereignis +auch: Ereignisse, Ereignissen, Ereignisses +Etwas, das der Mensch an einem Fensterprogramm tut, zum Beispiel einen Knopf anklicken. Das Programm reagiert darauf mit einem Zuhörer (ActionListener). + +### Interface +auch: Interfaces +Eine Art Vertrag in Java: Er legt fest, welche Methoden eine Klasse haben muss. \`ActionListener\` ist ein Interface mit der Methode \`actionPerformed\`. + +### Exception +auch: Exceptions +Ein Fehler, der erst beim Ausführen auftritt, zum Beispiel ein Index außerhalb des Arrays. Fängt ihn kein \`catch\` auf, bricht das Programm ab. + +### Attribut +auch: Attribute, Attributs +Eine Variable, die direkt in der Klasse steht und nicht in einer Methode. Mit \`static\` gehört sie zur Klasse selbst und lebt so lange wie das Programm, zum Beispiel ein Klickzähler, den mehrere Zuhörer ändern. + +### Scanner +Ein fertiger Baustein von Java, der Eingaben über die Tastatur liest, z. B. mit \`scanner.nextInt()\` eine Zahl. Er braucht ganz oben \`import java.util.Scanner;\`. + +### Kommentar +auch: Kommentare, Kommentaren, Kommentars +Eine Notiz im Code für Menschen. Java überspringt sie beim Ausführen. \`//\` gilt bis zum Ende der Zeile, \`/* … */\` kann über mehrere Zeilen gehen. + +### import +Eine Zeile ganz oben im Java-Code, die einen fertigen Baustein aus einem Paket holt, z. B. \`import java.util.Scanner;\`. Ohne sie kennt Java den Namen nicht. +`,t4=`## Grundbausteine + +### Anweisung + +Ein einzelner Schritt. Damit legst du Variablen an oder rechnest. + +\`\`\` +int zahl = 5 +double preis = 2.5 +String name = "Ada" +zahl = zahl + 1 +\`\`\` + +### Datentypen + +Der Datentyp steht vor dem Namen der Variablen. + +| Datentyp | Bedeutung | Beispiel | +|---|---|---| +| \`int\` | ganze Zahl | \`int anzahl = 3\` | +| \`double\` | Kommazahl (mit Punkt) | \`double preis = 2.5\` | +| \`String\` | Text in doppelten Anführungszeichen | \`String name = "Ada"\` | +| \`boolean\` | Wahrheitswert | \`boolean fertig = false\` | +| \`char\` | ein einzelnes Zeichen in einfachen Anführungszeichen | \`char note = 'C'\` | + +\`'C'\` ist ein \`char\`, \`"C"\` ein String. Ein Zeichen aus einem Text holst du mit \`charAt\`: \`char erster = name.charAt(0)\`. Jedes Zeichen hat einen Zeichencode: \`(int) 'A'\` ist 65, \`(char) 66\` ist \`'B'\`. + +### Eingabe + +Fragt beim Ausführen einen Wert ab und speichert ihn in einer Variablen. Der Text in Anführungszeichen ist die Frage. + +\`\`\` +input: int alter "Wie alt bist du?" +input: double preis "Preis eingeben" +input: String name "Wie heißt du?" +\`\`\` + +### Ausgabe + +Zeigt einen Text oder einen Wert an. Texte stehen in Anführungszeichen, mit \`+\` verbindest du Text und Variablen. + +\`\`\` +output: "Hallo" +output: summe +output: "Du bist " + alter + " Jahre alt." +\`\`\` + +> In der Ausgabe hängt \`+\` die Teile immer aneinander: \`output: a + b\` zeigt bei 3 und 4 also 34. Rechne deshalb vorher in einer Variablen, z. B. \`int summe = a + b\`, und gib dann \`summe\` aus. + +## Verzweigungen + +### Verzweigung + +Prüft eine Bedingung. Ist sie wahr, wird der linke Zweig (true) ausgeführt, sonst der rechte (false). + +\`\`\` +alter >= 18 +zahl % 2 == 0 +note < 1 || note > 6 +\`\`\` + +### Fallauswahl + +Wählt je nach Wert einer Variablen einen von mehreren Fällen. Passt kein Fall, gilt \`default\`. Fälle fügst du rechts mit **Weiteren Fall hinzufügen** hinzu. + +## Schleifen + +### While-Schleife + +Wiederholt den Inhalt, **solange** die Bedingung wahr ist. Die Bedingung wird vor jedem Durchlauf geprüft. + +\`\`\` +zahl != 1 +i < 10 +\`\`\` + +### Do-while-Schleife + +Führt den Inhalt **mindestens einmal** aus und prüft die Bedingung erst danach. + +### For-Schleife + +Zählt eine Variable von einem Startwert bis zu einer Grenze. Die drei Felder sind Start, Bedingung und Schritt. + +\`\`\` +int i = 0 +i < 5 +i++ +\`\`\` + +### Endlosschleife + +Wiederholt den Inhalt ohne Bedingung. Mit einem **Aussprung** im Inneren verlässt du sie. + +### Aussprung + +Verlässt die umgebende Schleife (\`break\`). + +## Unterprogramme + +### Aufruf + +Steht für ein Unterprogramm, z. B. \`berechneSumme()\`. Mit Parametern und Rückgabewert hat das Unterprogramm eine Kopfzeile als Titel: + +\`\`\` +int quadrat(int x) Kopfzeile des Unterprogramms +return x * x gibt das Ergebnis zurück +int q = quadrat(5) Aufruf, q bekommt 25 +zeigeSumme(3, 4) Aufruf eines void-Unterprogramms +\`\`\` + +## Rechnen und Vergleichen + +### Rechenzeichen und Vergleiche + +- \`+ - * /\` Grundrechenarten +- \`%\` Rest beim Teilen (\`7 % 2\` ist 1) +- \`==\` gleich, \`!=\` ungleich +- \`<\` \`<=\` \`>\` \`>=\` kleiner, kleiner gleich, größer, größer gleich +- \`&&\` und, \`||\` oder + +## Arrays + +### Arrays + +Mehrere Werte unter einem Namen. Gezählt wird ab 0. + +\`\`\` +int[] zahlen = {3, 7, 1} +output: zahlen[0] +int[] leer = new int[5] +\`\`\` + +Ein **2D-Array** ist eine Tabelle mit Zeilen und Spalten: + +\`\`\` +boolean[][] sitze = new boolean[3][5] +sitze[1][4] = true +output: sitze.length + " Reihen, " + sitze[0].length + " Plätze" +\`\`\` + +## Java + +### Kommentare + +Notizen im Code. Java überspringt sie, das Struktogramm bleibt gleich. + +\`\`\`java +/* + * Aufgabe: die Zahlen von 1 bis 10 addieren + * (mehrzeiliger Kommentar) + */ +// Verarbeitung (einzeiliger Kommentar) +int summe = 0; +for (int i = 1; i <= 10; i++) { + summe = summe + i; // Kommentar hinter dem Code +} // Ende for +\`\`\` + +Gut für: die Aufgabenstellung, die Einteilung in Eingabe, Verarbeitung und Ausgabe, eine Erklärung, das Ende eines Blocks hinter \`}\`, die erwartete Ausgabe und Notizen fürs nächste Mal. +`,n4=`--- +titel: What is a structure chart? +bereich: First steps +kurz: Show and read algorithms as a series of clear steps. +--- + +## Skills I will gain now + +::: kompetenzen +- explain what an algorithm is +- read a structure chart +- recognise the three basic building blocks: sequence, branch and loop +- read a flowchart and build one myself +- explain why jumps in a flowchart lead to mistakes +- read a simple algorithm as pseudocode +::: + +## An algorithm is an exact set of instructions + +An **algorithm** describes step by step how to solve a task. Every step must be so clear that someone can carry it out without asking, a person just as well as a computer. + +You know algorithms from everyday life: a recipe, directions to a place or the instructions for building a wardrobe. + +::: diagramm l1-tee.visustruct +Making tea as a structure chart: every box is one step. +::: + +## How to read a structure chart + +You read a structure chart **from top to bottom**. Every box is one step. Only when a step is finished does the next one start. + +This way of drawing was invented by **Isaac Nassi and Ben Shneiderman** (1973). That is why it is also called a Nassi-Shneiderman diagram. In Germany it is standardised as DIN 66261. + +::: bild ike-nassi.jpg ben-shneiderman.jpg +Left: Isaac “Ike” Nassi (photo: [Ed Schipul](https://commons.wikimedia.org/wiki/File:Me_with_Ike_Nassi!!!!!_%286893328729%29.jpg), [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/), cropped), right: Ben Shneiderman (photo: [Robert Kosara](https://commons.wikimedia.org/wiki/File:Ben_Shneiderman_at_UNCC_%283x4_cropped%29.jpg), CC0). +::: + +> A structure chart always has exactly one start (at the top) and one end (at the bottom). There are no arrows and no jumps all over the place. Programs that jump all over the place are called **spaghetti code**, because their flow gets tangled like noodles on a plate. More on this in step 10. + +::: angeberwissen +Baaah, listen up! In 1972 Nassi and Shneiderman were still PhD students at Stony Brook University near New York. Shneiderman was about 25 and Nassi about 23. So basically two students who wrote computer science history on the side. +::: + +## Building block 1: the sequence + +Every algorithm can be built from just **three basic building blocks**: **sequence**, [**branch**]{.blau} and [**loop**]{.rosa}. The colours help you match them: [statements]{.gelb} are yellow, branches blue, loops pink. The sequence has no colour of its own, it is simply the row of statements one below the other. You see the same colours in the editor and later in the code. You can switch them off in the settings under “Colored blocks”. In this step and the next two you get to know them one by one. + +The **sequence** is the simplest building block: several statements run **one after another**, each exactly once. + +This is what it looks like: + +- Every statement is a **simple rectangle**. +- The rectangles sit **on top of each other** without a gap. +- They run from top to bottom, one statement after the other. + +::: diagramm l1-sequenz.visustruct +Four statements as a sequence. First you get up, then you brush your teeth, and so on. +::: + +> The tea example above is a sequence, too. + +::: angeberwissen +15 minutes! That is how long Shneiderman needed for the first sketch with sequence, branch and loop. I need longer than that to choose between hay and clover. +::: + +## Building block 2: the branch + +Often the next step depends on a **condition**. A condition is a question you can only answer with **yes or no**, for example *Is it raining?* In VisuStruct yes is **true** and no is **false**. + +For decisions like this there is the **branch**. This is what it looks like: + +- At the top, the condition sits in a **triangle**. +- Below it, the box splits into **two columns**: on the left the path for **true**, on the right the path for **false**. +- **Only one** of the two paths ever runs. After that, both paths continue together below the branch. + +::: diagramm l1-verzweigung.visustruct +If it is raining, the left path runs, otherwise the right one. After that, both cases continue with “Leave”. +::: + +> If nothing should happen in one case, that path stays empty. The sign **ø** shows this. + +::: angeberwissen +Spelling alert! It is Shneiderman, with no c. Anyone who writes “Schneiderman” gets a gentle nudge from my horns. He himself points out that people keep sneaking a c into his name. +::: + +## Building block 3: the loop + +If something should happen **several times**, you do not write it down several times. Instead you use a **loop**, also called repetition. + +This is what it looks like: + +- At the top is the condition, for example *Plate not empty*. +- The steps that are repeated are **indented** below it. At the top and on the left, the box forms an **upside-down L** around them. +- Before every pass the condition is checked. As long as it is **true**, the steps inside the upside-down L run once more. If it is **false**, the program continues below the loop. + +::: diagramm l1-wiederholung.visustruct +As long as the plate is not empty, you take a bite. After that, the plate is cleared. +::: + +> There are more kinds of loops. You will meet them in later lessons. + +## All three together + +The building blocks become really useful when you combine them. This diagram contains all three: a sequence from top to bottom, a [branch]{.blau} and a [loop]{.rosa}. The yellow boxes are simple [statements]{.gelb}. The statements inside a branch or a loop are yellow too. Strictly speaking, the whole diagram is a sequence, because the branch and the loop also stand in the row from top to bottom. + +::: diagramm l1-grundbausteine.visustruct +You recognise the branch by its triangle and the loop by its upside-down L. Everything together sits in a sequence. +::: + +The boxes can also be **nested** inside each other: a loop or a path can contain sequences, branches and loops again. + +::: angeberwissen +Comfort for anyone who has messed up a test: the famous journal *Communications of the ACM* rejected the structure chart article. According to Nassi, the reviewer even said they should collect every copy and burn it. Ouch! It then appeared in 1973 in a smaller journal and today it is quoted thousands of times. Ha! +::: + +## Other ways to draw it: the flowchart + +There are two more ways to show an algorithm: the **flowchart** and **pseudocode**. You will meet both in class. + +Here you see our structure chart for drinking tea from “All three together” once more. Next we look at the flowchart, using the same example. + +::: diagramm l1-grundbausteine.visustruct +The tea example as a structure chart: first the cup, then the branch for the sugar, then the loop. +::: + +### The same algorithm as a flowchart + +::: grafik l01-pap.svg +The tea example as a flowchart. The arrow from “Wait 1 minute” back up forms the loop. +::: + +### The symbols + +A flowchart is made of a few symbols joined by **arrows**. It is standardised as DIN 66001 (ISO 5807). + +- **Oval:** start or end. Every flowchart has exactly one start and one end. +- **Rectangle:** a statement, for example *Put a cup on the table*. +- **Diamond:** a decision. The diamond holds a question, and two arrows lead out of it: **yes** and **no**. +- **Parallelogram:** an input or output. The tea example does not have one. +- **Arrow:** shows which step comes next. + +A loop has no symbol of its own in a flowchart. You recognise it by an arrow that leads **back up**. + +### The advantages + +- **Very easy to read**, even for people who have never seen a flowchart. You simply follow the arrows with your finger. +- Flowcharts are not only used in programming but wherever a process is explained: in user manuals, for troubleshooting (“Is the lamp on? No: is it plugged in?”) or in companies for work processes. + +## Exercise: Baking a cake as a flowchart + +Now you build a flowchart yourself. Ludwig bakes a cake like this: + +He puts the ingredients in the bowl and stirs the batter. If the batter is not smooth yet, he keeps stirring. Once it is smooth, he pours the batter into the tin and bakes the cake for 30 minutes. Then he checks with a wooden skewer: if batter still sticks to it, he bakes for 5 more minutes and checks again. Once the skewer comes out clean, he takes the cake out and calls: “The cake is ready!” + +::: pap +titel: Exercise: Baking a cake as a flowchart +auftrag: The places in the chart are empty. Put each element in its place. The shape of the place helps you. +start: Start +anweisung: Put ingredients in the bowl +anweisung: Stir the batter +frage: Batter smooth? | nein -> Stir the batter +anweisung: Pour batter into the tin +anweisung: Bake for 30 minutes +frage: Skewer clean? | nein: Bake 5 more minutes +anweisung: Take the cake out +ausgabe: “The cake is ready!” +ende: End +erklärung: Two loops, two arrows back up: when stirring, the arrow leads back to “Stir the batter”; when baking, it leads from “Bake 5 more minutes” back to the question. The output sits in the parallelogram. +legende: ja +::: + +## Drawbacks of the flowchart: jumps + +An arrow in a flowchart may lead from any symbol to any other. That sounds handy, but it is dangerous. + +In the old days, programs were written exactly like that. Every line had a **number**, and the command **GOTO** jumped to a line number. Every GOTO is an arrow from the flowchart. Our tea example would look like this: + +\`\`\` +10 Put a cup on the table +20 IF no sugar wanted, GOTO 40 +30 Add sugar +40 IF tea not too hot, GOTO 70 +50 Wait 1 minute +60 GOTO 40 +70 Drink the tea +\`\`\` + +### One more line, and the jumps go wrong + +Now you improve the algorithm: after the sugar, the tea bag should come out. You insert the new line 40, and all lines below move down one number. But the jumps still point to the old numbers: + +\`\`\` +10 Put a cup on the table +20 IF no sugar wanted, GOTO 40 +30 Add sugar +40 Take out the tea bag +50 IF tea not too hot, GOTO 70 +60 Wait 1 minute +70 GOTO 40 +80 Drink the tea +\`\`\` + +Play it through: line 70 no longer sends you to the check in line 50 but to the tea bag. And when the tea is cool enough, line 50 jumps to line 70 instead of *Drink the tea*. So you keep taking out the tea bag and never drink. With every change you have to check every GOTO. In a big program with hundreds of jumps, something easily goes wrong. + +### All over the place: spaghetti code + +With arrows you can also jump out of the middle of a loop, or from outside into the middle of a loop. Such jumps quickly make the chart confusing. With many jumps the arrows cross until the chart looks like a plate of spaghetti. That is why it is called **spaghetti code**. You can hardly follow the flow any more, and mistakes hide well. + +A structure chart has no arrows. If you insert a box, everything below simply moves down with it, and no jump can point to the wrong place. For leaving a loop early there is a separate, tidy box, the break. You will meet it in lesson 18. + +::: angeberwissen +In 1968 the computer scientist Edsger Dijkstra wrote a famous letter: “Go To Statement Considered Harmful”. Since then, programs are built only from sequence, branch and loop. In Java, \`goto\` is still a reserved word today, but you are not allowed to use it. Baah, I would rather eat spaghetti than program it. +::: + +## Pseudocode and comparison + +**Pseudocode** is text that looks like a program but is written in plain language. Fixed words such as IF and WHILE show the building blocks, and the **indentation** shows what belongs to them. There are no jumps here either. This is our tea example: + +\`\`\` +Put a cup on the table +IF sugar wanted THEN + Add sugar +END IF +WHILE tea still too hot + Wait 1 minute +END WHILE +Drink the tea +\`\`\` + +Pseudocode has **no fixed notation**. Some people write WHEN instead of IF, others use an arrow for assignment (\`number ← 5\`) or leave out the END lines. All of that is fine. What matters is that anyone can understand it without an explanation. So pseudocode is not another programming language you have to learn. + +::: angeberwissen +Does pseudocode look familiar? The programming language Python looks very similar, and that is on purpose: its inventor Guido van Rossum wanted programs to read almost like plain text. Python also uses indentation to show what belongs together. But careful: Python is a real programming language with strict rules. One space too many and the computer complains. Pseudocode is more relaxed, just like me at breakfast. +::: + +### Compared + +- **Structure chart:** boxes inside boxes, the loop is an upside-down L. You see the structure at a glance, and wild jumps are impossible. +- **Flowchart:** symbols with arrows, the loop is an arrow back up. Very easy to picture, but big charts quickly get confusing, and jumps all over the place are possible. +- **Pseudocode:** text with indentation, the loop sits between WHILE and END WHILE. Quick to write and already close to program code. + +> All three describe the same algorithm. Once you can read one form, you learn the others quickly. + +::: angeberwissen +Nassi and Shneiderman were out to get the arrows! Their 1973 article was called “Flowchart Techniques for Structured Programming”. With arrows you can jump all over the place until the chart looks like a plate of spaghetti. In a structure chart that is simply impossible. Baah, that is how I like it: tidy, like my stable. +::: + +## Structure first, then code + +When you program, two things happen at once: you have to think about the steps and pay attention to how the programming language is written. A structure chart lets you keep the two apart. + +1. First you think about the **logic**: which steps, which conditions, which repetitions? +2. Then you translate the finished structure into **Java, Python or JavaScript**. VisuStruct can even generate the code for you. + +With the **simulation** you can also run your structure chart step by step and check whether it really does what it should. + +## Game: Which building block? + +::: spiel frage +titel: Game: Which building block? +intro: Ludwig describes things from his everyday life. Which of the three building blocks is hidden in each? Eight rounds. +antworten: sequence | branch | loop + +runde: +frage: "Toothpaste on the brush, brush your teeth, rinse your mouth." +richtig: sequence +> Three steps, each exactly once and always in this order. + +runde: +frage: "If it rains, take the umbrella, otherwise the sunglasses." +richtig: branch +> A condition decides which of the two ways is taken. + +runde: +frage: "Stir until the dough is smooth." +richtig: loop +> Stirring is repeated as long as the dough isn't smooth yet. + +runde: +frage: "Run ten laps around the sports field." +richtig: loop +> The same lap is run ten times. + +runde: +frage: "Shoes on, jacket on, door open, off you go." +richtig: sequence +> One step after the other, nothing is skipped or repeated. + +runde: +frage: "If the light is green, you cross the street." +richtig: branch +> Even without "otherwise" it is a branch. The otherwise branch is simply empty. + +runde: +frage: "Roll the dice until you get a six." +richtig: loop +> You don't know beforehand how often. You roll until the condition is met. + +runde: +frage: "If someone says 'Come in', you go in. Otherwise you wait at the door." +richtig: branch +> The answer decides between two ways: go in or wait. +::: + +## 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. + +::: checkliste +- I can explain what an algorithm is. → An algorithm is an exact set of instructions +- I can read a structure chart from top to bottom. → How to read a structure chart +- I can name the three basic building blocks: sequence, branch and loop. → Building block 1: the sequence +- I can recognise every building block in a structure chart by its shape. → All three together +- I can name the symbols of a flowchart and read a simple flowchart. → Other ways to draw it: the flowchart +- I can build a simple algorithm as a flowchart myself. → Exercise: Baking a cake as a flowchart +- I can explain why jumps with GOTO lead to mistakes and spaghetti code. → Drawbacks of the flowchart: jumps +- I can read a simple algorithm as pseudocode. → Pseudocode and comparison +::: + +## Quiz + +::: quiz +? In which direction do you read a structure chart? +→ How to read a structure chart +- [ ] From left to right +- [x] From top to bottom +- [ ] From bottom to top +> Every box is one step, and the steps follow each other from top to bottom. + +? Which building block is NOT one of the three basic building blocks? +→ Building block 1: the sequence +- [ ] Sequence +- [ ] Branch +- [x] Jump +- [ ] Loop +> There are no jumps in a structure chart. Sequence, branch and loop are enough for every algorithm. + +? How do you recognise a branch in a structure chart? +→ All three together +- [ ] By an upside-down L +- [x] By a triangle with the condition and two columns below it +- [ ] By several rectangles on top of each other +> The upside-down L belongs to the loop, and rectangles on top of each other are a sequence. + +? When does the inside of a loop run once more? +→ All three together +- [x] As long as the condition is true +- [ ] Only if the condition is false +- [ ] Always exactly twice +> The condition is checked before every pass. If it is false, the program continues below the loop. + +? What is an algorithm? +→ An algorithm is an exact set of instructions +- [x] Clear step-by-step instructions for solving a task +- [ ] A particular program in Java +- [ ] A picture that explains a program +> An algorithm does not depend on a programming language. A structure chart is one way to write it down. + +? How do you recognise a loop in a flowchart? +→ Other ways to draw it: the flowchart +- [ ] By an upside-down L +- [x] By an arrow that leads back up +- [ ] By the word WHILE +> The upside-down L belongs to the structure chart, and WHILE to pseudocode. + +? Match each flowchart symbol to its meaning. +→ Other ways to draw it: the flowchart += Oval -> Start or end += Rectangle -> Statement += Diamond -> Decision += Parallelogram -> Input or output +> The diamond has two exits: yes and no. + +? You insert a new line into a program with GOTO. What can happen? +→ Drawbacks of the flowchart: jumps +- [x] The jumps point to the wrong lines because the numbers have moved +- [ ] Nothing, the jumps adjust by themselves +- [ ] The program automatically gets faster +> Every GOTO points to a fixed line number. If the lines move down, the program jumps to the wrong place. + +? In pseudocode, what shows which lines belong to a loop? +→ Pseudocode and comparison +- [ ] The colour +- [x] The indentation and the END WHILE +- [ ] An arrow +> Everything between WHILE and END WHILE is indented and is repeated. +::: +`,i4=`--- +titel: The editor +bereich: First steps +kurz: Insert elements, type text, move and delete. +--- + +## Skills I will gain now + +::: kompetenzen +- insert an element from the Elements area and replace a placeholder +- change the text of a box and switch between Statement, Input and Output +- move, copy and delete boxes and undo steps +::: + +## The screen + +VisuStruct has two editors: the [structure chart editor](#zeige-editor), which this lesson is about, and on the right the [Code](#zeige-codelive) area for Java code (from lesson 4). If the structure chart editor is collapsed, this lesson opens it for you. The blue words show you the areas, even when they are collapsed: move the mouse over one, and the area opens next to the learning area and lights up. Click it (or tap it), and it stays open. + +The structure chart editor has several areas. Move the mouse over a blue word or tap it, and that area lights up in the editor; collapsed areas such as Elements open. + +- **At the very top, the [toolbar](#zeige-leiste):** New, Open and Save. On the far right, the gear for [Settings](#zeige-einstellungen): text size and language. +- **Below it, the [tools](#zeige-werkzeuge)** above the elements and the structure chart: Undo, Cut, Copy, Paste, Delete, Export, Code and Simulation. The buttons only show icons. Hold the mouse over one and its name appears. +- **On the left, the [Elements](#zeige-elemente):** Here are all the building blocks you can drag into the structure chart. Some people also call this area the palette. +- **In the middle, the [structure chart](#zeige-struktogramm):** A new diagram contains only an empty placeholder, marked with **ø**. +- **At the bottom, the [Object Inspector](#zeige-objektinspektor):** Here you edit the text of the selected element. + +> You can collapse this learning area at any time with the [sidebar icon](#zeige-lernen) at the top of this area. Then only the slim “🎓 Learn” strip stays on the left; click it to open the area again. It stays open next to the editor so you can try out right away what you read. In the same way there is the [📁 Files](#zeige-dateien) column on the left for your saved programs (lesson 3) and the [Code](#zeige-codelive) area on the right for Java (from lesson 4). + +## Insert an element + +Drag an element from the **Elements** area onto the structure chart. While you drag, a blue line shows where it will land: + +- **Onto the placeholder ø:** The element replaces the placeholder. +- **Onto the top half of a box:** The element goes in front of it. +- **Onto the bottom half of a box:** The element goes after it. + +::: grafik l02-einfuegen.svg +Where you drop it decides where the new element lands. +::: + +It also works without dragging: **click** an element in the Elements area (or tap it). Then it is inserted after the selected box. If the placeholder **ø** is selected, it replaces it. + +With the keyboard, press **Tab** to jump to an element and press **Enter**. The new element also goes after the selected box. + +::: angeberwissen +Grabbing boxes and dragging them around, just like you are doing now, has a fancy name: **direct manipulation**. Ben Shneiderman coined the term in 1982. Yes, the structure chart guy. That man worked harder than I do when I graze. +::: + +## Type text + +Click a box. It gets a blue outline, and its text appears in the Object Inspector below the diagram. Whatever you type there shows up in the diagram straight away. + +The box from the Elements area is called a **Statement**. At the top of the Object Inspector you choose what sort of statement it should be: + +- **Statement:** calculate or set something, e.g. \`int number = 5\`. You will learn how in lesson 4. +- **Input:** ask for a value while the chart runs. That comes in lesson 6. +- **Output:** show something. In the diagram it then has \`output:\` in front, e.g. \`output: "Hello"\`. + +To start with, you only need Output. Texts that should be shown exactly as they are go in **quotation marks**. + +::: diagramm l2-ausgabe.visustruct +Two outputs one after the other. Open the diagram in the editor and start the simulation to see the output. +::: + +## Move, copy, delete + +- **Move:** Drag an existing box to a new place with the mouse. +- **Copy and paste:** Select a box, then press Ctrl+C and Ctrl+V (on a Mac ⌘C and ⌘V). The copy goes after the selected box. +- **Delete:** Select a box and press Del, or click the [trash can](#zeige-loeschen) „Delete Selection“ in the tools. +- **Undo:** Ctrl+Z undoes the last step, Ctrl+Shift+Z brings it back (on a Mac ⌘Z and ⌘⇧Z). + +## Exercise: Hello World + +::: übung l2-hallo +titel: Hello World +auftrag: Build a structure chart that outputs **Hello World**. +Drag a **Statement** from the Elements onto the placeholder **ø** and click the box. In the Object Inspector below the structure chart there are three buttons at the top: Statement, Input and Output. Click **Output**. Then type \`"Hello World"\` in the text field below, with quotation marks. +test: - -> Hello World +braucht: anweisung +tipp: You only need one single box. The text that should appear goes into the text field in the Object Inspector. +tipp: Watch out for the quotation marks. Without them, VisuStruct looks for a variable called Hello. +lösung: l2-hallo-loesung.visustruct +::: + +Click **Check** when you are done. VisuStruct runs your structure chart and compares the output. + +## Exercise: Two lines + +::: übung l2-zwei-zeilen +titel: Two lines +auftrag: First output **Hello** and then **I am learning structure charts**, each on its own line. +test: - -> Hello | I am learning structure charts +tipp: Two lines means two outputs. The boxes sit on top of each other and run from top to bottom. +tipp: Every output is a box of its own. Drag the second Statement onto the bottom half of the first one. +lösung: l2-zwei-zeilen-loesung.visustruct +::: + +## Game: Editor pro + +::: spiel frage +titel: Game: Editor pro +intro: Ludwig tests whether you have the editor under control. Seven rounds. + +runde: +frage: You drag a statement onto the placeholder **ø**. What happens? +- [x] The statement replaces the placeholder. +- The statement goes after the placeholder. +- Nothing, you can't drop anything on ø. +> The placeholder only keeps the place free. The new element takes it. + +runde: +frage: You drag an element onto the **top** half of a box. Where does it end up? +- [x] in front of it +- after it +- It replaces the box. +> Top half means in front, bottom half means after. The blue line shows you while dragging. + +runde: +frage: You drag an element onto the **bottom** half of a box. Where does it end up? +- in front of it +- [x] after it +- at the very end of the structure chart +> Bottom half means: directly after this box. + +runde: +frage: You deleted a box by accident. What brings it back? +- Ctrl+C / ⌘C +- [x] Ctrl+Z / ⌘Z +- Ctrl+V / ⌘V +> Ctrl+Z / ⌘Z undoes the last step. Ctrl+C / ⌘C copies, Ctrl+V / ⌘V pastes. + +runde: +frage: When it runs, exactly **Hello** should appear. What is in the box? +- [x] output: "Hello" +- output: Hello +- "Hello" +> Text that should be shown exactly like that goes in quotation marks. The editor puts \`output:\` in front when you choose the kind Output. + +runde: +frage: Where do you change the text of the selected box? +- in the Elements +- [x] in the Object Inspector +- in the toolbar at the very top +> The Object Inspector below the diagram shows the text of the selected box. + +runde: +frage: You click an element in the Elements area without dragging. Where does it end up? +- [x] after the selected box +- at the very beginning +- at the very end +> Without dragging (click, or Tab and Enter) the new element goes after the box that is selected right now. +::: + +## 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. + +::: checkliste +- I can insert an element from the Elements area and replace a placeholder. → Insert an element +- I can change the text of a box and switch between Statement, Input and Output. → Type text +- I can move, copy and delete boxes and undo steps. → Move, copy, delete +::: + +## Quiz + +::: quiz +? What does the sign ø in a box mean? +→ Insert an element +- [ ] The box contains a mistake. +- [x] There is still an empty placeholder here. +- [ ] The program ends here. +> A placeholder is replaced when you drag an element onto it. + +? You drag a Statement onto the bottom half of a box. Where does it land? +→ Insert an element +- [ ] In front of it +- [x] After it +- [ ] The box is replaced. + +? How do you output the text Good morning exactly as it is? +→ Type text +- [ ] output: Good morning +- [x] output: "Good morning" +- [ ] input: "Good morning" +> Without quotation marks, Good morning is understood as the name of a variable. +::: +`,a4=`--- +titel: Save, open, export +bereich: First steps +kurz: Keep your files safe, use your workspace, open several diagrams and share them as an image or PDF. +--- + +## Skills I will gain now + +::: kompetenzen +- give a diagram a title +- save a diagram as a .visustruct file and open it again +- export a diagram as an image (PNG) or PDF +- open a second diagram in a new tab +- create my workspace \`VisuStruct-Files\` +- save a program in my workspace +::: + +## The .visustruct file + +Structure charts are saved as **.visustruct** files. All versions of VisuStruct use the same format: in the browser, on Mac, iPad and iPhone, and the Java app on the computer. So you can start in the browser at school and carry on in the app at home. + +::: angeberwissen +When Nassi was a student, there were no files to save. There were punched cards. Nassi says a Saturday night date looked like this: his future wife sat with him in the computer centre and punched his cards. Romance, computer science style! +::: + +::: grafik l03-lochkarte.svg l03-lochkarte-beschriftet.svg +This is what a punched card looked like. One card held one line of a program, here \`PRINT *, 'HELLO WORLD'\` in the Fortran language. Each column is one character, and the holes in it are its code. A whole program was a stack of these cards. If you dropped it, you had to sort everything again. +::: + +## Save and open + +- **[Save](#zeige-speichern)** (Ctrl+S, on a Mac ⌘S): The diagram is saved as a file. If the **Files** column is set up (see below), it goes there. Otherwise the browser asks where to put it or puts the file in your downloads folder. +- **[Open](#zeige-oeffnen)** (Ctrl+O, on a Mac ⌘O): Load a saved file again. You can also simply drag a file into the browser window. + +> The browser remembers your exercises automatically. But that only works in this browser on this device. So always save important work as a file as well. + +## The Files column + +To the left of the learning area you find the [📁 Files](#zeige-dateien) column. There you keep all your programs in one place, your **workspace**. + +**Your turn:** Set up your workspace right now, before you read on. From today on you save all your programs there. + +1. Create a workspace: open the column and click **Choose folder**. In the window, go to your **Documents**, use **New Folder** to create a folder called \`VisuStruct-Files\` there and select it. Allow VisuStruct to use the folder. This works in Chrome and Edge. On the iPad and in other browsers, click **Save in the browser** instead. +2. Save as usual. In your workspace, VisuStruct automatically creates a folder with today's date, for example \`2026-10-23\`, and saves the program in it. The file name comes from the title. + +This is what your workspace looks like then: + +\`\`\`text +VisuStruct-Files ← workspace +└── 2026-10-23 ← day + └── Factorial.visustruct +\`\`\` + +Clicking a program in the column opens it again. That way you quickly find every lesson later. + +Your **learning progress** goes into the workspace too: the file \`learnProgress.json\` lists the lessons and exercises you have finished. If you open the workspace in another browser, your progress is back. + +> Why a real folder? Your learning progress and your programs are stored in it as files. You can take the folder with you, for example on a USB stick or in your cloud folder such as OneDrive. That way you carry on at home on another computer exactly where you stopped. If you only save in the browser, everything stays in this one browser on this device. If someone deletes the browser data, your learning progress is gone too. + +## Several diagrams in tabs + +Above the structure chart you see the [tabs](#zeige-reiter). With **+** or [New](#zeige-neu) you open another, empty diagram. A dot • in front of the name shows that there are unsaved changes. + +You type the [title](#zeige-titel) of a diagram into the field above the structure chart. It also appears when you export and is suggested as the file name. + +## Share: image, PDF or file + +With [Export](#zeige-exportieren) in the tools (icon with an arrow pointing up) you can share your structure chart: + +- **Image (PNG):** to put into a worksheet or a presentation +- **Vector graphic (SVG):** stays sharp at any size +- **PDF (A4):** one page to hand in or print +- **VisuStruct file (.visustruct):** to pass on to someone who should open and keep editing your structure chart in VisuStruct, for example by email or through the learning platform +- **Print** (Ctrl+P, on a Mac ⌘P): straight to the printer + +Under the [gear](#zeige-textgroesse) at the top right, Text size sets the font size. Larger text also shows when you export an image. + +## Game: How do you pass it on? + +::: spiel frage +titel: Game: How do you pass it on? +intro: Ludwig wants to pass on his structure chart. Which format fits best? Six rounds. +frage: Which format fits? +antworten: .visustruct | PNG | SVG | PDF + +runde: +frage: You want to keep working on your structure chart tomorrow. +richtig: .visustruct +> Only the .visustruct file can be opened and edited in VisuStruct again. + +runde: +frage: The structure chart should go into a presentation as a picture. +richtig: PNG +> A PNG image can be put into any presentation and any worksheet. + +runde: +frage: Your teacher wants to print your work as one A4 page. +richtig: PDF +> The PDF is exactly one A4 page to hand in or print. + +runde: +frage: The structure chart goes on a poster and should stay sharp even when huge. +richtig: SVG +> A vector graphic stays sharp at any size. A PNG gets pixelated when you enlarge it. + +runde: +frage: Your friend should change the structure chart in her VisuStruct app on the iPad. +richtig: .visustruct +> All VisuStruct versions open the same .visustruct file: in the browser, on Mac, iPad and iPhone. + +runde: +frage: You want to send a picture into a chat quickly. +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: + +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. + +::: checkliste +- I can give a diagram a title. → Try it out +- I can save a diagram as a .visustruct file and open it again. → Save and open +- I can export a diagram as an image (PNG) or PDF. → Share: image, PDF or file +- I can open a second diagram in a new tab. → Several diagrams in tabs +- I can create my workspace \`VisuStruct-Files\`. → The Files column +- I can save a program in my workspace. → The Files column +::: + +## Quiz + +::: quiz +? Which file can you open again in the Mac app and in the Java app? +→ Save and open +- [x] The .visustruct file +- [ ] The exported PNG image +- [ ] The exported PDF +> Images and PDFs are only for looking at. You can only keep editing the .visustruct file. + +? The browser remembers your exercises. Why should you still save? +→ Save and open +- [ ] Because otherwise the exercises are not checked +- [x] Because the browser only keeps the data on this device and it can get lost +- [ ] Because you cannot export without saving + +? Today you save a program in your workspace. Where does it end up? +→ The Files column +- [ ] In the downloads folder +- [x] In the workspace, inside a folder with today's date +- [ ] Directly in the workspace without a subfolder +> VisuStruct automatically creates a date folder for each day. That keeps the programs sorted by lesson. +::: +`,s4=`--- +titel: Variables and data types +bereich: Basics +kurz: Store values, get to know the data types int, double, String and boolean, and calculate. +--- + +## Skills I will gain now + +::: kompetenzen +- create a variable with a data type, a name and a value +- tell the data types int, double, String and boolean apart +- explain that = is an assignment and not a comparison +- calculate with + - * / % and use whole-number division +- create and output variables in Java +::: + +## What is a variable? + +A **variable** is like a labelled box. It has a **name**, a **data type** and a **value**. + +\`\`\` +int age = 14 +\`\`\` + +Here the variable is called \`age\`, its data type is \`int\` (whole number), and its value is 14. You can use the value again later through its name. + +::: grafik l04-variable.svg +The variable as a box: the name on the label, the data type as a sticker, the value inside. +::: + +> Variable names start with a **lowercase letter** and contain no spaces. Good names say what is inside: \`price\` is better than \`p\`. + +::: angeberwissen +In September 1999 the Mars Climate Orbiter space probe was lost. One team calculated the thrust in American units (pounds), the other expected metric units (newtons). The data only contained the number, not the unit. The probe flew too low into the Martian atmosphere and burned up, a loss of about 125 million dollars. A meaningful name like \`impulseInNewtonSeconds\` would have said what is inside. By the way, I always label my hay box \`hayInKilos\`. +::: + +If a name is made of several words, you write them together and start every further word with a capital letter: \`priceWithTax\`, \`numberOfStudents\`. This way of writing is called **camelCase**. + +::: angeberwissen +camelCase got its name because the capital letters in the middle stick out of the word like the humps of a camel: \`priceWithTax\` has two humps. Me, I'm a billy goat with zero humps but two horns. Sadly, nobody has invented GoatCase yet. +::: + +::: grafik l04-camelcase.svg +The capitals W and T stick out like the camel's two humps. +::: + +## The four data types + +The data type says what kind of value may be stored in the variable. + +- **int:** whole numbers, e.g. \`int count = 3\` or \`int temperature = -5\` +- **double:** decimal numbers, e.g. \`double price = 2.5\`. You write a **point**, never a comma. +- **String:** text, e.g. \`String name = "Mia"\`. Text goes in quotation marks. +- **boolean:** truth values, only \`true\` or \`false\` + +There are more data types. You will soon need one of them: \`char\` for a **single character**, e.g. \`char grade = 'C'\`. A \`char\` goes in **single** quotation marks. You will get to know it better in lesson 17. + +::: diagramm l05-datentypen.visustruct +Three variables with different data types. Open the diagram and start the simulation. +::: + +You mostly meet truth values in **conditions**: \`age >= 18\` is either \`true\` or \`false\`. That is what lesson 8 is about. A variable of type \`boolean\` simply gets \`true\` or \`false\`: + +\`\`\` +boolean adult = false +\`\`\` + +::: angeberwissen +On 4 June 1996 the Ariane 5 rocket exploded just 37 seconds after launch. The cause was a single line: a decimal number for the speed was put into a whole-number variable that was too small for such large values. So the data type is no small matter, it can cost half a billion euros. +::: + +## Assignment with = + +The sign \`=\` is called an **assignment**. It does not mean “equals” as in maths. It means: work out the right-hand side and store the result in the variable on the left. + +\`\`\` +int points = 10 +points = points + 5 +\`\`\` + +In maths the second line would be wrong, because no number equals itself plus 5. In programming you read it like this: take the old value 10, add 5 and store 15 in \`points\`. You only write the data type the first time, when the variable is created. + +::: grafik l04-zuweisung.svg +First the right-hand side is calculated, then the result lands in the variable on the left. +::: + +## Calculating + +You can calculate with numbers: + +- \`+\` plus, \`-\` minus, \`*\` times, \`/\` divided by +- \`%\` remainder of a division (called “modulo”), e.g. \`17 % 5\` is 2 + +You know **division with remainder** from primary school, before you learned about decimals: 17 ÷ 5 = 3 remainder 2. 5 fits into 17 three times, that makes 15. To get to 17, 2 are still missing: that is the remainder. The computer calculates with whole numbers in exactly this way: \`/\` gives the result without the remainder, \`%\` gives only the remainder. + +| Primary school | with \`/\` | with \`%\` | +|---|---|---| +| 17 ÷ 5 = 3 remainder 2 | \`17 / 5\` gives 3 | \`17 % 5\` gives 2 | +| 20 ÷ 5 = 4 remainder 0 | \`20 / 5\` gives 4 | \`20 % 5\` gives 0 | +| 3 ÷ 5 = 0 remainder 3 | \`3 / 5\` gives 0 | \`3 % 5\` gives 3 | + +If the remainder is 0, the division works out exactly. Later you use this to check whether a number is even: for even numbers, \`number % 2\` is 0. + +**Multiplication and division come before addition and subtraction**, and brackets are worked out first: \`2 * (3 + 4)\` is 14. + +## Exercise: Rectangle + +::: übung l05-rechteck +titel: Work out a rectangle +auftrag: A rectangle is 7 long and 4 wide. Create the variables \`length\` and \`width\`. Calculate the area and the perimeter in variables of their own and output both, like this: +\`Area: 28\` and on the next line \`Perimeter: 22\`. +test: - -> Area: 28 | Perimeter: 22 +braucht: anweisung +tipp: First think about which variables you need: two for the measurements and two for the results. They are all whole numbers. +tipp: The area is length times width, the perimeter is 2 times (length plus width). For the output you write e.g. \`output: "Area: " + area\`. The \`+\` joins the text and the value of the variable together. +lösung: l05-rechteck-loesung.visustruct +::: + +## Whole-number division + +If you divide two whole numbers and store the result in an \`int\` variable, everything after the decimal point is dropped. It is **not rounded**. + +\`\`\` +int x = 7 / 2 gives 3 +int r = 7 % 2 gives 1 (the remainder) +double d = 7.0 / 2 gives 3.5 +\`\`\` + +With \`/\` and \`%\` together you can convert things nicely, for example minutes into hours and minutes: + +::: diagramm l05-division.visustruct +135 minutes are 2 hours (135 / 60) with 15 minutes left over (135 % 60). +::: + +## Exercise: Convert seconds + +::: übung l05-sekunden +titel: Convert seconds +auftrag: 200 seconds should be output as minutes and seconds. The first and the last statement are already there. Insert statements between them that calculate \`minutes\` and \`remainder\`. +start: l05-sekunden-start.visustruct +test: - -> 3 minutes and 20 seconds +braucht: anweisung +tipp: How many whole minutes fit into 200 seconds, and how many seconds are left over? Work it out in your head first. +tipp: A minute has 60 seconds. Use \`/\` for the whole minutes and \`%\` for the remainder. Both variables have the type \`int\`. +lösung: l05-sekunden-loesung.visustruct +::: + +## Exercise: Shopping + +::: übung l05-einkauf +titel: Shopping +auftrag: You buy 3 exercise books at 2.5 euros each. Create \`count\` as an \`int\` and \`price\` as a \`double\`, calculate the total price in a variable \`totalPrice\` and output \`Total: 7.5 euros\`. +test: - -> Total: 7.5 euros +braucht: anweisung +tipp: The count times the price gives the total price. For each variable, think about whether it is a whole number or a decimal number. +tipp: The total price is a decimal number, so \`totalPrice\` needs the type \`double\`. +lösung: l05-einkauf-loesung.visustruct +::: + +## Now in Java + +A structure chart is a plan. In **Java** it becomes a program that the computer runs. Your shopping from the exercise looks like this: + +\`\`\`java +int count = 3; +double price = 2.5; +double totalPrice = count * price; +System.out.println("Total: " + totalPrice + " euros"); +\`\`\` + +- First the data type, then the name, then the value, just like in the box. +- Every statement ends with a **semicolon** \`;\`. +- Output in Java is written \`System.out.println(…)\`. + +::: angeberwissen +Java was first called **Oak**, after the tree outside James Gosling’s office window. From 1991 his team at Sun Microsystems wanted to program small devices such as TV set-top boxes. But another company already had the name Oak. So in 1995 it became **Java**, like the coffee from the island of Java. That is why the logo is a steaming cup. +::: + +## Text in Java + +Variables do not only store numbers. For text there is the data type \`String\`: + +\`\`\`java editor +String name = "Mia"; +int age = 14; +double height = 1.62; +System.out.println(name + " is " + age + " years old."); +System.out.println("Height: " + height + " m"); +\`\`\` + +- Text goes in quotation marks. +- You write \`String\` with a capital letter, \`int\`, \`double\` and \`boolean\` in lowercase. Java tells them apart. +- With \`+\` you join text and numbers together. + +You type Java in the [Code](#zeige-codelive) area. The structure chart builds itself as you type. “Open in editor” brings the example into the Code area. Click “Run” there, then change the name, age or height and try again. + +::: übung l04-java-steckbrief +titel: Profile in Java +code: java +auftrag: Write a profile of Ludwig the billy goat. Create three variables: the name **Ludwig**, the age **7** and the height **1.2**. Then output these two lines: + **Ludwig is 7 years old.** and **Height: 1.2 m** + “Open in editor” also opens the Code area on the right. Type your code there; the structure chart builds itself. Then click Check. +test: - -> Ludwig is 7 years old. | Height: 1.2 m +braucht: anweisung +tipp: You need a \`String\`, an \`int\` and a \`double\`. Every line ends with a semicolon. +tipp: \`String name = "Ludwig";\`, \`int age = 7;\` and \`double height = 1.2;\`. You join the output with \`+\`: \`System.out.println(name + " is " + age + " years old.");\` +lösung: l04-java-steckbrief-loesung.visustruct +::: + +## Fill in the gaps: data types + +::: lückentext +titel: Profile in Java +auftrag: Fill in the missing words. On the outside is the frame that every Java program in its own file needs. The variables go inside it. +\`\`\`java +[[public]] class Profile { + public static [[void]] main(String[] args) { + [[int]] age = 14; + [[double]] height = 1.62; + [[String]] name = "Mia"; + [[boolean]] hasPet = true; + System.out.[[println]](name + " is " + age + " years old."); + } +} +\`\`\` +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”. +::: + +## Find the bug: seconds + +::: übung l04-java-fehler +titel: Fix the seconds +code: java +auftrag: The program should convert 200 seconds into minutes and seconds and output **3 min 20 s**. But it outputs **20 min 3 s**. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l04-java-fehler-start.visustruct +test: - -> 3 min 20 s +braucht: anweisung +tipp: \`/\` divides without a remainder, \`%\` gives the remainder. Which one do you need for the minutes, which one for the seconds left over? +tipp: The two operators are swapped: \`int minutes = seconds / 60;\` and \`int rest = seconds % 60;\` +lösung: l04-java-fehler-loesung.visustruct +::: + +## Game: Which data type? + +::: spiel frage +titel: Game: Which data type? +intro: Ludwig has collected values. Which data type fits each value? Eight rounds. +antworten: int | double | String | boolean + +runde: +frage: Which data type fits \`17\`? +richtig: int +> A whole number without a decimal point is an \`int\`. + +runde: +frage: Which data type fits \`3.5\`? +richtig: double +> Numbers with a decimal point are \`double\`. + +runde: +frage: Which data type fits \`"Hello"\`? +richtig: String +> Text in quotation marks is a \`String\`. + +runde: +frage: Which data type fits \`true\`? +richtig: boolean +> \`true\` and \`false\` are the two truth values, data type \`boolean\`. + +runde: +frage: Which data type fits \`"17"\`? +richtig: String +> Careful, quotation marks! Here 17 is a text you can't calculate with. + +runde: +frage: Which data type fits \`-4\`? +richtig: int +> Negative whole numbers are \`int\` as well. + +runde: +frage: Which data type fits \`0.0\`? +richtig: double +> The point makes it a decimal number, even if there is only a 0 behind it. + +runde: +frage: Which data type fits \`"false"\`? +richtig: String +> In quotation marks, false is just a text too. The truth value has no quotation marks. +::: + +## 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. + +::: checkliste +- I can create a variable with a data type, a name and a value. → What is a variable? +- I can tell the data types int, double, String and boolean apart. → The four data types +- I can explain that = is an assignment and not a comparison. → Assignment with = +- I can calculate with + - * / % and use whole-number division. → Calculating +- I can create and output variables in Java. → Now in Java +::: + +## Quiz + +::: quiz +? Which data type fits the value 3.75? +→ The four data types +- [ ] int +- [x] double +- [ ] String +- [ ] boolean +> Decimal numbers have the type double. In VisuStruct you write them with a point. + +? What value does x have after \`int x = 17 / 5\`? +→ Calculating +- [ ] 3.4 +- [x] 3 +- [ ] 4 +> With whole numbers, everything after the decimal point is dropped. It is not rounded. + +? What does \`17 % 5\` give? +→ Calculating +- [x] 2 +- [ ] 3 +- [ ] 3.4 +> 17 divided by 5 is 3, remainder 2. The operator % gives the remainder. + +? At the start, \`int points = 10\`. What is in points after \`points = points * 2\`? +→ Assignment with = +- [ ] 10 +- [ ] 12 +- [x] 20 +> The right-hand side is calculated with the old value 10, and the result 20 is stored in points. + +? Which line correctly creates a decimal number in Java? +→ Now in Java +- [ ] double price = 2,5; +- [x] double price = 2.5; +- [ ] Double price = 2.5 +> Decimal numbers use a point, and the line ends with a semicolon. +::: +`,r4=`--- +titel: Sequence +bereich: Basics +kurz: Run steps one after another, watch the order and swap values. +--- + +## Skills I will gain now + +::: kompetenzen +- explain that a sequence runs from top to bottom +- explain why the order of the steps matters +- swap two values with a temporary variable +- write a sequence in Java +::: + +## Step by step + +A **sequence** is a series of steps that run exactly once and in exactly this order. In the structure chart the boxes simply sit on top of each other. + +Each box only starts when the box above it is finished. Nothing is skipped and nothing is repeated. + +::: diagramm l05-sequenz.visustruct +A sequence of four boxes: first \`length\` and \`width\` get their values, then the area is calculated, and finally it is output. Each box runs exactly once, from top to bottom. Output: 15. +::: + +> The sequence is the simplest of the three basic building blocks. Almost every structure chart is mostly made of sequences. + +## Order matters + +When you make tea, you notice straight away if the order is wrong. With calculations it is just the same, only it is harder to spot. + +::: diagramm l04-rechnen.visustruct +First double, then add 1: the result is 7. If you swap the two middle boxes, you get 8. +::: + +The statement \`number = number * 2\` means: take the value of \`number\`, multiply it by 2 and store the result in \`number\` again. So what is in \`number\` depends on what happened before. + +::: angeberwissen +Structure charts are not just school stuff. According to Shneiderman, companies like IBM and Siemens planned their programs with them too. So you are learning pro stuff here. Baaa-mazing! +::: + +## Exercise: Put in order + +::: übung l04-reihenfolge +titel: Put in order +auftrag: The start diagram has the right boxes, but in the wrong order. Move them so that **20** is output at the end. +start: l04-reihenfolge-start.visustruct +test: - -> 20 +braucht: anweisung +tipp: Read each box and ask yourself: which variable does it need, and where does that variable get its value? +tipp: A variable has to be created before you calculate with it. The output comes right at the end. Check in your head: (2 + 3) · 4 = 20. +lösung: l04-reihenfolge-loesung.visustruct +::: + +## Swap two values + +Imagine two glasses: one with juice, one with water. If you want to swap what is in them, you need a third, empty glass. + +It is exactly the same with variables. If you simply write \`a = b\` and then \`b = a\`, the old value of \`a\` is already lost. In the end both variables have the same value. + +The solution is a **temporary variable** that keeps the old value for a short time: + +::: grafik l05-tauschen.svg +Three steps with an empty glass: first the juice into temp, then the water to the left, then the juice from temp to the right. +::: + +::: diagramm l04-tauschen.visustruct +First a is kept in temp. Then a gets the value of b, and b gets the kept value from temp. +::: + +## Exercise: Swap glasses + +::: übung l04-glaeser-tauschen +titel: Swap glasses +auftrag: The left glass holds juice, the right one water. Swap the contents of the variables \`left\` and \`right\` before they are output. +Do not change the first two boxes. Insert new statements between them instead. +start: l04-tauschen-start.visustruct +test: - -> Left: water | Right: juice +braucht: anweisung +tipp: How do you swap two full glasses in real life? You need a third, empty glass. +tipp: Create a temporary variable with \`String temp = left\`. After that you need two more assignments. +lösung: l04-tauschen-loesung.visustruct +::: + +## Now in Java + +As in lesson 4, you can also write a sequence directly in Java. The swap from above looks like this: + +\`\`\`java +int a = 5; +int b = 9; +int temp = a; +a = b; +b = temp; +System.out.println("a = " + a); +System.out.println("b = " + b); +\`\`\` + +- Every box becomes one line. The lines run from top to bottom, just like the boxes. +- Every statement ends with a **semicolon** \`;\`. +- An output is called \`System.out.println(…)\` in Java. Mind the capital S in \`System\`: Java tells upper and lower case apart. + +You type Java in the [Code](#zeige-codelive) area to the right of the structure chart. While you type, VisuStruct builds the structure chart along with it. So you see straight away which box belongs to which line. + +::: übung l05-java-kino +titel: Cinema tickets in Java +code: java +auftrag: A cinema ticket costs 9 euros. Write a Java program that calculates the price of 3 tickets and outputs **Total: 27**. + “Open in editor” also opens the Code area on the right. Type your code there; the structure chart builds itself. Then click Check. +test: - -> Total: 27 +braucht: anweisung +tipp: You need three variables: the price, the number of tickets and the result. Every line ends with a semicolon. +tipp: \`int price = 9;\` and \`int count = 3;\` create the variables. \`int total = price * count;\` calculates, and \`System.out.println("Total: " + total);\` outputs the result. +lösung: l05-java-kino-loesung.visustruct +::: + +## Fill in the gaps: swapping glasses + +::: lückentext +titel: Swap two values +auftrag: The values of \`a\` and \`b\` should be swapped. Fill in the missing words. +\`\`\`java +int a = 3; +int b = 8; +[[int]] temp = [[a]]; +a = [[b]]; +b = [[temp]]; +System.out.println("a = " + a + ", b = " + b); +\`\`\` +erklärung: First you save \`a\` in the helper variable, then \`a\` gets the value of \`b\`, and finally \`b\` gets the saved value. Output: **a = 8, b = 3** +::: + +## Find the bug: credit + +::: übung l05-java-fehler +titel: Fix the credit +code: java +auftrag: The canteen card holds 20 euros. A meal costs 7 euros. The program should output the credit **after** paying, so **Left: 13**. But it outputs **Left: 20**. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l05-java-fehler-start.visustruct +test: - -> Left: 13 +braucht: anweisung +tipp: All lines are right, only their order is not. When is the credit output, and when is the meal paid? +tipp: Swap the last two lines: first \`credit = credit - price;\`, then the output. +lösung: l05-java-fehler-loesung.visustruct +::: + +## Game: Sort the boxes + +::: spiel reihenfolge +titel: Game: Sort the boxes +intro: Ludwig has mixed up the boxes. Put them in the right order. Four rounds. + +runde: +frage: At the end, **7** should be output. +- \`int number = 3\` +- \`number = number * 2\` +- \`number = number + 1\` +- \`output: number\` +> First double, then add 1: 3 · 2 + 1 = 7. The other way round you'd get (3 + 1) · 2 = 8. + +runde: +frage: At the end, **8** should be output. +- \`int number = 3\` +- \`number = number + 1\` +- \`number = number * 2\` +- \`output: number\` +> The same boxes, a different order, a different result: (3 + 1) · 2 = 8. + +runde: + int a = 3 + int b = 5 +frage: a and b should swap their values. +- \`int temp = a\` +- \`a = b\` +- \`b = temp\` +- \`output: a + " " + b\` +> First a is saved in temp. Otherwise the old value is gone as soon as a gets the value of b. + +runde: +frage: Ludwig makes tea. +- Fill the kettle with water +- Switch the kettle on +- Wait until the water boils +- Pour the water over the tea bag +- Let the tea brew +> Every step needs the one before. Just like in a structure chart. +::: + +## 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. + +::: checkliste +- I can explain that a sequence runs from top to bottom. → Step by step +- I can explain why the order of the steps matters. → Order matters +- I can swap two values with a temporary variable. → Swap two values +- I can write a sequence in Java. → Now in Java +::: + +## Quiz + +::: quiz +? How often does each box of a sequence run? +→ Step by step +- [ ] Until a condition is false +- [x] Exactly once +- [ ] Not at all if it is empty +> In a sequence nothing is repeated and nothing is skipped. Loops are there for repetition. + +? At the start a = 5 and b = 9. Then \`a = b\` runs and after that \`b = a\`. What is in the variables at the end? +→ Swap two values +- [ ] a = 9 and b = 5 +- [x] a = 9 and b = 9 +- [ ] a = 5 and b = 5 +> After \`a = b\` the old value 5 is lost. \`b = a\` then only copies the 9 back. + +? Why do you need a temporary variable when swapping? +→ Swap two values +- [x] So that a value is not overwritten before it is needed +- [ ] So that the structure chart gets longer +- [ ] Because otherwise you cannot output variables + +? What does the sequence \`int x = 4\`, \`x = x + 1\`, \`x = x * 3\`, \`output: x\` output? +→ Order matters +- [ ] 13 +- [x] 15 +- [ ] 4 +> First x becomes 5, then 15. + +? What does every statement end with in Java? +→ Now in Java +- [ ] With a full stop . +- [x] With a semicolon ; +- [ ] With a colon : +> If the semicolon is missing, VisuStruct shows a hint below the code. +::: +`,o4=`--- +titel: Input and output +bereich: Basics +kurz: Ask for values, show results and use the IPO model. +--- + +## Skills I will gain now + +::: kompetenzen +- explain the IPO model +- write an input with a data type, a name and a question +- join text and variables in an output with + +- work out a result first and store it in a variable, then output that variable, e.g. \`int sum = a + b\`, then \`output: sum\` +- pick out input, process and output from a task +- read numbers in Java with the scanner +- write comments with \`//\` and \`/* */\` and use them to structure and explain my code +::: + +## The IPO model + +Many programs work in three parts: + +1. **Input:** The program asks for values, e.g. two numbers. +2. **Process:** It calculates with the values. +3. **Output:** It shows the result. + +The first letters give **IPO**. So far the values were fixed in the structure chart. With an input, a different value can be used every time the chart runs. + +::: diagramm l06-eva.visustruct +Input at the top, process in the middle, output at the bottom. Start the simulation and try different numbers. +::: + +## Input with input: + +An input asks for a value while the chart runs and stores it in a variable. You write the **data type**, the **name** and a **question** in quotation marks: + +\`\`\` +input: int age "How old are you?" +input: double price "Price in euros?" +input: String name "What is your name?" +\`\`\` + +In the editor you choose the kind **Input** at the top of a Statement. The word \`input:\` is then already in front, and you only type \`int age "How old are you?"\`. + +> The data type decides what may be typed in. With \`int\`, the simulation reports an error if someone types 2.5 or Hello. + +## Output with output: + +An output shows text and values. Text goes in quotation marks, variables do not. With \`+\` you **join** the parts together: + +\`\`\` +output: "Hello " + name + "!" +output: "You are " + age + " years old." +\`\`\` + +Watch out for the spaces inside the quotation marks. Without them everything sticks together, and you see \`HelloMia!\` instead of \`Hello Mia!\`. + +## Exercise: Greeting + +::: übung l06-begruessung +titel: Greeting +auftrag: Ask for a name and greet the person. When Ada is typed in, **Hello Ada!** should be output. +test: Ada -> Hello Ada! +test: Ben -> Hello Ben! +braucht: anweisung +tipp: First comes an input for the name, then an output that uses the name. +tipp: The name is text, so the input needs the type \`String\`. In the output you join \`"Hello "\`, the variable and \`"!"\` with \`+\`. +lösung: l06-begruessung-loesung.visustruct +::: + +## Careful with + in an output + +In an output, \`+\` **always** joins the parts together, even with numbers. If \`a\` is 3 and \`b\` is 4, then + +\`\`\` +output: a + b +\`\`\` + +does not show 7 but **34**. So calculate in a variable first and then output the variable: + +\`\`\` +int sum = a + b +output: "Sum: " + sum +\`\`\` + +That also fits the IPO model: you calculate in the process part, not in the output. + +## From the task to the structure chart + +Before you drag the first box, read the task carefully and take it apart. This is called **problem analysis**. Three questions help you: + +1. **What is given?** These values become the **input**. Also think about the data type. +2. **What are you looking for?** That becomes the **output**. +3. **How do you get from what is given to what you are looking for?** That is the **process**, often a formula. + +An example: *A cinema ticket costs 9 euros. The program asks how many tickets someone buys and shows the total price.* + +- Given: the number of tickets → \`input: int count "How many tickets?"\` +- Looking for: the total price → \`output: "Total price: " + total\` +- Way: count times 9 → \`int total = count * 9\` + +Now you only have to put the three parts on top of each other in the order I, P, O. + +> Look out for signal words in the task: *asks*, *reads in* or *enters* point to an input. *Shows*, *outputs* or *reports* point to an output. + +## Exercise: Calculator + +::: übung l06-rechner +titel: Sum and product +auftrag: Ask for two whole numbers. Then output their sum and their product, each on its own line. +With 3 and 4 it looks like this: \`Sum: 7\` and \`Product: 12\`. +test: 3, 4 -> Sum: 7 | Product: 12 +test: 10, -2 -> Sum: 8 | Product: -20 +test: 0, 5 -> Sum: 5 | Product: 0 +braucht: anweisung +tipp: Plan the order: first read in both numbers, then calculate, then output. +tipp: You need two inputs, two statements for calculating and two outputs. Calculate the sum in a variable of its own, otherwise \`+\` joins the numbers together. +lösung: l06-rechner-loesung.visustruct +::: + +## Exercise: Mean + +::: übung l06-mittelwert +titel: Mean +auftrag: Ask for two numbers, which may also be decimal numbers. Output their mean, so for 2 and 3 that is \`Mean: 2.5\`. +test: 2, 3 -> Mean: 2.5 +test: 4, 6 -> Mean: 5.0 +test: 1.5, 2 -> Mean: 1.75 +braucht: anweisung +tipp: You get the mean of two numbers by adding them and halving the result. +tipp: For decimal numbers you use the type \`double\`. The mean is the sum divided by 2. Remember the brackets: \`(x + y) / 2\`. +lösung: l06-mittelwert-loesung.visustruct +::: + +## Now in Java + +This is the IPO example from the start in Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("First number?"); +int a = scanner.nextInt(); +System.out.println("Second number?"); +int b = scanner.nextInt(); +int sum = a + b; +System.out.println("Sum: " + sum); +\`\`\` + +- For input, Java needs a **Scanner**. You write the first two lines once at the very top, then you can read as often as you like. +- \`scanner.nextInt()\` reads a whole number, \`scanner.nextDouble()\` a decimal number and \`scanner.next()\` a word. +- The question to the user is a normal output right before it. VisuStruct turns both lines together into one input box. + +::: angeberwissen +Java was originally meant to control small devices, and it still does: many SIM cards in phones and many bank cards run a mini version called **Java Card**. Quite possibly you have Java in your pocket right now. +::: + +::: übung l06-java-tage +titel: Age in days +code: java +auftrag: Write a Java program that asks for the age in years and outputs roughly how many days that is. Use 365 days per year. For 2 years it shows **That is about 730 days.** +test: 2 -> That is about 730 days. +test: 10 -> That is about 3650 days. +test: 1 -> That is about 365 days. +braucht: anweisung +tipp: First the two scanner lines, then the question and the input, then the calculation, then the output. +tipp: \`int years = scanner.nextInt();\` reads. \`int days = years * 365;\` calculates, and \`System.out.println("That is about " + days + " days.");\` outputs. +lösung: l06-java-tage-loesung.visustruct +::: + +## Comments in code + +You may write notes in your code. They are called **comments**. Java skips them when it runs, so the program and the structure chart stay the same. There are two kinds: + +- \`//\` turns the rest of the line into a comment. This is a **single-line comment**. +- \`/*\` starts a **multi-line comment** and \`*/\` ends it. Everything in between belongs to the comment, however many lines. Java does not need the stars at the start of the lines in between, they just look tidy. + +In finished programs you sometimes also see \`/** … */\` with two stars at the start. That is a **Javadoc comment**, from which Java can create a description of the program. For you, \`//\` and \`/* */\` are enough. + +This is the IPO example with comments: + +\`\`\`java editor +/* + * Task: The program asks for two numbers + * and outputs their sum. + */ +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +// Input +System.out.println("First number?"); +int a = scanner.nextInt(); +System.out.println("Second number?"); +int b = scanner.nextInt(); + +// Process +int sum = a + b; // add the two numbers + +// Output +System.out.println("Sum: " + sum); // for 3 and 4 I expect: Sum: 7 + +// Next time: allow decimal numbers too +\`\`\` + +What comments are good for: + +- **The task:** the multi-line comment at the top says what the program should do. +- **Structure:** \`// Input\`, \`// Process\` and \`// Output\` divide the code by the IPO model. +- **Explanation:** a comment after a line says what your algorithm does there. +- **Expectation:** write down which output you expect. When you test, you compare. +- **Matching brackets:** later you will meet blocks in curly brackets \`{ }\`. Then, for example, \`} // end for\` shows which bracket closes what. +- **Keeping your thoughts:** what do you need to remember when you carry on next time? + +Click **Open in editor**, change a comment or add a new one. The structure chart stays the same, and VisuStruct keeps your comments. + +> Don't put a comment after every line. Explain what your algorithm does and why, not every single character. + +::: angeberwissen +Both kinds are much older than Java: \`/* … */\` comes from the language PL/I from 1964, \`//\` from BCPL from 1967. Java inherited them via C and C++. +::: + +## Fill in the gaps: comments + +::: lückentext +titel: Add the comments +auftrag: Add the characters so that a multi-line comment with the task is at the top and the other two notes are single-line comments. +\`\`\`java +[[/*]] + * Task: The program converts euros to cents. + [[*/]] +int euros = 3; +[[//]] Process +int cents = euros * 100; +[[//]] Output, expected: 300 +System.out.println(cents); +\`\`\` +erklärung: \`/*\` opens the multi-line comment and \`*/\` closes it. \`//\` only lasts until the end of the line, so every note needs its own \`//\`. +::: + +## Fill in the gaps: input + +::: lückentext +titel: Read a name and an age +auftrag: Fill in the missing words so that the program reads a name and an age. +\`\`\`java +import java.util.[[Scanner]]; +Scanner scanner = [[new]] Scanner(System.[[in]]); + +System.out.println("What is your name?"); +[[String]] name = scanner.[[next]](); +System.out.println("How old are you?"); +int age = scanner.[[nextInt]](); +System.out.println("Hello " + name + ", next year you will be " + [[(age + 1)]] + "."); +\`\`\` +erklärung: \`scanner.next()\` reads a word, \`scanner.nextInt()\` a whole number. The brackets around \`age + 1\` matter: without them Java first appends \`age\` and then \`1\` to the text, and 14 would become **141**. +::: + +## Find the bug: sum + +::: übung l06-java-fehler +titel: Fix the sum +code: java +auftrag: The program reads two numbers and should output their sum. For 3 and 4, however, it shows **Sum: 34** instead of **Sum: 7**. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l06-java-fehler-start.visustruct +test: 3, 4 -> Sum: 7 +test: 10, 5 -> Sum: 15 +test: 0, 9 -> Sum: 9 +braucht: anweisung +tipp: Read the output from left to right: what is \`"Sum: " + a\`? And what happens when \`+ b\` comes after it? +tipp: Add brackets so that Java calculates first: \`System.out.println("Sum: " + (a + b));\` +lösung: l06-java-fehler-loesung.visustruct +::: + +## Game: What is output? + +::: spiel frage +titel: Game: What is output? +intro: Ludwig has built inputs and outputs. Predict what happens. Seven rounds. + +runde: + int a = 3 + int b = 4 + output: a + b +frage: What is output? +- 7 +- [x] 34 +- a + b +> In an output, \`+\` always joins the parts together, even numbers. + +runde: + int a = 3 + int b = 4 + int sum = a + b + output: "Sum: " + sum +frage: What is output? +- [x] Sum: 7 +- Sum: 34 +- Sum: sum +> The calculating happens before, in a variable. The output only joins text and result. + +runde: + input: String name "What is your name?" + output: "Hello" + name + "!" +frage: You type Mia. What is output? +- Hello Mia! +- [x] HelloMia! +- Hello name! +> The text \`"Hello"\` has no space at the end. That's why everything sticks together. + +runde: + input: int age "How old are you?" +frage: You type 2.5. What happens? +- age is 2. +- age is 2.5. +- [x] The simulation reports an error. +> The data type \`int\` only allows whole numbers. + +runde: + input: double price "Price in euros?" +frage: Which part of IPO does this box belong to? +- [x] Input +- Process +- Output +> \`input:\` asks for a value. That is the input. + +runde: + double mean = (a + b) / 2.0 +frage: Which part of IPO does this box belong to? +- Input +- [x] Process +- Output +> Here something is calculated. That is the process. + +runde: + output: "Mean: " + mean +frage: Which part of IPO does this box belong to? +- Input +- Process +- [x] Output +> \`output:\` shows the result. That is the output. +::: + +## 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. + +::: checkliste +- I can explain the IPO model. → The IPO model +- I can write an input with a data type, a name and a question. → Input with input: +- I can join text and variables in an output with +. → Careful with + in an output +- I can work out a result first and store it in a variable, then output that variable, e.g. \`int sum = a + b\`, then \`output: sum\`. → Careful with + in an output +- I can pick out input, process and output from a task. → From the task to the structure chart +- I can read numbers in Java with the scanner. → Now in Java +- I can write comments with \`//\` and \`/* */\` and use them to structure and explain my code. → Comments in code +::: + +## Quiz + +::: quiz +? What does IPO stand for? +→ The IPO model +- [x] Input, process, output +- [ ] Input, program, order +- [ ] Insert, paste, open +> Many programs first ask for values, process them and then show the result. + +? The variables a and b have the values 3 and 4. What does \`output: a + b\` show? +→ Careful with + in an output +- [ ] 7 +- [x] 34 +- [ ] a + b +> In an output, + joins the parts together. Calculate the sum in a variable first. + +? Which input fits if a price such as 4.99 should be typed in? +→ Input with input: +- [ ] input: int price "Price?" +- [x] input: double price "Price?" +- [ ] input: String "Price?" +> 4.99 is a decimal number, so double. Also, every input needs a variable name. + +? What does \`output: "Age: " + age\` show if age has the value 12? +→ Careful with + in an output +- [x] Age: 12 +- [ ] "Age: " + 12 +- [ ] Age: age + +? Task: *The program asks for the radius of a circle and shows its circumference.* Match each part of the text to where it belongs in the IPO model. +→ From the task to the structure chart += asks for the radius -> Input += circumference = 2 * 3.14 * radius -> Process += shows its circumference -> Output +> The radius is given, the circumference is what you are looking for. The formula connects the two. + +? What does \`scanner.nextInt()\` read? +→ Now in Java +- [x] A whole number +- [ ] A decimal number +- [ ] A whole sentence +> For decimal numbers there is \`scanner.nextDouble()\`, for a word \`scanner.next()\`. + +? What does Java do with a comment? +→ Comments in code +- [ ] It outputs it as text. +- [x] It skips it. +- [ ] It reports an error. +> Comments are notes for people. The program runs exactly the same with or without them. + +? Where does a comment that starts with \`/*\` end? +→ Comments in code +- [x] At \`*/\` +- [ ] At the end of the line +- [ ] At the next empty line +> That is why a comment with \`/*\` can span several lines. A comment with \`//\`, on the other hand, ends at the end of the line. +::: +`,l4=`--- +titel: Simulation and desk check +bereich: Basics +kurz: Run a structure chart step by step, work it out by hand and find mistakes. +--- + +## Skills I will gain now + +::: kompetenzen +- start the simulation, pause it, run single steps and stop it +- read the variables, the output and the last step during the simulation +- do a desk check by hand as a table +- find a mistake by comparing the values with what I expect +- follow Java code with Step and breakpoints +::: + +## Start the simulation + +Before branches and loops come along, you get to know your most important tool. From now on you can use the simulation to check every exercise yourself. + +With the [▶︎ Start simulation](#zeige-simulation) button on the right of the tools, VisuStruct runs your structure chart. While the simulation is running, you cannot edit the diagram. The same button is then called **■ End simulation**; it takes you back to editing. + +On the right, the **Controls** appear: + +- **Play** runs the diagram automatically, step by step. You set how long it waits between two steps under **Pause per step**. +- **Pause** stops for a moment. Then you carry on with Play or Step. +- **Step** runs exactly one step. That way you can watch calmly. +- **Stop** cancels and resets everything to the start. + +Open the following diagram in the editor and go through it with **Step**: + +::: diagramm sim-tausch.visustruct +The values of a and b are swapped. The variable temp keeps one value meanwhile. +::: + +## What the simulation shows + +- **Highlight:** One box in the diagram is coloured. With **Last step** it is the box that has just run. With **Next step** it is the box that comes next. +- **Input:** If the diagram asks for a value, you type it in here and confirm with **OK**. +- **Last Step:** Here you see what has just happened, e.g. \`a = 5 -> 5\` after the box \`a = b\`. On the left, the variables have already been replaced by their values; to the right of the arrow is the result. +- **Variables:** All variables with their current values. +- **Output:** Everything that was output with \`output:\`. + +If the [Code](#zeige-codelive) area is open on the right, the [console](#zeige-konsole) runs along there as well. It is cleared at the start and then shows output and input just as they would appear in the real program. + +At the end, **Simulation finished.** appears. If something goes wrong, the simulation stops on the faulty box and shows a message, e.g. **Unknown variable: total**. + +## The desk check + +In a **desk check** you play the computer yourself. You go through the structure chart with pen and paper and write down the values of the variables after every step. It is best to make a table: one column for the step, one for each variable and one for the output. + +For the diagram above, the table looks like this: + +| Step | a | b | temp | Output | +|---|---|---|---|---| +| \`int a = 3\` | 3 | – | – | | +| \`int b = 5\` | 3 | 5 | – | | +| \`int temp = a\` | 3 | 5 | 3 | | +| \`a = b\` | 5 | 5 | 3 | | +| \`b = temp\` | 5 | 3 | 3 | | +| \`output: "a = " + a\` | 5 | 3 | 3 | a = 5 | +| \`output: "b = " + b\` | 5 | 3 | 3 | b = 3 | + +Then compare your table with the simulation. Do the values under **Variables** match your row after every step? + +> A desk check is especially useful in tests. There you have no computer, but you can still show what your structure chart does. + +## Find mistakes + +If a structure chart outputs something wrong, do this: + +1. **Write down what you expect:** What should come out for a particular input? +2. **Run it step by step:** Start the simulation with **Step** and watch the variables. +3. **Find the spot:** Where does a value first differ from what you expected? That is exactly where the mistake is. + +Common mistakes in a sequence are: + +- The **order** is wrong: a variable is used before it has a value. +- A value is **overwritten** before it is needed. +- **Brackets** are missing: \`a + b / 2\` is not the same as \`(a + b) / 2\`. +- Two whole numbers are divided: \`7 / 2\` gives \`3\`, because with \`int\` everything after the decimal point is dropped. + +> Later, branches and loops come along. Then the simulation also shows you which path is taken and how often a loop runs. + +::: angeberwissen +On 9 September 1947 Grace Hopper’s team found a real moth stuck between two contacts in the Harvard Mark II computer. They taped it into the logbook and wrote: “First actual case of bug being found.” Today the moth is in a museum in Washington. +::: + +## Exercise: Fix the swap + +::: übung sim-tausch +titel: Fix the swap +auftrag: The structure chart should read in two numbers and output them swapped. So with 3 and 5, first **5** and then **3** should appear. But it outputs 5 twice. + Do a desk check or use **Step** and fix the mistake. +start: sim-tausch-start.visustruct +test: 3, 5 -> 5 | 3 +test: 1, 2 -> 2 | 1 +test: 7, 7 -> 7 | 7 +braucht: anweisung +tipp: Go through the diagram with **Step** and write down the values of a and b after every step. Where does the 3 disappear? +tipp: Look at a after the step \`a = b\`. Where did the old value of a go? Keep it in a temporary variable first, as in the example above. +lösung: sim-tausch-loesung.visustruct +::: + +## Exercise: Fix the cinema tickets + +::: übung sim-kino +titel: Fix the cinema tickets +auftrag: A cinema ticket costs 8.50 euros. The structure chart should ask for the number of tickets and output the total price, so for 2 tickets \`Total: 17.0\`. + Start the simulation. It stops with an error message. Find out why and fix the structure chart. +start: sim-kino-start.visustruct +test: 2 -> Total: 17.0 +test: 3 -> Total: 25.5 +test: 0 -> Total: 0.0 +braucht: anweisung +tipp: Read the error message of the simulation carefully. Which variable does it not know yet? +tipp: The simulation runs the boxes from top to bottom. Does total already have a value when the output comes? You can move boxes with the mouse. +lösung: sim-kino-loesung.visustruct +::: + +> If a simulation keeps running forever, click **Stop**. When you **Check** an exercise, VisuStruct stops by itself after a very large number of steps. + +## Now in Java + +You can run Java code step by step too. In the [Code](#zeige-codelive) area the tool for this is called the **debugger**: + +- Click a line number on the left. A red dot appears: that is a **breakpoint**. [▶︎ Run](#zeige-ausfuehren) pauses before this line. +- The [Step](#zeige-einzelschritt) button runs exactly one line, like **Step** in the simulation. +- Below the code you see the current value of every variable. That is your desk check, except that the computer writes it down for you. + +::: übung l07-java-pizza +titel: Fix the pizza order +code: java +auftrag: A pizza costs 8 euros, extra cheese 2 euros. For 3 pizzas with extra cheese the program should output **Total: 30**. But it outputs 14. + Go through the Java code with Step and watch \`total\`. Find the mistake and fix it in the code. +start: l07-java-pizza-start.visustruct +test: - -> Total: 30 +braucht: anweisung +tipp: What value is in \`total\` after the fourth line? Work out in your head what Java calculates first. +tipp: As in maths, multiplication comes before addition: \`price + cheese * count\` is \`8 + 6\`. Add brackets: \`(price + cheese) * count\`. +lösung: l07-java-pizza-loesung.visustruct +::: + +## Fill in the gaps: desk check + +::: lückentext +titel: What is in the variables? +auftrag: Do a desk check in your head. After each line, write down the value the variable has afterwards, and in the last line what is output. +\`\`\`java +int a = 5; +int b = 2; +a = a + b; // a is now [[7]] +b = a * 2; // b is now [[14]] +a = b - a; // a is now [[7]] +System.out.println(a + b); // output: [[21]] +\`\`\` +erklärung: Each line calculates with the values that are in the variables right now: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, output 7 + 14 = 21. You can check it with Step in the Code area. +::: + +## Find the bug: score + +::: übung l07-java-fehler +titel: Fix the score +code: java +auftrag: In a game Ludwig first gets 10 points, then 5 points, then he loses 3 points. At the end **Points: 12** should appear. But **Points: 3** appears. + Go through the code with Step and watch \`points\`. Fix the wrong line and click Check. +start: l07-java-fehler-start.visustruct +test: - -> Points: 12 +braucht: anweisung +tipp: After which line does \`points\` suddenly have the value 3? What should actually happen in that line? +tipp: Ludwig loses 3 points, so 3 is subtracted from the old value: \`points = points - 3;\` +lösung: l07-java-fehler-loesung.visustruct +::: + +## Game: Defuse the bomb + +::: spiel bombe +titel: Game: Defuse the bomb +intro: Every program contains **exactly one mistake**, and the bomb is ticking. Do the desk check in your head and tap the wrong line before time runs out. The programs are in Java, but every line is a box like in the structure chart. Six rounds, 30 seconds each. +zeit: 30 + +runde: + int a = 3; + int b = 5; + int temp = a; + a = b; + b = a; +frage: Should swap the values of a and b. +fehler: 5 +besser: b = temp; +> a already holds the value of b. The old value of a is in temp. + +runde: + int a = 4; + int b = 6; + double mean = a + b / 2; + System.out.println(mean); +frage: Should output the mean 5.0. +fehler: 3 +besser: double mean = (a + b) / 2.0; +> Without brackets the division comes first: 4 + 6 / 2 = 7. + +runde: + int tickets = 3; + double price = 8.5; + double total = tickets + price; + System.out.println("Total: " + total); +frage: Should output the price for 3 cinema tickets at €8.50 each. +fehler: 3 +besser: double total = tickets * price; +> For the total price you multiply, you don't add. + +runde: + int minutes = 135; + int hours = minutes / 60; + int rest = minutes / 60; + System.out.println(hours + " h " + rest + " min"); +frage: Should output 2 h 15 min. +fehler: 3 +besser: int rest = minutes % 60; +> \`%\` gives the remainder of a division. With \`/\` rest would hold a 2 as well. + +runde: + String name = "Ada"; + System.out.println("Hello " + "name" + "!"); +frage: Should output "Hello Ada!". +fehler: 2 +besser: System.out.println("Hello " + name + "!"); +> In quotation marks, name is just a text. The variable has no quotation marks. + +runde: + double price = 100; + price = price * 0.1; + System.out.println(price); +frage: Should raise the price by 10 %, so output 110.0. +fehler: 2 +besser: price = price + price * 0.1; +> Times 0.1 only gives the 10 %, so 10.0. That has to be added to the old price. +::: + +## 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. + +::: checkliste +- I can start the simulation, pause it, run single steps and stop it. → Start the simulation +- I can read the variables, the output and the last step during the simulation. → What the simulation shows +- I can do a desk check by hand as a table. → The desk check +- I can find a mistake by comparing the values with what I expect. → Find mistakes +- I can follow Java code with Step and breakpoints. → Now in Java +::: + +## Quiz + +::: quiz +? Which button runs exactly one step? +→ Start the simulation +- [ ] Play +- [x] Step +- [ ] Stop +> Play keeps going automatically, Step runs only one step. + +? What do you write down after every step in a desk check? +→ The desk check +- [ ] Only the output at the end +- [x] The current values of all variables +- [ ] The generated Java code +> That way you see exactly where a value is different from what you expected. + +? First \`int a = 3\`, then \`int b = 5\`, then \`a = b\`. What values do a and b have afterwards? +→ The desk check +- [ ] a = 5 and b = 3 +- [x] a = 5 and b = 5 +- [ ] a = 3 and b = 5 +> The old value of a has been overwritten. That is why you need a temporary variable when swapping. + +? The Last Step field shows \`price = 4 * 2.5 -> 10.0\`. What does that mean? +→ What the simulation shows +- [ ] The variable price now has the value 4. +- [x] 4 * 2.5 was worked out and the result 10.0 was stored in price. +- [ ] The simulation has found a mistake. + +? The simulation reports **Unknown variable: sum**. What is a likely reason? +→ Find mistakes +- [x] sum is used before it has been given a value. +- [ ] sum is too big. +- [ ] The structure chart has too many boxes. + +? What does a red dot in front of a line number in the Code area do? +→ Now in Java +- [ ] It marks an error. +- [x] The program pauses before this line. +- [ ] The line is skipped. +> That is a breakpoint. ▶︎ or Step carries on. +::: +`,u4=`--- +titel: Branch +bereich: Basics +kurz: Use a condition to decide which of two paths runs. +--- + +## Skills I will gain now + +::: kompetenzen +- explain that exactly one path of a branch runs +- use the comparison operators == != < <= > >= +- tell == and = apart +- build a branch with an empty path +- write a branch with if and else in Java +::: + +## If, then, else + +So far every box always ran. But often a program should **decide**: if a condition is met, do one thing, otherwise do the other. + +That is what the **branch** is for. The condition sits in the triangle at the top. Below it, the structure chart splits into two paths: + +- **true** (left): runs if the condition is true +- **false** (right): runs if the condition is false + +Always **exactly one** of the two paths runs. After that, the program continues below the branch. + +::: diagramm l07-alter-pruefen.visustruct +Depending on the age typed in, one message or the other appears. Try 17 and 18 in the simulation. +::: + +## Insert a branch + +Drag the **Branch** from the Elements area into the structure chart. Click the triangle and type the condition in the Object Inspector, e.g. \`age >= 18\`. The word \`if\` is already in front. + +Each path starts with a placeholder ø. Drag statements into it. A path may also hold several boxes on top of each other. + +## Comparison operators + +A condition is usually a **comparison**. Its result is always \`true\` or \`false\`. + +- \`==\` equal, e.g. \`number == 0\` +- \`!=\` not equal, e.g. \`answer != 42\` +- \`<\` less than, \`<=\` less than or equal +- \`>\` greater than, \`>=\` greater than or equal + +> Do not mix up \`==\` and \`=\`. A single \`=\` is an assignment and stores a value. To compare, you need two equals signs. + +With \`%\` you check whether a number can be divided by another: \`number % 2 == 0\` is true if \`number\` is even. + +## Exercise: Even or odd + +::: übung l07-gerade +titel: Even or odd +auftrag: Ask for a whole number. Output **even** if it is even, otherwise **odd**. +test: 4 -> even +test: 7 -> odd +test: 0 -> even +braucht: verzweigung +tipp: There are two possibilities here, so you need a branch. How do you recognise an even number? +tipp: A number is even if there is no remainder when you divide it by 2. The condition is \`number % 2 == 0\`. +lösung: l07-gerade-loesung.visustruct +::: + +## Exercise: The larger number + +::: übung l07-maximum +titel: The larger number +auftrag: Ask for two whole numbers and output only the larger one. If both are the same, output that number. +test: 3, 8 -> 8 +test: 9, 2 -> 9 +test: 5, 5 -> 5 +braucht: verzweigung +tipp: A branch compares the two numbers. Each path holds exactly one output. +tipp: Compare with \`a > b\`. In the true path you output \`a\`, in the false path \`b\`. +lösung: l07-maximum-loesung.visustruct +::: + +## An empty path + +Sometimes something should only happen if the condition is true, and otherwise nothing at all. Then the false path stays **empty**. In the structure chart it shows the placeholder **ø**. + +::: diagramm l07-rabatt.visustruct +From 50 euros on, you get 5 euros off. Otherwise nothing happens; the false path is empty. The output below runs in both cases. +::: + +## Exercise: Absolute value + +::: übung l07-betrag +titel: Absolute value of a number +auftrag: Ask for a whole number. If it is negative, make it positive. Then output the number. So -5 becomes 5, and 7 stays 7. +Use a branch with an empty path and only **one** output below the branch. +test: -5 -> 5 +test: 7 -> 7 +test: 0 -> 0 +test: -12 -> 12 +braucht: verzweigung +tipp: Only negative numbers need to be changed. What happens to a number if you multiply it by -1? +tipp: The condition is \`number < 0\`. In the true path you flip the sign, e.g. with \`number = 0 - number\`. The false path stays empty. +lösung: l07-betrag-loesung.visustruct +::: + +## Now in Java + +This is the age check from the start of this lesson in Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("How old are you?"); +int age = scanner.nextInt(); +if (age >= 18) { + System.out.println("You are an adult."); +} else { + System.out.println("You are not an adult yet."); +} +\`\`\` + +- The condition comes after \`if\` in **round brackets** \`( )\`. +- The true branch is in **curly brackets** \`{ }\`, the false branch follows after \`else\` in its own curly brackets. There is no semicolon after a curly bracket. +- If the false branch is empty, simply leave out \`else { }\`. +- Your program needs the first two lines once as soon as it reads input. After that, \`scanner.nextInt()\` reads a whole number. The question before it is a normal output. + +::: angeberwissen +Java has a mascot too: **Duke**, a little black-and-white fellow with a big red nose. He was drawn by the Java team in 1992 and has been waving from conferences and T-shirts ever since. Ludwig thinks a billy goat would have been a better fit. +::: + +::: übung l08-java-bestanden +titel: Passed in Java +code: java +auftrag: Write a Java program that asks for the number of points. From 50 points on it outputs **passed**, otherwise **not passed**. + Type the code in the Code area and then click Check. +test: 50 -> passed +test: 49 -> not passed +test: 100 -> passed +test: 0 -> not passed +braucht: verzweigung +tipp: Start with the two lines for the scanner. Then ask for the points, read them and compare them with \`if\`. +tipp: The condition is \`points >= 50\`. One branch has \`System.out.println("passed");\`, and after \`else\` comes \`System.out.println("not passed");\`. +lösung: l08-java-bestanden-loesung.visustruct +::: + +## Fill in the gaps: even or odd + +::: lückentext +titel: Even or odd +auftrag: Fill in the missing words and symbols. The program should output whether a number is even. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Which number?"); +int number = scanner.nextInt(); +[[if]] (number [[%]] 2 [[==]] 0) [[{]] + System.out.println("even"); +[[}]] [[else]] { + System.out.println("odd"); +} +\`\`\` +erklärung: \`number % 2\` is the remainder when dividing by 2. If it is 0, the number is even. To compare you need \`==\`, a single \`=\` is an assignment. Both branches are in curly brackets. +::: + +## Find the bug: admission + +::: übung l08-java-fehler +titel: Fix the admission +code: java +auftrag: At the zoo, children **under** 6 get in for free, everyone else pays 4 euros. But the program also lets six-year-olds in for free. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l08-java-fehler-start.visustruct +test: 5 -> Free entry +test: 6 -> 4 euros +test: 10 -> 4 euros +test: 0 -> Free entry +braucht: verzweigung +tipp: Try the program with 6. Which comparison operator still lets 6 through? +tipp: “Under 6” means \`age < 6\`. \`<=\` means “less than or equal to”. +lösung: l08-java-fehler-loesung.visustruct +::: + +## Game: Which way? + +::: spiel frage +titel: Game: Which way? +intro: Ludwig has written branches in Java. Work out the condition in your head and predict what is output. Seven rounds. + +runde: + int x = 5; + if (x > 5) { + System.out.println("big"); + } else { + System.out.println("small"); + } +frage: What is output? +- big +- [x] small +- nothing +> 5 > 5 is false, because 5 is not greater than 5. So the false branch. + +runde: + int x = 5; + if (x >= 5) { + System.out.println("big"); + } else { + System.out.println("small"); + } +frage: What is output? +- [x] big +- small +- big and small +> \`>=\` means "greater than or equal". 5 >= 5 is true. + +runde: + int number = 7; + if (number % 2 == 0) { + System.out.println("even"); + } else { + System.out.println("odd"); + } +frage: What is output? +- even +- [x] odd +- 1 +> 7 % 2 is the remainder 1, so not 0. The number is odd. + +runde: + int x = -4; + if (x < 0) { + x = -x; + } + System.out.println(x); +frage: What is output? +- -4 +- [x] 4 +- nothing +> -4 < 0 is true, so the sign is turned around. + +runde: + int x = 4; + if (x < 0) { + x = -x; + } + System.out.println(x); +frage: What is output? +- -4 +- [x] 4 +- nothing +> 4 < 0 is false. The false branch is empty, the program simply carries on below. + +runde: + int grade = 3; + if (grade != 3) { + System.out.println("different"); + } else { + System.out.println("three"); + } +frage: What is output? +- different +- [x] three +- nothing +> \`!=\` means "not equal". 3 != 3 is false. + +runde: + int a = 8; + int b = 12; + if (a > b) { + System.out.println(a); + } else { + System.out.println(b); + } +frage: What is output? +- 8 +- [x] 12 +- 20 +> The program outputs the bigger of the two numbers. +::: + +## 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. + +::: checkliste +- I can explain that exactly one path of a branch runs. → If, then, else +- I can use the comparison operators == != < <= > >=. → Comparison operators +- I can tell == and = apart. → Comparison operators +- I can build a branch with an empty path. → An empty path +- I can write a branch with if and else in Java. → Now in Java +::: + +## Quiz + +::: quiz +? Which path runs if the condition is false? +→ If, then, else +- [ ] The true path +- [x] The false path +- [ ] Both paths +- [ ] Neither, the program ends +> With false, the right path runs. After that, the program continues below the branch. + +? Which condition checks whether age is exactly 18? +→ Comparison operators +- [ ] age = 18 +- [x] age == 18 +- [ ] age >= 18 +> A single = is an assignment. To compare, you need ==. + +? What does ø in a path mean? +→ An empty path +- [x] Nothing happens in this case. +- [ ] The program ends here. +- [ ] The condition is false. + +? The condition is \`points >= 50\`. For which value is it true? +→ Comparison operators +- [ ] 49 +- [x] 50 +- [ ] 0 +> >= means greater than or equal. So 50 is included. + +? In textbooks the branch often has another name. Which one? +→ If, then, else +- [ ] Multiple selection +- [x] Conditional statement +- [ ] Iteration +> The statements in a path only run under a condition. That is why it is also called a conditional statement. + +? Where does the condition of a branch go in Java? +→ Now in Java +- [x] In round brackets right after if +- [ ] In curly brackets after else +- [ ] After a semicolon +> \`if (age >= 18) { … }\`: the round brackets belong to the condition, the curly ones to the branch. +::: +`,c4=`--- +titel: Combining conditions +bereich: Basics +kurz: Join several conditions with and, or and not, and check ranges of values. +--- + +## Skills I will gain now + +::: kompetenzen +- explain when a combination with && is true +- explain when a combination with || is true +- turn a condition round with ! +- check whether a value is in a range such as 1 to 6 +- read the truth table for &&, || and ! +- store the result of a condition in a boolean variable +- evaluate combined conditions confidently +- combine conditions in Java with && and || +::: + +## And: && + +Sometimes a single comparison is not enough. For example, you only get a youth ticket if you are **at least 12 and younger than 18**. + +With \`&&\` (and) you join two conditions. The result is only \`true\` if **both** conditions are true. + +::: diagramm l08-jugendticket.visustruct +Both comparisons must be right. Try 11, 12, 17 and 18 in the simulation. +::: + +## Or: || + +With \`||\` (or) the result is \`true\` if **at least one** of the conditions is true. Both may be true as well. + +\`\`\` +day == 6 || day == 7 +\`\`\` + +This condition is true if \`day\` has the value 6 or the value 7, so on Saturday or Sunday. + +> On many keyboards you type the vertical bar \`|\` with Shift and the backslash key. On a German keyboard it is AltGr and \`<\`, on a Mac Option and 7. + +## Exercise: Weekend + +::: übung l08-wochenende +titel: Weekend +auftrag: Ask for a day of the week as a number (1 is Monday, 7 is Sunday). Output **Weekend** if it is Saturday or Sunday, otherwise **Weekday**. +test: 6 -> Weekend +test: 7 -> Weekend +test: 1 -> Weekday +test: 5 -> Weekday +braucht: verzweigung +tipp: It is the weekend if the day is 6 **or** 7. For that you need two comparisons in one condition. +tipp: Saturday is 6, Sunday is 7. Join the two comparisons with \`||\`. +lösung: l08-wochenende-loesung.visustruct +::: + +## Check ranges of values + +In German schools, grades go from 1 (best) to 6. You check whether a grade is **in the range** with two comparisons and \`&&\`: + +\`\`\` +grade >= 1 && grade <= 6 +\`\`\` + +::: grafik l08-zahlenstrahl.svg +The green range from 1 to 6 is valid; both ends are included. +::: + +The other way round, a grade is **outside** the range if it is too small **or** too big: + +::: diagramm l08-note.visustruct +There is no grade smaller than 1 or bigger than 6. +::: + +> The way you write it in maths, \`1 <= grade <= 6\`, does not work. You have to split it into two comparisons and join them with \`&&\`. + +## Exercise: Valid grade + +::: übung l08-note-gueltig +titel: Valid grade +auftrag: Ask for a grade as a whole number. Output **valid** if it is between 1 and 6 (1 and 6 are included), otherwise **invalid**. +test: 1 -> valid +test: 6 -> valid +test: 3 -> valid +test: 0 -> invalid +test: 7 -> invalid +braucht: verzweigung +tipp: A valid grade has to meet two things at once: not too small **and** not too big. +tipp: The grade must be greater than or equal to 1 and at the same time less than or equal to 6. +lösung: l08-gueltig-loesung.visustruct +::: + +## Not and brackets + +With \`!\` (not) you turn a condition round: \`true\` becomes \`false\` and the other way round. + +\`\`\` +!(grade >= 1 && grade <= 6) +\`\`\` + +This is true if the grade is **not** in the range, and it means the same as \`grade < 1 || grade > 6\`. + +If \`&&\` and \`||\` appear together, \`&&\` is worked out first, just like multiplication before addition. It is better to use **brackets**; then it is clear what belongs together: + +\`\`\` +(age >= 12 && age < 18) || student == 1 +\`\`\` + +## The truth table + +A **truth table** shows at a glance what \`&&\`, \`||\` and \`!\` produce. On the left are all four possibilities for two conditions \`a\` and \`b\`, on the right the result: + +::: grafik l09-wahrheitstabelle.svg +Green is true, red is false. With && there is only one green row, with || only one red one. +::: + +Rules of thumb: + +- \`a && b\` is only true if **both** are true. +- \`a || b\` is only false if **both** are false. +- \`!a\` flips the value. + +::: angeberwissen +The data type \`boolean\` is named after **George Boole**. As early as 1847 this Englishman showed that you can calculate with true and false just like with numbers, almost a hundred years before the first computer existed. Today his logic is in every chip. +::: + +## Truth values in variables + +The result of a condition is a **truth value** of type \`boolean\`. You can store it in a variable just like a number and use it later: + +\`\`\` +boolean weekend = day == 6 || day == 7 +\`\`\` + +The branch then only says \`weekend\`. That reads almost like a sentence: "If weekend, then …". Don't write \`weekend == true\`, because \`weekend\` already is true or false. + +With \`!weekend\` you ask for the opposite, a weekday. + +::: ludwig +Long conditions become clearer when you put parts of them into boolean variables with meaningful names, for example \`boolean teenager = age >= 12 && age < 18\`. +::: + +## Game: True or false? + +Now it's your turn. Work out each condition in your head. After every answer you see how VisuStruct evaluates it step by step. + +::: spiel +age: 8..20 +day: 1..7 +grade: 0..7 +student: boolean +weekend: boolean +? age >= 18 +? day == 6 +? grade != 3 +? age >= 12 && age < 18 +? day == 6 || day == 7 +? student && weekend +? !student +? grade >= 1 && grade <= 6 +? !(age < 18) +? student || age >= 18 +? (age >= 12 && age < 18) || student +? !(grade >= 1 && grade <= 6) +? !weekend && day != 3 +? age >= 12 && age < 18 && !student +::: + +## Exercise: Leap year + +::: übung l08-schaltjahr +titel: Leap year +auftrag: A year is a leap year if it can be divided by 4 but not by 100. Years that can be divided by 400 are leap years anyway. +Ask for a year and output **Leap year** or **Not a leap year**. +test: 2024 -> Leap year +test: 2023 -> Not a leap year +test: 1900 -> Not a leap year +test: 2000 -> Leap year +braucht: verzweigung +tipp: Check the rule with examples first: 2024 is a leap year, 1900 is not, 2000 is. “Can be divided” means the remainder is 0. +tipp: Divisible by 4 means \`year % 4 == 0\`, not divisible by 100 means \`year % 100 != 0\`. Join these two with \`&&\`, put brackets around them and add the case for 400 with \`||\`. +lösung: l08-schaltjahr-loesung.visustruct +::: + +## Now in Java + +The youth ticket from the start looks like this in Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("How old are you?"); +int age = scanner.nextInt(); +if (age >= 12 && age < 18) { + System.out.println("Youth ticket"); +} else { + System.out.println("No youth ticket"); +} +\`\`\` + +The symbols \`&&\`, \`||\` and \`!\` are exactly the ones you already use in the structure chart. They come from Java. As always, the whole condition is in the round brackets after \`if\`. + +::: übung l09-java-schule +titel: School or free time +code: java +auftrag: Write a Java program that asks for the hour (0 to 23). From 8 up to and including 15 it outputs **School**, otherwise **Free time**. +test: 8 -> School +test: 15 -> School +test: 16 -> Free time +test: 7 -> Free time +braucht: verzweigung +tipp: The hour has to meet two conditions at the same time. Which operator means “and”? +tipp: \`if (hour >= 8 && hour <= 15) { … } else { … }\` +lösung: l09-java-schule-loesung.visustruct +::: + +## Fill in the gaps: conditions + +::: lückentext +titel: Grade and weekend +auftrag: Fill in the missing operators and words. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Which grade?"); +int grade = scanner.nextInt(); +if (grade >= 1 [[&&]] grade [[<=]] 6) { + System.out.println("valid grade"); +} else { + System.out.println("invalid grade"); +} +System.out.println("Which day (1 to 7)?"); +int day = scanner.nextInt(); +[[boolean]] weekend = day == 6 [[||]] day == 7; +if ([[!]]weekend) { + System.out.println("school day"); +} +\`\`\` +erklärung: A grade is valid when **both** conditions are true, so \`&&\`. It is the weekend when **one** of the two is true, so \`||\`. The result fits into a \`boolean\` variable, and \`!\` turns it around. +::: + +## Find the bug: no school + +::: übung l09-java-fehler +titel: Fix the day off +code: java +auftrag: The program should output **no school** for day 6 (Saturday) and day 7 (Sunday), otherwise **school**. But it always outputs **school**. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l09-java-fehler-start.visustruct +test: 6 -> no school +test: 7 -> no school +test: 3 -> school +test: 1 -> school +braucht: verzweigung +tipp: Can \`day\` be 6 **and** 7 at the same time? +tipp: It is enough if one of the two conditions is true: \`day == 6 || day == 7\`. +lösung: l09-java-fehler-loesung.visustruct +::: + +## 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. + +::: checkliste +- I can explain when a combination with && is true. → And: && +- I can explain when a combination with || is true. → Or: || +- I can turn a condition round with !. → Not and brackets +- I can check whether a value is in a range such as 1 to 6. → Check ranges of values +- I can read the truth table for &&, || and !. → The truth table +- I can store the result of a condition in a boolean variable. → Truth values in variables +- I can evaluate combined conditions confidently (at least 8 of 10 right in the game). → Game: True or false? +- I can combine conditions in Java with && and ||. → Now in Java +::: + +## Quiz + +::: quiz +? When is \`a && b\` true? +→ And: && +- [ ] If a or b is true +- [x] Only if a and b are both true +- [ ] If exactly one of them is true +> With && both parts must be right. If one is false, the whole thing is false. + +? The variable day has the value 6. What does \`day == 6 || day == 7\` give? +→ Or: || +- [x] true +- [ ] false +> With || it is enough if one side is true. + +? Which condition checks whether number is between 10 and 20 (both included)? +→ Check ranges of values +- [ ] 10 <= number <= 20 +- [ ] number >= 10 || number <= 20 +- [x] number >= 10 && number <= 20 +> With || every number would be allowed, because every number is greater than 10 or less than 20. + +? What does \`!(5 > 3)\` give? +→ Not and brackets +- [ ] true +- [x] false +> 5 > 3 is true, and ! turns that round. + +? How do you write “age is at least 12 and less than 18” in Java? +→ Now in Java +- [ ] if (12 <= age < 18) +- [x] if (age >= 12 && age < 18) +- [ ] if (age >= 12 || age < 18) +> Each comparison stands on its own, joined with \`&&\`. +::: +`,m4=`--- +titel: Switch +bereich: Basics +kurz: Run one of many cases, depending on the value of a variable. +--- + +## Skills I will gain now + +::: kompetenzen +- insert a switch, add cases and change case names +- explain when the case default runs +- decide whether a switch or a branch fits better +- write a case selection in Java with switch +::: + +## Many possibilities, one variable + +A drinks machine has three buttons: 1 for water, 2 for juice, 3 for cocoa. With branches you need three boxes nested inside each other. That quickly gets wide and confusing. + +::: diagramm l09-verschachtelt.visustruct +The machine with three nested branches. Each branch checks the same variable choice again. +::: + +Whenever you compare **one variable** with **several fixed values**, there is an easier way: the **switch**. + +## How a switch is built + +At the top of the box is the variable that decides. Below it there is a column of its own for every case. Above each column is the value it belongs to. + +::: diagramm l09-automat.visustruct +The same machine as a switch. If choice has the value 2, only column 2 runs. +::: + +- The simulation looks for the case whose name matches the value exactly. +- If no case matches, **default** runs. This case is always on the far right. +- After that, the program continues below the switch. Only **one** case ever runs. + +> A new switch has the cases 1, 2 and default. Click a case to change its **Case name** in the Object Inspector. With **Add Case** you get a new column in front of default. + +## Cases with text + +The cases do not have to be numbers. You can also choose by the content of a \`String\` variable. Then you write the text as the case name, for example \`red\`. + +::: diagramm l09-ampel.visustruct +A traffic light: depending on the colour typed in, a different message appears. In the simulation, also try a colour that does not exist. +::: + +Upper and lower case matter: \`Red\` does not match the case \`red\`. + +## Exercise: Grade in words + +::: übung l09-note +titel: Grade in words +auftrag: Ask for a grade as a whole number and output it in words: 1 very good, 2 good, 3 satisfactory, 4 sufficient, 5 poor, 6 fail. + For any other number, **Not a valid grade** should appear. +test: 1 -> very good +test: 4 -> sufficient +test: 6 -> fail +test: 9 -> Not a valid grade +braucht: fallauswahl +tipp: For many fixed values, a switch is clearer than lots of branches. Every grade gets a case of its own. +tipp: Keep using “Add Case” until you have the cases 1 to 6 and default. At the top of the switch you write \`grade\`. +lösung: l09-note-loesung.visustruct +::: + +## Exercise: Calculator + +::: übung l09-rechner +titel: Calculator +auftrag: Ask, one after another, for a whole number \`a\`, an operator as a \`String\` and a second whole number \`b\`. + For \`+\`, \`-\` and \`*\` you output the result. For any other sign, **Unknown operator** appears. +test: 3, +, 4 -> 7 +test: 10, -, 4 -> 6 +test: 6, *, 7 -> 42 +test: 1, x, 2 -> Unknown operator +braucht: fallauswahl +tipp: First read in all three values. After that, a switch on the operator decides what is calculated. +tipp: Before the switch, create \`int result = 0\`. In each case you calculate, for example, \`result = a + b\` and then output \`result\`. The case names are simply \`+\`, \`-\` and \`*\`. +lösung: l09-rechner-loesung.visustruct +::: + +## Switch or branch? + +The switch only checks whether a value is **exactly equal** to a case name. So: + +- **Switch:** one variable, several fixed values. Examples: choosing from a menu, day of the week as a number, grades. +- **Branch:** ranges and combined conditions. Examples: \`age >= 18\`, \`temperature < 0 || temperature > 30\`. + +So for “age 18 or older” you still need the branch. You cannot create a case of its own for every possible age. + +## Now in Java + +The drinks machine looks like this in Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("1 water, 2 juice, 3 cocoa"); +int choice = scanner.nextInt(); +switch (choice) { + case 1 -> { + System.out.println("Here is your water."); + } + case 2 -> { + System.out.println("Here is your juice."); + } + case 3 -> { + System.out.println("Here is your cocoa."); + } + default -> { + System.out.println("This button does not exist."); + } +} +\`\`\` + +- After \`switch\`, the variable being compared is in round brackets. +- Every case starts with \`case\`, the value and an arrow \`->\`. After it, curly brackets hold what should happen. +- \`default\` is the otherwise case. It runs when no value matches. + +::: angeberwissen +The arrow \`case 1 ->\` has only existed in Java since 2020 (Java 14). Before that you wrote \`case 1:\` and had to end every case with \`break;\`. If you forgot it, the program simply ran on into the next case. So the arrow has saved a lot of programmers a lot of trouble. +::: + +::: übung l10-java-wuerfel +titel: Dice in words +code: java +auftrag: Write a Java program with \`switch\` that reads a number. For 1 it outputs **one**, for 2 **two**, for 3 **three** and otherwise **unknown**. +test: 1 -> one +test: 2 -> two +test: 3 -> three +test: 7 -> unknown +braucht: fallauswahl +tipp: You need three \`case\` branches and one \`default\` branch. +tipp: \`switch (number) { case 1 -> { System.out.println("one"); } … default -> { System.out.println("unknown"); } }\` +lösung: l10-java-wuerfel-loesung.visustruct +::: + +## Fill in the gaps: switch + +::: lückentext +titel: Months in words +auftrag: Fill in the missing words and symbols of the case selection. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Which month (1 to 3)?"); +int month = scanner.nextInt(); +[[switch]] (month) { + [[case]] 1 -> { + System.out.println("January"); + } + case 2 [[->]] { + System.out.println("February"); + } + [[case]] 3 -> { + System.out.println("March"); + } + [[default]] -> { + System.out.println("Unknown"); + } +} +\`\`\` +erklärung: After \`switch\` the variable is in round brackets. Each case starts with \`case\`, the value and the arrow \`->\`. \`default\` runs when no case matches. +::: + +## Find the bug: calculator + +::: übung l10-java-fehler +titel: Fix the calculator +code: java +auftrag: The calculator reads two numbers and a choice: 1 plus, 2 minus, 3 times. For 7, 3 and choice 2 the result should be **4**, but it calculates **-4**. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l10-java-fehler-start.visustruct +test: 7, 3, 2 -> 4 +test: 7, 3, 1 -> 10 +test: 7, 3, 3 -> 21 +test: 7, 3, 5 -> Not an option +test: 10, 4, 2 -> 6 +braucht: fallauswahl +tipp: Plus and times are right. Take a close look at \`case 2\`. +tipp: With minus the order matters: \`a - b\` instead of \`b - a\`. +lösung: l10-java-fehler-loesung.visustruct +::: + +## Game: Which case? + +::: spiel frage +titel: Game: Which case? +intro: Ludwig presses buttons on the drinks machine and other case selections. What happens? Six rounds. + +runde: + int choice = 2; + switch (choice) { + case 1 -> { System.out.println("water"); } + case 2 -> { System.out.println("juice"); } + case 3 -> { System.out.println("cocoa"); } + default -> { System.out.println("There is no such button."); } + } +frage: What is output? +- water +- [x] juice +- There is no such button. +> choice is 2, so exactly \`case 2\` runs. + +runde: + int choice = 4; + switch (choice) { + case 1 -> { System.out.println("water"); } + case 2 -> { System.out.println("juice"); } + case 3 -> { System.out.println("cocoa"); } + default -> { System.out.println("There is no such button."); } + } +frage: What is output? +- cocoa +- nothing +- [x] There is no such button. +> No case fits 4, so \`default\` runs. + +runde: + String day = "monday"; + switch (day) { + case "Monday" -> { System.out.println("maths"); } + case "Tuesday" -> { System.out.println("sports"); } + default -> { System.out.println("free"); } + } +frage: What is output? +- maths +- sports +- [x] free +> With texts every letter counts: "monday" with a small m is not "Monday". + +runde: + int grade = 0; + switch (grade) { + case 1 -> { System.out.println("very good"); } + case 2 -> { System.out.println("good"); } + case 3 -> { System.out.println("satisfactory"); } + } +frage: What is output? +- very good +- [x] nothing +- satisfactory +> No case fits, and there is no \`default\`. Then simply nothing happens. + +runde: +frage: You want to check whether \`age >= 18\`. What fits better? +- [x] a branch +- a case selection +> A case selection only compares with fixed values. For "greater than or equal" you need a branch. + +runde: +frage: A dice shows 1 to 6, and for every number a different word should appear. What fits better? +- a branch +- [x] a case selection +> One variable, six fixed values: that's exactly what the case selection is for. +::: + +## 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. + +::: checkliste +- I can insert a switch, add cases and change case names. → How a switch is built +- I can explain when the case default runs. → How a switch is built +- I can decide whether a switch or a branch fits better. → Switch or branch? +- I can write a case selection in Java with switch. → Now in Java +::: + +## Quiz + +::: quiz +? The variable day has the value 5. There are the cases 1, 2, 3 and default. What runs? +→ How a switch is built +- [ ] Nothing at all +- [ ] The case 3 +- [x] The case default +> No case name matches 5, so default applies. + +? How many cases run each time the switch runs? +→ How a switch is built +- [x] Exactly one +- [ ] All cases from the matching one on +- [ ] All cases +> After the matching case, the program continues straight below the switch. + +? What is a switch NOT suitable for? +→ Switch or branch? +- [ ] Choosing menu item 1, 2 or 3 +- [x] Checking whether a temperature is above 30 degrees +- [ ] Handling a colour such as red, yellow or green +> “Above 30” is a range. For that you need a branch with a comparison. + +? At the traffic light you type \`Red\`, and the case is called \`red\`. What happens? +→ How a switch is built +- [ ] The case red runs. +- [x] The case default runs. +- [ ] The simulation reports an error. +> Upper and lower case matter. Red and red are different texts. + +? Under which name do you also find the switch in textbooks? +→ How a switch is built +- [ ] Conditional statement +- [ ] Sequence +- [x] Multiple selection +> One of many cases is selected. That is why it is also called multiple selection. + +? What is the otherwise case of a switch called in Java? +→ Now in Java +- [ ] else +- [x] default +- [ ] case 0 +::: +`,d4=`--- +titel: While loop +bereich: Basics +kurz: Repeat steps as long as a condition is true. +--- + +## Skills I will gain now + +::: kompetenzen +- explain that the while loop checks its condition before every pass +- use a counter variable with a start value, a condition and a change +- notice when a loop never ends and fix the mistake +- follow a loop pass by pass in a desk check +- write a while loop in Java +::: + +## Repeat as long as something holds + +Often a program should do something several times. Instead of writing the same box five times, you use a **loop**. + +The **while loop** repeats its inside **as long as** its condition is true. The condition is at the top, in the head of the box. The inside is indented below it, framed by a bracket on the left. + +::: diagramm l10-countdown.visustruct +A countdown: as long as number is greater than 0, number is output and gets smaller by 1. After that, Start! appears. +::: + +## The condition comes first + +The while loop is a **pre-test loop**. Before **every** pass, the condition is checked: + +1. Check the condition. +2. If it is true, run the inside once and start again at 1. +3. If it is false, the program continues below the loop. + +::: grafik l10-kopfgesteuert.svg +After every pass it goes back to the condition. Only when it is false does the program continue below the loop. +::: + +In the countdown the condition is checked four times: with 3, 2 and 1 it is true, with 0 it is false. + +> If the condition is already false the first time it is checked, the inside runs **not even once**. Start the countdown with \`int number = 0\` and only Start! appears. + +## A counter variable + +Many loops count along. For that you need three things: + +- **A start value before the loop**, e.g. \`int i = 1\` +- **A condition in the head**, e.g. \`i <= 5\` +- **A change inside**, e.g. \`i = i + 1\` (short: \`i++\`) + +If one of these parts is missing, the loop counts wrongly or not at all. + +::: angeberwissen +Counting loops are ancient! In their 1973 article, Nassi and Shneiderman showed their idea using the **factorial**, among other things: 5! = 1 · 2 · 3 · 4 · 5 = 120. Here is my goat version of it. Try it with **Step** in the simulation and watch \`factorial\` grow. Baaah, that goes fast! +::: + +::: diagramm l10-fakultaet.visustruct +The factorial with a counter variable \`i\`, rebuilt from an example in the 1973 article. +::: + +## Exercise: Count to n + +::: übung l10-bis-n +titel: Count to n +auftrag: Ask for a whole number \`n\` and output all numbers from 1 to \`n\`, each on its own line. +test: 3 -> 1 | 2 | 3 +test: 5 -> 1 | 2 | 3 | 4 | 5 +test: 1 -> 1 +braucht: whileSchleife +tipp: You need a counter variable that starts at 1 and grows by 1 in every pass. +tipp: Before the loop, create \`int i = 1\`. The condition is \`i <= n\`. Inside, you output \`i\` and then increase \`i\` by 1. +lösung: l10-bis-n-loesung.visustruct +::: + +## Watch out: endless loop + +If nothing inside the loop changes the condition, it stays true forever. The loop never stops. This is called an **endless loop**. + +::: diagramm l10-endlos.visustruct +Here number = number - 1 is missing. The loop outputs 3 again and again and never reaches Start! +::: + +Ask yourself for every loop: **What inside makes sure that the condition becomes false at some point?** When an exercise is checked, VisuStruct stops after a very large number of steps and reports a possible endless loop. + +## Exercise: Double up to 100 + +::: übung l10-verdoppeln +titel: Double up to 100 +auftrag: Ask for a whole number. Keep doubling it until it is at least 100. + At the end, output **how often** you doubled it. +test: 10 -> 4 +test: 30 -> 2 +test: 1 -> 7 +test: 100 -> 0 +braucht: whileSchleife +tipp: The loop runs as long as the number is still too small. Count along how often it has run. +tipp: You need a second variable \`int steps = 0\`. The condition is \`number < 100\`. Inside, you double the number with \`number = number * 2\` and increase \`steps\` by 1. If the number is already 100, the loop does not run at all. +lösung: l10-verdoppeln-loesung.visustruct +::: + +## Loops in a desk check + +With a loop, the **desk check** is especially valuable. You see exactly how often the loop runs and with which value it stops. Every check of the condition gets a row of its own. + +::: diagramm l16-schreibtisch.visustruct +A while loop adds up the numbers 1, 2 and 3. +::: + +| Step | sum | i | Output | +|---|---|---|---| +| \`int sum = 0\` | 0 | – | | +| \`int i = 1\` | 0 | 1 | | +| \`i <= 3\` → true | 0 | 1 | | +| \`sum = sum + i\` | 1 | 1 | | +| \`i = i + 1\` | 1 | 2 | | +| \`i <= 3\` → true | 1 | 2 | | +| \`sum = sum + i\` | 3 | 2 | | +| \`i = i + 1\` | 3 | 3 | | +| \`i <= 3\` → true | 3 | 3 | | +| \`sum = sum + i\` | 6 | 3 | | +| \`i = i + 1\` | 6 | 4 | | +| \`i <= 3\` → false | 6 | 4 | | +| \`output: sum\` | 6 | 4 | 6 | + +Common mistakes in loops are: + +- The loop runs **once too often or once too few**, e.g. \`<\` instead of \`<=\`. +- A variable is **not changed** in the loop, or changed in the wrong direction. Then the loop never ends. +- A variable gets its start value **inside** the loop instead of before it and is reset in every pass. + +## Exercise: Fix the countdown + +::: übung l16-countdown +titel: Fix the countdown +auftrag: The countdown should count down from the start value and output **Go!** at the end. So with 3: 3, 2, 1, Go! + The start diagram has two mistakes. Find and fix both. +start: l16-countdown-start.visustruct +test: 3 -> 3 | 2 | 1 | Go! +test: 1 -> 1 | Go! +test: 0 -> Go! +tipp: There are two mistakes. One is about counting, the other about the output at the end. +tipp: Start the simulation with start value 3 and watch i under Variables. Does i get smaller? Also compare the last output carefully with the task. +lösung: l16-countdown-loesung.visustruct +::: + +## Now in Java + +The countdown from the start of this lesson looks like this in Java: + +\`\`\`java +int number = 3; +while (number > 0) { + System.out.println(number); + number = number - 1; +} +System.out.println("Start!"); +\`\`\` + +- After \`while\` the condition is in round brackets, as with \`if\`. +- Everything that is repeated is in curly brackets. That is the body of the loop. +- The body is indented. As in the structure chart, you can see what belongs to the loop. + +::: übung l11-java-gerade +titel: Even numbers in Java +code: java +auftrag: Write a Java program that reads a whole number \`n\` and uses a while loop to output all even numbers from 2 up to at most \`n\`. For 7 that is 2, 4 and 6. +test: 7 -> 2 | 4 | 6 +test: 8 -> 2 | 4 | 6 | 8 +test: 2 -> 2 +braucht: whileSchleife +tipp: You need a counter variable that starts at 2. The loop runs as long as it is not greater than \`n\`. +tipp: \`int number = 2;\` before the loop, then \`while (number <= n) { … }\`. In the body you output \`number\` and increase it with \`number = number + 2;\`. +lösung: l11-java-gerade-loesung.visustruct +::: + +## Fill in the gaps: while + +::: lückentext +titel: Sum from 1 to 10 +auftrag: The program should add up the numbers from 1 to 10. Fill in the missing words and symbols. +\`\`\`java +int sum = 0; +int number = 1; +[[while]] (number [[<=]] 10) [[{]] + sum = sum + [[number]]; + [[number]] = number + 1; +} +System.out.println("Sum: " + sum); +\`\`\` +erklärung: The loop runs as long as \`number\` is at most 10. In each pass \`number\` is added to the sum, then \`number\` goes up by 1. Without that line it would be an endless loop. Output: **Sum: 55** +::: + +## Find the bug: saving + +::: übung l11-java-fehler +titel: Fix the savings plan +code: java +auftrag: Ludwig saves 5 euros every week. The program asks for the savings goal and should output after how many weeks he has reached it. For 50 euros that is 10 weeks, but the program says **Weeks: 11**. + Go through the code with Step and watch \`money\` and \`weeks\`. Fix the bug and click Check. +start: l11-java-fehler-start.visustruct +test: 50 -> Weeks: 10 +test: 12 -> Weeks: 3 +test: 5 -> Weeks: 1 +test: 1 -> Weeks: 1 +braucht: whileSchleife +tipp: How much money does Ludwig have when the loop runs for the last time? Does he really need to save for another week? +tipp: He only saves as long as the goal has **not been reached** yet: \`while (money < goal)\`. +lösung: l11-java-fehler-loesung.visustruct +::: + +## Game: How often? + +::: spiel frage +titel: Game: How often? +intro: Ludwig has written while loops. Do the desk check in your head. Six rounds. + +runde: + int number = 3; + while (number > 0) { + System.out.println(number); + number = number - 1; + } + System.out.println("Go!"); +frage: What is output? +- [x] 3\\n2\\n1\\nGo! +- 3\\n2\\n1\\n0\\nGo! +- Go! +> When number is 0, \`number > 0\` is false, so the 0 is not output any more. + +runde: + int i = 10; + while (i < 5) { + System.out.println(i); + i = i + 1; + } +frage: What is output? +- [x] nothing +- 10 +- 10 to 4 +> The condition is checked first. 10 < 5 is false, the body doesn't run even once. + +runde: + int i = 1; + while (i <= 3) { + System.out.println(i); + } +frage: What happens? +- 1, 2 and 3 are output. +- [x] The loop never stops. +- Nothing is output. +> i never gets bigger in the body. The condition always stays true: an endless loop. + +runde: + int number = 1; + while (number < 100) { + number = number * 2; + } + System.out.println(number); +frage: What is output? +- 64 +- 100 +- [x] 128 +> 1, 2, 4, 8, 16, 32, 64, 128. Only at 128 is \`number < 100\` false. + +runde: + int i = 0; + while (i < 5) { + i = i + 2; + } + System.out.println(i); +frage: What is output? +- 4 +- 5 +- [x] 6 +> i runs 0, 2, 4, 6. At 6, \`i < 5\` is false. The 5 is skipped. + +runde: + int i = 1; + while (i <= 10) { + i = i + 3; + } +frage: How often does the body run? +- 3 times +- [x] 4 times +- 10 times +> The body runs at i = 1, 4, 7 and 10. After that i is 13. +::: + +## 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. + +::: checkliste +- I can explain that the while loop checks its condition before every pass. → The condition comes first +- I can use a counter variable with a start value, a condition and a change. → A counter variable +- I can notice when a loop never ends and fix the mistake. → Watch out: endless loop +- I can follow a loop pass by pass in a desk check. → Loops in a desk check +- I can write a while loop in Java. → Now in Java +::: + +## Quiz + +::: quiz +? What does pre-test loop mean? +→ The condition comes first +- [x] The condition is checked before every pass. +- [ ] The condition is checked after every pass. +- [ ] The loop always runs exactly once. +> The head with the condition is at the top and is worked out first. + +? \`int i = 5\`, then a while loop with the condition \`i < 3\`. How often does the inside run? +→ The condition comes first +- [x] Not at all +- [ ] Once +- [ ] Three times +> The very first time it is checked, 5 < 3 is false. + +? Why does a loop with the condition \`number > 0\` never end if the inside only contains \`output: number\`? +→ Watch out: endless loop +- [ ] Because output makes the number bigger +- [x] Because number never changes and the condition stays true +- [ ] Because the condition is written wrongly +> Something has to happen inside that makes the condition false at some point. + +? What else are loops called in textbooks? +→ The condition comes first +- [x] Iteration or repetition +- [ ] Branches +- [ ] Subprograms +> A loop repeats statements. That is why it is also called iteration or repetition. + +? A loop should count from 1 to 5, but it only goes up to 4. What is the likely mistake? +→ A counter variable +- [x] The condition says i < 5 instead of i <= 5. +- [ ] The loop is a while loop. +- [ ] The variable i has the wrong name. + +? Which line starts a while loop correctly in Java? +→ Now in Java +- [ ] while number > 0 { +- [x] while (number > 0) { +- [ ] while (number > 0); +> The condition is in round brackets, then \`{\` opens the body. +::: +`,h4=`--- +titel: Do-while loop +bereich: Basics +kurz: Run first, check afterwards: loops with at least one pass. +--- + +## Skills I will gain now + +::: kompetenzen +- explain that the do-while loop only checks its condition after the inside +- explain why the inside runs at least once +- repeat an input until it is valid +- write a do-while loop in Java +::: + +## Do first, check afterwards + +The **do-while loop** is a **post-test loop**. The condition is at the bottom, in the foot of the box. This is how it runs: + +1. Run the inside once. +2. Check the condition. +3. If it is true, start again at 1. If it is false, the program continues below the loop. + +::: grafik l11-vergleich.svg +On the left, the while loop checks first; on the right, the do-while loop runs first. +::: + +At the top of the box is \`do\`, and the condition is in the foot. When you click the loop, the word \`while\` is in front of the text field in the Object Inspector: the condition means “repeat as long as …”. + +> Just like with the while loop, the condition says **when the loop repeats**. As long as it is true, the loop keeps running. + +::: angeberwissen +Python has no do-while loop at all. If you want “do first, check later” there, you write \`while True:\` and leave the loop with \`break\`. Java, C and JavaScript, on the other hand, have had \`do … while\` for decades. +::: + +## At least one pass + +Because the condition is only checked at the end, the inside **always runs at least once**. That is the most important difference from the while loop. + +::: diagramm l11-einmal.visustruct +i is 10 and so it is not less than 5. Still, 10 is output once, because the check only comes afterwards. +::: + +With a while loop and the same condition \`i < 5\`, nothing at all would be output here. + +## Typical use: repeat an input + +The do-while loop fits whenever something has to happen first before you can check it. The best example is an input: only after someone has typed something do you know whether it is valid. + +::: diagramm l11-eingabe-pruefen.visustruct +The question comes again until a number from 1 to 10 has been typed in. In the simulation, first try 0 and then 12. +::: + +Here the condition describes the **invalid** input: \`number < 1 || number > 10\`. As long as the input is invalid, the question is asked again. + +## Exercise: Valid grade + +::: übung l11-note +titel: Valid grade +auftrag: Ask for a grade. If it is not between 1 and 6, ask again. If it is valid, output it, for example **Your grade: 3**. +test: 3 -> Your grade: 3 +test: 0, 7, 2 -> Your grade: 2 +test: 9, 6 -> Your grade: 6 +test: -1, 1 -> Your grade: 1 +braucht: doUntilSchleife +tipp: The grade is asked for at least once. After that, the condition decides whether to ask again. +tipp: Before the loop, create \`int grade = 0\`. The input \`input: grade "Grade from 1 to 6"\` goes inside the loop. The condition is \`grade < 1 || grade > 6\`. +lösung: l11-note-loesung.visustruct +::: + +## Exercise: Sum until 0 + +::: übung l11-summe +titel: Sum until 0 +auftrag: Keep asking for numbers until a 0 is typed in. Then output the sum of all the numbers typed in. +test: 3, 4, 0 -> 7 +test: 10, 0 -> 10 +test: 5, 5, 5, 0 -> 15 +test: 0 -> 0 +braucht: doUntilSchleife +tipp: You need a variable for the sum that starts at 0 before the loop. In every pass the new number is added. +tipp: Before the loop, create \`int sum = 0\` and \`int number = 0\`. In the loop you ask for \`number\` and calculate \`sum = sum + number\`. Adding the 0 does no harm. The loop keeps running as long as \`number != 0\`. +lösung: l11-summe-loesung.visustruct +::: + +## Now in Java + +The loop that still runs once looks like this in Java: + +\`\`\`java +int i = 10; +do { + System.out.println(i); + i = i + 1; +} while (i < 5); +\`\`\` + +- The body is between \`do {\` and \`}\`, the condition only comes afterwards. +- Here there is a **semicolon** after \`while (…)\`. That is different from the while loop. + +::: übung l12-java-verdoppeln +titel: Double at least once +code: java +auftrag: Write a Java program that reads a start number. A do-while loop doubles it and outputs it as long as it is less than 100. A number of 100 or more is still doubled at least once: 200 becomes 400. +test: 30 -> 60 | 120 +test: 200 -> 400 +test: 13 -> 26 | 52 | 104 +braucht: doUntilSchleife +tipp: In the body you double the number and output it. The condition comes at the end. +tipp: \`do { number = number * 2; System.out.println(number); } while (number < 100);\` +lösung: l12-java-verdoppeln-loesung.visustruct +::: + +## Fill in the gaps: do-while + +::: lückentext +titel: Tripling +auftrag: The number is tripled and output as long as it is less than 100. Fill in the missing words and symbols. +\`\`\`java +int number = 1; +[[do]] { + number = number * 3; + System.out.println(number); +} [[while]] (number [[<]] 100)[[;]] +\`\`\` +erklärung: The body is between \`do {\` and \`}\`, the condition only comes afterwards. In a do-while loop there is a semicolon after \`while (…)\`. Output: 3, 9, 27, 81 and 243. +::: + +## Find the bug: halving + +::: übung l12-java-fehler +titel: Fix the halving +code: java +auftrag: The program reads a start number and keeps dividing it by 2 (whole-number division) with a do-while loop. Every result is output until **0** is reached. For 10 that is 5, 2, 1 and 0. But the 0 is missing. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l12-java-fehler-start.visustruct +test: 10 -> 5 | 2 | 1 | 0 +test: 1 -> 0 +test: 7 -> 3 | 1 | 0 +test: 20 -> 10 | 5 | 2 | 1 | 0 +braucht: doUntilSchleife +tipp: What value does \`number\` have after the 1 has been output? Does the loop run once more then? +tipp: The loop should keep going as long as the number is greater than 0: \`while (number > 0);\` +lösung: l12-java-fehler-loesung.visustruct +::: + +## Game: At least once? + +::: spiel frage +titel: Game: At least once? +intro: While or do-while? Ludwig shows you loops. Predict what happens. Six rounds. + +runde: + int i = 10; + do { + System.out.println(i); + i = i + 1; + } while (i < 5); +frage: What is output? +- nothing +- [x] 10 +- 10 to 4 +> First do, then check: the body runs once, after that 11 < 5 is false. + +runde: + int i = 10; + while (i < 5) { + System.out.println(i); + i = i + 1; + } +frage: What is output? +- [x] nothing +- 10 +- 11 +> In a while loop the condition comes first. 10 < 5 is false, so nothing runs at all. + +runde: + int number = 200; + do { + number = number * 2; + } while (number < 100); + System.out.println(number); +frage: What is output? +- 200 +- [x] 400 +- 800 +> It is doubled once no matter what. After that 400 < 100 is false. + +runde: + int number = 30; + do { + number = number * 2; + System.out.println(number); + } while (number < 100); +frage: What is output? +- 60 +- [x] 60\\n120 +- 60\\n120\\n240 +> After 60, 60 < 100 is true, so it goes on. After 120 it stops. + +runde: +frage: Which line ends a do-while loop in Java correctly? +- [x] \`} while (i < 5);\` +- \`} while (i < 5)\` +- \`while (i < 5) {\` +> After the \`while (…)\` of a do-while loop there is a semicolon. + +runde: +frage: What is a do-while loop typically used for? +- [x] repeating an input until it is valid +- counting from 1 to 10 +- swapping two values +> The question is asked at least once. Only after that do you know whether the input was valid. +::: + +## 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. + +::: checkliste +- I can explain that the do-while loop only checks its condition after the inside. → Do first, check afterwards +- I can explain why the inside runs at least once. → At least one pass +- I can repeat an input until it is valid. → Typical use: repeat an input +- I can write a do-while loop in Java. → Now in Java +::: + +## Quiz + +::: quiz +? What does post-test loop mean? +→ Do first, check afterwards +- [ ] The condition is checked before every pass. +- [x] The condition is checked after every pass. +- [ ] The loop has no condition. +> The condition is in the foot, at the bottom, and is worked out after the inside. + +? The condition of a do-while loop is false from the start. How often does the inside run? +→ At least one pass +- [ ] Not at all +- [x] Exactly once +- [ ] Forever +> The inside runs first. Only then does the loop notice that it should stop. + +? You want to ask for a number from 1 to 10. Which condition goes in the foot? +→ Typical use: repeat an input +- [ ] \`number >= 1 && number <= 10\` +- [x] \`number < 1 || number > 10\` +- [ ] \`number == 10\` +> The loop repeats as long as the input is invalid, that is, less than 1 or greater than 10. + +? When is a do-while loop better than a while loop? +→ At least one pass +- [x] When the inside has to run at least once, e.g. for an input +- [ ] When the loop might not need to run at all +- [ ] When you want to count exactly to 10 + +? What comes at the end of a do-while loop in Java? +→ Now in Java +- [ ] } while (condition) { +- [x] } while (condition); +- [ ] } until (condition); +> A semicolon follows the condition. +::: +`,g4=`--- +titel: For loop +bereich: Basics +kurz: Count a fixed number of passes with Init, Condition and Step. +--- + +## Skills I will gain now + +::: kompetenzen +- name the three parts Init, Condition and Step of the for loop +- explain in which order the three parts run +- count forwards, backwards and in bigger steps with a for loop +- write a for loop in Java and explain its three fields +::: + +## Counting with a fixed plan + +In the while loop you already counted along: a start value before the loop, a condition in the head, a change inside. The **for loop** puts these three parts together in the head. That way you see at a glance how it counts. + +When you click a for loop, it has three fields on the right: + +- **Init:** \`int i = 1\` creates the counter variable. +- **Condition:** \`i <= 5\` says how long to count. +- **Step:** \`i++\` increases \`i\` by 1 after every pass. + +::: diagramm l12-eins-bis-fuenf.visustruct +A for loop that outputs the numbers from 1 to 5. +::: + +::: angeberwissen +Why is the counting variable almost always called \`i\`? In maths \`i\` has long stood for an index. And in FORTRAN, one of the first programming languages from 1957, all variables starting with I to N were automatically whole numbers. Programmers have not broken the habit to this day. +::: + +## In which order? + +The three parts run at different times: + +1. **Init** runs exactly once, right at the start. +2. **Condition** is checked before every pass. If it is false, the loop is finished. +3. After the inside comes the **Step**, then the condition again. + +::: grafik l12-for-ablauf.svg +Init only runs once. After that, condition, inside and step repeat. +::: + +So the for loop is a pre-test loop, like the while loop. Go through the example in the simulation with **Step** and watch how \`i\` changes. + +> Use the for loop when you know beforehand how often something should happen. If the end depends on something that only happens during the loop, for example an input, the while or do-while loop is better. + +## Example: sum from 1 to n + +A for loop is good for adding up numbers. Before the loop there is \`int sum = 0\`. In every pass the current number \`i\` is added. + +::: diagramm l12-summe.visustruct +With n = 4 the loop calculates 0 + 1 + 2 + 3 + 4. At the end, 10 is output. +::: + +## Other steps + +The step does not always have to be \`i++\`: + +- \`i--\` counts backwards, for example with Init \`int i = 10\` and Condition \`i >= 1\`. +- \`i = i + 2\` jumps in steps of two, for example 0, 2, 4, 6. + +Make sure that Init, Condition and Step fit together. With Init \`int i = 1\`, Condition \`i >= 1\` and Step \`i++\`, the condition never becomes false. + +::: übung l12-countdown +titel: Countdown +auftrag: Ask for a whole number \`n\`. Use a for loop to count backwards from \`n\` to 1 and output each number. Then output **Go!**. +test: 3 -> 3 | 2 | 1 | Go! +test: 5 -> 5 | 4 | 3 | 2 | 1 | Go! +test: 1 -> 1 | Go! +braucht: forSchleife +tipp: This time the for loop counts backwards. Think about where it starts, when it stops and how it counts. +tipp: Init is \`int i = n\`, the condition \`i >= 1\` and the step \`i--\`. The output Go! goes below the loop, not inside it. +lösung: l12-countdown-loesung.visustruct +::: + +## Exercise: Times table + +::: übung l12-einmaleins +titel: Times table +auftrag: Ask for a number and output its times table from 1 to 10. Each line looks like this: **3 x 1 = 3**, **3 x 2 = 6** and so on. +test: 3 -> 3 x 1 = 3 | 3 x 2 = 6 | 3 x 3 = 9 | 3 x 4 = 12 | 3 x 5 = 15 | 3 x 6 = 18 | 3 x 7 = 21 | 3 x 8 = 24 | 3 x 9 = 27 | 3 x 10 = 30 +test: 7 -> 7 x 1 = 7 | 7 x 2 = 14 | 7 x 3 = 21 | 7 x 4 = 28 | 7 x 5 = 35 | 7 x 6 = 42 | 7 x 7 = 49 | 7 x 8 = 56 | 7 x 9 = 63 | 7 x 10 = 70 +braucht: forSchleife +tipp: The loop counts from 1 to 10. In every pass you output one line of the table. +tipp: Inside, first calculate \`int product = number * i\`. Then output \`number + " x " + i + " = " + product\`. Remember the spaces inside the quotation marks. +lösung: l12-einmaleins-loesung.visustruct +::: + +## Exercise: Fix the sum + +::: übung l16-summe +titel: Fix the sum +auftrag: The structure chart should add up all numbers from 1 to n. So with n = 4 the result should be 1 + 2 + 3 + 4 = **10**. But it outputs 6. + Do a desk check or use **Step** and fix the mistake. +start: l16-summe-start.visustruct +test: 4 -> 10 +test: 1 -> 1 +test: 5 -> 15 +braucht: forSchleife +tipp: Go through the loop with n = 4 in your head or with **Step**. Which numbers are really added? +tipp: Look at the last value of i the loop runs with. With n = 4, i = 4 must be added too. +lösung: l16-summe-loesung.visustruct +::: + +## Now in Java + +The sum from 1 to n looks like this in Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Up to which number?"); +int n = scanner.nextInt(); +int sum = 0; +for (int i = 1; i <= n; i++) { + sum = sum + i; +} +System.out.println(sum); +\`\`\` + +The round brackets after \`for\` hold the three fields of the for loop, separated by semicolons: + +| Field | In Java | Meaning | +|---|---|---| +| Init | \`int i = 1\` | \`i\` starts at 1. | +| Condition | \`i <= n\` | The loop runs as long as this is true. | +| Step | \`i++\` | After every pass \`i\` gets 1 bigger. | + +\`i++\` is short for \`i = i + 1\`. To count backwards, use \`i--\`. + +::: übung l13-java-quadrate +titel: Square numbers in Java +code: java +auftrag: Write a Java program that reads a whole number \`n\` and uses a for loop to output the square numbers from 1 to \`n\`, each on its own line. For 3 that is 1, 4 and 9. +test: 3 -> 1 | 4 | 9 +test: 5 -> 1 | 4 | 9 | 16 | 25 +test: 1 -> 1 +braucht: forSchleife +tipp: The loop counts \`i\` from 1 to \`n\`. The square of \`i\` is \`i * i\`. +tipp: \`for (int i = 1; i <= n; i++) { … }\` and in the body \`System.out.println(i * i);\`. +lösung: l13-java-quadrate-loesung.visustruct +::: + +## Fill in the gaps: for + +::: lückentext +titel: Counting up and down +auftrag: The first loop adds up the numbers from 1 to 5, the second counts down from 10 to 0. Fill in the missing words and symbols. +\`\`\`java +int sum = 0; +[[for]] ([[int]] i = 1; i [[<=]] 5; [[i++ | i += 1 | i = i + 1]]) { + sum = sum + i; +} +System.out.println("Sum: " + sum); +for (int i = 10; i [[>=]] 0; [[i-- | i -= 1 | i = i - 1]]) { + System.out.println(i); +} +\`\`\` +erklärung: The round brackets hold the start value, the condition and the step, separated by semicolons. \`i++\` counts up, \`i--\` counts down. When counting down to 0 the condition is \`i >= 0\`. +::: + +## Find the bug: times table + +::: übung l13-java-fehler +titel: Fix the times table +code: java +auftrag: The program asks for a times table and should output it from 1 times to 10 times, for 7 that is 7, 14, … up to 70. But the 70 is missing. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l13-java-fehler-start.visustruct +test: 7 -> 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 +test: 3 -> 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 +braucht: forSchleife +tipp: How often does the loop run? Count which values \`i\` takes. +tipp: \`i\` should also take the value 10: \`i <= 10\` instead of \`i < 10\`. +lösung: l13-java-fehler-loesung.visustruct +::: + +## Game: Defuse the bomb + +::: spiel bombe +titel: Game: Defuse the bomb +intro: Every program hides **exactly one mistake**, and the bomb is ticking. Read what the program should do and tap the wrong line before time runs out. Eight rounds, 25 seconds each. +zeit: 25 + +runde: + for (int i = 1; i <= 3; i++) { + System.out.println(i) + } +frage: Should output 1, 2 and 3. +fehler: 2 +besser: System.out.println(i); +> The semicolon at the end of the statement is missing. + +runde: + for (int i = 1, i <= 5, i++) { + System.out.println(i); + } +frage: Should output 1 to 5. +fehler: 1 +besser: for (int i = 1; i <= 5; i++) { +> The three fields of the for loop are separated by semicolons, not commas. + +runde: + for (int i = 10; i >= 1; i++) { + System.out.println(i); + } +frage: Should count backwards from 10 to 1. +fehler: 1 +besser: for (int i = 10; i >= 1; i--) { +> With \`i++\`, \`i\` keeps growing and the condition \`i >= 1\` stays true: an endless loop. To count backwards, use \`i--\`. + +runde: + int sum = 0; + for (int i = 1; i <= 4; i++) { + sum = i; + } + System.out.println(sum); +frage: Should output the sum 1 + 2 + 3 + 4 = 10. +fehler: 3 +besser: sum = sum + i; +> \`sum = i\` overwrites the sum in every pass. In the end it only holds 4. + +runde: + for (int i = 0; i <= 5; i++) { + System.out.println("Baaa"); + } +frage: Should output Baaa exactly five times. +fehler: 1 +besser: for (int i = 0; i < 5; i++) { +> From 0 up to and including 5 there are six passes. If you start at 0, use \`<\`. + +runde: + for (int i = 1; i <= 3; i++) { + system.out.println(i); + } +frage: Should output 1, 2 and 3. +fehler: 2 +besser: System.out.println(i); +> Java tells upper and lower case apart: \`System\` is written with a capital S. + +runde: + int number = 7; + for (int i = 1; i <= 10; i++) { + System.out.println(number + " x " + i + " = " + number * number); + } +frage: Should output the 7 times table: 7 x 1 = 7, 7 x 2 = 14 and so on. +fehler: 3 +besser: System.out.println(number + " x " + i + " = " + number * i); +> \`number * number\` is always 49. It has to be \`number * i\`. + +runde: + for (int i = 2; i <= 10; i + 2) { + System.out.println(i); + } +frage: Should output the even numbers 2, 4, 6, 8 and 10. +fehler: 1 +besser: for (int i = 2; i <= 10; i = i + 2) { +> \`i + 2\` only calculates and stores nothing. For \`i\` to really grow, you need \`i = i + 2\`. +::: + +## 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. + +::: checkliste +- I can name the three parts Init, Condition and Step of the for loop. → Counting with a fixed plan +- I can explain in which order the three parts run. → In which order? +- I can count forwards, backwards and in bigger steps with a for loop. → Other steps +- I can write a for loop in Java and explain its three fields. → Now in Java +::: + +## Quiz + +::: quiz +? How often does the Init of a for loop run? +→ In which order? +- [x] Exactly once +- [ ] Before every pass +- [ ] After every pass +> Init creates the counter variable once at the start. + +? Init \`int i = 0\`, Condition \`i < 3\`, Step \`i++\`. Which values does i have inside the loop? +→ Counting with a fixed plan +- [ ] 1, 2, 3 +- [x] 0, 1, 2 +- [ ] 0, 1, 2, 3 +> With i = 3 the condition is false, so the inside does not run any more. + +? Init \`int i = 2\`, Condition \`i <= 10\`, Step \`i = i + 2\`. How often does the inside run? +→ Other steps +- [ ] 4 times +- [x] 5 times +- [ ] 10 times +> i takes the values 2, 4, 6, 8 and 10. + +? When does a for loop fit best? +→ Counting with a fixed plan +- [x] When you know beforehand how often to repeat +- [ ] When you keep asking until an input is valid +- [ ] When only a single value is checked + +? What does \`i++\` mean in a for loop? +→ Counting with a fixed plan +- [ ] i is doubled. +- [x] i gets 1 bigger. +- [ ] i is output. +> \`i++\` is short for \`i = i + 1\`. +::: +`,p4=`--- +titel: Nesting +bereich: Basics +kurz: Combine branches inside loops and loops inside loops. +--- + +## Skills I will gain now + +::: kompetenzen +- put a branch inside a loop +- put a loop inside another loop +- explain that the inner loop runs all the way through in every pass of the outer one +- write nested loops and branches in Java +::: + +## Building blocks inside each other + +You now know all the important building blocks: sequence, branch, switch and three kinds of loops. They only get really powerful together. + +Every path and every loop body is a sequence itself. You may put any element there, including more branches and loops. This is called **nesting**. + +> To do this, simply drag an element onto the placeholder ø inside a loop or a path. + +## A branch inside a loop + +The loop goes through all the numbers, and the branch decides for each single number whether something happens. That way you can count, for example, how many even numbers there are from 1 to n. + +::: diagramm l13-gerade-zaehlen.visustruct +In every pass the branch checks with i % 2 == 0 whether i is even. Only then is count increased by 1. The false path stays empty. +::: + +With n = 7 these are the numbers 2, 4 and 6, so 3 is output. + +## Exercise: Count even inputs + +::: übung l13-gerade-eingaben +titel: Count even inputs +auftrag: Ask for exactly **five** whole numbers, one after another. Then output how many of them were even. +test: 1, 2, 3, 4, 5 -> 2 +test: 2, 4, 6, 8, 10 -> 5 +test: 1, 3, 5, 7, 9 -> 0 +test: 10, 11, 0, 7, 8 -> 3 +braucht: forSchleife, verzweigung +tipp: Doing the same thing five times means: loop. In every pass a number is read in and checked. +tipp: A for loop from 1 to 5. Inside, first comes the input \`input: int number "Enter a number"\`, below it a branch with \`number % 2 == 0\`. In the true path you increase \`count\` by 1. +lösung: l13-gerade-eingaben-loesung.visustruct +::: + +## A loop inside a loop + +If one loop sits inside another, the **inner loop runs all the way through in every pass of the outer one**. With this you can build patterns of rows and columns. + +::: diagramm l13-dreieck.visustruct +The outer loop counts the lines. The inner one adds as many stars to the text as the line number says. With n = 3 you get a triangle of 1, 2 and 3 stars. +::: + +With \`String text = ""\` every line starts empty. \`text = text + "*"\` adds a star. Only when the line is finished is it output. + +## Exercise: Rectangle + +::: übung l13-rechteck +titel: Rectangle +auftrag: Ask for a width and a height. Output a rectangle made of \`#\`: as many lines as the height, and in each line as many \`#\` as the width. +test: 3, 2 -> ### | ### +test: 1, 3 -> # | # | # +test: 4, 1 -> #### +test: 2, 2 -> ## | ## +braucht: forSchleife +tipp: You need two loops inside each other: one for the lines and inside it one for the characters of a line. +tipp: Build it like the triangle. The difference: the inner loop always counts up to \`width\`, not up to the line number. The outer loop counts up to \`height\`. +lösung: l13-rechteck-loesung.visustruct +::: + +## Keep track + +With nested diagrams, the drawing helps you: whatever is further inside is indented and surrounded by its loop or path. + +- Read from the outside in: what repeats? What is decided in every pass? +- Give counter variables meaningful names such as \`line\` and \`column\`. Two loops must not change the same counter variable. +- Go through an example in the simulation with **Step** and watch the variables. + +::: angeberwissen +This is exactly what the structure chart was invented for. Shneiderman asked himself: if we are supposed to do without GOTO, why not do without the arrows in the flowchart as well? The result: no arrow spaghetti, and every block stays nicely in its pen. +::: + +## Now in Java + +Counting the even numbers looks like this in Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Up to which number?"); +int n = scanner.nextInt(); +int count = 0; +for (int i = 1; i <= n; i++) { + if (i % 2 == 0) { + count++; + } // end if +} // end for +System.out.println(count); +\`\`\` + +What is nested in the structure chart is nested in curly brackets in Java. Every level is indented four spaces further. If your code gets messy, the **Indent** button at the top of the Code area helps. + +With many closing brackets \`}\` it is easy to lose track: which bracket belongs to which block? A comment after it tells you, for example \`} // end if\` and \`} // end for\`. This also helps when you carry on later. + +\`count++\` is short for \`count = count + 1\`. + +::: übung l14-java-treppe +titel: Stairs of stars +code: java +auftrag: Write a Java program that reads the number of steps and outputs stairs made of stars. For 3 steps that is \`*\`, \`**\` and \`***\`, each step on its own line. +test: 3 -> * | ** | *** +test: 1 -> * +test: 4 -> * | ** | *** | **** +braucht: forSchleife +tipp: An outer loop counts the steps. In each step an inner loop builds a text of stars. +tipp: In the outer loop: \`String line = "";\`, then \`for (int j = 1; j <= i; j++) { line = line + "*"; }\` and after that \`System.out.println(line);\`. +lösung: l14-java-treppe-loesung.visustruct +::: + +## Fill in the gaps: nesting + +::: lückentext +titel: Rectangle of stars +auftrag: The program outputs a rectangle of 3 lines with 4 stars each. Fill in the missing words and symbols. +\`\`\`java +for (int line = 1; line <= 3; line++) { + String text = [[""]]; + [[for]] (int column = 1; column [[<=]] 4; [[column++ | column += 1 | column = column + 1]]) { + text = text [[+]] "*"; + } + System.out.[[println]](text); +[[}]] +\`\`\` +erklärung: The inner loop builds one line of 4 stars, the outer loop repeats that three times. Each line starts with an empty text \`""\`. The last bracket closes the outer loop. +::: + +## Find the bug: divisible by 3 + +::: übung l14-java-fehler +titel: Fix the counting +code: java +auftrag: The program should count how many numbers from 1 to \`n\` are divisible by 3 and output the result **once**. For 10 that is just **Count: 3**. But it outputs far too many lines. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l14-java-fehler-start.visustruct +test: 10 -> Count: 3 +test: 3 -> Count: 1 +test: 2 -> Count: 0 +braucht: forSchleife, verzweigung +tipp: Look at the curly brackets: is the output inside the loop or after it? +tipp: Move the line \`System.out.println("Count: " + count);\` after the closing bracket of the loop. +lösung: l14-java-fehler-loesung.visustruct +::: + +## Game: Inside and outside + +::: spiel frage +titel: Game: Inside and outside +intro: Ludwig has put building blocks inside each other. Read from the outside in and predict what happens. Six rounds. + +runde: + for (int i = 1; i <= 3; i++) { + for (int j = 1; j <= 2; j++) { + System.out.println("*"); + } + } +frage: How many stars are output? +- 3 +- 5 +- [x] 6 +> The inner loop runs completely in each of the 3 runs of the outer loop: 3 · 2 = 6. + +runde: + for (int i = 1; i <= 2; i++) { + for (int j = 1; j <= 3; j++) { + System.out.println(i + " " + j); + } + } +frage: Which line is output fourth? +- 1 4 +- [x] 2 1 +- 2 2 +> First j runs through for i = 1: 1 1, 1 2, 1 3. Then j starts again at 1, now with i = 2. + +runde: + int count = 0; + for (int i = 1; i <= 10; i++) { + if (i % 3 == 0) { + count++; + } + } + System.out.println(count); +frage: What is output? +- [x] 3 +- 10 +- 4 +> The branch only counts 3, 6 and 9. + +runde: + for (int i = 1; i <= 4; i++) { + if (i % 2 == 0) { + System.out.println("even"); + } else { + System.out.println(i); + } + } +frage: What is output? +- 1\\n2\\n3\\n4 +- [x] 1\\neven\\n3\\neven +- even\\neven +> For every number the branch decides again: odd numbers themselves, even ones as a word. + +runde: + for (int i = 1; i <= 3; i++) { + String line = ""; + for (int j = 1; j <= i; j++) { + line = line + "*"; + } + System.out.println(line); + } +frage: What is output? +- ***\\n***\\n*** +- [x] *\\n**\\n*** +- ***\\n**\\n* +> The inner loop runs up to i. That's why every line gets one star longer. + +runde: + for (int i = 1; i <= 3; i++) { + for (int i = 1; i <= 3; i++) { + System.out.println(i); + } + } +frage: What happens? +- 1 to 3 is output three times. +- 1 to 3 is output once. +- [x] Java reports an error. +> Two loops inside each other need two different counter variables, for example \`row\` and \`column\`. +::: + +## 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. + +::: checkliste +- I can put a branch inside a loop. → A branch inside a loop +- I can put a loop inside another loop. → A loop inside a loop +- I can explain that the inner loop runs all the way through in every pass of the outer one. → A loop inside a loop +- I can write nested loops and branches in Java. → Now in Java +::: + +## Quiz + +::: quiz +? The outer loop runs 3 times, the inner one 4 times. How often does the inside of the inner loop run in total? +→ A loop inside a loop +- [ ] 7 times +- [x] 12 times +- [ ] 4 times +> In each of the 3 outer passes, the inner loop runs 4 times, so 3 · 4 = 12. + +? How can you tell whether a number is even? +→ A branch inside a loop +- [ ] \`number / 2 == 0\` +- [x] \`number % 2 == 0\` +- [ ] \`number == 2\` +> % gives the remainder of a division. For even numbers, the remainder when dividing by 2 is zero. + +? There is a branch inside a for loop. How often is the condition of the branch checked? +→ A branch inside a loop +- [ ] Once +- [x] Once per pass of the loop +- [ ] Only if it is true +> The branch is part of the inside and runs in every pass. + +? How can you tell in Java what belongs to a loop? +→ Now in Java +- [ ] By the colour +- [x] By the curly brackets and the indentation +- [ ] By the semicolons +::: +`,f4=`--- +titel: Arrays +bereich: Basics +kurz: Store many values under one name, reach them with the index and go through them with a loop. +--- + +## Skills I will gain now + +::: kompetenzen +- create an array with values or with \`new int[5]\` +- explain that the index starts at 0 and that the last index is \`length - 1\` +- go through and fill an array with a for loop +- calculate the sum and the maximum of an array +- create an array in Java and go through it with a loop +::: + +## Many values under one name + +Imagine you want to store the points from five tests. With five variables \`points1\` to \`points5\` that quickly gets confusing. An **array** is a row of slots that all have the same name and the same data type. + +You create an array with a statement. After the data type you write square brackets \`[]\`: + +\`\`\` +int[] numbers = {2, 4, 6, 8, 10} +String[] names = {"Ada", "Ben", "Cem"} +\`\`\` + +The values in the curly brackets go straight into the slots. You can also create an empty array with a fixed number of slots: + +\`\`\` +int[] points = new int[5] +String[] names = new String[3] +\`\`\` + +With \`new int[5]\` all five slots hold zeros at first, with \`new String[3]\` empty texts. + +## The index starts at 0 + +Every slot has a number, the **index**. Counting starts at **0**. So with \`int[] numbers = {2, 4, 6, 8, 10}\`: + +- \`numbers[0]\` is 2 +- \`numbers[1]\` is 4 +- \`numbers[4]\` is 10 + +::: grafik l14-array.svg +Five slots with the indices 0 to 4. The index is above the slot, the value inside it. +::: + +**Why start at 0?** In computer science the index is not “which slot” but the **distance from the start**. The first slot is right at the start, so 0 steps away. The second is 1 step away, the third 2 steps. You know this from a lift: the ground floor is **0**, and the first floor is one level above it. + +This gives you a rule worth remembering: with 5 slots the **last index is 4**, always one less than the number of slots. + +::: angeberwissen +Counting from 0 is pretty old. The programming language C from 1972 already works like this: the computer knows the address of the first slot, and for \`numbers[i]\` it simply calculates “start plus i slots further”. With i = 0 it stays at the start, which saves a calculation. Java, Python and JavaScript took this over. By the way, I count my horns from 0 as well: horn 0 on the left, horn 1 on the right. +::: + +With the index you read a value or write a new one into it: + +\`\`\` +output: numbers[0] +numbers[1] = 99 +\`\`\` + +> An array with 5 slots has the indices 0 to 4. \`numbers[5]\` does not exist. The simulation then reports an invalid expression. + +## The length of an array + +\`numbers.length\` tells you how many slots an array has. With five values it is 5. So the **last** index is always \`numbers.length - 1\`: + +\`\`\` +output: numbers.length +output: numbers[numbers.length - 1] +\`\`\` + +The second line outputs the last value, however long the array is. VisuStruct also understands \`numbers.length()\`. + +::: übung l14-erster-letzter +titel: First and last value +auftrag: Create the array \`int[] values = {4, 8, 15, 16, 23, 42}\`. Then output on three lines: the first value, the last value and the number of values. + For the last value, use the length and do not simply write the index 5. +test: - -> 4 | 42 | 6 +braucht: anweisung +tipp: Counting starts at 0, so the first slot has the index 0. And what is the index of the last slot? +tipp: The first value is \`values[0]\`. The last one is \`values[values.length - 1]\`. The number of values is \`values.length\`. +lösung: l14-erster-letzter-loesung.visustruct +::: + +## Go through an array with a loop + +An array shows its strength together with a **for loop**. The counter variable \`i\` runs from 0 to the last index and is used as the index: + +\`\`\` +int i = 0 +i < numbers.length +i++ +\`\`\` + +In the first pass \`i\` is 0, in the last one 4. Because the condition is \`i < numbers.length\`, the loop fits any length. + +::: diagramm l14-array-durchlaufen.visustruct +The for loop outputs all five values one after another. Under Variables in the simulation, watch i count from 0 to 4. +::: + +This is also how you fill an empty array with inputs. As the target of the input you write the slot \`names[i]\`: + +::: diagramm l14-namen-eingeben.visustruct +Three names are asked for and written into the slots 0, 1 and 2. +::: + +::: übung l14-rueckwaerts +titel: Print backwards +auftrag: Create an array for 4 whole numbers and read in the 4 numbers with a loop. Then output them in **reverse** order, each on its own line. +test: 1, 2, 3, 4 -> 4 | 3 | 2 | 1 +test: 7, 0, 5, 9 -> 9 | 5 | 0 | 7 +braucht: forSchleife +tipp: You need two loops: one for reading in from front to back and one for outputting from back to front. +tipp: You create the array with \`int[] numbers = new int[4]\`. The input is \`input: numbers[i] "Enter a number"\`. For the second loop you start at \`int i = numbers.length - 1\`, check \`i >= 0\` and count down with \`i--\`. +lösung: l14-rueckwaerts-loesung.visustruct +::: + +## Sum and maximum + +Two tasks come up with arrays again and again: + +- **Sum:** You start with \`sum = 0\` and add every value in the loop. +- **Maximum:** First you remember the value in slot 0 as the largest so far. In the loop you check every value. If it is larger, it becomes the new maximum. + +::: diagramm l14-summe-maximum.visustruct +Sum and maximum in one single pass. The maximum starts with points[0] and not with 0, so that it is also right for negative numbers. +::: + +::: übung l14-summe-max +titel: Sum and maximum +auftrag: Read 5 whole numbers into an array. Then output **Sum: …** and on the next line **Maximum: …**. +test: 3, 9, 2, 9, 1 -> Sum: 24 | Maximum: 9 +test: 10, 20, 30, 40, 50 -> Sum: 150 | Maximum: 50 +test: -5, -2, -9, -1, -3 -> Sum: -20 | Maximum: -1 +braucht: forSchleife, verzweigung +tipp: Go through the array with a loop. Add every value to the sum and remember the largest value seen so far. +tipp: Calculate the sum and the maximum in variables of their own and only output them at the end, e.g. with \`output: "Sum: " + sum\`. If your maximum starts at 0, the third test fails. +lösung: l14-summe-max-loesung.visustruct +::: + +## Now in Java + +Going through an array looks like this in Java: + +\`\`\`java +int[] numbers = {2, 4, 6, 8, 10}; +for (int i = 0; i < numbers.length; i++) { + System.out.println(numbers[i]); +} +\`\`\` + +- \`int[]\` means “array of whole numbers”. The values are in curly brackets. +- You create an empty array with 5 slots with \`new int[5]\`. +- \`numbers[i]\` is the slot with index \`i\`, \`numbers.length\` is the length. + +::: übung l15-java-noten +titel: Sum of grades in Java +code: java +auftrag: Create the array \`grades\` in Java with the values 2, 3, 1 and 4. Add up all grades with a for loop and output **Sum: 10**. +test: - -> Sum: 10 +braucht: forSchleife +tipp: Create \`int sum = 0;\` before the loop. The loop runs from 0 to \`grades.length - 1\`. +tipp: \`int[] grades = {2, 3, 1, 4};\`, then \`for (int i = 0; i < grades.length; i++) { sum = sum + grades[i]; }\` and finally \`System.out.println("Sum: " + sum);\`. +lösung: l15-java-noten-loesung.visustruct +::: + +## Fill in the gaps: arrays + +::: lückentext +titel: Finding the maximum +auftrag: The program looks for the largest value in the array. Fill in the missing words and symbols. +\`\`\`java +[[int]][] values = {3, 7, 1, 9, 4}; +int max = values[0]; +[[for]] (int i = 1; i < values.[[length]]; i++) { + if (values[i] [[>]] max) { + max = values[i]; + } +} +System.out.println("Maximum: " + max); +\`\`\` +erklärung: \`int[]\` is an array of whole numbers, \`values.length\` is its length. \`max\` starts with the first value, and the loop compares all the others with it. Output: **Maximum: 9** +::: + +## Find the bug: temperatures + +::: übung l15-java-fehler +titel: Fix the highest temperature +code: java +auftrag: In January the temperatures -5, -2, -8 and -3 degrees were measured. The program should output the highest, so **Highest temperature: -2**. But it claims 0 degrees, although it was never that warm. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l15-java-fehler-start.visustruct +test: - -> Highest temperature: -2 +braucht: forSchleife, verzweigung +tipp: What value does \`max\` start with? Is any of the temperatures greater than this start value? +tipp: \`max\` has to start with a value from the array: \`int max = temperatures[0];\` +lösung: l15-java-fehler-loesung.visustruct +::: + +## Game: Defuse the bomb + +::: spiel bombe +titel: Game: Defuse the bomb +intro: Every program contains **exactly one mistake** to do with arrays, and the bomb is ticking. Tap the wrong line before time runs out. Six rounds, 30 seconds each. +zeit: 30 + +runde: + int[] numbers = {2, 4, 6, 8, 10}; + for (int i = 0; i <= numbers.length; i++) { + System.out.println(numbers[i]); + } +frage: Should output all five values. +fehler: 2 +besser: for (int i = 0; i < numbers.length; i++) { +> With \`<=\`, i runs up to 5. There is no slot \`numbers[5]\`. + +runde: + String[] names = {"Ada", "Ben", "Cem"}; + System.out.println(names[1]); +frage: Should output the first name, Ada. +fehler: 2 +besser: System.out.println(names[0]); +> Counting starts at 0. \`names[1]\` is already Ben. + +runde: + int[] numbers = {2, 4, 6, 8, 10}; + System.out.println(numbers[numbers.length]); +frage: Should output the last value, 10. +fehler: 2 +besser: System.out.println(numbers[numbers.length - 1]); +> The last index is always one less than the length. + +runde: + int[] points = {3, 9, 2}; + int sum = 0; + for (int i = 0; i < points.length; i++) { + sum = points[i]; + } + System.out.println(sum); +frage: Should output the sum 14. +fehler: 4 +besser: sum = sum + points[i]; +> Like this every value overwrites the one before, and at the end sum only holds 2. + +runde: + int[] points = {-5, -2, -9}; + int max = 0; + for (int i = 0; i < points.length; i++) { + if (points[i] > max) { + max = points[i]; + } + } + System.out.println(max); +frage: Should output the maximum -2. +fehler: 2 +besser: int max = points[0]; +> None of the numbers is greater than 0, so max would stay 0. That's why the maximum starts with the first slot. + +runde: + int[] numbers = {2, 4, 6, 8, 10}; + for (int i = numbers.length; i >= 0; i--) { + System.out.println(numbers[i]); + } +frage: Should output the values backwards, from 10 to 2. +fehler: 2 +besser: for (int i = numbers.length - 1; i >= 0; i--) { +> Backwards you start at the last index, and that is \`numbers.length - 1\`. +::: + +## 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. + +::: checkliste +- I can create an array with values or with \`new int[5]\`. → Many values under one name +- I can explain that the index starts at 0 and that the last index is \`length - 1\`. → The index starts at 0 +- I can go through and fill an array with a for loop. → Go through an array with a loop +- I can calculate the sum and the maximum of an array. → Sum and maximum +- I can create an array in Java and go through it with a loop. → Now in Java +::: + +## Quiz + +::: quiz +? What does \`output: numbers[2]\` output with \`int[] numbers = {5, 10, 15, 20}\`? +→ The index starts at 0 +- [ ] 10 +- [x] 15 +- [ ] 20 +> Counting starts at 0: numbers[0] is 5, numbers[1] is 10, numbers[2] is 15. + +? An array has 8 slots. Which index is the last one? +→ The index starts at 0 +- [ ] 8 +- [x] 7 +- [ ] 9 +> The last index is always length - 1. + +? Which condition fits a for loop that goes through all values of \`numbers\` and starts at \`int i = 0\`? +→ Go through an array with a loop +- [x] i < numbers.length +- [ ] i <= numbers.length +- [ ] i > numbers.length +> With <= the loop would also read numbers[length], and that slot does not exist. + +? What should the maximum start with before the loop begins? +→ Sum and maximum +- [ ] Always with 0 +- [x] With the first value of the array +- [ ] With the length of the array +> If it starts with 0, then with only negative numbers the result would be 0, although 0 is not in the array at all. + +? What does \`output: numbers.length\` output with \`int[] numbers = {5, 10, 15, 20}\`? +→ Many values under one name +- [ ] 3 +- [x] 4 +- [ ] 20 +> length is the number of slots, not the last index and not the last value. + +? Which line creates an array with three numbers in Java? +→ Now in Java +- [x] int[] numbers = {1, 2, 3}; +- [ ] int numbers = [1, 2, 3]; +- [ ] array numbers = (1, 2, 3); +::: +`,b4=`--- +titel: Two-dimensional arrays +bereich: Basics +kurz: Store values in rows and columns, like the seats in a cinema, and go through them with two nested loops. +--- + +## Skills I will gain now + +::: kompetenzen +- create a 2D array and explain what the two numbers mean +- read and write a slot with a row and a seat +- tell \`seats.length\` and \`seats[0].length\` apart +- explain in which order two nested loops visit the slots +- create and go through a two-dimensional array in Java +::: + +## A cinema as a table + +A cinema has several **rows**, and every row has several **seats**. For every seat we want to remember whether its ticket has already been sold. That is a yes-or-no question, so the data type \`boolean\` fits: \`true\` means sold, \`false\` means free. + +A normal array is one single row of slots. For the cinema we need a **table** with rows and columns. That is a **two-dimensional array**, 2D array for short. You write two pairs of square brackets for it: + +\`\`\` +boolean[][] seats = new boolean[3][5] +\`\`\` + +That gives 3 rows with 5 seats each, so 15 slots. At the start every slot holds \`false\`: all seats are free. + +::: grafik kino-saal.svg +The first index is the row, the second the seat. Both are counted from 0. +::: + +## Reach a slot + +For a slot you now need **two** indices: first the row, then the seat. + +\`\`\` +seats[1][2] = true +\`\`\` + +Now seat 2 in row 1 is sold. Reading works the same way: \`seats[1][2]\` is now \`true\`. + +You can also ask for the size: + +- \`seats.length\` is the number of **rows**, here 3. +- \`seats[0].length\` is the number of **seats** in row 0, here 5. + +::: diagramm kino-verkaufen.visustruct +Three tickets are sold. After that, the diagram outputs the size of the cinema and whether row 1, seat 2 is sold. Watch under Variables in the simulation: seats is shown row by row. +::: + +> Just like with a normal array, there is no slot \`seats[3][0]\`, because the rows are called 0, 1 and 2. The simulation then reports an invalid expression. + +## Two loops inside each other + +To look at **all** seats, you need two for loops inside each other: + +- The **outer loop** counts the row: \`row\` runs from 0 to 2. +- The **inner loop** counts the seat: \`seat\` runs from 0 to 4. + +::: grafik kino-schleifen.svg +Blue is the outer loop, orange the inner one. The numbers show the order in which the seats come up. +::: + +For every row, the inner loop runs **all the way** through once. Only when \`seat\` has visited all five seats does the outer loop move \`row\` on by one. Then \`seat\` starts at 0 again. That way all 3 · 5 = 15 seats come up exactly once. + +The conditions are \`row < seats.length\` and \`seat < seats[row].length\`. That way the loops fit a cinema of any size. + +::: diagramm kino-saalplan.visustruct +The seating plan: for every row, a line of X (sold) and O (free) is put together and output. Go through it with Step and watch how seat keeps starting again from the beginning while row only slowly counts on. +::: + +::: angeberwissen +Every phone photo is a 2D array! A photo with 4000 · 3000 pixels has 3000 rows with 4000 slots each, so 12 million pixels. Every slot holds the colour of one dot. When you make a photo brighter, the phone runs over all the pixels with two nested loops. My profile picture, by the way, has only one slot: brown. +::: + +## Exercise: Count free seats + +::: übung kino-frei +titel: Count free seats +auftrag: In the start diagram three tickets have already been sold. Use two nested loops to count how many seats are still **free**, and output e.g. \`Free: 12\`. +start: kino-frei-start.visustruct +test: - -> Free: 12 +braucht: forSchleife, verzweigung +tipp: Just like for the seating plan, you go over all seats with two loops. Instead of outputting something, you count. +tipp: Before the loops, create \`int free = 0\`. A seat is free if \`seats[row][seat]\` is false. The condition for that is \`!seats[row][seat]\`. +lösung: kino-frei-loesung.visustruct +::: + +## Exercise: Sell a ticket + +::: übung kino-karte +titel: Sell a ticket +auftrag: The start diagram asks for a row and a seat. If the seat is already sold, output \`Already sold\`. Otherwise mark it as sold and output e.g. \`Sold: row 0, seat 4\`. +start: kino-karte-start.visustruct +test: 1, 2 -> Already sold +test: 0, 4 -> Sold: row 0, seat 4 +test: 2, 0 -> Sold: row 2, seat 0 +braucht: verzweigung +tipp: First check whether the seat is sold. Depending on the answer, something different happens. +tipp: You do not need a loop here. A branch with the condition \`seats[row][seat]\` is enough. In the false path you set the slot to \`true\`. +lösung: kino-karte-loesung.visustruct +::: + +## Exercise: Times table grid + +::: übung kino-einmaleins +titel: Times table grid +auftrag: Create \`int[][] table = new int[10][10]\` and fill it with the times tables up to 10 using two loops. Then ask for two numbers from 1 to 10 and read the result from the table, e.g. \`3 · 4 = 12\`. +test: 3, 4 -> 3 · 4 = 12 +test: 7, 8 -> 7 · 8 = 56 +test: 10, 10 -> 10 · 10 = 100 +braucht: forSchleife +tipp: First two nested loops fill the table; after that you read only one single slot. +tipp: The indices run from 0 to 9, but the numbers from 1 to 10. That is why the slot \`table[i][j]\` holds the value \`(i + 1) * (j + 1)\`, and for 3 · 4 you read \`table[a - 1][b - 1]\`. +lösung: kino-einmaleins-loesung.visustruct +::: + +## Now in Java + +The cinema looks like this in Java: + +\`\`\`java +boolean[][] seats = new boolean[3][5]; +seats[0][2] = true; +seats[1][1] = true; +seats[1][2] = true; +System.out.println("Rows: " + seats.length); +System.out.println("Seats per row: " + seats[0].length); +System.out.println("Row 1, seat 2 sold? " + seats[1][2]); +\`\`\` + +- Two pairs of square brackets \`[][]\` stand for a table: first the row, then the seat. +- \`seats.length\` is the number of rows, \`seats[0].length\` the number of seats in one row. +- With fixed values you write every row in its own curly brackets: \`int[][] t = {{1, 2}, {3, 4}};\` + +::: übung l16-java-punkte +titel: Add up the points +code: java +auftrag: Three players have played two rounds each. Create the table \`points\` in Java with the rows {3, 5}, {4, 1} and {2, 2}. Add up all points with two nested for loops and output **Sum: 17**. +test: - -> Sum: 17 +braucht: forSchleife +tipp: The outer loop goes through the rows, the inner one through the seats of a row. +tipp: \`int[][] points = {{3, 5}, {4, 1}, {2, 2}};\` and in the inner loop \`sum = sum + points[i][j];\`. The inner loop runs up to \`points[i].length\`. +lösung: l16-java-punkte-loesung.visustruct +::: + +## Fill in the gaps: tables + +::: lückentext +titel: Adding up all fields +auftrag: The program adds up all numbers in the table. Fill in the missing words and symbols. +\`\`\`java +[[int]][][] grid = {{1, 2, 3}, {4, 5, 6}}; +int sum = 0; +for (int r = 0; r < grid.[[length]]; r++) { + for (int c = 0; c < grid[r].[[length]]; c++) { + sum = sum [[+]] grid[r][c]; + } +} +System.out.println("Sum: " + sum); +\`\`\` +erklärung: \`int[][]\` is a table. \`grid.length\` is the number of rows (2), \`grid[r].length\` the number of fields in row \`r\` (3). Output: **Sum: 21** +::: + +## Find the bug: points + +::: übung l16-java-fehler +titel: Fix player 2 +code: java +auftrag: In the table \`points\` each row stands for one player. The program should add up the points of player 2 (row 1), so **Player 2: 11**. Instead it reports an error. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l16-java-fehler-start.visustruct +test: - -> Player 2: 11 +braucht: forSchleife +tipp: In \`points[a][b]\`, \`a\` is the row and \`b\` the place in the row. Which number stands for the row of player 2? +tipp: The indices are swapped: \`points[1][j]\` instead of \`points[j][1]\`. +lösung: l16-java-fehler-loesung.visustruct +::: + +## Game: Which seat? + +::: spiel frage +titel: Game: Which seat? +intro: Ludwig is selling cinema tickets. First the row, then the seat, both from 0. Seven rounds. + +runde: + boolean[][] seats = new boolean[3][5]; + System.out.println(seats.length); +frage: What is output? +- [x] 3 +- 5 +- 15 +> \`seats.length\` is the number of rows. + +runde: + boolean[][] seats = new boolean[3][5]; + System.out.println(seats[0].length); +frage: What is output? +- 3 +- [x] 5 +- 15 +> \`seats[0]\` is row 0. Its length is the number of seats in this row. + +runde: + int[][] table = new int[4][6]; +frage: How many slots does the table have? +- 10 +- [x] 24 +- 35 +> 4 rows with 6 seats each: 4 · 6 = 24. + +runde: + int[][] t = {{1, 2}, {3, 4}}; + System.out.println(t[1][0]); +frage: What is output? +- 2 +- [x] 3 +- 4 +> Row 1 is \`{3, 4}\`, and seat 0 in it is the 3. + +runde: + boolean[][] seats = new boolean[3][5]; + seats[3][0] = true; +frage: What happens? +- The first seat in row 3 is sold. +- The first seat in the last row is sold. +- [x] There is an error, because the rows are called 0, 1 and 2. +> Just like with a normal array, the last index is one less than the length. + +runde: + int[][] t = {{1, 2, 3}, {4, 5, 6}}; + int sum = 0; + for (int row = 0; row < t.length; row++) { + for (int seat = 0; seat < t[row].length; seat++) { + sum = sum + t[row][seat]; + } + } + System.out.println(sum); +frage: What is output? +- 6 +- 15 +- [x] 21 +> The two loops visit all six slots: 1 + 2 + 3 + 4 + 5 + 6 = 21. + +runde: +frage: Two loops go through the cinema \`new boolean[3][5]\`. Which slot comes right after \`seats[0][4]\`? +- \`seats[0][5]\` +- [x] \`seats[1][0]\` +- \`seats[1][4]\` +> Row 0 is done. The outer loop counts on, and the seat starts again at 0. +::: + +## 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. + +::: checkliste +- I can create a 2D array and explain what the two numbers mean. → A cinema as a table +- I can read and write a slot with a row and a seat. → Reach a slot +- I can tell \`seats.length\` and \`seats[0].length\` apart. → Reach a slot +- I can explain in which order two nested loops visit the slots. → Two loops inside each other +- I can create and go through a two-dimensional array in Java. → Now in Java +::: + +## Quiz + +::: quiz +? How many slots does \`boolean[][] seats = new boolean[4][6]\` have? +→ A cinema as a table +- [ ] 10 +- [x] 24 +- [ ] 46 +> 4 rows with 6 seats each: 4 · 6 = 24. + +? What is in all slots after \`new boolean[3][5]\`? +→ A cinema as a table +- [ ] true +- [x] false +- [ ] Nothing, the slots are empty +> A new boolean array is filled with false. In the cinema that means: all seats are free. + +? Two nested loops run over 3 rows with 5 seats. How often does the inside of the **inner** loop run? +→ Two loops inside each other +- [ ] 3 times +- [ ] 8 times +- [x] 15 times +> For each of the 3 rows the inner loop runs 5 times: 3 · 5 = 15. + +? Match what each expression means in the cinema. +→ Reach a slot += seats.length -> Number of rows += seats[0].length -> Number of seats in row 0 += seats[2][4] -> Row 2, seat 4 += seats[1][0] = true -> Seat 0 in row 1 is sold + +? What does \`seats.length\` give for \`new boolean[3][5]\`? +→ Reach a slot +- [x] 3, the number of rows +- [ ] 5, the number of seats +- [ ] 15, all seats together +::: +`,x4=`--- +titel: Strings +bereich: Basics +kurz: Work with text: read single characters, cut out parts, search, compare and split. +--- + +## Skills I will gain now + +::: kompetenzen +- explain that the characters of a String are also counted from 0 +- work with \`length()\` and \`charAt(i)\` +- tell a \`char\` from a String and use the character code with \`(int)\` and \`(char)\` +- cut a part out of a text with \`substring\` +- use \`indexOf\`, \`contains\`, \`toUpperCase\` and \`equals\` +- go through a text character by character with a loop +- split a text into a String array with \`split\` +- read a text in Java and compare it with \`equals\` +- use more methods such as \`lastIndexOf\`, \`replace\`, \`compareTo\` and \`Integer.parseInt\` +- split a text from a file into lines with \`split("\\n")\` +- look up a method in the Java API and read its description +::: + +## Text is a row of characters + +You already know \`String\`: \`String name = "Ludwig"\`. In computer science such a text is called a **string**, because the characters hang one after another like beads on a string. Every character has a place with an index, just like in an array. Here, too, **counting starts at 0**: the first character is 0 steps away from the start. + +::: grafik zk-zeichen.svg +The nine characters of “Billygoat” with their indices 0 to 8. +::: + +A String comes with **methods**. You write the name of the variable, a dot and the method: + +- \`word.length()\` gives the number of characters, here 9. +- \`word.charAt(0)\` gives the character with the index 0, here \`'B'\`. + +> With Strings you write \`length()\` **with** brackets, with arrays \`length\` **without**. Sadly, that is just how Java is. + +Just like in an array, the last character has the index \`length() - 1\`. + +## A single character: char + +Java has its own data type for a single character: **char**, short for *character*. A \`char\` goes in **single** quotation marks, a String in double ones: + +- \`'C'\` is a \`char\`: exactly one character. +- \`"C"\` is a String: a text that is only one character long. +- A \`char\` always holds exactly one character. There is no empty \`char\` like \`''\`, but there is an empty String \`""\`. + +\`charAt\` gives you such a character from a text: + +\`\`\` +char first = word.charAt(0) +char last = word.charAt(word.length() - 1) +\`\`\` + +You compare two \`char\` values with \`==\`: \`word.charAt(0) == 'B'\` is \`true\`. + +Behind every character there is a number, its **character code**. Which number belongs to which character is listed in the ASCII table: \`'A'\` has the code 65, \`'B'\` 66, \`'C'\` 67 and so on up to \`'Z'\` with 90. With \`(int)\` you get the code of a character, with \`(char)\` a code turns back into a character: + +\`\`\` +int code = (int) 'C' +code = code + 1 +char next = (char) code +\`\`\` + +After that \`code\` is 68 and \`next\` is \`'D'\`. This is how you shift a letter in the alphabet, and that is exactly what you will need later for the Caesar cipher. + +## Cut out parts + +With \`substring\` you cut a part out of the text: + +- \`word.substring(0, 5)\` gives the characters from index 0 **up to just before** index 5, so \`"Billy"\`. +- \`word.substring(5)\` gives everything from index 5 to the end, so \`"goat"\`. + +The end is **not** included. Handy: \`substring(0, 5)\` gives exactly 5 characters. + +::: diagramm zk-zeichen.visustruct +All the methods from this lesson in one example. Go through it in the simulation and compare every output with the picture. +::: + +## Search and compare + +More methods you often need: + +| Method | Meaning | Example with \`"Billygoat"\` | +|---|---|---| +| \`indexOf("goat")\` | Where does the text start? | 5 | +| \`indexOf("x")\` | not found | -1 | +| \`contains("lly")\` | Does the text appear? | true | +| \`toUpperCase()\` | all capitals | BILLYGOAT | +| \`toLowerCase()\` | all small letters | billygoat | +| \`equals("Billygoat")\` | same text? | true | + +> In Java you compare two Strings with \`equals\`, not with \`==\`. Two single characters (\`char\`), on the other hand, you compare with \`==\`, e.g. \`word.charAt(i) == 'e'\`. + +::: angeberwissen +Try \`"Billygoat".equals("billygoat")\`. The answer is false! For a computer, B and b are completely different characters. Inside, every character is stored as a number: B is 66 and b is 98. This numbering is called ASCII and dates from 1963. Baah, so for a computer Ludwig and ludwig are two different goats. I am the one with the capital L. +::: + +## Character by character + +With a for loop you go through a text character by character. The index \`i\` runs from 0 to \`word.length() - 1\`, just like with an array: + +::: diagramm zk-zaehlen.visustruct +Counts how often the letter e appears. In the simulation, try “cheese” and watch i and count. +::: + +## Split with split + +Often several pieces of information sit in one single line, separated by a character, e.g. \`"Ludwig;billy goat;7"\`. With \`split\` you cut the line apart at this character. The result is a **String array**: + +\`\`\` +String[] parts = line.split(";") +\`\`\` + +After that, \`parts[0]\` is \`"Ludwig"\`, \`parts[1]\` is \`"billy goat"\` and \`parts[2]\` is \`"7"\`. With \`parts.length\` you find out how many parts there are. + +::: diagramm zk-split.visustruct +The line is split at the semicolon, and every part is output with its index. +::: + +> CSV files, which you know from spreadsheets, are built the same way: one line per record, the values separated by a comma or semicolon. + +## Exercise: Initials + +::: übung zk-initialen +titel: Initials +auftrag: Ask for a first name and a last name and output the initials. So for Ludwig Billygoat that is \`L. B.\` +test: Ludwig, Billygoat -> L. B. +test: Ada, Lovelace -> A. L. +test: Ben, Shneiderman -> B. S. +braucht: anweisung +tipp: The initial is the first letter of a name. Which method gives the character at a particular place? +tipp: \`firstName.charAt(0)\` gives the first letter. The output is then \`firstName.charAt(0) + ". " + lastName.charAt(0) + "."\` +lösung: zk-initialen-loesung.visustruct +::: + +## Exercise: Backwards + +::: übung zk-rueckwaerts +titel: Backwards +auftrag: Ask for a word and output it backwards. Ludwig becomes \`giwduL\`. +test: Ludwig -> giwduL +test: Anna -> annA +test: a -> a +braucht: forSchleife +tipp: Go through the word character by character, but from back to front, and build a new text as you go. +tipp: Create \`String backwards = ""\`. The loop starts at the last index \`word.length() - 1\` and counts down to 0 with \`i--\`. In every pass you add \`word.charAt(i)\` at the end. +lösung: zk-rueckwaerts-loesung.visustruct +::: + +## Exercise: Count words + +::: übung zk-woerter +titel: Count words +auftrag: Ask for a sentence and output how many words it has, e.g. \`Words: 4\` for “Ludwig is a goat”. The words are separated by exactly one space. +test: Ludwig is a goat -> Words: 4 +test: Hello -> Words: 1 +test: I like goats -> Words: 3 +braucht: anweisung +tipp: There is always a space between the words. Which method splits a text at a character? +tipp: Split the sentence into a String array with \`sentence.split(" ")\`. Its length is the number of words. +lösung: zk-woerter-loesung.visustruct +::: + +## Now in Java + +The methods in this lesson already are Java. A whole program with a text looks like this: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("What is your name?"); +String name = scanner.next(); +System.out.println("Hello " + name.toUpperCase() + "!"); +System.out.println("Your name has " + name.length() + " letters."); +\`\`\` + +- \`scanner.next()\` reads one word, that is text up to the next space. For numbers you keep using \`scanner.nextInt()\`. +- Text goes in **double** quotes \`"Ludwig"\`, a single character in **single** quotes \`'L'\`. +- \`length()\`, \`toUpperCase()\` and the other methods always have round brackets after them, even when nothing is inside. +- You compare two texts with \`equals\`. Every letter counts: \`"Ludwig".equals("ludwig")\` is false. + +::: übung l17-java-passwort +titel: Check the password +code: java +auftrag: Write a Java program that asks for the password. If it is **Ludwig**, it outputs **Welcome!**, otherwise **Wrong password**. + Mind upper and lower case: \`ludwig\` is wrong. +test: Ludwig -> Welcome! +test: ludwig -> Wrong password +test: Geißbock -> Wrong password +braucht: verzweigung +tipp: Read the password with \`scanner.next()\` into a String variable. Then compare it in a selection. +tipp: The condition is \`input.equals("Ludwig")\`. In Java, \`==\` does not reliably compare texts. +lösung: l17-java-passwort-loesung.visustruct +::: + +## Fill in the gaps: texts + +::: lückentext +titel: Examining a word +auftrag: Fill in the missing methods and words. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("A word?"); +[[String]] word = scanner.next(); +System.out.println("Length: " + word.[[length]]()); +System.out.println("Capitals: " + word.[[toUpperCase]]()); +System.out.println("First letter: " + word.[[charAt]](0)); +if (word.[[equals]]("Ludwig")) { + System.out.println("Hello Ludwig!"); +} +\`\`\` +erklärung: \`length()\` counts the characters, \`toUpperCase()\` makes everything upper case, \`charAt(0)\` gives the first character. You compare texts with \`equals\`, not with \`==\`. +::: + +## Find the bug: initials + +::: übung l17-java-fehler +titel: Fix the initials +code: java +auftrag: The program reads a first name and a last name and should output the initials. For Ludwig Geißbock that is **L. G.** But it outputs **u. e.** + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l17-java-fehler-start.visustruct +test: Ludwig, Geißbock -> L. G. +test: Mia, Meyer -> M. M. +test: Ada, Lovelace -> A. L. +braucht: anweisung +tipp: At which index does Java start counting? +tipp: The first character has the index 0: \`first.charAt(0)\` and \`last.charAt(0)\`. +lösung: l17-java-fehler-loesung.visustruct +::: + +## Even more methods + +A String can do much more. You will often need these methods too: + +| Method | Meaning | Example | Result | +|---|---|---|---| +| \`lastIndexOf("l")\` | Where is the last l? | \`"Billygoat".lastIndexOf("l")\` | 3 | +| \`isEmpty()\` | Is the text empty? | \`"".isEmpty()\` | true | +| \`equalsIgnoreCase(…)\` | same text, whether upper or lower case? | \`"Billygoat".equalsIgnoreCase("BILLYGOAT")\` | true | +| \`replace(old, new)\` | replaces every occurrence | \`"Billygoat".replace("Billy", "Nanny")\` | Nannygoat | +| \`repeat(n)\` | the text n times in a row | \`"Baa".repeat(3)\` | BaaBaaBaa | +| \`concat(…)\` | adds text to the end, like \`+\` | \`"Billy".concat("goat")\` | Billygoat | +| \`compareTo(…)\` | Which comes first in the alphabet? | \`"Anna".compareTo("Ben")\` | -1 | + +\`compareTo\` returns a number: **negative** if the text comes earlier in the alphabet, **0** if both are the same, and **positive** if it comes later. You can use it to sort names. + +Two methods do not belong to a text but to a class. That is why the class name comes first: + +- \`Integer.parseInt("7")\` turns the text "7" into the number 7. You can calculate with it. +- \`String.valueOf(7)\` turns the number 7 into the text "7". + +::: diagramm zk-mehr.visustruct +All the new methods in one example. Go through it in the simulation and compare every output with the table. +::: + +## Text from a file + +Programs often get their text from a **file**. Princess Zora has written Ludwig a letter. It is ready as the file \`letter.txt\`: + +::: datei letter.txt +Dear Ludwig, +the fox has locked me in his tower. +The door has a lock with a secret word. +You can only find the word with Java. +Please help me! +Yours, Princess Zora +::: + +These lines read the whole file into a String: + +\`\`\` +import java.nio.file.*; + +String letter = Files.readString(Path.of("letter.txt")); +\`\`\` + +You will learn exactly how reading works later, in a lesson of its own about files. For now this is enough: afterwards the whole letter is in \`letter\`, with all its lines. + +At the end of every line there is an invisible character for the **line break**. In Java you write it as \`"\\n"\`. So \`letter.split("\\n")\` splits the letter into its lines. + +::: übung l17-java-brief +titel: Where is the fox? +code: java +auftrag: The start code already reads the letter. Split it into lines and output **Lines:** and the number of lines. Then find the line that contains **fox** and output **Fox in line** and its number. The first line has the number 1. +start: l17-java-brief-start.visustruct +test: - -> Lines: 6 | Fox in line 2 +braucht: forSchleife, verzweigung +tipp: \`String[] lines = letter.split("\\n");\` splits the letter. Then a for loop goes through all the lines. +tipp: In the loop you check \`lines[i].contains("fox")\`. The index starts at 0, so you output \`(i + 1)\`. You need the brackets so that Java calculates instead of adding 1 to the text. +lösung: l17-java-brief-loesung.visustruct +::: + +## The Java API + +Nobody knows all methods by heart, not even professionals. They look them up in the **Java API**. API stands for Application Programming Interface. It means the description of everything Java already brings along. + +You can find all methods of String here: [String in the Java API](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/String.html) + +Scroll down to the table **Method Summary**. Each row describes one method: + +| Column | Example | Meaning | +|---|---|---| +| Modifier and Type | \`int\` | What the method returns | +| Method | \`lastIndexOf(String str)\` | Name and parameters with their data type | +| Description | Returns the index within this string of the last occurrence … | What the method does | + +::: ludwig +The page is very long. Press Ctrl+F (on a Mac ⌘+F) and search for the name of the method to get there at once. +::: + +Look up these methods. They are not in this lesson: + +::: quiz +? Look up \`strip()\`. What does the method do? +- [ ] It removes all spaces in the text. +- [x] It removes the spaces at the beginning and the end. +- [ ] It cuts off the last character. +> Like \`trim()\`. But \`strip()\` also knows special spaces from other writing systems. + +? Look up \`isBlank()\`. What does \`" ".isBlank()\` return? +- [x] true +- [ ] false +- [ ] 3 +> isBlank checks whether the text is empty or only contains spaces. \`" ".isEmpty()\`, on the other hand, would be false. + +? Look up \`toCharArray()\`. Which data type does the method return? +- [ ] String +- [ ] String[] +- [x] char[] +> An array with all characters of the text, one element for each character. + +? Look up \`indexOf\` with two parameters. What does \`"Billygoat".indexOf("l", 3)\` return? +- [ ] 2 +- [x] 3 +- [ ] -1 +> The search only starts at index 3. The first l from there is at index 3. + +? Look up \`startsWith\`. Which data type does the method return? +- [x] boolean +- [ ] int +- [ ] String +> The column “Modifier and Type” says boolean: the answer is true or false. +::: + +## Game: Rescue the princess + +Now you help Ludwig. The fox has locked Princess Zora in his tower, and the gate only opens with a secret word. + +::: spiel prinzessin +titel: Game: Rescue the princess +intro: On the way to the tower Ludwig comes to **six stations**. Each one has a piece of Java code, and a number comes out. \`alphabet.charAt(number)\` turns the number into a letter that goes into the **crossword**. Solve the crossword, and the yellow squares spell the secret word for the gate. + +station: At the moat + String name = " Zora "; + int number = name.trim().length(); +frage: Which number is in \`number\`? +zahl: 4 +feld: 5 1 +tipp: \`trim()\` cuts off the spaces at the front and the back. Then count the characters. +> After \`trim()\` only \`"Zora"\` is left, and that is 4 characters. + +station: In the fox forest + String place = "Fox lair"; + int number = place.length(); +frage: Which number is in \`number\`? +zahl: 8 +feld: 4 4 +tipp: \`length()\` counts every character, the space too. +> F-o-x, the space and l-a-i-r make 8 characters. + +station: At the goat rock + String text = "Ludwig the goat"; + int number = text.indexOf(" "); +frage: Which number is in \`number\`? +zahl: 6 +feld: 4 6 +tipp: \`indexOf\` returns the position of the first space. The L has index 0. +> L u d w i g has the indexes 0 to 5, so the first space is at index 6. + +station: On the tower stairs + String word = "Princess"; + int number = word.indexOf("s", 7); +frage: Which number is in \`number\`? Look up \`indexOf(String str, int fromIndex)\` in the Java API. +zahl: 7 +feld: 6 6 +tipp: The search starts at index 7, and index 7 itself counts. Write the indexes under the letters. +> P r i n c e s s has the indexes 0 to 7. Searching from index 7, the first “s” is right at 7. + +station: In front of the fox den + int number = "Zora".compareTo("Zoe"); +frage: Which number is in \`number\`? +zahl: 13 +feld: 1 9 +tipp: \`compareTo\` looks for the first position where the texts differ and subtracts the character codes. \`'r'\` is 114, \`'e'\` is 101. +> “Zo” is the same, then \`'r'\` meets \`'e'\`: 114 − 101 = 13. + +station: At the tower gate + int number = Integer.parseInt("1" + "1") / 5; +frage: Which number is in \`number\`? +zahl: 2 +feld: 6 5 +tipp: First the texts are joined, then they become a number. With \`int\`, division drops the remainder. +> \`"1" + "1"\` is \`"11"\`, \`parseInt\` makes 11 of it, and 11 / 5 is 2 for whole numbers. + +kreuzwort: You already have the blue letters. Fill the other squares with Java terms. Click a clue to jump to its word. +- → 1 3 BOOLEAN: Data type for true or false +- → 4 1 STRING: Data type for text +- → 6 5 CHAR: Data type for a single character +- ↓ 1 6 LENGTH: Method that counts the characters of a string +- ↓ 2 1 ELSE: The “otherwise” part of a branch +- ↓ 3 3 BREAK: Jumps straight out of a loop +lösung: 1 3, 4 3, 2 6, 6 7, 7 3 + +tor: Ludwig stands in front of the gate. The lock compares your word with \`equals\`. Enter the secret word. + String word = "___"; + if (word.equals(secretWord)) { + gate.open(); + } +ende: Zora is free, and the fox has run off. The secret word was \`BREAK\`: with \`break\` you get out of any loop, and Zora gets out of the tower. +::: + +## 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. + +::: checkliste +- I can explain that the characters of a String are also counted from 0. → Text is a row of characters +- I can work with \`length()\` and \`charAt(i)\`. → Text is a row of characters +- I can tell a \`char\` from a String and use the character code with \`(int)\` and \`(char)\`. → A single character: char +- I can cut a part out of a text with \`substring\`. → Cut out parts +- I can use \`indexOf\`, \`contains\`, \`toUpperCase\` and \`equals\`. → Search and compare +- I can go through a text character by character with a loop. → Character by character +- I can split a text into a String array with \`split\`. → Split with split +- I can read a text in Java and compare it with \`equals\`. → Now in Java +- I can use more methods such as \`lastIndexOf\`, \`replace\`, \`compareTo\` and \`Integer.parseInt\`. → Even more methods +- I can split a text from a file into lines with \`split("\\n")\`. → Text from a file +- I can look up a method in the Java API and read its description. → The Java API +::: + +## Quiz + +::: quiz +? What does \`"Ludwig".charAt(1)\` give? +→ Text is a row of characters +- [ ] L +- [x] u +- [ ] d +> Counting starts at 0: L has the index 0, u the index 1. + +? What is \`'C'\`? +→ A single character: char +- [x] a \`char\`, that is, exactly one character +- [ ] a String +- [ ] a variable called C +> Single quotation marks stand for a single character, a \`char\`. \`"C"\` in double ones would be a String. + +? \`'A'\` has the character code 65. What does \`(char) 67\` give? +→ A single character: char +- [ ] 'B' +- [x] 'C' +- [ ] 67 +> 65 is A, 66 is B, 67 is C. With \`(char)\` the code turns back into a character. + +? What does \`"Structure".substring(0, 6)\` give? +→ Cut out parts +- [x] Struct +- [ ] Structu +- [ ] tructu +> The characters with the indices 0 to 5. The end 6 is not included. + +? A word has 7 characters. Which index does the last character have? +→ Text is a row of characters +- [ ] 7 +- [x] 6 +- [ ] 8 +> Just like with an array: always one less than the length. + +? How do you compare two Strings for the same content in Java? +→ Search and compare +- [ ] a == b +- [x] a.equals(b) +- [ ] a = b + +? Match each method to what it gives for \`"Billygoat"\`. +→ Search and compare += length() -> 9 += charAt(0) -> B += indexOf("goat") -> 5 += substring(5) -> goat + +? Which condition checks in Java whether \`input\` contains the text Ludwig? +→ Now in Java +- [ ] input = "Ludwig" +- [ ] input == 'Ludwig' +- [x] input.equals("Ludwig") +> You compare texts with equals. Single quotes are only for a single character. + +? What does \`Integer.parseInt("12") + 1\` return? +→ Even more methods +- [ ] "121" +- [x] 13 +- [ ] an error message +> parseInt turns the text into a number. After that Java calculates as usual. +::: +`,v4=`--- +titel: Call and break +bereich: Basics +kurz: Split big tasks into subprograms and leave loops early. +--- + +## Skills I will gain now + +::: kompetenzen +- split a big task into smaller problems +- insert a call and build a subprogram in a tab of its own +- pass values to a subprogram with parameters +- hand back a return value with return and store it when calling +- explain why a subprogram cannot change a number but can change an array +- explain what a Break does and why it sits in a branch +- end a loop with a Break or through its condition +- recognise a method in Java and leave a loop with \`break\` +::: + +## Split big tasks + +Long structure charts quickly get confusing. That is why you split a big task into **smaller problems**. Every smaller problem gets a name of its own and a structure chart of its own, a **subprogram**. + +A quiz, for example, has three parts: greet, ask questions, show the result. The main program only names these three parts: + +::: diagramm l15-hauptprogramm.visustruct +The main program is made of just three calls. What happens in each part is in a structure chart of its own. +::: + +That way you see at a glance how the program is built. The details are somewhere else. + +## The call + +A **call** is a box with double vertical lines on the left and right. It means: run the subprogram with this name here, then carry on. + +- You drag **Call** from the Elements area and type the name into it, e.g. \`showGreeting()\`. +- The round brackets at the end show that it is a subprogram. That is how you write it in Java, Python and JavaScript, too. +- You build the subprogram itself as a structure chart of its own in a new tab. As the title you type the same name. + +::: diagramm l15-unterprogramm.visustruct +The subprogram showGreeting() as a structure chart of its own. +::: + +> **In the simulation:** When the simulation reaches a call, it looks among the open tabs for the structure chart with this title and runs it. Then it carries on in the main program. While the subprogram is running, the call box stays highlighted. A subprogram like this one, with only a name as its title, shares its variables with the main program. You will soon learn how a subprogram gets variables of its own. If there is no matching tab, the simulation skips the call and shows a note. + +::: angeberwissen +Why does your teacher always say “method” in Java and never “function” or “procedure”? Because in Java every subprogram has to belong to a class, and the subprograms of a class are called methods. The difference still exists, though: if a method hands back a result, it is really a function. If it has \`void\` in front, it hands back nothing and is really a procedure. Java just keeps it simple and calls both methods. So do I: my method is called Munching. +::: + +## Exercise: Add a call + +::: übung l15-titel +titel: Greeting with a call +auftrag: Imagine the subprogram \`showTitle()\` already exists. Build the main program: first it calls \`showTitle()\`. Then it asks for a name and outputs **Hello** and the name. + So when Ada is typed in, **Hello Ada** appears. +test: Ada -> Hello Ada +test: Ben -> Hello Ben +braucht: aufruf +tipp: The main program has three parts: the call, the input and the output. +tipp: Drag a Call from the Elements area right to the top and type \`showTitle()\` into it. Below it come the input \`input: String name "What is your name?"\` and the output. +lösung: l15-titel-loesung.visustruct +::: + +## Pass values: parameters + +Often a subprogram should work with values that are only known when it is called. Then it gets a **header line** as its title: + +\`\`\` +void showSum(int a, int b) +\`\`\` + +- \`void\` means: the subprogram does not hand back a result. +- \`showSum\` is the name. +- The brackets hold the **parameters**: variables with a data type that get their values when the subprogram is called. You separate several of them with commas. + +::: diagramm l15-zeige-summe.visustruct +The subprogram with the header line as its title. It calculates with a and b as if they were normal variables. +::: + +In the call box you write the values in the brackets, e.g. \`showSum(3, 4)\`. The first value goes into \`a\`, the second into \`b\`. Instead of numbers you can also use variables and calculations such as \`showSum(x, x + 1)\`. + +::: diagramm l15-zeige-summe-haupt.visustruct +The main program calls showSum twice with different values. Open both diagrams and start the simulation here. +::: + +> **Local variables:** The parameters and all variables created in the subprogram belong only to the subprogram. It gets **copies** of the values; more on that below under call by value. During the call, the simulation only shows the variables of the subprogram. + +## Hand back a result: return + +A subprogram can also hand back a result, the **return value**. Then the header line has the data type of the result instead of \`void\`: + +\`\`\` +int square(int x) +\`\`\` + +The statement \`return result\` hands back the value and ends the subprogram straight away. When you call it, you store the result in a variable: after \`int q = square(5)\`, \`q\` holds the value 25. + +::: diagramm l15-quadrat.visustruct +The subprogram square calculates and hands back the result with return. +::: + +::: diagramm l15-quadrat-haupt.visustruct +The main program stores the return value in q. Open both diagrams and try the simulation. +::: + +> A subprogram with a return value has to end with \`return\`. If the return is missing, the simulation reports an error. + +In the **code view**, the header line becomes a Java method (\`public static int square(int x)\`), a \`def\` in Python and a \`function\` in JavaScript. If the subprograms are open in other tabs, they appear in the code together with the main program. + +## Exercise: Calculate the area + +::: übung l15-flaeche +titel: Calculate the area +auftrag: Build two diagrams. The subprogram \`int area(int a, int b)\` hands back the area of a rectangle, that is a times b. The main program asks for the length and the width, calls \`area\` and outputs **Area:** and the result. + With 3 and 4, **Area: 12** appears. +test: 3, 4 -> Area: 12 +test: 5, 5 -> Area: 25 +test: 7, 0 -> Area: 0 +braucht: aufruf +tipp: You build two diagrams: a subprogram that only calculates and hands back the result, and a main program for input and output. +tipp: Open a new tab with **+** and give it the title \`int area(int a, int b)\`. One statement is enough inside: \`return a * b\`. In the main program you type \`int f = area(length, width)\` into the call box. +lösung: l15-flaeche-loesung.visustruct +unterprogramm: l15-flaeche-unterprogramm-loesung.visustruct +::: + +## Copy or original: call by value and call by reference + +What happens if a subprogram changes its parameter? That depends on **what** is passed. + +**Call by value:** With \`int\`, \`double\`, \`boolean\`, \`char\` and \`String\`, the subprogram gets a **copy** of the value. If it changes its parameter, the caller's variable stays as it was. + +**Call by reference:** With an **array**, the subprogram does not get a copy but a reference to the same array. If it changes a slot, the slot is changed for the caller too. The header line for this looks like this: + +\`\`\` +void clear(boolean[] seats) +\`\`\` + +::: grafik uebergabe.svg +At the top, doubleIt gets a copy of number. At the bottom, row and seats point to the same array. +::: + +Try out both. Open the three diagrams and start the simulation in the main program: + +::: diagramm uebergabe-verdopple.visustruct +doubleIt only changes its copy x. +::: + +::: diagramm uebergabe-leeren.visustruct +clear sets all seats to false, for example when a showing is cancelled. +::: + +::: diagramm uebergabe-haupt.visustruct +number is still 5 after the call. The seats in row, on the other hand, are free after the call. +::: + +> If you want to get a number back from a subprogram, use \`return\`, e.g. \`number = doubleIt(number)\` with the header line \`int doubleIt(int x)\`. An array, on the other hand, can be changed by the subprogram directly. + +::: angeberwissen +Strictly speaking, Java only knows call by value. But with an array, the whole array is not copied, only its **address** in memory. With the copied address, the subprogram finds the same array. It is as if I gave you a copy of my locker key: the key is copied, but the hay in the locker only exists once. +::: + +## Exercise: Bonus points + +::: übung uebergabe-bonus +titel: Bonus points +auftrag: The main program calls \`bonus(points)\` and then outputs all the points. Build the subprogram \`void bonus(int[] points)\` that increases every score in the array by 1. Instead of 3, 5 and 8 you then see **4**, **6** and **9**. +start: uebergabe-bonus-start.visustruct +test: - -> 4 | 6 | 9 +braucht: aufruf +tipp: The main program is already finished. You only build the subprogram in a new tab. +tipp: Open a new tab with **+** and the title \`void bonus(int[] points)\`. Inside, a for loop runs over all slots and calculates \`points[i] = points[i] + 1\`. You do not need a return, because the array is changed directly. +lösung: uebergabe-bonus-loesung.visustruct +unterprogramm: uebergabe-bonus-unterprogramm-loesung.visustruct +::: + +## The break + +Sometimes a loop should end **early**, in the middle of its body. That is what the **Break** is for. It leaves the loop it is in straight away. The program carries on with the first box after the loop. In Java, Python and JavaScript this is called \`break\`. + +You recognise the Break by the point on its left edge. You can write a short comment into the box, e.g. \`Leave the loop\`. It appears in the code as a comment after \`break\`. + +A Break almost always sits in a **branch**: the loop is only left if a condition is met. + +A typical case is the **endless loop with a Break**. The loop itself has no condition. It runs until the Break is reached: + +::: diagramm l15-endlos-aussprung.visustruct +The loop keeps asking for a number. With 0 it jumps out, otherwise it adds the number to the sum. +::: + +Without a Break, an endless loop would really never end. + +## Break in the simulation + +The simulation runs the Break like \`break\`: it leaves the innermost loop and carries on after it. If a Break is outside every loop, the subprogram ends; in the main program, the whole program ends. \`return\` does the same. + +Often you can do without a Break altogether: you write the stop condition straight into the loop. That is usually even clearer. + +## Exercise: Sum until 0 + +::: übung l15-bis-null +titel: Sum until 0 +auftrag: Rebuild the program “Sum until 0” **without** a Break. It keeps asking for whole numbers until someone types 0. Then it outputs **Sum:** and the sum of all the numbers typed in. +test: 3, 4, 0 -> Sum: 7 +test: 0 -> Sum: 0 +test: 10, -2, 5, 0 -> Sum: 13 +tipp: Without a Break, the condition of the loop itself has to check whether 0 was typed in. +tipp: Ask for the first number before the loop. The while loop runs with the condition \`number != 0\`. In the body you add the number to the sum and then ask for the next number. For the second input you only write \`input: number "…"\`, because \`number\` already exists. +lösung: l15-bis-null-loesung.visustruct +::: + +## Now in Java + +In Java a subprogram is called a **method**. The square from above looks like this: + +\`\`\`java +public static int square(int x) { + int result = x * x; + return result; +} +\`\`\` + +The main program calls the method by its name and passes the value in round brackets: + +\`\`\`java +int q = square(number); +System.out.println("The square is " + q); +\`\`\` + +- In the header, what the method returns (\`int\`) comes before the name. If it returns nothing, it says \`void\`. +- The parameters go in the round brackets with their data type: \`(int x)\`. You separate several with commas. +- In the Code area you write every method in its own tab, just as every subprogram has its own structure chart. +- In Java the exit is called \`break\`. With \`while (true)\` you build a loop that only ends through \`break\`. + +::: übung l18-java-kasse +titel: Till with break +code: java +auftrag: Write a till in Java. It keeps asking for a price in whole euros. At 0 it leaves the loop with \`break\`. Then it outputs how many items there were and what they cost altogether. + For 3, 4 and then 0 you see **Items: 2** and **Total: 7**. +test: 3, 4, 0 -> Items: 2 | Total: 7 +test: 0 -> Items: 0 | Total: 0 +test: 10, 2, 5, 0 -> Items: 3 | Total: 17 +braucht: endlosschleife, aussprung +tipp: You need two variables that start at 0 before the loop: one for the sum and one for the count. +tipp: Inside \`while (true) { … }\` you read the price. Right after that you check \`if (price == 0) { break; }\`. Only after that do you add the price to the sum and increase the count by 1. +lösung: l18-java-kasse-loesung.visustruct +::: + +## Fill in the gaps: methods and break + +::: lückentext +titel: Method and exit +auftrag: Fill in the missing words. At the top is the method that calculates a square. Below is the main program that calls it. In the Code area both are in tabs of their own. +\`\`\`java +public static [[int]] square(int x) { + [[return]] x * x; +} +\`\`\` +\`\`\`java +int number = 1; +while ([[true]]) { + int q = [[square]](number); + if (q > 50) { + [[break]]; + } + System.out.println(q); + number = number + 1; +} +\`\`\` +erklärung: \`int\` before the method name means: the method returns a whole number, with \`return\`. If a method returns nothing, it says \`void\` there. \`while (true)\` runs endlessly until \`break\` leaves the loop. Output: 1, 4, 9, 16, 25, 36 and 49. +::: + +## Find the bug: guessing + +::: übung l18-java-fehler +titel: Fix the try counter +code: java +auftrag: In this guessing game the secret number is 7. The program keeps asking for a guess until 7 comes, then it outputs the number of tries. For 3, 5 and 7 that was 3 tries, but the program says **Tries: 2**. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l18-java-fehler-start.visustruct +test: 3, 5, 7 -> Tries: 3 +test: 7 -> Tries: 1 +test: 1, 2, 3, 7 -> Tries: 4 +braucht: endlosschleife, aussprung +tipp: What happens with the right guess? Is it still counted before \`break\` leaves the loop? +tipp: Count first, then check: \`tries = tries + 1;\` belongs before the \`if\` with the \`break\`. +lösung: l18-java-fehler-loesung.visustruct +::: + +## Game: What comes back? + +::: spiel frage +titel: Game: What comes back? +intro: Ludwig calls methods and jumps out of loops. Predict what is output. Seven rounds. + +runde: + public static int square(int x) { + return x * x; + } + + int q = square(5); + System.out.println(q); +frage: What is output? +- 5 +- 10 +- [x] 25 +> The call puts 5 into x, and return gives back 5 · 5. + +runde: + public static void showSum(int a, int b) { + System.out.println(a + b); + } + + int x = 2; + showSum(x, x + 1); +frage: What is output? +- [x] 5 +- 23 +- 3 +> The first value 2 goes into a, the second value 3 into b. In Java, \`a + b\` calculates with numbers as usual. + +runde: +frage: What does a method return when \`void\` stands in front of its name? +- a whole number +- [x] nothing +- always 0 +> \`void\` means: no return value. With \`int\` there, a whole number comes back. + +runde: + public static void doubleIt(int x) { + x = x * 2; + } + + int number = 5; + doubleIt(number); + System.out.println(number); +frage: What is output? +- [x] 5 +- 10 +- 0 +> Call by value: doubleIt gets a copy. number stays 5. + +runde: + public static void clear(boolean[] seats) { + for (int i = 0; i < seats.length; i++) { + seats[i] = false; + } + } + + boolean[] row = {true, true}; + clear(row); + System.out.println(row[0]); +frage: What is output? +- true +- [x] false +> With an array, row and seats point to the same array. The caller sees the change too. + +runde: + int sum = 0; + for (int i = 1; i <= 10; i++) { + if (i == 4) { + break; + } + sum = sum + i; + } + System.out.println(sum); +frage: What is output? +- [x] 6 +- 10 +- 55 +> At i = 4, \`break\` jumps out of the loop straight away. Only 1 + 2 + 3 have been added. + +runde: + int number = 1; + while (true) { + number = number * 3; + if (number > 20) { + break; + } + } + System.out.println(number); +frage: What is output? +- 9 +- 20 +- [x] 27 +> 3, 9, 27. Only 27 is greater than 20, then the endless loop ends with break. +::: + +## 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. + +::: checkliste +- I can split a big task into smaller problems. → Split big tasks +- I can insert a call and build a subprogram in a tab of its own. → The call +- I can pass values to a subprogram with parameters. → Pass values: parameters +- I can hand back a return value with return and store it when calling. → Hand back a result: return +- I can explain why a subprogram cannot change a number but can change an array. → Copy or original: call by value and call by reference +- I can explain what a Break does and why it sits in a branch. → The break +- I can end a loop with a Break or through its condition. → Break in the simulation +- I can recognise a method in Java and leave a loop with \`break\`. → Now in Java +::: + +## Quiz + +::: quiz +? What does a call box with the text \`showResult()\` mean? +→ The call +- [ ] The program ends here. +- [x] The subprogram showResult() runs here, and then the program carries on. +- [ ] The word showResult() is output here. + +? Where does the program carry on after a Break? +→ The break +- [ ] At the start of the loop +- [x] At the first box after the loop +- [ ] Right at the start of the program +> The Break leaves the loop it is in. In Java, Python and JavaScript it is called break. + +? Why does a Break usually sit in a branch? +→ The break +- [x] So that the loop is only left if a condition is met +- [ ] Because otherwise a Break cannot be saved +- [ ] Because a branch is a loop itself +> Without a branch, the loop would be left in the very first pass. + +? Where does the simulation find the subprogram for a call \`showResult()\`? +→ The call +- [ ] It has to be in the same structure chart. +- [x] In an open tab with the title showResult() +- [ ] The simulation cannot run subprograms. +> Build every subprogram in a tab of its own and give it the name from the call as its title. + +? The subprogram has the header line \`void showSum(int a, int b)\`. Which call fits? +→ Pass values: parameters +- [ ] showSum() +- [x] showSum(3, 4) +- [ ] int s = showSum(3, 4) +> Two parameters need two values. And \`void\` means nothing comes back that you could store. + +? After \`int q = square(5)\`, q holds 25. What is at the end of the subprogram square? +→ Hand back a result: return +- [ ] output: x * x +- [x] return x * x +- [ ] q = x * x +> With return the subprogram hands the value back to the call. An output would only show it. + +? \`void doubleIt(int x)\` calculates \`x = x * 2\`. The main program has \`int number = 5\` and then the call \`doubleIt(number)\`. What value does number have afterwards? +→ Copy or original: call by value and call by reference +- [x] 5 +- [ ] 10 +- [ ] 0 +> Call by value: doubleIt only changed a copy of number. + +? \`void clear(boolean[] seats)\` sets all slots to false. What is true for the array row in the main program after \`clear(row)\`? +→ Copy or original: call by value and call by reference +- [ ] It is unchanged, because the subprogram gets a copy. +- [x] All slots are false, because seats and row are the same array. +- [ ] The array is deleted. +> Call by reference: an array is passed as a reference. The caller sees changes to the slots too. + +? What is a subprogram called in Java? +→ Now in Java +- [ ] Class +- [x] Method +- [ ] Loop +> In Java a subprogram is a method, for example the \`main\` method. Depending on its kind, it is also called a procedure or a function. + +? Many building blocks have a second name in textbooks. Match each term from VisuStruct to its other name. +→ Now in Java += Branch -> Conditional statement += Switch -> Multiple selection += Loop -> Iteration += Subprogram -> Method +> Both names mean the same thing. If you know one of them, you understand the other as well. + +? What is written in the header of a Java method that returns nothing? +→ Hand back a result: return +- [ ] int +- [x] void +- [ ] return +> void means “empty”: the method does something but returns no value. +::: +`,y4=`--- +titel: Searching and sorting +bereich: Basics +kurz: Use playing cards to understand how linear search, binary search and bubble sort work, and why some methods are much faster. +--- + +## Skills I will gain now + +::: kompetenzen +- explain how linear search goes through an array +- build a linear search as a structure chart +- explain why binary search only works with sorted values +- explain why binary search is much faster with many values +- show one round of bubble sort with playing cards +- search an array in Java and count matches +::: + +## Look for a card + +A pile of playing cards lies face down in a row in front of you. You are looking for the 9. What do you do? You turn over one card after another until you find the 9 or have turned over all the cards. + +::: grafik ss-lineare-suche.svg +The cards are mixed up. Every card you turn over is one comparison: is this the 9? +::: + +This is exactly how **linear search** works: it goes through the array from index 0 to the end and compares every slot with the value it is looking for. It always works, even if the values are mixed up. + +In the array our cards are numbers. We leave out jack, queen and king. + +::: diagramm ss-lineare-suche.visustruct +The loop runs until the card is found or there is no slot left. The variable comparisons counts how often a comparison was made. In the simulation, look for the 2, the 27 and the 4. +::: + +> If the card is not there, \`position\` stays at **-1**. There is no index -1, so here -1 means “not found”. + +## Exercise: Find a card + +::: übung ss-karte-suchen +titel: Find a card +auftrag: Create the array \`int[] cards = {8, 4, 11, 4, 6}\` and ask for a card. Output the position of the **first** matching card, e.g. \`Position: 1\` for the 4. If the card is not there, output \`Not found\`. +test: 4 -> Position: 1 +test: 6 -> Position: 4 +test: 8 -> Position: 0 +test: 9 -> Not found +braucht: whileSchleife, verzweigung +tipp: Go through the array from front to back and compare every card with the one you are looking for. +tipp: Rebuild the example above. You do not need the variable comparisons here. The loop has to stop as soon as \`position\` is no longer -1, otherwise for the 4 you find the second one instead of the first. +lösung: ss-karte-suchen-loesung.visustruct +::: + +## Binary search: sorted is faster + +Now the cards lie in front of you **sorted**, from small to large. You are looking for the 27. You no longer turn over the first card at the front, but the **middle** one: + +- If it is the one you are looking for, you are done. +- If it is smaller, the card you are looking for can only be on the right. The whole left half drops out. +- If it is larger, the right half drops out. + +You do the same again with the rest. With every comparison the pile is halved. + +::: grafik ss-binaere-suche.svg +Three comparisons instead of fourteen: with every middle, half of the remaining cards drop out. +::: + +In the structure chart, two variables remember the range that is still being searched: \`left\` and \`right\`. The middle is \`(left + right) / 2\`. Because this is whole-number division, the result is always a whole index. + +::: diagramm ss-binaere-suche.visustruct +The same array as for the linear search. In the simulation, look for the 27 again and compare the output Comparisons with the linear search. +::: + +> Binary search **only works with sorted values**. With mixed-up cards, after looking at the middle you do not know which half to keep searching in. + +::: angeberwissen +I think of a number from 1 to 100. You may guess, and I only say “higher” or “lower”. With binary search you need at most **7** guesses. For a number up to a million it is at most 20, for a billion 30. Every doubling costs only one single extra guess. This is how databases search millions of entries in a fraction of a second. I search linearly, by the way: I eat the meadow from left to right. +::: + +## How fast is it? + +How good a method is gets measured by the number of comparisons it needs **in the worst case**. For linear search, that is the case where the card is right at the back or missing. + +::: grafik ss-vergleiche.svg +With 100 cards, linear search needs up to 100 comparisons, binary search at most 7. +::: + +| Number of cards | Linear search | Binary search | +|---|---|---| +| 10 | 10 | 4 | +| 100 | 100 | 7 | +| 1,000 | 1,000 | 10 | +| 1,000,000 | 1,000,000 | 20 | + +Linear search grows at the same rate as the number of cards. With binary search, twice as many cards add only **one** comparison. + +## Sorting with bubble sort + +For binary search the values must be sorted. One of the simplest ways of sorting is **bubble sort**. You go through the row from left to right and always compare **two neighbours**. If the larger card is on the left, you swap the two. + +::: grafik ss-bubblesort.svg +After one round, the largest card is on the far right. +::: + +After the first round the largest card is on the far right, like an air bubble rising to the top. That is where the name comes from. Then you repeat the round for the remaining cards. With 5 cards you need 4 rounds. + +The structure chart has two for loops inside each other. The outer one counts the rounds, the inner one compares the neighbours \`cards[i]\` and \`cards[i + 1]\`. You already know how to swap: it needs a **temporary variable**. + +::: diagramm ss-bubblesort.visustruct +The inner loop gets shorter with every round, because the largest cards on the right are already in the right place. Go through it in the simulation with Step and watch the array under Variables. +::: + +Bubble sort is easy to understand, but slow. With n cards it needs up to n · (n − 1) / 2 comparisons: with 10 cards 45, with 100 cards already 4,950 and with 1,000 cards almost half a million. You may get to know faster methods such as quicksort later. + +## Exercise: Sort descending + +::: übung ss-absteigend +titel: Sort descending +auftrag: The start diagram reads in 5 cards and sorts them with bubble sort **ascending**, that is from small to large. Change it so that the cards are output **descending**, the largest first. +start: ss-absteigend-start.visustruct +test: 3, 1, 4, 1, 5 -> 5 | 4 | 3 | 1 | 1 +test: 10, 20, 30, 40, 50 -> 50 | 40 | 30 | 20 | 10 +test: 2, 9, 2, 7, 6 -> 9 | 7 | 6 | 2 | 2 +braucht: forSchleife, verzweigung +tipp: Look at the condition in the branch. It decides when two neighbours are swapped. +tipp: You only need to change one single character. When should two neighbours be swapped if the larger card is supposed to go to the left? +lösung: ss-absteigend-loesung.visustruct +::: + +## Now in Java + +The linear search from the exercise looks like this in Java: + +\`\`\`java +int[] cards = {8, 4, 11, 4, 6}; +int wanted = 4; +int position = -1; +int i = 0; +while (position == -1 && i < cards.length) { + if (cards[i] == wanted) { + position = i; + } + i = i + 1; +} +System.out.println("Position: " + position); +\`\`\` + +- \`&&\` means “and”: the loop only runs while nothing has been found **and** there are still cards left. +- If the false branch is empty, you simply leave out \`else\`. +- The swap in bubble sort needs a helper variable in Java too: \`int temp = cards[i];\` + +::: übung l19-java-zaehlen +titel: Count cards +code: java +auftrag: The cards {8, 4, 11, 4, 6} are in an array. Write a Java program that asks for a card and counts how often it appears. It outputs **Count:** and the number. + For 4 you see **Count: 2**. +test: 4 -> Count: 2 +test: 8 -> Count: 1 +test: 9 -> Count: 0 +braucht: forSchleife, verzweigung +tipp: Unlike the search, you do not stop at the first match. A for loop goes through all cards. +tipp: \`for (int i = 0; i < cards.length; i++)\` and inside it \`if (cards[i] == wanted) { count = count + 1; }\`. \`count\` starts at 0 before the loop. +lösung: l19-java-zaehlen-loesung.visustruct +::: + +## Fill in the gaps: bubble sort + +::: lückentext +titel: Sorting cards +auftrag: The program sorts the cards in ascending order with bubble sort. Fill in the missing words and symbols. +\`\`\`java +int[] cards = {5, 2, 8, 1}; +for (int round = 0; round < cards.[[length]] - 1; round++) { + for (int i = 0; i < cards.length - 1; i++) { + if (cards[i] [[>]] cards[i + 1]) { + [[int]] temp = cards[i]; + cards[i] = cards[i + 1]; + cards[i + 1] = [[temp]]; + } + } +} +for (int i = 0; i < cards.length; i++) { + System.out.println(cards[i]); +} +\`\`\` +erklärung: If a card is larger than its right neighbour, the two are swapped, with a helper variable as when swapping glasses. After \`length - 1\` rounds everything is sorted: 1, 2, 5, 8. +::: + +## Find the bug: search + +::: übung l19-java-fehler +titel: Fix the linear search +code: java +auftrag: The cards {8, 4, 11, 4, 6} are in an array. The program should output the **first** position of the card you are looking for, so for 4 **Position: 1**. But it outputs **Position: 3**. + “Open in editor” shows the code in the Code area. Find the bug, fix it and click Check. +start: l19-java-fehler-start.visustruct +test: 4 -> Position: 1 +test: 6 -> Position: 4 +test: 9 -> Position: -1 +test: 8 -> Position: 0 +braucht: whileSchleife, verzweigung +tipp: The loop always runs up to the last card. What happens when the 4 comes a second time? +tipp: The loop should stop as soon as something has been found: \`while (position == -1 && i < cards.length)\`. +lösung: l19-java-fehler-loesung.visustruct +::: + +## Game: Search pro + +::: spiel frage +titel: Game: Search pro +intro: Ludwig searches and sorts cards. How fast is it, and what comes out? Seven rounds. + +runde: + int[] cards = {8, 4, 11, 4, 6}; + int wanted = 4; + int position = -1; + int i = 0; + while (position == -1 && i < cards.length) { + if (cards[i] == wanted) { + position = i; + } + i = i + 1; + } + System.out.println("Position: " + position); +frage: What is output? +- [x] Position: 1 +- Position: 3 +- Position: 2 +> The search stops at the first 4. It lies in slot 1, counting from 0. + +runde: + int[] cards = {8, 4, 11, 4, 6}; + int wanted = 7; +frage: With the same linear search: what is in position afterwards? +- 0 +- 5 +- [x] -1 +> The 7 isn't there. position stays -1, which means "not found". + +runde: +frage: For which cards does binary search work? +- for all of them +- [x] only for sorted ones +- only for fewer than 100 +> Only if the cards are sorted do you know, after looking at the middle, in which half to keep searching. + +runde: +frage: How many comparisons does binary search need at most for 100 cards? +- 50 +- [x] 7 +- 100 +> Every comparison halves the pile. Halving 7 times is enough for up to 128 cards, so for 100 as well. + +runde: +frage: Instead of 1,000 cards there are now 2,000. How many more comparisons does binary search need at most? +- [x] one +- twice as many +- 1,000 +> The first comparison halves 2,000 to 1,000. After that it goes on as before. + +runde: + int[] cards = {5, 3, 8, 1}; +frage: One pass of bubble sort compares two neighbours at a time, from left to right. What is the order of the cards afterwards? +- 1, 3, 5, 8 +- [x] 3, 5, 1, 8 +- 3, 5, 8, 1 +> 5 and 3 swap, 5 and 8 stay, 8 and 1 swap. The biggest card is on the far right. + +runde: +frage: Bubble sort swaps \`cards[i]\` and \`cards[i + 1]\`. What does it need for that? +- [x] a temporary variable +- a second array +- a binary search +> Just like swapping two variables: \`int temp = cards[i];\`, otherwise a value gets lost. +::: + +## 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. + +::: checkliste +- I can explain how linear search goes through an array. → Look for a card +- I can build a linear search as a structure chart. → Exercise: Find a card +- I can explain why binary search only works with sorted values. → Binary search: sorted is faster +- I can explain why binary search is much faster with many values. → How fast is it? +- I can show one round of bubble sort with playing cards. → Sorting with bubble sort +- I can search an array in Java and count matches. → Now in Java +::: + +## Quiz + +::: quiz +? What does binary search need? +→ Binary search: sorted is faster +- [ ] The array must have exactly 100 slots. +- [x] The values must be sorted. +- [ ] The value you are looking for must be there. +> Only with sorted values do you know, after looking at the middle, which half to keep searching in. + +? A sorted array has 1,000 values. How many comparisons does binary search need at most? +→ How fast is it? +- [ ] 500 +- [ ] 100 +- [x] 10 +> 1,000 → 500 → 250 → 125 → 63 → 32 → 16 → 8 → 4 → 2 → 1: after about 10 halvings, one value is left. + +? What does bubble sort compare in every step? +→ Sorting with bubble sort +- [ ] The first and the last card +- [x] Two neighbouring cards +- [ ] Every card with the middle +> If the larger card is on the left, the neighbours are swapped. + +? Where is the largest card after the first round of bubble sort? +→ Sorting with bubble sort +- [ ] On the far left +- [ ] In the middle +- [x] On the far right +> It is swapped on with every comparison and rises to the right like a bubble. + +? What does \`position = -1\` mean in linear search? +→ Look for a card +- [x] The card has not been found (yet). +- [ ] The card is right at the back. +- [ ] The array is empty. + +? Match each method to the right description. +→ Look for a card += Linear search -> look at one card after another += Binary search -> look at the middle and drop one half += Bubble sort -> compare neighbours and swap them + +? Why do you use a for loop for counting and not a search that stops at the first match? +→ Now in Java +- [ ] A for loop is always faster. +- [x] You have to look at every card, otherwise later matches are missing. +- [ ] A while loop cannot go through arrays. +> The card can appear several times. That is why you go through all cards to the end. +::: +`,w4=`--- +titel: Structure chart and code +bereich: From structure chart to code +kurz: All elements in Java at a glance, generate code, write Java in the Code area, run it and find mistakes. +--- + +## Skills I will gain now + +::: kompetenzen +- open the code view and choose Java as the language +- recognise output, input, branches and loops in Java +- explain the difference between Snippet and Class +- rebuild a short Java program as a structure chart +- type Java in the Code area and read the structure chart that is built +- run a program with ▶︎ and use input and output in the console +- set breakpoints and follow a program step by step +::: + +## The code view + +In lessons 4 to 19 you have already written every element in Java. Here you see everything at a glance and learn how VisuStruct turns a whole structure chart into a Java program. + +A structure chart describes a process. For a computer to run it, you need a program in a programming language. VisuStruct writes this code for you. + +Click [Code](#zeige-code) in the tools (icon with angle brackets). On the right, the **Code generator** appears: + +- At the top you choose the language: **Java**, **Python** or **JavaScript**. +- For Java you also choose under **Java output** between **Snippet** (only the statements) and **Class** (a complete Java file). +- **Diagram text as comments** writes the text of every box as a comment above the code. +- **Copy** puts the code on the clipboard, **Save Java…** saves a \`.java\` file. + +The code changes straight away whenever you change something in the structure chart. + +::: angeberwissen +Later on, Nassi worked on the programming language Ada and was in charge of software at Apple. So if you invent structure charts, you do not end up in a goat shed, you end up at Apple. +::: + +::: diagramm l17-beispiel.visustruct +A small program with an input, a for loop and a branch. Open it and look at the Java code for it. +::: + +## This is the example in Java + +For the diagram above, VisuStruct generates this code as a **Snippet**: + +\`\`\` +// import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Which times table?"); +int number = scanner.nextInt(); +for (int i = 1; i <= 3; i++) { + int result = number * i; + System.out.println(i + " times " + number + " = " + result); +} +if (number > 10) { + System.out.println("That was hard!"); +} else { + System.out.println("That was easy."); +} +\`\`\` + +In Java every statement ends with a **semicolon** \`;\`. Whatever is inside a box goes in **curly brackets** \`{ }\` in Java. The indentation shows you what belongs together. + +## The elements in Java + +| Element | Java | Lesson | +|---|---|---| +| Statement | \`int sum = 0;\` | 4, 5 | +| Output | \`System.out.println(sum);\` | 6 | +| Input | \`int number = scanner.nextInt();\` | 6 | +| Branch | \`if (condition) { … } else { … }\` | 8, 9 | +| Switch | \`switch (value) { case 1 -> { … } default -> { … } }\` | 10 | +| While loop | \`while (condition) { … }\` | 11 | +| Do-while loop | \`do { … } while (condition);\` | 12 | +| For loop | \`for (int i = 0; i < 5; i++) { … }\` | 13 | +| Endless loop | \`while (true) { … }\` | 11, 18 | +| Break | \`break;\` | 18 | +| Call | \`calculate();\` | 18 | +| Array | \`int[] numbers = new int[5];\` | 15, 16 | +| Text (String) | \`String name = scanner.next();\` | 17 | + +For input, \`import java.util.Scanner;\` and \`Scanner scanner = new Scanner(System.in);\` are written once at the very top. Before every input VisuStruct outputs the question with \`System.out.println(…)\`. + +If the false path of a branch is empty, VisuStruct still generates an \`else\` part that contains only the comment \`// empty element\`. If you switch off **Emit empty else branch in code**, the empty \`else\` part disappears. + +## Snippet or Class + +You can paste a **Snippet** into the \`main\` method of an existing Java program. With **Class** you get a complete file that you can compile and run straight away: + +\`\`\` +import java.util.Scanner; + +public class TimesTable { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + System.out.println("Which times table?"); + int number = scanner.nextInt(); + ... + } // end main +} // end class +\`\`\` + +The comments \`// end main\` and \`// end class\` after the last two brackets are not needed, but very helpful: you see at once which bracket closes what, and you don't forget one. + +The name of the class comes from the **title** of the diagram. The file must have exactly the same name, so here \`TimesTable.java\`. **Save Java…** takes care of that for you. + +> The generated code is a good start, but check it. If you first create a variable and later read it in again with an input, VisuStruct still writes \`int pin = scanner.nextInt();\`. Java then reports that \`pin\` already exists. Simply delete the \`int\` in that line. + +::: angeberwissen +Every compiled Java file (\`.class\`) starts with the same four bytes, written in hexadecimal: \`CA FE BA BE\`. That is how the computer recognises it as Java. James Gosling came up with this “cafe babe”, to go with the coffee in the name. +::: + +## The Java language mode + +Under the [gear](#zeige-einstellungen) at the top right you can switch on **Code keywords**. Then the building blocks in the Elements area have the same names as the commands in Java: \`if\`, \`switch\`, \`for\`, \`while\`, \`do\`, \`while(true)\`, \`break\` and \`call\`. The rest of the interface stays in your language. + +This helps you match the boxes to the Java commands. Your diagram itself stays unchanged. + +## Write Java directly + +So far you drew the structure chart first and then looked at the code. In the [Code](#zeige-codelive) area it also works the other way round. Click the slim **Code** strip on the right. Next to the structure chart a column appears where you type Java yourself. + +- **Structure chart to code:** When you change something in the structure chart, the Java code changes right away. +- **Code to structure chart:** When you type Java, VisuStruct builds the structure chart as you type. If something is still missing, for example a closing bracket \`}\`, a hint appears below the code. +- **Suggestions:** While you type, VisuStruct suggests templates, for example for \`if\`, \`for\` or \`while\`. Press Enter to accept a template. Simply replace the grey placeholders with your own text. +- **Indent:** If your code has got messy, click the **Indent** button at the top of the Code area. Every level then sits four spaces deeper, as in Eclipse or IntelliJ. If you have selected lines, VisuStruct only indents those. + +So you can try both ways. Drawing the structure chart first is good for planning a process. Writing code directly is faster when you already know what you want. The structure chart then helps you check your code. + +## Run the program + +At the top of the Code area, [▶︎ Run](#zeige-ausfuehren) starts your program and **■ Stop** ends it, for example in an endless loop. What your program outputs appears below in the [console](#zeige-konsole). If it asks for input, type it there and press Enter. + +You can drag the border between code and console up or down with the mouse. + +> The Code area understands the Java commands that also exist as boxes in the structure chart. It does not know your own classes and objects yet. Windows with Swing work anyway: turn on **Real Java (with Swing)** under the gear (lesson “Your first window”). + +::: angeberwissen +Professionals call a program where you write code, run it and look for mistakes an **IDE** (Integrated Development Environment). With the Code area, VisuStruct is a small IDE with a built-in structure chart. +::: + +## Find mistakes with the debugger + +Sometimes a program runs but calculates something wrong. Then the **debugger** helps: it runs your program slowly while you watch. + +- **Breakpoint:** Click a line number on the left. A red dot appears. [▶︎ Run](#zeige-ausfuehren) pauses before this line. Click again to remove the dot. +- **Yellow line:** This line runs next. The matching box is selected in the structure chart. +- **Variables:** Below the code you see the current value of every variable. Whatever changed since the last pause lights up yellow for a moment. +- **Step:** The [Step](#zeige-einzelschritt) button next to ▶︎ runs exactly one line and pauses again. Without a breakpoint it starts the program and pauses before the first line. +- **Continue:** ▶︎ runs to the next breakpoint or to the end. **■ Stop** ends it. + +Try it with this program. Set a breakpoint on line 3 and press ▶︎ several times. How do \`i\` and \`summe\` grow? + +\`\`\` +int summe = 0; +for (int i = 1; i <= 4; i++) { + summe = summe + i; +} +System.out.println("Summe: " + summe); +\`\`\` + +::: ludwig +This is a desk check, except the computer takes the notes for you. Before each step, think about which value the variable should have next. When the table doesn't match your guess, you have found the place with the mistake. +::: + +## Exercise: Code first, then the structure chart + +This time you don't draw. Open the Code area and type in this Java code: + +\`\`\` +System.out.println("Start number?"); +int zahl = scanner.nextInt(); +while (zahl > 0) { + System.out.println(zahl); + zahl = zahl - 1; +} +System.out.println("Start!"); +\`\`\` + +::: übung l20-countdown +titel: Countdown +bereich: beide +auftrag: Type the Java code above into the Code area. Run it with ▶︎ and enter a start number in the console. + Then look at the structure chart that was built and click Check. +test: 3 -> 3 | 2 | 1 | Start! +test: 1 -> 1 | Start! +test: 0 -> Start! +braucht: whileSchleife +tipp: Open the Code area with the slim strip on the far right and just start typing. +tipp: Watch out for the semicolon at the end of every statement and the curly brackets of the while loop. A hint below the code tells you when something is still missing. +lösung: l20-countdown-loesung.visustruct +::: + +## Exercise: Java as a structure chart + +Now the other way round: here is a piece of Java code. Rebuild it as a structure chart. + +\`\`\` +System.out.println("Enter a number"); +int n = scanner.nextInt(); +int factorial = 1; +for (int i = 1; i <= n; i++) { + factorial = factorial * i; +} +System.out.println(factorial); +\`\`\` + +::: übung l17-fakultaet +titel: Factorial from Java +bereich: beide +auftrag: Rebuild the Java code above as a structure chart. The program reads in a number n and outputs the product 1 · 2 · … · n. + At the end, check in the code view whether your Java code looks the same. +test: 3 -> 6 +test: 5 -> 120 +test: 1 -> 1 +braucht: forSchleife +tipp: Read the Java code line by line and think about which box fits each line. +tipp: The first two Java lines together are one single input: \`input: int n "Enter a number"\`. The for loop has the three fields \`int i = 1\`, \`i <= n\` and \`i++\`. +lösung: l17-fakultaet-loesung.visustruct +::: + +## Exercise: else if + +In Java, several cases are often written as \`else if\`: + +\`\`\` +if (age < 6) { + System.out.println("Free entry"); +} else if (age < 18) { + System.out.println("Child ticket: 4 euros"); +} else { + System.out.println("Adult ticket: 8 euros"); +} +\`\`\` + +There is no \`else if\` in a structure chart. There, a second branch sits in the false path of the first one. If the false path holds only this one branch, VisuStruct turns it back into \`else if\` when it generates the code, and into \`elif\` in Python. + +::: übung l17-ticket +titel: Ticket price +auftrag: Ask for the age as a whole number and rebuild the Java code above as a structure chart. +test: 5 -> Free entry +test: 6 -> Child ticket: 4 euros +test: 17 -> Child ticket: 4 euros +test: 18 -> Adult ticket: 8 euros +braucht: verzweigung +tipp: In the Java code there is another \`if\` inside an \`else\`. In the structure chart that is a branch inside a path. +tipp: Drag a second branch with the condition \`age < 18\` into the false path of the first branch. +lösung: l17-ticket-loesung.visustruct +::: + +## Game: Which box? + +::: spiel frage +titel: Game: Which box? +intro: Ludwig shows you Java. Which box from the structure chart is behind it? Eight rounds. +frage: Which box is this? + +runde: + do { + number = number * 2; + } while (number < 100); +- While loop +- [x] Do-while loop +- For loop +> The condition is at the bottom. So the body runs at least once. + +runde: + switch (choice) { + case 1 -> { System.out.println("water"); } + default -> { System.out.println("There is no such button."); } + } +- Branch +- [x] Switch +- Call +> One variable is compared with fixed values: that is the switch. + +runde: + break; +- Call +- Endless loop +- [x] Break +> \`break\` leaves the loop it stands in straight away. + +runde: + calculate(); +- [x] Call +- Output +- Statement +> A name with round brackets: a subprogram is called here. + +runde: + int number = scanner.nextInt(); +- Output +- [x] Input +- Call +> The scanner reads in a value. That is an input. + +runde: + while (true) { + System.out.println("Hello"); + } +- While loop with a condition +- [x] Endless loop +- Do-while loop +> \`while (true)\` has no real condition. Only a break could end it. + +runde: +frage: You want a complete Java file that you can compile and run straight away. What do you choose in the code view? +- Snippet +- [x] Class +> A snippet is only the statements for the \`main\` method. Class creates the whole file. + +runde: +frage: In the debugger, a line is yellow. What does that mean? +- It has a mistake. +- [x] It runs next. +- There is a breakpoint there. +> Yellow is the next line. A breakpoint is a red dot at the line number. +::: + +## 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. + +::: checkliste +- I can open the code view and choose Java as the language. → The code view +- I can recognise output, input, branches and loops in Java. → The elements in Java +- I can explain the difference between Snippet and Class. → Snippet or Class +- I can rebuild a short Java program as a structure chart. → Exercise: Java as a structure chart +- I can type Java in the Code area and read the structure chart that is built. → Write Java directly +- I can run a program with ▶︎ and use input and output in the console. → Run the program +- I can set breakpoints and follow a program step by step. → Find mistakes with the debugger +::: + +## Quiz + +::: quiz +? What does \`output: "Hello"\` look like in Java? +→ The elements in Java +- [ ] print("Hello") +- [x] System.out.println("Hello"); +- [ ] console.log("Hello"); +> print is Python, console.log is JavaScript. + +? Where does the class name come from with Class? +→ Snippet or Class +- [ ] It is always called Main. +- [x] From the title of the diagram +- [ ] From the first box +> Without a title, the class is called Main. + +? Which Java code belongs to a do-while loop? +→ The elements in Java +- [ ] while (condition) { … } +- [x] do { … } while (condition); +- [ ] for (;;) { … } +> With do-while the condition is at the end, so the body runs at least once. + +? What does a Break become in Java code? +→ The elements in Java +- [x] break; +- [ ] return; +- [ ] exit(); + +? What happens at a red dot before the line number? +→ Find mistakes with the debugger +- [ ] The line is skipped. +- [x] The program pauses before this line. +- [ ] The line contains a mistake. +> That is a breakpoint. Continue with ▶︎ or Step. +::: +`,z4=`--- +titel: Python and JavaScript +bereich: From structure chart to code +kurz: Generate Python and JavaScript code from the structure chart and run JavaScript straight in the browser. +--- + +## Skills I will gain now + +::: kompetenzen +- choose and compare Python and JavaScript in the code view +- explain that Python forms blocks by indentation and needs no data types +- explain what VisuStruct adjusts when translating to Python +- run JavaScript with Test in browser +::: + +## The same diagram, three languages + +In the code view ([Code](#zeige-code) in the tools) you choose the language at the top. The structure chart stays the same; only the way it is written changes. That way you can compare the languages easily. + +::: diagramm l18-beispiel.visustruct +A number is made smaller by 3 again and again until it is no longer greater than 0. +::: + +## Python + +For the diagram above, VisuStruct generates this Python code: + +\`\`\` +number = int(input("Start value?")) +while number > 0: + print(number) + number = number - 3 +print("End") +\`\`\` + +What is different in Python compared with Java: + +- There are **no semicolons** and **no curly brackets**. Python recognises what belongs to a loop or a branch by the **indentation** alone. After \`while\`, \`if\` and \`else\` there is a colon. +- Variables get **no data type**: \`int number = 5\` becomes \`number = 5\`. +- Output is called \`print(…)\`, input \`input(…)\`. For a number, \`int(…)\` goes around it. +- In Python, arrays are called **lists**: \`int[] numbers = {2, 4, 6}\` becomes \`numbers = [2, 4, 6]\`, and \`numbers.length\` becomes \`len(numbers)\`. +- A simple for loop such as \`int i = 0\`, \`i < 5\`, \`i++\` becomes \`for i in range(5):\`. + +## What to watch out for in Python + +In some places Python is stricter than Java. That is why VisuStruct translates the Java way of writing things when it exports: + +- **Text and number with +:** \`"Sum: " + sum\` becomes \`"Sum: " + str(sum)\`. Without \`str(…)\`, Python stops with an error. +- **There is no i++:** it becomes \`i += 1\`. +- **&&, || and !** are called \`and\`, \`or\` and \`not\` in Python, and \`true\` and \`false\` become \`True\` and \`False\`. +- **Whole-number division:** In Python, \`7 / 2\` always gives 3.5. If the structure chart divides two \`int\` values, VisuStruct writes \`7 // 2\`, which gives 3, just like in Java. +- **For loops:** Counting loops become \`for … in range(…)\`, also with \`i <= n\`, counting backwards or steps such as \`i = i + 2\`. If a loop does not fit that pattern, it becomes a \`while\` loop. +- **There is no do-while:** it becomes \`while True:\` with \`if not (…): break\` at the end. + +If a diagram is marked as **pseudocode**, only a note appears above the code. Then the text is a sketch and not a runnable program. + +## JavaScript + +The same diagram in JavaScript: + +\`\`\` +"use strict"; + +let number = parseInt((prompt("Start value?") ?? "0"), 10); +while (number > 0) { + console.log(number); + number = number - 3; +} +console.log("End"); +\`\`\` + +JavaScript looks similar to Java: curly brackets, semicolons, \`while (…)\` and \`if (…)\`. The differences: + +- Variables are created with \`let\`, without a data type. Constants with \`const\`. +- Output is called \`console.log(…)\`, input \`prompt(…)\`. \`parseInt(…)\` turns the input into a whole number. +- Arrays go in square brackets: \`let numbers = [2, 4, 6];\`. +- \`"use strict";\` at the very top makes JavaScript complain about typos in variable names. +- JavaScript has only one number type. If the structure chart divides two \`int\` values, VisuStruct writes \`Math.trunc(a / b)\`. Then the digits after the decimal point are dropped, just like in Java. + +::: angeberwissen +JavaScript has almost nothing to do with Java. Brendan Eich built it in 1995 in just ten days for the Netscape browser. First it was called Mocha, then LiveScript. Because everyone was excited about Java at the time, it was renamed JavaScript shortly before launch, for advertising reasons. People have been mixing the two up ever since. Programmers say: Java is to JavaScript as car is to carpet. +::: + +## Run JavaScript in the browser + +JavaScript is the language of browsers. That is why VisuStruct can **run the code straight away**: + +::: angeberwissen +Why are links in the browser blue, anyway? In 1985 Ben Shneiderman's team tested which colour is easy to see but does not get in the way when you read. Light blue won. Red stood out more, but people remembered the text less well afterwards. +::: + +1. Choose **JavaScript** in the code view. +2. Click **Test in browser**. +3. Whatever \`console.log\` outputs appears under **Output**. If the program asks for a value with \`prompt\`, type it in and click **OK**. +4. **Stop** cancels the program. + +VisuStruct stops an endless loop \`while (true)\` by itself after 100,000 passes and reports **Execution stopped: possible infinite loop.** + +> In JavaScript code, a **Call** needs a subprogram with that name, otherwise JavaScript reports an error. Unlike the simulation, the browser does not look in the other tabs. + +## Exercise: Python as a structure chart + +This Python program outputs all even numbers from 0 up to a limit: + +\`\`\` +limit = int(input("Up to which number?")) +for i in range(0, limit + 1, 2): + print(i) +\`\`\` + +\`range(0, limit + 1, 2)\` means: start at 0, stop before \`limit + 1\`, count in steps of two. + +::: übung l18-python +titel: Even numbers +auftrag: Rebuild the Python program above as a structure chart with a for loop. With the limit 7 it outputs 0, 2, 4 and 6. +test: 7 -> 0 | 2 | 4 | 6 +test: 4 -> 0 | 2 | 4 +test: 0 -> 0 +braucht: forSchleife +tipp: \`range(0, limit + 1, 2)\` counts from 0 up to the limit in steps of two. That is a for loop. +tipp: The three fields of the for loop are \`int i = 0\`, \`i <= limit\` and \`i = i + 2\`. +lösung: l18-python-loesung.visustruct +::: + +## Exercise: JavaScript as a structure chart + +\`\`\` +let age = parseInt((prompt("How old are you?") ?? "0"), 10); +if (age >= 16) { + console.log("You may vote."); +} else { + let years = 16 - age; + console.log("Wait " + years + " more years."); +} +\`\`\` + +::: übung l18-js +titel: Voting from 16 +auftrag: Rebuild the JavaScript code above as a structure chart. Then test in the code view with **JavaScript** and **Test in browser** whether your code outputs the same as the simulation. +test: 12 -> Wait 4 more years. +test: 16 -> You may vote. +test: 13 -> Wait 3 more years. +test: 40 -> You may vote. +braucht: verzweigung +tipp: Read the code line by line. \`if\` and \`else\` become a branch. +tipp: \`prompt\` and \`parseInt\` together are one input: \`input: int age "How old are you?"\`. The false path holds two boxes: first \`int years = 16 - age\`, then the output. +lösung: l18-js-loesung.visustruct +::: + +## Game: Which language? + +::: spiel frage +titel: Game: Which language? +intro: Ludwig has mixed up lines from three languages. Can you tell where each comes from? Eight rounds. +frage: Which language is this written in? +antworten: Java | Python | JavaScript + +runde: + print(number) +richtig: Python +> In Python the output is called \`print(…)\`, without a semicolon. + +runde: + console.log(number); +richtig: JavaScript +> \`console.log\` is the output in JavaScript. + +runde: + System.out.println(number); +richtig: Java +> The long output with \`System.out\` only exists in Java. + +runde: + let numbers = [2, 4, 6]; +richtig: JavaScript +> \`let\` and square brackets: an array in JavaScript. + +runde: + for i in range(5): +richtig: Python +> A colon instead of curly brackets, and \`range\`: typical Python. + +runde: + int[] numbers = {2, 4, 6}; +richtig: Java +> Only Java writes the data type \`int[]\` in front. + +runde: + number = int(input("Start value?")) +richtig: Python +> No data type in front of the variable, no semicolon, and \`int(…)\` around the input. + +runde: + let number = parseInt(prompt("Start value?"), 10); +richtig: JavaScript +> \`prompt\` asks for a value in the browser, \`parseInt\` turns it into a number. +::: + +## 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. + +::: checkliste +- I can choose and compare Python and JavaScript in the code view. → The same diagram, three languages +- I can explain that Python forms blocks by indentation and needs no data types. → Python +- I can explain what VisuStruct adjusts when translating to Python. → What to watch out for in Python +- I can run JavaScript with Test in browser. → Run JavaScript in the browser +::: + +## Quiz + +::: quiz +? How does Python recognise which lines belong to a loop? +→ Python +- [ ] By the curly brackets +- [x] By the indentation +- [ ] By the semicolon at the end of the line + +? What is \`output: sum\` in JavaScript? +→ The same diagram, three languages +- [ ] print(sum) +- [ ] System.out.println(sum); +- [x] console.log(sum); + +? Which language can VisuStruct run straight in the browser? +→ Run JavaScript in the browser +- [ ] Java +- [ ] Python +- [x] JavaScript +> Every browser can run JavaScript. For Java and Python you need a program of its own. + +? What happens in Python with \`print("Sum: " + sum)\` if sum is the number 7? +→ What to watch out for in Python +- [ ] Sum: 7 is output. +- [x] Python reports an error, because text and a number cannot be joined with +. +- [ ] Sum: is output. +> str(sum) turns the number into text. +::: +`,I4=`--- +titel: When the program crashes: try and catch +bereich: Catching errors +kurz: Use real Java to read error messages and catch crashes with try and catch. +--- + +## Skills I will gain now + +::: kompetenzen +- switch on real Java in the Code area +- read the exception and the line from an error message +- catch an exception with try and catch +- turn text into a number with Integer.parseInt and catch the NumberFormatException +- write a program that divides safely, even by 0 +::: + +## Crashed! + +This program should print three grades. Type it into the [Code](#zeige-codelive) area and click [▶︎ Run](#zeige-ausfuehren): + +\`\`\`java +int[] grades = {2, 3, 1}; +System.out.println("First grade: " + grades[0]); +System.out.println("Fourth grade: " + grades[3]); +System.out.println("Done!"); +\`\`\` + +The first grade appears, then it stops. VisuStruct reports “Invalid expression: grades[3]”, and “Done!” never shows up. The array only has the slots 0, 1 and 2; there is no slot 3. + +::: ludwig +Has this ever happened to you? One small mistake, and the whole program is gone. It happened to me so often that I cried in front of the screen. But there is a solution, and it is called **try** and **catch**. +::: + +::: angeberwissen +In 1947 Grace Hopper's team found a moth in the Mark II computer at Harvard University that had caused a fault. They taped it into the logbook and wrote: “First actual case of bug being found”. Since then, program errors have been called **bugs**. +::: + +## Switching on real Java + +The Code area normally calculates with the same simulation as the structure chart. It simply stops when there is an error. To see what real Java does, switch on real Java: + +1. Click the [gear](#zeige-einstellungen) at the top right and choose Java as the **Programming language**. +2. In the Java section, tick **Real Java (with Swing)**. + +The first time you run a program, VisuStruct downloads about 40 MB once. After that your code is compiled and run just like in a real Java development environment. + +> With real Java, input from the console (\`Scanner\`) does not work yet. That is why our examples work without input. + +Now write the program as a whole class, so that the line numbers match, and run it: + +\`\`\`java +public class Grades { + public static void main(String[] args) { + int[] grades = {2, 3, 1}; + System.out.println("First grade: " + grades[0]); + System.out.println("Fourth grade: " + grades[3]); + System.out.println("Done!"); + } +} +\`\`\` + +The [console](#zeige-konsole) now shows: + +\`\`\` +First grade: 2 +java.lang.ArrayIndexOutOfBoundsException: 3 + at Grades.main(Grades.java:5) +\`\`\` + +## Reading the error message + +A message like this looks scary at first. But it tells you exactly what is going on: + +| Part | Meaning | +|---|---| +| \`ArrayIndexOutOfBoundsException\` | The kind of error: the index is outside the array. | +| \`3\` | The wrong index. | +| \`Grades.java:5\` | The line where it happened: line 5. | + +Java calls an error like this, at run time, an **exception**. We say: Java *throws* an exception. If nobody catches it, the program stops. That is why “Done!” does not appear. + +::: ludwig +Always read error messages from the top: first the name of the exception, then the line number. In the Code area the line numbers are on the left next to the code. +::: + +## try and catch + +With **try** and **catch** you catch the exception. Change the line with \`grades[3]\` like this: + +\`\`\`java +try { + System.out.println("Fourth grade: " + grades[3]); +} catch (ArrayIndexOutOfBoundsException e) { + System.out.println("This grade does not exist."); +} +System.out.println("Done!"); +\`\`\` + +- \`try\` means “give it a go”. Java runs the block in curly brackets as usual. +- If a line in it throws an exception, Java jumps straight into the \`catch\` block. The rest of the \`try\` block is skipped. +- The brackets after \`catch\` say which exception is caught, plus a name for it, usually \`e\`. +- After that the program carries on as normal. Now “Done!” appears too. + +If everything in the \`try\` block goes well, the \`catch\` block is simply skipped. + +::: ludwig +try and catch are like the net under the trapeze at the circus: as long as everything works, you don't notice it. If someone falls, the net catches them and the show goes on. +::: + +> The structure chart has no box for try and catch. So VisuStruct shows the whole block as one statement. You can only run it with real Java. + +## Turning text into a number + +Often a number is text at first, for example later in a text field in a window. \`Integer.parseInt\` turns text into a whole number: + +\`\`\`java +String input = "twelve"; +try { + int number = Integer.parseInt(input); + System.out.println("Double: " + number * 2); +} catch (NumberFormatException e) { + System.out.println("That is not a number: " + input); +} +\`\`\` + +Java cannot convert “twelve” and throws a \`NumberFormatException\`. The program prints “That is not a number: twelve”. Change the first line to \`String input = "12";\` and run it again: now “Double: 24” appears. + +## Expert knowledge: exceptions are objects + +This is not in the curriculum, but it is useful to know. + +::: angeberwissen +Every exception is an object of its own class, for example \`ArithmeticException\` for dividing by 0. \`e.getMessage()\` gives you its message, such as \`/ by zero\`. + +A \`try\` may be followed by several \`catch\` blocks, one for each kind of error. \`catch (Exception e)\` catches all exceptions, but then tells you less about what happened. And a \`finally { … }\` block at the end always runs, whether there was an error or not. +::: + +## Game: Does the net catch it? + +::: spiel frage +titel: Game: Does the net catch it? +intro: Ludwig is swinging on the trapeze. Do try and catch save him, or does the program crash? Seven rounds. + +runde: + int[] grades = {2, 3, 1}; + System.out.println(grades[3]); + System.out.println("Done!"); +frage: What happens with real Java? +- 1 and Done! appear. +- Only Done! appears. +- [x] The program crashes with an ArrayIndexOutOfBoundsException. +> There is no slot 3. Nobody catches the exception, so Done! never arrives. + +runde: + int[] grades = {2, 3, 1}; + try { + System.out.println(grades[3]); + } catch (ArrayIndexOutOfBoundsException e) { + System.out.println("This grade does not exist."); + } + System.out.println("Done!"); +frage: What is output? +- Done! +- [x] This grade does not exist.\\nDone! +- This grade does not exist. +> The catch block catches the exception, and after that the program carries on as normal. + +runde: + try { + System.out.println("A"); + System.out.println(10 / 0); + System.out.println("B"); + } catch (ArithmeticException e) { + System.out.println("C"); + } +frage: What is output? +- A\\nB\\nC +- [x] A\\nC +- C +> At 10 / 0, Java jumps straight into the catch block. The rest of the try block, B, is skipped. + +runde: + String input = "12"; + try { + int number = Integer.parseInt(input); + System.out.println("Double: " + number * 2); + } catch (NumberFormatException e) { + System.out.println("That is not a number: " + input); + } +frage: What is output? +- [x] Double: 24 +- That is not a number: 12 +- Double: 1212 +> "12" can be converted. If everything goes well in the try block, catch is skipped. + +runde: +frage: Which exception does \`Integer.parseInt("2.5")\` throw? +- ArithmeticException +- [x] NumberFormatException +- none, the result is 2 +> parseInt only converts whole numbers. With a point it isn't a valid format. + +runde: +frage: Which exception does \`12 / 0\` throw with \`int\`? +- [x] ArithmeticException +- NumberFormatException +- ArrayIndexOutOfBoundsException +> Dividing by 0 doesn't work with whole numbers. The message is \`/ by zero\`. + +runde: + try { + int pieces = 12 / 0; + } catch (NumberFormatException e) { + System.out.println("Error!"); + } + System.out.println("Done!"); +frage: What happens? +- Error! and Done! appear. +- Only Done! appears. +- [x] The program crashes. +> catch only catches the exception named in the brackets. An ArithmeticException falls through the net. +::: + +## Task: dividing safely + +This program crashes: + +\`\`\`java +int cake = 12; +int people = 0; +System.out.println("Everyone gets " + cake / people + " pieces."); +System.out.println("Enjoy!"); +\`\`\` + +1. Run it with real Java and read the error message. Which exception is it? +2. Catch it with try and catch. Instead of the crash, “You can't share without people.” should appear, and “Enjoy!” should still be printed. +3. Set \`people\` to 4 and check that “Everyone gets 3 pieces.” appears. + +::: ludwig +The exception is called \`ArithmeticException\`. Only put the line that can crash into the \`try\` block. +::: + +## 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. + +::: checkliste +- I can switch on real Java in the Code area. → Switching on real Java +- I can read the exception and the line from an error message. → Reading the error message +- I can catch an exception with try and catch. → try and catch +- I can turn text into a number with Integer.parseInt and catch the NumberFormatException. → Turning text into a number +- I can write a program that divides safely, even by 0. → Task: dividing safely +::: + +## Quiz + +::: quiz +? What happens if an exception is not caught? +→ Reading the error message +- [ ] Java skips the line and carries on. +- [x] The program stops. +- [ ] The computer restarts. +> That is why “Done!” does not appear in the first example. + +? What happens in the try block after the line that throws an exception? +→ try and catch +- [ ] The remaining lines run anyway. +- [x] The rest is skipped and Java jumps into the catch block. +- [ ] Java starts the try block again. + +? Which exception does Integer.parseInt("twelve") throw? +→ Turning text into a number +- [ ] ArithmeticException +- [ ] ArrayIndexOutOfBoundsException +- [x] NumberFormatException +> “twelve” is not in a number format that Java understands. + +? Match each exception to its cause. +→ Reading the error message += ArrayIndexOutOfBoundsException -> index outside the array += ArithmeticException -> dividing by 0 += NumberFormatException -> text is not a number +::: +`,k4=`--- +titel: Reading and saving text +bereich: Files +kurz: Read a text file line by line with Scanner and save a file with PrintWriter. +--- + +## Skills I will gain now + +::: kompetenzen +- explain why programs save data in files +- read a text file line by line with Scanner, hasNextLine and nextLine +- explain why Java requires try and catch or throws for files +- write a file with PrintWriter and finish it with close +- read a file, add to it and save it again with numbers +::: + +## Why files? + +Everything stored in variables is gone as soon as the program ends. If a program should remember something, for example a game score, a list or grades, it saves the data in a **file**. The next time it starts, it reads the file again. + +Zora is free, and Ludwig is planning a party. His shopping list is ready in the file \`shopping.txt\`: + +::: datei shopping.txt +Hay +Apples +Carrots +Dandelions +::: + +A file ending in \`.txt\` contains only text, line by line. You can open it with any editor, for example Notepad on Windows or TextEdit on a Mac. + +## Reading a file with Scanner + +You already know the \`Scanner\`: \`new Scanner(System.in)\` reads from the keyboard. If you give it a file instead of \`System.in\`, it reads from the file: + +\`\`\`java +import java.io.*; +import java.util.Scanner; + +Scanner file = new Scanner(new File("shopping.txt")); +while (file.hasNextLine()) { + String line = file.nextLine(); + System.out.println(line); +} +file.close(); +\`\`\` + +| Method | Meaning | +|---|---| +| \`new File("shopping.txt")\` | the file with this name | +| \`hasNextLine()\` | Is there another line? \`true\` or \`false\` | +| \`nextLine()\` | returns the next line and moves on by one line | +| \`close()\` | closes the file when you are done | + +The loop runs as long as there is another line. In each pass, \`nextLine()\` fetches the next line. \`File\` belongs to the package \`java.io\`, so you need \`import java.io.*;\`. + +::: diagramm dt-lesen.visustruct +This is what reading looks like in a structure chart. Try it in the simulation. +::: + +::: ludwig +Imagine the Scanner as a finger pointing at a line. \`nextLine()\` reads the line under the finger and moves the finger down one line. Once the finger is below the last line, \`hasNextLine()\` returns \`false\`. +::: + +## What if the file is missing? + +If the file does not exist, Java cannot read it and throws a \`FileNotFoundException\`. Java insists that your program is prepared for this. Either you catch it with try and catch, as in lesson 22: + +\`\`\`java +try { + Scanner file = new Scanner(new File("shopping.txt")); + // ... read ... + file.close(); +} catch (FileNotFoundException e) { + System.out.println("The file shopping.txt is missing!"); +} +\`\`\` + +Or you write \`throws Exception\` after \`main\`. It means: "This method may throw an exception, I won't deal with it." Then the program stops if the file is missing. + +\`\`\`java +public static void main(String[] args) throws Exception { +\`\`\` + +> VisuStruct adds \`throws Exception\` after \`main\` automatically as soon as your program works with files. In the simulation, VisuStruct reports a missing file with "There is no file called …". + +## Exercise: Numbering the shopping list + +::: übung l23-java-nummern +titel: Numbering the shopping list +code: java +auftrag: Read \`shopping.txt\` line by line and print each line with its number: **1. Hay**, **2. Apples** and so on. +start: l23-java-nummern-start.visustruct +test: - -> 1. Hay | 2. Apples | 3. Carrots | 4. Dandelions +braucht: whileSchleife +tipp: Create \`int number = 1;\` before the loop and increase the number at the end of each pass. +tipp: The output is \`System.out.println(number + ". " + line);\` +lösung: l23-java-nummern-loesung.visustruct +::: + +## Writing to a file with PrintWriter + +For writing there is the \`PrintWriter\`. Its methods have the same names as those of \`System.out\`: + +\`\`\`java +PrintWriter out = new PrintWriter("greeting.txt"); +out.println("Hello Zora!"); +out.println("See you tomorrow, Ludwig"); +out.close(); +\`\`\` + +Afterwards \`greeting.txt\` contains: + +\`\`\` +Hello Zora! +See you tomorrow, Ludwig +\`\`\` + +- \`println\` writes the text and then starts a new line, \`print\` writes without a new line. +- If the file already exists, it is **overwritten**. The old content is gone. +- After the run, VisuStruct shows below the output what was saved in the file. + +::: ludwig +Don't forget \`close()\`! The PrintWriter first collects the text in a buffer and only writes it to the file when it is closed. Without \`close()\` the file stays empty. I once lost a whole story that way. +::: + +## Exercise: Adding to the shopping list + +::: übung l23-java-ergaenzen +titel: Adding to the shopping list +code: java +auftrag: Ludwig still needs cake. Read \`shopping.txt\` and write each line to the new file \`shopping-new.txt\`. Then add **Cake** as the last line. At the end, print how many lines were saved: **5 lines saved**. +start: l23-java-ergaenzen-start.visustruct +test: - -> 5 lines saved +datei: shopping-new.txt -> Hay | Apples | Carrots | Dandelions | Cake +braucht: whileSchleife +tipp: In the loop, read a line with \`file.nextLine()\` and write it straight out again with \`out.println(line)\`. +tipp: After the loop comes \`out.println("Cake");\`. Close both files with \`close()\`, otherwise \`shopping-new.txt\` stays empty. +lösung: l23-java-ergaenzen-loesung.visustruct +::: + +## Game: What is in the file? + +::: spiel frage +titel: Game: What is in the file? +intro: Ludwig writes files with the PrintWriter. Read the code and predict what is in the file afterwards. Six rounds. +frage: What is in the file afterwards? + +runde: + PrintWriter out = new PrintWriter("greeting.txt"); + out.println("Hello"); + out.println("Zora"); + out.close(); +- [x] Hello\\nZora +- HelloZora +- Zora +> \`println\` starts a new line after each text. + +runde: + PrintWriter out = new PrintWriter("word.txt"); + out.print("He"); + out.print("llo"); + out.println("!"); + out.close(); +- He\\nllo\\n! +- [x] Hello! +- He llo ! +> \`print\` carries on without a new line, so the parts are joined directly. + +runde: + PrintWriter out = new PrintWriter("secret.txt"); + out.println("The treasure is in the tower"); +- The treasure is in the tower +- [x] Nothing, the file stays empty. +- Java reports an error. +> Without \`close()\` the text never reaches the file. It stays in the buffer. + +runde: + // Before, note.txt contains: Old + PrintWriter out = new PrintWriter("note.txt"); + out.println("New"); + out.close(); +- Old\\nNew +- [x] New +- New\\nOld +> A new PrintWriter overwrites the file. The old content is gone. + +runde: + PrintWriter out = new PrintWriter("numbers.txt"); + for (int i = 1; i <= 3; i++) { + out.println(i * 2); + } + out.close(); +- 1\\n2\\n3 +- 246 +- [x] 2\\n4\\n6 +> The loop writes 2, 4 and 6, each number on its own line. + +runde: + // shopping.txt contains: Hay, Apples (one per line) + Scanner file = new Scanner(new File("shopping.txt")); + PrintWriter out = new PrintWriter("big.txt"); + while (file.hasNextLine()) { + out.println(file.nextLine().toUpperCase()); + } + file.close(); + out.close(); +- Hay\\nApples +- [x] HAY\\nAPPLES +- HAYAPPLES +> Each line is read, turned into capital letters and written on its own line. +::: + +## 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. + +::: checkliste +- I can explain why programs save data in files. → Why files? +- I can read a text file line by line with Scanner, hasNextLine and nextLine. → Reading a file with Scanner +- I can explain why Java requires try and catch or throws for files. → What if the file is missing? +- I can write a file with PrintWriter and finish it with close(). → Writing to a file with PrintWriter +- I can read a file, add to it and save it again with numbers. → Exercise: Adding to the shopping list +::: + +## Quiz + +::: quiz +? What does hasNextLine() return? +→ Reading a file with Scanner +- [ ] the next line +- [x] true if there is another line, otherwise false +- [ ] the number of lines +> With hasNextLine() the loop checks whether to carry on. + +? What happens if you call new PrintWriter("list.txt") for a file that already exists? +→ Writing to a file with PrintWriter +- [ ] The new text is added at the end. +- [x] The file is overwritten. +- [ ] Java reports an error. + +? Why does a file stay empty even though println was called? +→ Writing to a file with PrintWriter +- [ ] Because println only writes to the console. +- [x] Because close() is missing. +- [ ] Because the file name ends in .txt. +> Only close() writes the buffer into the file. + +? Match each method to its job. +→ Reading a file with Scanner += nextLine() -> reads the next line += println(text) -> writes a line += close() -> closes the file +::: +`,S4=`--- +titel: Line by line with BufferedReader +bereich: Files +kurz: Read with BufferedReader and readLine until null comes, and read a whole file at once with Files. +--- + +## Skills I will gain now + +::: kompetenzen +- read a file with BufferedReader and readLine +- spot the end of a file, because readLine returns null there +- count how often a word appears in a file +- read a whole file with Files.readString and split it into lines with split +- find the longest entry in a file +::: + +## The cake is gone! + +The morning after the party, Ludwig's cake has disappeared. Luckily the castle keeps a logbook. Every line starts with the day and the time: + +::: datei logbook.txt +Mo 08:15 Ludwig feeds the goats +Mo 12:30 Zora reads in the tower +Mo 18:00 Fox sneaks past the gate +Tu 09:00 Ludwig bakes a cake +Tu 14:45 Hare brings carrots +Tu 16:20 Fox asks for the recipe +Tu 23:55 The cake is gone +We 07:00 Zora finds crumbs at Fox's den +::: + +You could already read it with the Scanner from lesson 23. For files, though, professionals often use the **BufferedReader**. + +## Reading with BufferedReader + +\`\`\`java +import java.io.*; + +BufferedReader reader = new BufferedReader(new FileReader("logbook.txt")); +String line = reader.readLine(); +while (line != null) { + System.out.println(line); + line = reader.readLine(); +} +reader.close(); +\`\`\` + +- \`new FileReader("logbook.txt")\` opens the file, and \`new BufferedReader(…)\` puts a buffer around it. It fetches the file in large chunks and is therefore faster for long files. +- \`readLine()\` returns the next line. When there are no more lines, it returns **null**. +- That is why the loop runs as long as \`line != null\`. At the end of each pass it reads the next line. + +::: diagramm dt-buffered.visustruct +First read a line, then check, then read the next one at the end of the pass. +::: + +**null** means "nothing at all". It is not the empty text \`""\`, but no text. A variable holding \`null\` has no methods: \`line.length()\` then stops with a \`NullPointerException\`. So always check \`line != null\` first. + +| | Scanner | BufferedReader | +|---|---|---| +| Create | \`new Scanner(new File(…))\` | \`new BufferedReader(new FileReader(…))\` | +| Is there another line? | \`hasNextLine()\` | \`readLine()\` returns \`null\` | +| Next line | \`nextLine()\` | \`readLine()\` | +| Strength | can also read numbers (\`nextInt()\`) | fast, even with large files | + +::: ludwig +The loop looks different from the Scanner one: the first line is read **before** the loop, every further one **at the end** of the pass. If you forget the read at the end, the program reads the same line again and again and never stops. +::: + +::: angeberwissen +Where a line ends is not the same everywhere: Windows writes two invisible characters, “carriage return” and “line feed”, Linux and macOS only the line feed. The names come from the typewriter, where the carriage moved back and the paper moved up one line. \`readLine()\` copes with both. +::: + +## Exercise: How often does the fox appear? + +::: übung l24-java-fuchs +titel: How often does the fox appear? +code: java +auftrag: Read the logbook with the BufferedReader and count the lines that contain **Fox**. At the end, print **Fox:** and the count. +start: l24-java-fuchs-start.visustruct +test: - -> Fox: 3 +braucht: whileSchleife, verzweigung +tipp: Create \`int count = 0;\` before the loop. In the loop, check \`line.contains("Fox")\`. +tipp: The \`line = reader.readLine();\` belongs at the end of the loop, after the if. +lösung: l24-java-fuchs-loesung.visustruct +::: + +## Closing automatically + +So that \`close()\` isn't forgotten even after an exception, there is a short form of try: whatever is created in the round brackets after \`try\` is closed by Java on its own at the end. + +\`\`\`java +try (BufferedReader reader = new BufferedReader(new FileReader("logbook.txt"))) { + String line = reader.readLine(); + while (line != null) { + System.out.println(line); + line = reader.readLine(); + } +} catch (IOException e) { + System.out.println("The logbook is missing."); +} +\`\`\` + +This is called **try-with-resources**. \`IOException\` catches all errors while reading and writing, including a missing file. + +> Like try and catch, try-with-resources only runs with real Java (lesson 22). In the simulation, you write \`close()\` yourself. + +## The shortcut: Files + +Since Java 11 it is even shorter. \`Files.readString\` reads the whole file at once, as you know from lesson 17. With \`split("\\n")\` you split the text into an array of lines: + +\`\`\`java +import java.nio.file.*; + +String text = Files.readString(Path.of("logbook.txt")); +String[] lines = text.split("\\n"); +for (int i = 0; i < lines.length; i++) { + System.out.println(lines[i]); +} +\`\`\` + +Now all lines are in the array. You can look at them in any order, for example backwards or only every second one. + +| Way | Good for | +|---|---| +| \`Scanner\` | small files, reading numbers and words | +| \`BufferedReader\` | large files, line by line | +| \`Files.readString\` | small files that fit into the program as a whole | + +::: ludwig +A file with a million lines is better read line by line with the BufferedReader. With \`Files.readString\` the whole file would have to go into memory at once. +::: + +## Exercise: The longest entry + +::: übung l24-java-laengster +titel: The longest entry +code: java +auftrag: In the start code, the lines of the logbook are already in the array \`lines\`. Find the longest line and print it like this: **Longest entry:** followed by the line. +start: l24-java-laengster-start.visustruct +test: - -> Longest entry: We 07:00 Zora finds crumbs at Fox's den +braucht: forSchleife, verzweigung +tipp: Remember the longest line so far in \`String longest = lines[0];\` and go through the other lines with a for loop. +tipp: If \`lines[i].length() > longest.length()\`, then \`lines[i]\` becomes the new longest. +lösung: l24-java-laengster-loesung.visustruct +::: + +## Game: File detective + +::: spiel frage +titel: Game: File detective +intro: Who took the cake? Each program searches the **logbook** from the top. Predict what it prints and collect the clues. Five rounds. +frage: What does the program print? + +runde: + String line = reader.readLine(); + line = reader.readLine(); + System.out.println(line.substring(9)); +- Ludwig feeds the goats +- [x] Zora reads in the tower +- Mo 12:30 Zora reads in the tower +> The second \`readLine()\` returns the second line. The text after the time starts at index 9. + +runde: + int n = 0; + String line = reader.readLine(); + while (line != null) { + if (line.startsWith("Tu")) n++; + line = reader.readLine(); + } + System.out.println(n); +- 3 +- [x] 4 +- 8 +> Four entries are from Tuesday. + +runde: + String line = reader.readLine(); + while (line != null) { + if (line.contains("cake")) { + System.out.println(line.substring(3, 8)); + } + line = reader.readLine(); + } +- [x] 09:00\\n23:55 +- 09:00 +- Tu\\nTu +> Two lines contain "cake". \`substring(3, 8)\` cuts out the time. + +runde: + String line = reader.readLine(); + String last = ""; + while (line != null) { + if (line.contains("Fox")) last = line; + line = reader.readLine(); + } + System.out.println(last); +- Tu 16:20 Fox asks for the recipe +- [x] We 07:00 Zora finds crumbs at Fox's den +- Mo 18:00 Fox sneaks past the gate +> \`last\` is overwritten at every match. At the end it holds the last match. "Fox's den" contains "Fox" too. + +runde: + String line = reader.readLine(); + while (line != null) { + if (line.contains("crumbs")) { + int at = line.indexOf("at "); + System.out.println(line.substring(at + 3)); + } + line = reader.readLine(); + } +- [x] Fox's den +- at Fox's den +- crumbs +> The crumbs are at Fox's den. The fox asked for the recipe, and at 23:55 the cake was gone. Case solved! +::: + +## 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. + +::: checkliste +- I can read a file with BufferedReader and readLine. → Reading with BufferedReader +- I can spot the end of a file, because readLine returns null there (line != null). → Reading with BufferedReader +- I can count how often a word appears in a file. → Exercise: How often does the fox appear? +- I can read a whole file with Files.readString and split it into lines with split. → The shortcut: Files +- I can find the longest entry in a file. → Exercise: The longest entry +::: + +## Quiz + +::: quiz +? What does readLine() return when the file has ended? +→ Reading with BufferedReader +- [ ] "" +- [x] null +- [ ] -1 +> null means: there is no more text. + +? Why is there another line = reader.readLine() at the end of the loop? +→ Reading with BufferedReader +- [ ] So that the file is closed. +- [x] Otherwise line never changes and the loop never stops. +- [ ] So that the first line is printed twice. + +? What does try-with-resources do? +→ Reading with BufferedReader +- [ ] It reads the file faster. +- [x] It closes the file on its own at the end. +- [ ] It prevents every exception. + +? Match each way to what it is good for. +→ The shortcut: Files += BufferedReader -> large files, line by line += Files.readString -> small files all at once += Scanner -> reading numbers and words +::: +`,T4=`--- +titel: Tables as CSV +bereich: Files +kurz: Read a table as a CSV file, split each line with split and calculate with the numbers. +--- + +## Skills I will gain now + +::: kompetenzen +- explain how a CSV file is built: header, records, separator +- split a line with split and make a number out of it with Integer.parseInt +- skip the header before calculating +- calculate an average from a column of a CSV file +- find the best value in a column of a CSV file +- name one strength and one weakness of CSV +::: + +## A table in a text file + +Mrs Goat, the teacher at the castle school, has saved her class's grades as a table. As in Germany, 1 is the best grade and 6 the worst: + +| Name | Maths | German | English | +|---|---|---|---| +| Ludwig | 2 | 3 | 1 | +| Zora | 1 | 2 | 2 | +| Fox | 4 | 3 | 5 | +| Hare | 2 | 1 | 3 | + +In the file, the table looks like this: + +::: datei class.csv +Name;Maths;German;English +Ludwig;2;3;1 +Zora;1;2;2 +Fox;4;3;5 +Hare;2;1;3 +::: + +This is a **CSV file**. CSV stands for "Comma-Separated Values". Each line is a row of the table, and the columns are separated by a separator character. In English-speaking countries this is usually a comma, in Germany and many other countries a **semicolon** \`;\`, because the comma is already used in numbers like \`2,5\`. We use the semicolon. + +- The first line is the **header**. It says what is in the columns. +- Every further line is a **record**, here one pupil. +- Excel, LibreOffice and Numbers open CSV files directly as a table. + +## Splitting a line with split + +You know \`split(";")\` from lesson 17. It splits a text at every semicolon and returns an array: + +\`\`\`java +String line = "Zora;1;2;2"; +String[] parts = line.split(";"); +// parts[0] is "Zora", parts[1] is "1", parts[2] is "2", parts[3] is "2" +\`\`\` + +Afterwards the grades are still **text**. You can only calculate with them once you have turned them into a number with \`Integer.parseInt\`: + +\`\`\`java +int maths = Integer.parseInt(parts[1]); +\`\`\` + +::: diagramm dt-csv.visustruct +Split a CSV line and read the maths grade as a number. +::: + +## Reading the whole file + +For the whole file, you combine the BufferedReader from lesson 24 with \`split\`. The header contains no grades, so you read it before the loop and skip it: + +\`\`\`java +BufferedReader reader = new BufferedReader(new FileReader("class.csv")); +String line = reader.readLine(); // header +line = reader.readLine(); // first record +while (line != null) { + String[] parts = line.split(";"); + System.out.println(parts[0] + ": Maths " + parts[1]); + line = reader.readLine(); +} +reader.close(); +\`\`\` + +::: ludwig +Without the second \`readLine()\` before the loop, the header ends up in the loop. Then \`Integer.parseInt("Maths")\` tries to make a number out of the word, and Java stops with a \`NumberFormatException\`. +::: + +## Exercise: Maths average + +::: übung l25-java-schnitt +titel: Maths average +code: java +auftrag: Calculate the average maths grade. Skip the header, add up the maths grades (column 1) and divide by the number of records. Print **Maths average:** and the average. +start: l25-java-schnitt-start.visustruct +test: - -> Maths average: 2.25 +braucht: whileSchleife +tipp: Create \`double sum = 0;\` and \`int count = 0;\` before the loop. With \`double\`, nothing is cut off when dividing. +tipp: In the loop: \`String[] parts = line.split(";");\`, then \`sum = sum + Integer.parseInt(parts[1]);\` and \`count++;\`. +lösung: l25-java-schnitt-loesung.visustruct +::: + +## Exercise: Best grade in English + +::: übung l25-java-beste +titel: Best grade in English +code: java +auftrag: Who has the best grade in English (column 3)? Print **Best grade in English:**, the name and the grade in brackets. +start: l25-java-beste-start.visustruct +test: - -> Best grade in English: Ludwig (1) +braucht: whileSchleife, verzweigung +tipp: Remember the best grade so far in \`int bestGrade = 7;\` and the name in \`String bestName = "";\`. Every real grade is better than 7. +tipp: If \`grade < bestGrade\`, remember the new grade and \`parts[0]\` as the name. +lösung: l25-java-beste-loesung.visustruct +::: + +## Strengths and weaknesses of CSV + +| Good | Tricky | +|---|---| +| Tables take up little space. | If the separator appears in the text, for example \`Hare;very good; hard-working\`, the line falls apart into too many parts. | +| Excel and other programs open the file directly. | Everything is a flat table. If an animal has several favourite foods, that doesn't fit well into one cell. | +| Every program can read it with \`split\`. | The file doesn't say whether \`1\` is a number or a text. | + +::: ludwig +Excel saves CSV files with semicolons in Germany and with commas in England and the USA. That is why someone opening a file from another country sometimes sees everything in one single column. +::: + +## Game: Broken line + +::: spiel bombe +titel: Game: Broken line +intro: In every CSV file **exactly one line is broken**, and the bomb is ticking. Compare each line with the header and tap the broken line before time runs out. Five rounds, 20 seconds each. +zeit: 20 +daten: csv + +runde: + Name;Maths;German;English + Ludwig;2;3;1 + Zora;1 + Fox;4;3;5 +frage: Every line needs four columns. +fehler: 3 +besser: Zora;1;2;2 +> Two grades are missing for Zora. Then there is no \`parts[3]\`, and Java stops with an \`ArrayIndexOutOfBoundsException\`. + +runde: + Name;Grade;Comment + Ludwig;2;works well with others + Hare;1;very good; hard-working + Zora;1;reads a lot +frage: Every line needs three columns. +fehler: 3 +besser: Hare;1;very good, hard-working +> The semicolon in the comment splits off a fourth column. The separator must not appear in the text. + +runde: + Name;Maths;German;English + Ludwig;2;3;1 + Zora;1;2;2 + Fox,4,3,5 +frage: The separator is a semicolon. +fehler: 4 +besser: Fox;4;3;5 +> Here there are commas instead of semicolons. \`split(";")\` finds no semicolon and returns the whole line as a single part. + +runde: + Name;Maths;German;English + Hare;2;1;3 + Fox;four;3;5 + Ludwig;2;3;1 +frage: Grades are numbers. +fehler: 3 +besser: Fox;4;3;5 +> \`Integer.parseInt("four")\` cannot make a number out of the word and throws a \`NumberFormatException\`. + +runde: + Name;Maths;German;English + Zora;1;2;2 + Hare;2;1;3 + Ludwig;2;;1 +frage: No field may be empty. +fehler: 4 +besser: Ludwig;2;3;1 +> There is nothing between the two semicolons. \`Integer.parseInt("")\` throws a \`NumberFormatException\`. +::: + +## 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. + +::: checkliste +- I can explain how a CSV file is built: header, records, separator. → A table in a text file +- I can split a line with split and make a number out of it with Integer.parseInt. → Splitting a line with split +- I can skip the header before calculating. → Reading the whole file +- I can calculate an average from a column of a CSV file. → Exercise: Maths average +- I can find the best value in a column of a CSV file. → Exercise: Best grade in English +- I can name one strength and one weakness of CSV. → Strengths and weaknesses of CSV +::: + +## Quiz + +::: quiz +? What does "Hare;2;1;3".split(";")[2] return? +→ Splitting a line with split +- [ ] "2" +- [x] "1" +- [ ] 1 +> Counting starts at 0. And the result is a text, not a number. + +? Why does the program call readLine() twice before the loop? +→ Reading the whole file +- [ ] So that the file is read faster. +- [x] The first line is the header without grades. It is skipped. +- [ ] Because readLine always needs two lines. + +? What happens with Integer.parseInt("Maths")? +→ Splitting a line with split +- [ ] It returns 0. +- [x] Java throws a NumberFormatException. +- [ ] It returns the length of the word. + +? Match. +→ Strengths and weaknesses of CSV += header -> says what is in the columns += record -> a line with values += separator -> separates the columns, often ; +::: +`,_4=`--- +titel: Data as JSON +bereich: Files +kurz: Understand JSON files, get values out with indexOf and substring, and write JSON yourself. +--- + +## Skills I will gain now + +::: kompetenzen +- recognise objects, keys, values and lists in JSON +- get a value out of a JSON line with indexOf and substring +- output all values of one key from a JSON file +- build and save a JSON entry with + and \\" +- save data as a JSON file +- name one strength and one weakness of JSON +::: + +## Data with names + +The castle zoo stores its animals in a file \`zoo.json\`: + +::: datei zoo.json +{ + "zoo": "Castle Zoo", + "animals": [ + {"name": "Ludwig", "species": "billy goat", "age": 7}, + {"name": "Zora", "species": "goat", "age": 6}, + {"name": "Fox", "species": "red fox", "age": 4}, + {"name": "Hare", "species": "brown hare", "age": 2} + ] +} +::: + +This is **JSON**, the "JavaScript Object Notation". Almost every web app and every game sends and stores data like this. Unlike in a CSV file, each value has its **name** in front of it, the **key**. + +| Character | Meaning | Example | +|---|---|---| +| \`{ … }\` | an **object**: pairs of key and value | \`{"name": "Zora", "age": 6}\` | +| \`"key": value\` | a pair, separated by a colon | \`"age": 6\` | +| \`[ … ]\` | a **list** of values, like an array | \`"animals": [ … ]\` | +| \`,\` | separates the pairs and the entries of a list | | +| \`"…"\` | a text. Numbers and \`true\`/\`false\` have no quotation marks. | \`"goat"\`, \`6\` | + +Objects and lists can be **nested**: the whole zoo object contains the list \`animals\`, and each animal is an object again. As with arrays, the list counts from 0: \`animals[1].name\` is \`"Zora"\`. + +::: angeberwissen +Douglas Crockford made JSON popular in the early 2000s. In the licence of his JSON program he wrote: “The Software shall be used for Good, not Evil.” So the company IBM asked whether it could use it anyway. He replied that IBM and its customers were allowed to use it for evil. +::: + +## Getting a value out + +Professionals read JSON with a library, for example **Gson**. It is not part of Java and has to be added first. For our zoo file, the string methods from lesson 17 are enough, because each animal is on its own line. + +In Java you write a quotation mark inside a text as \`\\"\`. So the text \`"\\"name\\": \\""\` is \`"name": "\`, exactly what comes before each name. + +\`\`\`java +String line = "{\\"name\\": \\"Zora\\", \\"species\\": \\"goat\\", \\"age\\": 6},"; +int start = line.indexOf("\\"name\\": \\"") + 9; +int end = line.indexOf("\\"", start); +String name = line.substring(start, end); +\`\`\` + +- \`indexOf("\\"name\\": \\"")\` finds the start of \`"name": "\`. That is 9 characters, so the name begins 9 characters further on. +- \`indexOf("\\"", start)\` searches for the next quotation mark **from** \`start\`. That is where the name ends. +- \`substring(start, end)\` cuts out the name: \`Zora\`. + +::: diagramm dt-json.visustruct +Getting the name out of a JSON line. +::: + +## Exercise: All the names in the zoo + +::: übung l26-java-namen +titel: All the names in the zoo +code: java +auftrag: Read \`zoo.json\` line by line. In every line that contains \`"name"\`, print only the name. +start: l26-java-namen-start.visustruct +test: - -> Ludwig | Zora | Fox | Hare +braucht: whileSchleife, verzweigung +tipp: Check with \`line.contains("\\"name\\"")\` whether there is a name in the line. Skip the other lines. +tipp: Inside the if: \`int start = line.indexOf("\\"name\\": \\"") + 9;\`, then \`int end = line.indexOf("\\"", start);\` and \`System.out.println(line.substring(start, end));\`. +lösung: l26-java-namen-loesung.visustruct +::: + +## Writing JSON + +To write, you put the text together with \`+\` and write it to the file with the PrintWriter from lesson 23. Texts in JSON need quotation marks, so \`\\"\` in the Java text, numbers don't: + +\`\`\`java +String name = "Zora"; +int points = 15; +String entry = "{\\"name\\": \\"" + name + "\\", \\"points\\": " + points + "}"; +// entry is {"name": "Zora", "points": 15} +\`\`\` + +In a list there is a comma between the entries, but **none** after the last one. You check that with an if. + +::: ludwig +A single forgotten quotation mark or one comma too many, and no program can read the file any more. JSON is strict. That is why professionals also use a library for writing. +::: + +## Exercise: Saving points as JSON + +::: übung l26-java-schreiben +titel: Saving points as JSON +code: java +auftrag: Save the points from the quiz tournament as a list in \`points.json\`. Each line contains an object with **name** and **points**, and there is a comma between the objects. At the end, print **3 entries saved**. +start: l26-java-schreiben-start.visustruct +test: - -> 3 entries saved +datei: points.json -> [ | {"name": "Ludwig", "points": 12}, | {"name": "Zora", "points": 15}, | {"name": "Fox", "points": 9} | ] +braucht: forSchleife, verzweigung +tipp: Go through the arrays with \`for (int i = 0; i < names.length; i++)\`. Build the entry with \`" {\\"name\\": \\"" + names[i] + "\\", \\"points\\": " + points[i] + "}"\`. +tipp: If \`i < names.length - 1\`, add \`","\`. After the loop, write \`"]"\` and close the file. +lösung: l26-java-schreiben-loesung.visustruct +::: + +## Strengths and weaknesses of JSON + +| Good | Tricky | +|---|---| +| Every value has a name. You can see at once what \`6\` means. | The file is longer than a CSV file, because the keys appear on every line. | +| Data can be nested, for example a list inside an object. | Java can't read JSON on its own. You need a library such as Gson. | +| JSON is the standard on the web. Almost every programming language knows it. | One character too many or too few makes the whole file unreadable. | + +## Game: Which key? + +::: spiel frage +titel: Game: Which key? +intro: Ludwig is looking for values in JSON files. Read the file and say which value is meant. Five rounds. + +runde: + {"name": "Zora", "species": "goat", "age": 6} +frage: What is the value of **age**? +- "age" +- [x] 6 +- "goat" +> The key comes before the colon, the value after it. Numbers have no quotation marks. + +runde: + { + "animals": [ + {"name": "Ludwig", "age": 7}, + {"name": "Zora", "age": 6}, + {"name": "Fox", "age": 4} + ] + } +frage: What is **animals[1].name**? +- Ludwig +- [x] Zora +- Fox +> The list counts from 0, like an array. \`animals[1]\` is the second animal. + +runde: + { + "zoo": "Castle Zoo", + "boss": {"name": "Ludwig", "species": "billy goat"} + } +frage: How do you get to **billy goat**? +- [x] boss.species +- species +- zoo.boss.species +> \`species\` is inside the object \`boss\`. So the way goes through \`boss\`. + +runde: + { + "name": "Hare", + "favouriteFood": ["carrots", "clover", "dandelions"] + } +frage: What is **favouriteFood[2]**? +- clover +- carrots +- [x] dandelions +> Index 0 is carrots, 1 is clover, 2 is dandelions. Something like this hardly fits into one cell in CSV. + +runde: + {"name": "Fox", "age": 4, "hungry": true} +frage: Which key has a truth value? +- name +- age +- [x] hungry +> \`true\` and \`false\` have no quotation marks, like numbers. In Java this would be a \`boolean\`. +::: + +## 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. + +::: checkliste +- I can recognise objects, keys, values and lists in JSON. → Data with names +- I can get a value out of a JSON line with indexOf and substring. → Getting a value out +- I can output all values of one key from a JSON file. → Exercise: All the names in the zoo +- I can build and save a JSON entry with + and \\". → Writing JSON +- I can save data as a JSON file. → Exercise: Saving points as JSON +- I can name one strength and one weakness of JSON. → Strengths and weaknesses of JSON +::: + +## Quiz + +::: quiz +? What comes before each value in JSON? +→ Data with names +- [ ] its line number +- [x] its key, for example "name" +- [ ] a semicolon +> Key and value are separated by a colon. + +? How do you write a quotation mark inside a Java text? +→ Writing JSON +- [ ] "" +- [x] \\" +- [ ] '"' + +? In {"animals": [{"name": "Ludwig"}, {"name": "Zora"}]}, what is the value of animals[0].name? +→ Data with names +- [x] Ludwig +- [ ] Zora +- [ ] animals +> The list counts from 0. + +? Match. +→ Strengths and weaknesses of JSON += { } -> an object with keys and values += [ ] -> a list += : -> separates key and value +::: +`,A4=`--- +titel: Comparing formats +bereich: Files +kurz: Compare the same data as txt, CSV and JSON, choose the right format and convert a file into another format. +--- + +## Skills I will gain now + +::: kompetenzen +- recognise the same data as txt, CSV and JSON +- compare strengths and weaknesses of txt, CSV and JSON +- convert a CSV file into sentences +- convert a CSV file into JSON +::: + +## The same animals three times + +Ludwig has saved the castle's animals in three files. They all contain the same, just written down differently. + +As text, the way you would write it to a person: + +::: datei animals.txt +Ludwig (billy goat) is 7 years old. +Zora (goat) is 6 years old. +Fox (red fox) is 4 years old. +::: + +As a table in CSV: + +::: datei animals.csv +Name;Species;Age +Ludwig;billy goat;7 +Zora;goat;6 +Fox;red fox;4 +::: + +As JSON: + +::: datei animals.json +[ + {"name": "Ludwig", "species": "billy goat", "age": 7}, + {"name": "Zora", "species": "goat", "age": 6}, + {"name": "Fox", "species": "red fox", "age": 4} +] +::: + +## What can each format do? + +| | txt | CSV | JSON | +|---|---|---|---| +| Easy for people to read | yes | so-so | so-so | +| Fixed order for programs | no | yes, columns | yes, keys | +| What does a value mean? | it's in the sentence | it's in the header | it's right in front of it | +| Nesting (a list inside an entry) | no | hard | yes | +| Opens in Excel | no | yes | no | +| Reading in Java | Scanner, BufferedReader | plus \`split\` | string methods or a library | +| Size | small | smallest | largest | + +In short: + +- **txt** for texts that people read: letters, notes, a logbook. +- **CSV** for tables: grades, measurements, a high-score list. Every line has the same columns. +- **JSON** for data with structure: game saves, settings, everything that goes back and forth between programs and on the web. + +::: ludwig +When your weather app fetches the temperature, the answer almost always comes as JSON. And when a teacher exports the grades from the school software, they often get a CSV file. +::: + +## Exercise: From CSV to sentences + +::: übung l27-java-saetze +titel: From CSV to sentences +code: java +auftrag: Convert \`animals.csv\` into text. For each animal, write a sentence like **Ludwig (billy goat) is 7 years old.** into the file \`sentences.txt\`. At the end, print **3 sentences saved**. +start: l27-java-saetze-start.visustruct +test: - -> 3 sentences saved +datei: sentences.txt -> Ludwig (billy goat) is 7 years old. | Zora (goat) is 6 years old. | Fox (red fox) is 4 years old. +braucht: whileSchleife +tipp: The start code already skips the header. Split each line with \`String[] parts = line.split(";");\`. +tipp: The sentence is \`parts[0] + " (" + parts[1] + ") is " + parts[2] + " years old."\`. Count along with \`count++\` and read the next line at the end of the loop. +lösung: l27-java-saetze-loesung.visustruct +::: + +## Exercise: From CSV to JSON + +::: übung l27-java-json +titel: From CSV to JSON +code: java +auftrag: Convert \`animals.csv\` into JSON and save it in \`animals-new.json\`, exactly like \`animals.json\` above. At the end, print **3 animals saved**. +start: l27-java-json-start.visustruct +test: - -> 3 animals saved +datei: animals-new.json -> [ | {"name": "Ludwig", "species": "billy goat", "age": 7}, | {"name": "Zora", "species": "goat", "age": 6}, | {"name": "Fox", "species": "red fox", "age": 4} | ] +braucht: forSchleife, verzweigung +tipp: \`lines[0]\` is the header. So start the for loop at \`i = 1\` and split \`lines[i]\` with \`split(";")\`. +tipp: Build the entry with \`\\"\` as in lesson 26. The age is a number and has no quotation marks. Only add a comma if \`i < lines.length - 1\`. +lösung: l27-java-json-loesung.visustruct +::: + +## Game: Which format fits? + +::: spiel frage +titel: Game: Which format fits? +intro: Ludwig wants to save data and doesn't know which format to use. Help him. Six rounds. +antworten: txt | CSV | JSON + +runde: +frage: The grades of the whole class should be opened in Excel. +richtig: CSV +> Grades are a table, and Excel opens CSV files directly. + +runde: +frage: Ludwig writes a letter to Zora. +richtig: txt +> A letter is text for people. It needs no columns and no keys. + +runde: +frage: A game save with a name, a level and a list of all the keys collected. +richtig: JSON +> A list inside an entry can be nested in JSON. In CSV it hardly fits into one cell. + +runde: +frage: A measuring device saves the time and temperature every minute, for a whole year. +richtig: CSV +> Many identical lines with the same columns: CSV is the smallest for this. JSON would repeat the keys on every line. + +runde: +frage: A weather app fetches the forecast from a server on the internet. +richtig: JSON +> JSON is the standard on the web. Almost every app gets its data this way. + +runde: +frage: The castle logbook, where every entry is a short sentence. +richtig: txt +> Every line is a sentence for people. It is read line by line, as in lesson 24. +::: + +## 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. + +::: checkliste +- I can recognise the same data as txt, CSV and JSON. → The same animals three times +- I can compare strengths and weaknesses of txt, CSV and JSON. → What can each format do? +- I can convert a CSV file into sentences. → Exercise: From CSV to sentences +- I can convert a CSV file into JSON. → Exercise: From CSV to JSON +::: + +## Quiz + +::: quiz +? Which format does Excel open directly as a table? +→ What can each format do? +- [ ] txt +- [x] CSV +- [ ] JSON + +? Why is a JSON file usually larger than a CSV file with the same data? +→ What can each format do? +- [ ] Because JSON stores more numbers. +- [x] Because the keys are repeated in every entry. +- [ ] Because JSON uses no commas. + +? In which format does every value say what it means? +→ What can each format do? +- [ ] txt +- [ ] CSV +- [x] JSON +> In JSON the key comes right before the value, for example "age": 7. + +? Match each purpose with a format. +→ What can each format do? += a letter to Zora -> txt += the class grade list -> CSV += a game save with lists -> JSON +::: +`,O4=`--- +titel: Your first window +bereich: Windows with Swing +kurz: Open your own window with Java and Swing, explained line by line. +--- + +## Skills I will gain now + +::: kompetenzen +- switch on “Real Java” in the Code area +- open a window with a title and a size +- explain what each line of the window program does +- explain why setVisible(true) comes last +::: + +## Programs with windows + +So far your programs have written text to the console. Most programs you know, however, have **windows** with buttons and text fields. This is called a graphical user interface. + +Java comes with a toolbox for this: **Swing**. In VisuStruct you switch it on like this: + +1. Open the [Code](#zeige-codelive) area on the right. +2. Click the [gear](#zeige-einstellungen) at the top right and choose Java as the **Programming language**. +3. Below that, in the Java section, tick **Real Java (with Swing)**. + +The first time you click [▶︎ Run](#zeige-ausfuehren), VisuStruct downloads about 40 MB once, which takes a moment. After that your code runs as real Java, and your windows appear in the Code area in the **Java windows** box above the console. + +> With “Real Java”, input from the console (\`Scanner\`) does not work yet. For programs with input, untick the box again. + +::: angeberwissen +Swing has been around since 1998. Before that, Java only had the older AWT with a class called \`Frame\`. So that nobody mixes up the new building blocks, almost all names in Swing start with **J**: \`JFrame\`, \`JButton\`, \`JLabel\`. The J tells you straight away that it is Swing. +::: + +## The whole program + +This is the smallest program that opens a window. Type it into the Code area and click [▶︎ Run](#zeige-ausfuehren): + +\`\`\`java +import javax.swing.*; + +public class MyWindow { + public static void main(String[] args) { + JFrame window = new JFrame("My first window"); + window.setSize(300, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setVisible(true); + } +} +\`\`\` + +An empty grey window with the title “My first window” appears. That's all, but it is your very own window! + +You already know the frame with \`public class\` and \`main\` from the Java lesson. The first line and the four lines inside \`main\` are new. Let's look at them one by one. + +::: ludwig +Look at the structure chart next to the code: every line in \`main\` is a box, one below the other. So at the start, a window program is just a sequence. +::: + +## Line by line + +| Line | What it does | +|---|---| +| \`import javax.swing.*;\` | Brings the Swing toolbox into the program. Without this line Java does not know \`JFrame\`. | +| \`JFrame window = new JFrame("My first window");\` | Builds a new window. The text in brackets is the title at the top of the window frame. After that you talk to it through the variable \`window\`. | +| \`window.setSize(300, 200);\` | The window becomes 300 pixels wide and 200 pixels high. | +| \`window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\` | When someone closes the window, the program ends too. | +| \`window.setVisible(true);\` | Only now does the window become visible. | + +The dot in \`window.setSize(…)\` means: “Window, do this!” Before the dot is who should do something, after it is what they should do. + +> Without \`setDefaultCloseOperation\`, Java only hides the window when it is closed. The program then keeps running invisibly. + +## Why setVisible comes last + +\`setVisible(true)\` shows the window exactly as it is at that moment. So you set everything up first: title, size, and later buttons too. Only at the very end do you make the window visible. + +Things you put into the window after \`setVisible(true)\` often do not appear. Java does not redraw the window on its own. Sometimes they only show up when you resize the window. Mistakes like that are hard to find. + +::: ludwig +Set up first, then show. Like in the theatre: the curtain only goes up once the stage is ready. +::: + +Try it: delete the line with \`setVisible(true)\` and run the program again. The program runs, but you do not see a window. + +## Expert knowledge: classes and objects + +This is not in the curriculum, but it helps you understand Swing. + +::: angeberwissen +Java is really an **object-oriented** language. \`JFrame\` is a class, a blueprint for windows. With \`new JFrame(…)\` Java builds a real window from this blueprint, an **object**. With two \`new\` you could build two windows, both from the same blueprint. + +\`setSize\` and \`setVisible\` are methods that every window object has. That is why you write \`window.setSize(…)\`: the object \`window\` runs its method. Your program itself is a class too, namely \`MyWindow\`. +::: + +## Game: What happens? + +::: spiel frage +titel: Game: What happens? +intro: Ludwig has been tinkering with the window program. Read the lines and predict what happens. Six rounds. + +runde: + JFrame window = new JFrame("Hello"); + window.setSize(300, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); +frage: What do you see after running it? +- a window with the title "Hello" +- [x] no window at all +- an error message +> \`setVisible(true)\` is missing. The window is built, but it stays invisible. + +runde: + JFrame window = new JFrame("Hello"); + window.setSize(200, 300); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setVisible(true); +frage: What does the window look like? +- wider than high +- [x] higher than wide +- square +> The first number is the width, the second the height: 200 wide, 300 high. + +runde: + JFrame window = new JFrame("Hello"); + window.setSize(300, 200); + window.setVisible(true); +frage: You close the window. What happens to the program? +- It ends. +- [x] It keeps running invisibly. +- The window opens again right away. +> Without \`setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)\` Java only hides the window. + +runde: + JFrame window = new JFrame(); + window.setSize(300, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setVisible(true); +frage: What is written at the top of the window frame? +- window +- JFrame +- [x] nothing, the title is empty +> Without text in the brackets the window has no title. The variable name \`window\` never shows up in the window. + +runde: + public class Test { + public static void main(String[] args) { + JFrame window = new JFrame("Test"); + window.setVisible(true); + } + } +frage: What does javac report? +- [x] cannot find symbol: class JFrame +- nothing, the window appears +- missing return statement +> The line \`import javax.swing.*;\` is missing. Without it Java doesn't know \`JFrame\`. + +runde: + JFrame a = new JFrame("One"); + JFrame b = new JFrame("Two"); + a.setSize(300, 200); + b.setSize(300, 200); + a.setVisible(true); +frage: What do you see? +- [x] one window with the title "One" +- two windows +- one window with the title "Two" +> Two windows from the same blueprint, but only \`a\` is made visible. +::: + +## Task: your own window + +Change the program so that + +- the title says “Hello” and your name, +- the window is 400 pixels wide and 300 pixels high, +- the program ends when you close the window. + +Run it and check all three points. + +::: ludwig +Don't feel like typing so much? With “Real Java” you may type just the four lines from \`main\` into the Code area. VisuStruct then wraps them in a class itself and adds the \`import\` lines. In a real Java development environment, though, you need the whole program. +::: + +## 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. + +::: checkliste +- I can switch on “Real Java” in the Code area. → Programs with windows +- I can open a window with a title and a size. → The whole program +- I can explain what each line of the window program does. → Line by line +- I can explain why setVisible(true) comes last. → Why setVisible comes last +::: + +## Quiz + +::: quiz +? Which line makes the window visible? +→ Why setVisible comes last +- [ ] window.setSize(300, 200); +- [x] window.setVisible(true); +- [ ] new JFrame("Hello"); +> Without setVisible(true) the window stays invisible. + +? Where is the best place for window.setVisible(true)? +→ Why setVisible comes last +- [ ] At the very start of main +- [x] At the end, once the window is set up +- [ ] It does not matter. +> Things added after setVisible(true) often do not appear. + +? What does setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) do? +→ Line by line +- [ ] The window closes immediately. +- [x] When you close the window, the program ends. +- [ ] The window can no longer be closed. + +? How do you recognise building blocks from Swing? +→ Line by line +- [x] Their name starts with J, e.g. JFrame. +- [ ] They are in curly brackets. +- [ ] They end in Window. +::: +`,C4=`--- +titel: A button in the window +bereich: Windows with Swing +kurz: Put a button into the window and arrange it neatly with a layout. +--- + +## Skills I will gain now + +::: kompetenzen +- build a button and put it into the window with add +- explain why the button goes in before setVisible +- use FlowLayout so that the button has its normal size +- build a window with a button you can press +::: + +## Building a button + +An empty window is boring. Now a button goes in. In Swing a button is called **JButton**. + +You need two new lines for it: + +\`\`\`java +JButton button = new JButton("Click me"); +window.add(button); +\`\`\` + +- \`new JButton("Click me")\` builds a button. The text in brackets will be written on the button. +- \`window.add(button)\` puts the button into the window. Without \`add\` the button exists, but it is not placed anywhere and you cannot see it. + +## The whole program + +Both lines go **before** \`setVisible(true)\`, because the window should be set up completely first and then shown: + +\`\`\`java +import javax.swing.*; + +public class ButtonWindow { + public static void main(String[] args) { + JFrame window = new JFrame("Button"); + window.setSize(300, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JButton button = new JButton("Click me"); + window.add(button); + + window.setVisible(true); + } +} +\`\`\` + +Run the program. Surprise: the button is huge and fills the whole window! + +::: ludwig +The order is the same as with your first window: set up, build the button, put the button in and show everything at the very end. The empty lines in the code help you see these parts. +::: + +## The giant button + +How a window arranges its parts is decided by its **layout**. Without further instructions, a \`JFrame\` puts everything in the middle and makes it as big as the whole window. + +With a different layout the button gets its normal size. The **FlowLayout** places everything side by side like words in a line, only as big as needed: + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class ButtonWindow { + public static void main(String[] args) { + JFrame window = new JFrame("Button"); + window.setSize(300, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new FlowLayout()); + + JButton button = new JButton("Click me"); + window.add(button); + + window.setVisible(true); + } +} +\`\`\` + +\`FlowLayout\` belongs to the older AWT toolbox. That is why there is a second line at the top: \`import java.awt.*;\`. + +::: angeberwissen +With FlowLayout the building blocks flow like text: if a button no longer fits into the line, it moves to the next one. Make the window narrow and watch the buttons wrap. That is where the name comes from. +::: + +## Clicking works, but nothing happens + +Click the button. It turns a little darker while you press it. So Swing shows that it was pressed. Apart from that, nothing happens. + +That is not a mistake: you have not told the program **what** should happen on a click yet. You will learn that in the next lesson. + +## Game: Defuse the bomb + +::: spiel bombe +titel: Game: Defuse the bomb +intro: Every window program contains **exactly one mistake**, and the bomb is ticking. Read what the program should do and tap the wrong line before time runs out. Six rounds, 25 seconds each. +zeit: 25 + +runde: + JFrame window = new JFrame("Button"); + window.setSize(300, 200); + JButton button = new JButton(Click me); + window.add(button); + window.setVisible(true); +frage: Should show a button "Click me". +fehler: 3 +besser: JButton button = new JButton("Click me"); +> The caption is a text and needs quotation marks. + +runde: + JFrame window = new JFrame("Button"); + window.setSize(300, 200); + JButton button = new JButton("OK"); + window.add(window); + window.setVisible(true); +frage: Should put the button "OK" into the window. +fehler: 4 +besser: window.add(button); +> The button goes into the window, not the window itself. + +runde: + import java.swing.*; + import java.awt.*; +frage: Should bring Swing and the FlowLayout into the program. +fehler: 1 +besser: import javax.swing.*; +> Swing lives in \`javax.swing\`, with an x. The FlowLayout comes from \`java.awt\`, without an x. + +runde: + JFrame window = new JFrame("Button"); + window.setSize(300, 200); + window.setLayout(new FlowLayout); + window.add(new JButton("OK")); + window.setVisible(true); +frage: Should show the button at its normal size. +fehler: 3 +besser: window.setLayout(new FlowLayout()); +> After \`new\` and the name there are always round brackets, even if nothing is inside. + +runde: + JFrame window = new JFrame("Button"); + window.setSize(300, 200); + window.setLayout(new FlowLayout()); + JButton button = new Jbutton("OK"); + window.add(button); + window.setVisible(true); +frage: Should show a button "OK". +fehler: 4 +besser: JButton button = new JButton("OK"); +> Java tells capital and small letters apart: \`JButton\` with a capital B. + +runde: + JFrame window = new JFrame("Button"); + window.setSize(300, 200); + window.setLayout(new FlowLayout()); + window.add(new JButton("OK")); + window.setVisible(false); +frage: Should show the window with the button. +fehler: 5 +besser: window.setVisible(true); +> With \`false\` the window stays invisible. +::: + +## Task: click me + +Build a window with the title “Button test”, 300 by 200 pixels, with a button “Click me” in normal size. It should be possible to press the button, even though nothing happens yet. + +Extra: put a second button “Me too” next to it. In which order are the buttons? Swap the two \`add\` lines and try again. + +::: ludwig +Every button needs its own variable, for example \`button\` and \`button2\`, and its own \`add\`. FlowLayout places the buttons in the order of the \`add\` lines. +::: + +## 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. + +::: checkliste +- I can build a button and put it into the window with add. → Building a button +- I can explain why the button goes in before setVisible(true). → The whole program +- I can use FlowLayout so that the button has its normal size. → The giant button +- I can build a window with a button you can press. → Task: click me +::: + +## Quiz + +::: quiz +? What does window.add(button) do? +→ Building a button +- [ ] It builds a new button. +- [x] It puts the button into the window. +- [ ] It makes the button clickable. +> The button is built with new JButton(…). + +? Why does the button fill the whole window without FlowLayout? +→ The giant button +- [ ] Because the text is too long +- [x] Because without its own layout the window makes everything as big as the window +- [ ] Because setSize is missing + +? Which import line do you need for FlowLayout? +→ The giant button +- [ ] import javax.swing.*; +- [x] import java.awt.*; +- [ ] import java.util.*; +> FlowLayout comes from the older AWT. + +? What happens when you click the button in this lesson? +→ Task: click me +- [ ] The program ends. +- [x] The button turns darker for a moment, nothing else happens. +- [ ] The button says “I was clicked”. +> What should happen on a click is what you learn in the next lesson. +::: +`,j4=`--- +titel: The button reacts +bereich: Windows with Swing +kurz: Use an ActionListener to decide what happens on a click. +--- + +## Skills I will gain now + +::: kompetenzen +- explain what an event is +- use addActionListener to decide what happens on a click +- run several statements on a click +- build a button that changes its text after the click +::: + +## A click is an event + +In the last lesson you could press the button, but nothing happened. In a window program it is the person who decides when something happens: they click, type or close a window. Each such action is called an **event**. + +So your program has to wait for the click and notice it. For this you register a listener with the button, an **ActionListener**. On every click the button calls its listener, and the listener runs your code. + +::: ludwig +Until now your program ran from top to bottom, just like the structure chart. The code in the listener only runs later, whenever someone clicks. Nobody knows in advance how often that will be. +::: + +## The line with the arrow + +This is how you register the listener: + +\`\`\`java +button.addActionListener(e -> button.setText("I was clicked")); +\`\`\` + +Read from the outside in: + +- \`button.addActionListener( … )\` registers a listener with the button. +- \`e\` is the event. It contains, for example, when the click happened. You do not need it here, but the name has to be there. +- Read \`->\` as “then do”. +- \`button.setText("I was clicked")\` is what happens on a click: the button gets a new label. + +The line comes after \`new JButton(…)\`, because the button has to exist already. And like everything else it comes before \`setVisible(true)\`. + +## The whole program + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class ClickMe { + public static void main(String[] args) { + JFrame window = new JFrame("Click me"); + window.setSize(300, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new FlowLayout()); + + JButton button = new JButton("Click me"); + button.addActionListener(e -> button.setText("I was clicked")); + window.add(button); + + window.setVisible(true); + } +} +\`\`\` + +Run it and click the button. Now it says “I was clicked”. + +> If the new text is longer than the old one, FlowLayout makes the button wider on its own. + +## Several statements on a click + +If more than one thing should happen on a click, put curly brackets after the arrow. Inside, every statement has its semicolon, just like in a loop body: + +\`\`\`java +button.addActionListener(e -> { + button.setText("I was clicked"); + window.setTitle("Thank you!"); + System.out.println("Click!"); +}); +\`\`\` + +\`System.out.println\` writes to the [console](#zeige-konsole) as usual. Click several times: every click adds a new line “Click!”. That shows you that the code in the listener really runs on every click. + +::: ludwig +Watch the ending: first \`}\` closes the block, then \`)\` closes the bracket of \`addActionListener\`, then comes the semicolon. So \`});\`. If any of it is missing, a hint appears below the code. +::: + +## Game: Who is listening? + +::: spiel zuhoerer +titel: Game: Who is listening? +intro: Ludwig shows you code and the window that goes with it. Below it you see which buttons are clicked, one after the other. What happens? After your answer Ludwig plays the clicks: you see which listener hears the event and which lines then run. +frage: What does the label say after the clicks? + +runde: + JFrame window = new JFrame("Greeting"); + JLabel text = new JLabel("Start"); + JButton button = new JButton("Hello"); + button.addActionListener(e -> text.setText("Hello world")); +klicks: Hello +- Start +- [x] Hello world +- Hello +> The button has a listener. On a click it runs \`text.setText("Hello world")\`, and the label shows “Hello world”. + +runde: + JFrame window = new JFrame("Fruit"); + JLabel text = new JLabel("?"); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + a.addActionListener(e -> text.setText("Apple")); + b.addActionListener(e -> text.setText("Pear")); +klicks: A, B +- Apple +- [x] Pear +- Apple Pear +> Each button has its own listener. First A writes “Apple”, then B overwrites it with “Pear”. \`setText\` replaces the old text, it doesn't add anything. + +runde: + JFrame window = new JFrame("Fruit"); + JLabel text = new JLabel("?"); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + a.addActionListener(e -> text.setText("Apple")); +klicks: B +- Apple +- Pear +- [x] ? +> Nobody signed up at button B: there is no \`b.addActionListener\`. The click is an event, but nobody is listening. So the question mark stays. + +runde: + JFrame window = new JFrame("Colours"); + JLabel text = new JLabel("none"); + JButton red = new JButton("Red"); + JButton blue = new JButton("Blue"); + red.addActionListener(e -> text.setText("Blue")); + blue.addActionListener(e -> text.setText("Red")); +klicks: Red +- Red +- [x] Blue +- none +> Careful: what happens is decided by the code in the listener, not by the caption of the button. The listener on the button “Red” writes “Blue”. + +runde: + JFrame window = new JFrame("Button"); + JLabel text = new JLabel("Please click"); + JButton button = new JButton("Click me"); + button.addActionListener(e -> { + button.setText("Thanks!"); + text.setText("Clicked"); + }); +klicks: Click me +frage: What does the button say after the click? +- Click me +- [x] Thanks! +- Clicked +> The block after the arrow has two statements. Both run on the click, one after the other: the button gets “Thanks!”, the label “Clicked”. + +runde: + JFrame window = new JFrame("Console"); + JButton button = new JButton("Go"); + button.addActionListener(e -> System.out.println("Click!")); +klicks: Go, Go, Go +frage: How many lines “Click!” are in the console afterwards? +- 1 +- [x] 3 +- 0 +> The listener runs on **every** click, not only on the first one. Three clicks, three lines. +::: + +## Expert knowledge: ActionListener is an interface + +This is not in the curriculum. If you want to know what is behind the arrow, read on. + +::: angeberwissen +\`ActionListener\` is an **interface**, a kind of contract. It says: whoever wants to be an ActionListener must have a method \`actionPerformed(ActionEvent e)\`. On every click the button calls exactly this method. +::: + +You already know the line with the arrow from step 3: + +\`\`\`java +button.addActionListener(e -> button.setText("I was clicked")); +\`\`\` + +Without the arrow you write the listener as a class without a name that fulfils the contract (an anonymous class): + +\`\`\`java +button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + button.setText("I was clicked"); + } +}); +\`\`\` + +For this you also need \`import java.awt.event.*;\` at the top. Both ways do exactly the same. The arrow \`e -> …\` is the short form (a lambda expression, since Java 8): \`e\` is the parameter of \`actionPerformed\`, and after the arrow comes its body. The short form works because the interface has only one method. So Java knows which method is meant. + +## Game: Contract fulfilled? + +::: spiel vertrag +titel: Game: Contract fulfilled? +intro: The contract \`ActionListener\` asks for exactly one method: \`public void actionPerformed(ActionEvent e)\`. Ludwig shows you code. Does it fulfil the contract, so that you can sign it up at a button? Ludwig checked every answer with the real Java compiler. +frage: Does this fulfil the contract ActionListener? +antworten: fulfilled | not fulfilled + +runde: + class Greeting implements ActionListener { + public void actionPerformed(ActionEvent e) { + System.out.println("Hello"); + } + } +richtig: fulfilled +> Everything is there: \`implements ActionListener\` signs the contract, and the method is called exactly \`actionPerformed\`, is \`public\`, returns nothing (\`void\`) and gets an \`ActionEvent\`. + +runde: + class Greeting implements ActionListener { + public void actionPerfomed(ActionEvent e) { + System.out.println("Hello"); + } + } +richtig: not fulfilled +> Look closely: \`actionPerfomed\` instead of \`actionPerformed\`, an r is missing. For Java that is a completely different method. The compiler reports that \`actionPerformed\` is missing. + +runde: + class Greeting implements ActionListener { + public void actionPerformed() { + System.out.println("Hello"); + } + } +richtig: not fulfilled +> The parameter is missing. The contract asks for \`actionPerformed(ActionEvent e)\`, because on a click the button hands over the event. + +runde: + class Greeting implements ActionListener { + public void actionPerformed(ActionEvent event) { + System.out.println("Hello"); + } + } +richtig: fulfilled +> You can choose the name of the parameter freely. Only the type \`ActionEvent\` matters. So instead of \`e\` it may also be called \`event\`. + +runde: + class Greeting implements ActionListener { + void actionPerformed(ActionEvent e) { + System.out.println("Hello"); + } + } +richtig: not fulfilled +> The \`public\` is missing. All methods of an interface are public, because the button has to be able to call them from outside. Without \`public\` the compiler reports an error. + +runde: + class Greeting implements ActionListener { + public int actionPerformed(ActionEvent e) { + return 0; + } + } +richtig: not fulfilled +> The contract says \`void\`: the method returns nothing. With \`int\` as the return type it no longer fits. + +runde: + class Greeting implements ActionListener { + public void actionPerformed(ActionEvent e) { + sayHello(); + } + void sayHello() { + System.out.println("Hello"); + } + } +richtig: fulfilled +> Extra methods are allowed. The contract only asks that \`actionPerformed\` is there, not that nothing else is there. + +runde: + class Greeting { + public void actionPerformed(ActionEvent e) { + System.out.println("Hello"); + } + } + button.addActionListener(new Greeting()); +richtig: not fulfilled +> The method is right, but the contract isn't signed: \`implements ActionListener\` is missing. At a button Java only accepts objects that officially fulfil the contract. + +runde: + button.addActionListener(e -> System.out.println("Hello")); +richtig: fulfilled +> The arrow is the short form. Because the contract has only one method, Java knows: \`e\` is the parameter of \`actionPerformed\`, and after the arrow comes its body. + +runde: + button.addActionListener((a, b) -> System.out.println("Hello")); +richtig: not fulfilled +> Here the arrow has two parameters. But \`actionPerformed\` gets exactly one, the event. So this short form doesn't fit the contract. +::: + +## Task: I was clicked + +Now you finish the task: build a window with a button “Click me” in normal size. After the click the button says “I was clicked”. + +Extra: build two buttons “Red” and “Blue”. Clicking a button writes its name into the window title, for example “You chose Red”. + +::: ludwig +Every button gets its own listener with its own \`addActionListener\`. You change the title with \`window.setTitle(…)\`. +::: + +## 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. + +::: checkliste +- I can explain what an event is. → A click is an event +- I can use addActionListener to decide what happens on a click. → The line with the arrow +- I can run several statements on a click. → Several statements on a click +- I can build a button that changes its text after the click. → Task: I was clicked +::: + +## Quiz + +::: quiz +? What is an ActionListener? +→ A click is an event +- [ ] A button with text +- [x] A listener that runs your code on every click +- [ ] A layout for windows +> You register it with the button using addActionListener. + +? When does button.setText("I was clicked") in the listener run? +→ The line with the arrow +- [ ] Right when the program starts +- [x] Every time someone clicks the button +- [ ] Only on the first click +> The code in the listener only runs when the event happens. + +? How does a listener with curly brackets end? +→ The line with the arrow +- [ ] };) +- [x] }); +- [ ] );} +> First the block closes, then the bracket of addActionListener, then the semicolon. + +? Match each part to its job. +→ The line with the arrow += JButton -> a button += addActionListener -> register a listener += setText -> change the label += setVisible(true) -> show the window +::: +`,P4=`--- +titel: Doubling a number in a window +bereich: Windows with Swing +kurz: Arrange a label, a text field and a button with a GridLayout and calculate with the text in the text field. +--- + +## Skills I will gain now + +::: kompetenzen +- put a JLabel and a JTextField into the window +- explain why only the last building block shows without a layout +- arrange everything below each other with GridLayout +- calculate with getText, Integer.parseInt and setText +- write a program that doesn't crash with “abc” +::: + +## The goal + +We build a small calculator with a window: at the top there is a label, below it a text field and a button **Calculate**. If you type 2 and click, the text field shows 4. Click again and it becomes 8, then 16 and so on. + +For this you need two new building blocks: + +- **JLabel**: a label, simply text in the window. +- **JTextField**: a text field you can type into. + +As in the last lessons, tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## Three building blocks in the window + +We put all three building blocks into the window, just like the button in lesson 29: + +\`\`\`java +import javax.swing.*; + +public class Doubling { + public static void main(String[] args) { + JFrame window = new JFrame("Double the number"); + window.setSize(250, 150); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JLabel label = new JLabel("Enter a number:"); + JTextField field = new JTextField(); + JButton button = new JButton("Calculate"); + window.add(label); + window.add(field); + window.add(button); + + window.setVisible(true); + } +} +\`\`\` + +Run the program. Oops: all you can see is the giant button. Where are the label and the text field? + +## Why only the button shows + +::: ludwig +Remember the giant button? Without a layout of its own, a \`JFrame\` has only **one** place: the middle. Every \`add\` puts the new building block exactly there, as big as the whole window. So the three building blocks land on top of each other in the same place, and the window only shows the last one you put in: the button. You can't use the program like this. +::: + +The solution is a layout again. This time we use the **GridLayout**. It divides the window into cells of equal size, like a grid: + +\`\`\`java +window.setLayout(new GridLayout(0, 1)); +\`\`\` + +The two numbers are rows and columns. \`0\` rows means “as many as needed”, \`1\` column means: everything below each other. For \`GridLayout\` you also need \`import java.awt.*;\` at the top. + +| Layout | How it arranges things | +|---|---| +| no layout | everything in the middle, on top of each other | +| \`FlowLayout\` | side by side like words, with a line break when needed | +| \`GridLayout(0, 1)\` | below each other, every row the same height | + +## The window with GridLayout + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Doubling { + public static void main(String[] args) { + JFrame window = new JFrame("Double the number"); + window.setSize(250, 150); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new GridLayout(0, 1)); + + JLabel label = new JLabel("Enter a number:"); + JTextField field = new JTextField(); + JButton button = new JButton("Calculate"); + window.add(label); + window.add(field); + window.add(button); + + window.setVisible(true); + } +} +\`\`\` + +Now all three are below each other. You can type into the text field and press the button. But the program doesn't calculate anything yet. + +::: angeberwissen +With \`new GridLayout(2, 3)\` you get 2 rows with 3 columns each, so 6 cells of the same size. That is how you build the keys of a calculator, for example. The building blocks fill the cells in the order of the \`add\` lines, row by row from left to right. +::: + +## Calculating with the text in the text field + +On a click, the program should take the number from the text field, double it and write it back. Three methods do this: + +- \`field.getText()\` gives you the text in the text field, for example \`"2"\`. +- \`Integer.parseInt(…)\` turns it into the number 2. You know this from lesson 22. +- \`field.setText(…)\` writes a new text into the text field. + +Together with the ActionListener from lesson 30 it looks like this: + +\`\`\`java +button.addActionListener(e -> { + int number = Integer.parseInt(field.getText()); + field.setText("" + number * 2); +}); +\`\`\` + +\`setText\` needs a text. \`"" + number * 2\` appends the result to an empty text and so turns the number into a text. + +## Not a number? No crash! + +Type “abc” into the text field and click Calculate. The window stays, but nothing happens, and the [console](#zeige-konsole) shows a \`NumberFormatException\`. From lesson 22 you know what to do: + +\`\`\`java +button.addActionListener(e -> { + try { + int number = Integer.parseInt(field.getText()); + field.setText("" + number * 2); + } catch (NumberFormatException error) { + label.setText("Please enter a whole number!"); + } +}); +\`\`\` + +Instead of an error in the console, you now see a hint in the window. + +::: ludwig +The arrow already has an \`e\` for the event. That is why the exception in \`catch\` needs a different name, here \`error\`. Java doesn't allow two variables with the same name. +::: + +## Game: What is in the window afterwards? + +::: spiel frage +titel: Game: What is in the window afterwards? +intro: Ludwig types something into the text field and clicks Calculate. Read the listener and predict what the window shows afterwards. Six rounds. + +runde: + button.addActionListener(e -> { + int number = Integer.parseInt(field.getText()); + field.setText("" + number * 2); + }); +frage: The text field says 21. What does it say after the click? +- 2121 +- [x] 42 +- 21 +> \`parseInt\` turns the text into the number 21. Double that is 42. + +runde: + button.addActionListener(e -> { + int number = Integer.parseInt(field.getText()); + field.setText("" + number * 2); + }); +frage: The text field says 21. You click twice. What does it say afterwards? +- 42 +- [x] 84 +- 4242 +> Every click doubles whatever is in the field right now: 21, 42, 84. + +runde: + button.addActionListener(e -> { + field.setText(field.getText() + field.getText()); + }); +frage: The text field says 21. What does it say after the click? +- 42 +- [x] 2121 +- 21 +> Without \`parseInt\` it stays a text, and \`+\` joins texts together. + +runde: + button.addActionListener(e -> { + try { + int number = Integer.parseInt(field.getText()); + field.setText("" + number * 2); + } catch (NumberFormatException error) { + label.setText("Please enter a whole number!"); + } + }); +frage: The text field says abc. What happens on the click? +- [x] The label shows "Please enter a whole number!" +- The text field says abcabc. +- The window crashes. +> \`parseInt\` throws a NumberFormatException, and \`catch\` catches it. + +runde: + button.addActionListener(e -> { + try { + int number = Integer.parseInt(field.getText()); + field.setText("" + number * 2); + } catch (NumberFormatException error) { + label.setText("Please enter a whole number!"); + } + }); +frage: The text field says 2.5. What happens on the click? +- The text field says 5.0. +- The text field says 5. +- [x] The label shows "Please enter a whole number!" +> \`Integer.parseInt\` only knows whole numbers. For it, 2.5 is not a number. + +runde: + button.addActionListener(e -> { + int number = Integer.parseInt(field.getText()); + field.setText("" + number + number); + }); +frage: The text field says 5. What does it say after the click? +- 10 +- [x] 55 +- 5 +> \`"" + number\` is already a text, and the second \`+\` adds the 5 once more. With \`"" + (number + number)\` Java calculates first. +::: + +## Task: doubling a number + +Put the whole program together: + +- a window with the title “Double the number”, 250 pixels wide and 150 pixels high, +- below each other a label, a text field and a button “Calculate”, +- every click doubles the number in the text field: 2, 4, 8, 16, … +- with “abc” a hint appears in the label instead of a crash. + +Extra: a second button “Halve” divides the number by 2. What happens with 5? + +::: ludwig +The “Halve” button goes into the GridLayout as the fourth row and gets its own ActionListener. With \`int\`, Java cuts off the decimal places when dividing. +::: + +## 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. + +::: checkliste +- I can put a JLabel and a JTextField into the window. → Three building blocks in the window +- I can explain why only the last building block shows without a layout. → Why only the button shows +- I can arrange everything below each other with GridLayout(0, 1). → The window with GridLayout +- I can calculate with getText, Integer.parseInt and setText. → Calculating with the text in the text field +- I can write a program that doesn't crash with “abc”. → Not a number? No crash! +::: + +## Quiz + +::: quiz +? Why does only the button show without a layout? +→ Why only the button shows +- [ ] Because the label and the text field are missing +- [x] Because all building blocks lie on top of each other in the middle and the last one hides the others +- [ ] Because the window is too small + +? What does new GridLayout(0, 1) mean? +→ The window with GridLayout +- [ ] No row and one column, so the window is empty +- [x] As many rows as needed in one column, so everything below each other +- [ ] One row, everything side by side + +? What does field.getText() give you? +→ Calculating with the text in the text field +- [ ] Always a number +- [x] The text in the text field +- [ ] The title of the window +> For a number you still need Integer.parseInt. + +? Match each building block to its job. +→ Three building blocks in the window += JLabel -> label += JTextField -> text field for typing += JButton -> button += GridLayout -> arrangement in a grid +::: +`,D4=`--- +titel: Click counter with reset +bereich: Windows with Swing +kurz: Two buttons change the same number: create a variable for the whole class. +--- + +## Skills I will gain now + +::: kompetenzen +- explain why a listener may not change a variable from main +- create a static variable in the class +- let two buttons change the same number +- build a counter with −1 that never goes below 0 +::: + +## The goal + +A window counts clicks: the number is at the top, two buttons below it. **+1** counts up by one, **Reset** sets the number back to 0. + +What's new this time: two buttons work with the **same** number. For that you need a variable that both listeners know. + +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## The first attempt + +The obvious idea is to create the number in \`main\` as usual and count it up in the listener: + +\`\`\`java +int count = 0; +button.addActionListener(e -> { + count++; + number.setText("" + count); +}); +\`\`\` + +If you run this with real Java, the compiler reports an error: + +\`\`\` +local variables referenced from a lambda expression must be final or effectively final +\`\`\` + +::: ludwig +The listener only runs later, on every click, long after \`main\` has finished. That is why it may read the variables from \`main\`, but not change them. Java insists: a variable from \`main\` that appears in the arrow must stay the same. For a number that changes on every click, we need a different place. +::: + +## A variable for the whole class + +The solution: the variable does **not** go into \`main\`, but directly into the class, above \`main\`. Then it belongs to the whole class, and every listener may change it: + +\`\`\`java +public class Counter { + static int count = 0; + + public static void main(String[] args) { + // the window as usual + } +} +\`\`\` + +- \`static\` means: the variable belongs to the class itself. Because \`main\` is \`static\` too, it is needed here. +- A variable like this is called a **field** of the class. It lives as long as the program, not just as long as \`main\`. + +## The whole program + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Counter { + static int count = 0; + + public static void main(String[] args) { + JFrame window = new JFrame("Click counter"); + window.setSize(250, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new GridLayout(0, 1)); + + JLabel number = new JLabel("0", SwingConstants.CENTER); + JButton plus = new JButton("+1"); + JButton reset = new JButton("Reset"); + + plus.addActionListener(e -> { + count++; + number.setText("" + count); + }); + reset.addActionListener(e -> { + count = 0; + number.setText("0"); + }); + + window.add(number); + window.add(plus); + window.add(reset); + window.setVisible(true); + } +} +\`\`\` + +\`SwingConstants.CENTER\` puts the text of the label in the middle. Click +1 a few times and then Reset. + +::: angeberwissen +With \`number.setFont(new Font("SansSerif", Font.BOLD, 48));\` the number becomes big and bold. \`Font\` comes from \`java.awt\`, which you have already imported. +::: + +## Game: Who is counting? + +::: spiel zuhoerer +titel: Game: Who is counting? +intro: Now the listeners calculate with the variable of the class. Ludwig shows you code, window and the clicks. Which number is shown at the end? Afterwards Ludwig plays the clicks. +frage: What does the label say after the clicks? + +runde: + static int count = 0; + JLabel number = new JLabel("0"); + JButton plus = new JButton("+1"); + plus.addActionListener(e -> { + count++; + number.setText("" + count); + }); +klicks: +1, +1, +1 +- 1 +- [x] 3 +- 0 +> The variable is in the class and keeps its value between the clicks. Every click counts up by one: 1, 2, 3. + +runde: + static int count = 0; + JLabel number = new JLabel("0"); + JButton plus = new JButton("+1"); + JButton reset = new JButton("Reset"); + plus.addActionListener(e -> { + count++; + number.setText("" + count); + }); + reset.addActionListener(e -> { + count = 0; + number.setText("0"); + }); +klicks: +1, +1, Reset, +1 +- 3 +- 0 +- [x] 1 +> After two clicks it shows 2. Reset sets the variable to 0, and the last click counts up to 1 again. + +runde: + static int count = 0; + JLabel number = new JLabel("0"); + JButton plus = new JButton("+1"); + plus.addActionListener(e -> count++); +klicks: +1, +1 +- 2 +- [x] 0 +- 1 +> Afterwards the variable is 2, but nobody writes it into the label. Without \`number.setText(…)\` the window keeps showing 0. Calculating and showing are two different things. + +runde: + static int count = 0; + JLabel number = new JLabel("Clicks: 0"); + JButton plus = new JButton("+1"); + plus.addActionListener(e -> { + count++; + number.setText("Clicks: " + count + 1); + }); +klicks: +1 +- Clicks: 2 +- Clicks: 1 +- [x] Clicks: 11 +> The bracket trap: Java works from left to right. \`"Clicks: " + count\` gives the text “Clicks: 1”, and \`+ 1\` adds another 1 to the end. + +runde: + static int count = 0; + JLabel number = new JLabel("0"); + JButton one = new JButton("+1"); + JButton ten = new JButton("+10"); + one.addActionListener(e -> { + count++; + number.setText("" + count); + }); + ten.addActionListener(e -> { + count += 10; + number.setText("" + count); + }); +klicks: +10, +1, +10 +- 12 +- [x] 21 +- 111 +> Both listeners change the same variable: 10, then 11, then 21. \`count += 10\` is the short form of \`count = count + 10\`. +::: + +## Task: click counter + +Rebuild the click counter and extend it: + +- a button **−1** that counts down by one, +- the number should never go below 0. If it is 0, −1 does nothing. + +::: ludwig +For “never below 0” the listener of −1 needs an \`if\`: only if \`count > 0\` does it count down. +::: + +## 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. + +::: checkliste +- I can explain why a listener may not change a variable from main. → The first attempt +- I can create a static variable in the class. → A variable for the whole class +- I can let two buttons change the same number. → The whole program +- I can build a counter with −1 that never goes below 0. → Task: click counter +::: + +## Quiz + +::: quiz +? Why may the listener not change the variable count from main? +→ The first attempt +- [ ] Because numbers are not allowed in Swing +- [x] Because the listener runs later and Java doesn't let the arrow change variables from main +- [ ] Because count gets too big + +? Where does static int count = 0; go? +→ A variable for the whole class +- [ ] In main, at the very top +- [x] In the class, outside main +- [ ] In the listener + +? What does SwingConstants.CENTER do in new JLabel("0", SwingConstants.CENTER)? +→ The whole program +- [x] It puts the text in the middle of the label. +- [ ] It puts the window in the middle of the screen. +- [ ] It makes the font bigger. +::: +`,B4=`--- +titel: A traffic light with colours +bereich: Windows with Swing +kurz: Set background colours and switch a traffic light on with a state variable. +--- + +## Skills I will gain now + +::: kompetenzen +- colour a label with setOpaque and setBackground +- remember a state with a static variable +- use BorderLayout to put something big in the middle and something narrow at the bottom +- explain what FlowLayout, GridLayout and BorderLayout are good for +- program a traffic light with four phases +::: + +## The goal + +We build a traffic light: a large area lights up red. Each click on **Next** switches it on: red, green, yellow and red again. + +New this time are **colours** and a **state**: the program has to remember which colour is currently showing. + +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## Colours in Swing + +Colours live in the class \`Color\` from \`java.awt\`. Ready-made colours are, for example, \`Color.RED\`, \`Color.GREEN\`, \`Color.YELLOW\`, \`Color.ORANGE\` and \`Color.WHITE\`. + +This is how you colour a label: + +\`\`\`java +JLabel light = new JLabel("", SwingConstants.CENTER); +light.setOpaque(true); +light.setBackground(Color.RED); +\`\`\` + +- \`setBackground(…)\` sets the background colour. +- A \`JLabel\` also needs \`setOpaque(true)\`. Without this line the background is transparent and the colour stays invisible. + +::: ludwig +\`opaque\` means “not see-through”. A label is normally transparent, like writing on a pane of glass. Only with \`setOpaque(true)\` does it get its own area that can be painted. +::: + +## Remembering the colour + +So that the traffic light knows what comes next, it remembers its state in a number: 0 means red, 1 means green, 2 means yellow. As with the click counter from lesson 32, the variable is in the class so that the listener may change it: + +\`\`\`java +static int phase = 0; +\`\`\` + +On every click the phase moves on by one. After yellow (2) comes red (0) again: + +\`\`\`java +next.addActionListener(e -> { + phase++; + if (phase > 2) { + phase = 0; + } + if (phase == 0) { + light.setBackground(Color.RED); + } else if (phase == 1) { + light.setBackground(Color.GREEN); + } else { + light.setBackground(Color.YELLOW); + } +}); +\`\`\` + +## The whole program + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class TrafficLight { + static int phase = 0; + + public static void main(String[] args) { + JFrame window = new JFrame("Traffic light"); + window.setSize(200, 300); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new BorderLayout()); + + JLabel light = new JLabel("", SwingConstants.CENTER); + light.setOpaque(true); + light.setBackground(Color.RED); + JButton next = new JButton("Next"); + + next.addActionListener(e -> { + phase++; + if (phase > 2) { + phase = 0; + } + if (phase == 0) { + light.setBackground(Color.RED); + } else if (phase == 1) { + light.setBackground(Color.GREEN); + } else { + light.setBackground(Color.YELLOW); + } + }); + + window.add(light, BorderLayout.CENTER); + window.add(next, BorderLayout.SOUTH); + window.setVisible(true); + } +} +\`\`\` + +This uses a new layout, the **BorderLayout**. It has five places: \`NORTH\` (top), \`SOUTH\` (bottom), \`WEST\` (left), \`EAST\` (right) and \`CENTER\` (middle). The middle gets all the space that is left. So the light becomes big, and the button stays narrow at the bottom. + +::: angeberwissen +BorderLayout is the layout a \`JFrame\` uses when you don't give it one. An \`add\` without a place lands in \`CENTER\`. That is why all the building blocks lay on top of each other in lesson 31. +::: + +::: angeberwissen +Professionals switch on in one line: \`phase = (phase + 1) % 3;\`. The remainder operator \`%\` gives the remainder of a division. 3 % 3 is 0, so after 2 it starts at 0 again. +::: + +## Which layout for what? + +You now know three layouts. Each one arranges the building blocks differently: + +| Layout | How it arranges | Good for | +|---|---|---| +| \`FlowLayout\` (lesson 29) | next to each other like words in a line, each block as big as needed | a few buttons in a row | +| \`GridLayout\` (lesson 31) | a grid of cells of the same size, filled row by row | forms, keypads like on a calculator | +| \`BorderLayout\` (this lesson) | five places: top, bottom, left, right and the middle, which gets the rest | something big in the middle, such as a picture or a display, with buttons at the edge | + +Without \`setLayout\` a window uses the BorderLayout. That is why everything then lands in the middle. + +::: ludwig +Ask yourself when planning: should all parts be the same size? Then GridLayout. Should one part be big and the rest narrow at the edge? Then BorderLayout. Should the parts simply keep their normal size? Then FlowLayout. +::: + +## Game: Where does the button go? + +::: spiel layout +titel: Game: Where does the button go? +intro: You now know three layouts and the window with no layout at all. Ludwig shows you code with the buttons A, B, C … What does the window look like? Tap the right picture. +frage: What does the window look like? + +runde: + window.add(new JButton("A")); + window.add(new JButton("B")); + window.add(new JButton("C")); +- flow: A B C +- grid: A / B / C +- [x] border: C=C +> Without a layout of its own, every \`add\` lands in the centre, as big as the window. The three lie on top of each other, and you only see the last one: C. + +runde: + window.setLayout(new FlowLayout()); + window.add(new JButton("A")); + window.add(new JButton("B")); + window.add(new JButton("C")); +- [x] flow: A B C +- grid: A B C +- border: C=C +> FlowLayout puts the buttons next to each other at their normal size, like words in a line, and centres them. + +runde: + window.setLayout(new GridLayout(0, 1)); + window.add(new JButton("A")); + window.add(new JButton("B")); + window.add(new JButton("C")); +- flow: A B C +- [x] grid: A / B / C +- grid: A B C +> One column, as many rows as needed: everything below each other, every row the same height and as wide as the window. + +runde: + window.setLayout(new GridLayout(0, 2)); + window.add(new JButton("A")); + window.add(new JButton("B")); + window.add(new JButton("C")); + window.add(new JButton("D")); +- grid: A C / B D +- [x] grid: A B / C D +- grid: A / B / C / D +> Two columns. The cells are filled row by row, always left first, then right: A B, then C D. + +runde: + window.setLayout(new GridLayout(2, 3)); + window.add(new JButton("A")); + window.add(new JButton("B")); + window.add(new JButton("C")); + window.add(new JButton("D")); + window.add(new JButton("E")); + window.add(new JButton("F")); +- grid: A B / C D / E F +- [x] grid: A B C / D E F +- flow: A B C D E F +> Rows come first, then columns: 2 rows with 3 columns each. + +runde: + window.setLayout(new GridLayout(0, 2)); + window.add(new JButton("A")); + window.add(new JButton("B")); + window.add(new JButton("C")); +- [x] grid: A B / C +- grid: A B C +- grid: A / B C +> Two columns, three buttons: the first row is full, in the second C is on the left, and the cell on the right stays empty. + +runde: + window.setLayout(new BorderLayout()); + window.add(new JButton("A"), BorderLayout.NORTH); + window.add(new JButton("B"), BorderLayout.CENTER); + window.add(new JButton("C"), BorderLayout.SOUTH); +- grid: A / B / C +- [x] border: N=A C=B S=C +- border: N=C C=B S=A +> NORTH is at the top, SOUTH at the bottom. The centre gets all the remaining space, which is why B is big. + +runde: + window.setLayout(new BorderLayout()); + window.add(new JButton("A"), BorderLayout.WEST); + window.add(new JButton("B")); + window.add(new JButton("C"), BorderLayout.EAST); +- flow: A B C +- border: N=A C=B S=C +- [x] border: W=A C=B E=C +> WEST is on the left, EAST on the right. B has no place given, so it lands in CENTER. +::: + +## Task: traffic light + +Rebuild the traffic light and make it more realistic. In the UK and Germany, red and amber light up together briefly after red. So add a fourth phase: + +- 0: red +- 1: red and amber (use \`Color.ORANGE\`) +- 2: green +- 3: amber (yellow) + +Extra: in each phase, also write with \`light.setText(…)\` what the light means, for example “Stop” or “Go”. + +::: ludwig +With four phases, 0 comes after 3. So change the number in \`if (phase > 2)\`. +::: + +## 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. + +::: checkliste +- I can colour a label with setOpaque and setBackground. → Colours in Swing +- I can remember a state with a static variable. → Remembering the colour +- I can use BorderLayout to put something big in the middle and something narrow at the bottom. → The whole program +- I can explain what FlowLayout, GridLayout and BorderLayout are good for. → Which layout for what? +- I can program a traffic light with four phases. → Task: traffic light +::: + +## Quiz + +::: quiz +? Why does the colour stay invisible without setOpaque(true)? +→ Colours in Swing +- [ ] Because Color.RED doesn't exist +- [x] Because a label is transparent otherwise +- [ ] Because the window is too small + +? Which place in the BorderLayout gets the space that is left? +→ The whole program +- [ ] NORTH +- [ ] SOUTH +- [x] CENTER + +? phase is 2 and the listener runs phase++ and then if (phase > 2) { phase = 0; }. What is phase afterwards? +→ Remembering the colour +- [x] 0 +- [ ] 2 +- [ ] 3 +> After phase++ it is 3, which is greater than 2, so it becomes 0. +::: +`,M4=`--- +titel: Grade calculator in a window +bereich: Windows with Swing +kurz: Enter points, work out the grade with else if and catch wrong input. +--- + +## Skills I will gain now + +::: kompetenzen +- turn points into a grade with else if +- show the grade in the window +- catch and report “abc” and points outside 0 to 100 +- test a program at the limits, for example with 90 and 89 +::: + +## The goal + +A window turns points into a grade: you type the points of a test (0 to 100), click **Calculate grade**, and the grade appears at the bottom. + +This time there is no new Swing building block. What's new is that you combine everything so far: text field, button, \`else if\` from lesson 20 and try/catch from lesson 22. + +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## The grading scale + +We use this grading scale: + +| Points | Grade | +|---|---| +| 90 to 100 | A | +| 80 to 89 | B | +| 70 to 79 | C | +| 60 to 69 | D | +| 0 to 59 | F | + +With \`else if\` you check from top to bottom. The first condition that is true wins: + +\`\`\`java +String grade; +if (points >= 90) { + grade = "A"; +} else if (points >= 80) { + grade = "B"; +} else if (points >= 70) { + grade = "C"; +} else if (points >= 60) { + grade = "D"; +} else { + grade = "F"; +} +\`\`\` + +::: ludwig +With 85 points, \`points >= 90\` is false, but \`points >= 80\` is true. So grade B, and the remaining conditions are not checked at all. That is why the lower limit is enough each time. +::: + +You can try this part without a window in the [Code](#zeige-codelive) area. Put \`int points = 85;\` in front of it and \`System.out.println("Grade: " + grade);\` after it. The structure chart shows you the nested branches. + +## The window + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class GradeCalculator { + public static void main(String[] args) { + JFrame window = new JFrame("Grade calculator"); + window.setSize(260, 180); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new GridLayout(0, 1)); + + JLabel question = new JLabel("Points (0 to 100):"); + JTextField field = new JTextField(); + JButton button = new JButton("Calculate grade"); + JLabel result = new JLabel("Grade: ?"); + + button.addActionListener(e -> { + int points = Integer.parseInt(field.getText()); + String grade; + if (points >= 90) { + grade = "A"; + } else if (points >= 80) { + grade = "B"; + } else if (points >= 70) { + grade = "C"; + } else if (points >= 60) { + grade = "D"; + } else { + grade = "F"; + } + result.setText("Grade: " + grade); + }); + + window.add(question); + window.add(field); + window.add(button); + window.add(result); + window.setVisible(true); + } +} +\`\`\` + +Try 100, 85, 60 and 12. + +## Catching wrong input + +Two things can still go wrong: + +1. Someone types “abc”. Then \`Integer.parseInt\` throws a \`NumberFormatException\`. +2. Someone types 150 or −5. That is a number, but not a valid score. + +You catch the first case with try/catch, the second with an \`if\` before working out the grade: + +\`\`\`java +button.addActionListener(e -> { + try { + int points = Integer.parseInt(field.getText()); + if (points < 0 || points > 100) { + result.setText("Please enter 0 to 100."); + } else { + // the grade calculation from above goes here + } + } catch (NumberFormatException error) { + result.setText("That is not a number."); + } +}); +\`\`\` + +::: ludwig +\`||\` means “or” (lesson 9). The condition is true if the points are too small **or** too big. +::: + +## Game: Which grade? + +::: spiel frage +titel: Game: Which grade? +intro: Ludwig has built grade calculators, but not all of them are right. Work out which grade comes out. Six rounds. + +runde: + if (points >= 90) { + grade = "A"; + } else if (points >= 80) { + grade = "B"; + } else if (points >= 70) { + grade = "C"; + } else { + grade = "D"; + } +frage: points is 80. Which grade comes out? +- A +- [x] B +- C +> 80 >= 90 is false, 80 >= 80 is true. The limit still belongs to B. + +runde: + if (points >= 90) { + grade = "A"; + } else if (points >= 80) { + grade = "B"; + } else if (points >= 70) { + grade = "C"; + } else if (points >= 60) { + grade = "D"; + } else { + grade = "F"; + } +frage: points is 69. Which grade comes out? +- C +- [x] D +- F +> 69 >= 70 is only just false, 69 >= 60 is true. So grade D. + +runde: + if (points >= 60) { + grade = "D"; + } else if (points >= 90) { + grade = "A"; + } else { + grade = "F"; + } +frage: points is 95. Which grade comes out? +- A +- [x] D +- F +> The first true condition wins. 95 >= 60 is already true, so A is never reached. That's why you check from the high points downwards. + +runde: + grade = "F"; + if (points >= 60) { + grade = "D"; + } + if (points >= 70) { + grade = "C"; + } +frage: points is 85. What is in grade afterwards? +- F +- D +- [x] C +> Without \`else\` every \`if\` is checked. Both are true, and the last one sets grade C. + +runde: + // grade has already been worked out + if (points < 0 || points > 100) { + result.setText("Please enter 0 to 100."); + } else { + result.setText("Grade: " + grade); + } +frage: The text field says 100. What does the window show? +- [x] Grade: A +- Please enter 0 to 100. +- That is not a number. +> 100 > 100 is false. So 100 points are valid and give grade A. + +runde: + // grade has already been worked out + if (points < 0 && points > 100) { + result.setText("Please enter 0 to 100."); + } else { + result.setText("Grade: " + grade); + } +frage: The text field says 150. What does the window show? +- Please enter 0 to 100. +- [x] a grade, although 150 is not valid +- That is not a number. +> With \`&&\` the points would have to be below 0 and above 100 at the same time. That never happens, so the program never warns. The right one is \`||\`. +::: + +## Task: grade calculator + +Put the grade calculator together, with both checks from the last step. Test it with 90, 89, 0, 100, 101 and “ten”. + +Extra: also write a word for the grade, for example “Grade: B (good)”. The words are excellent, good, satisfactory, poor and fail. + +::: ludwig +Always test the limits: 90 must be an A, 89 a B. Most mistakes hide at the limits, for example \`>\` instead of \`>=\`. +::: + +## 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. + +::: checkliste +- I can turn points into a grade with else if. → The grading scale +- I can show the grade in the window. → The window +- I can catch and report “abc” and points outside 0 to 100. → Catching wrong input +- I can test a program at the limits, for example with 90 and 89. → Task: grade calculator +::: + +## Quiz + +::: quiz +? Which grade does the scale give for 70 points? +→ The grading scale +- [ ] B +- [x] C +- [ ] D +> 70 is the lower limit for a C. + +? Why is the lower limit enough in each condition? +→ The grading scale +- [x] Because else if has already sorted out the higher cases +- [ ] Because Java doesn't know upper limits +- [ ] Because the points are always 100 + +? Which condition detects invalid points? +→ Catching wrong input +- [ ] points < 0 && points > 100 +- [x] points < 0 || points > 100 +- [ ] points >= 0 || points <= 100 +> A number can't be smaller than 0 and bigger than 100 at the same time, so you need or. +::: +`,Z4=`--- +titel: A calculator +bereich: Windows with Swing +kurz: Two columns with GridLayout, four arithmetic buttons and catching division by 0. +--- + +## Skills I will gain now + +::: kompetenzen +- build two columns with GridLayout +- explain why "" + (a + b) needs brackets +- program all four arithmetic buttons +- build a calculator that doesn't crash with 0 or “abc” +::: + +## The goal + +We build a small calculator: two text fields for the numbers, four buttons **+**, **-**, **\\*** and **/** and a line for the result. + +New this time are **two columns** in the GridLayout and **several buttons** that all calculate with the same text fields. + +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## Two columns + +So far \`GridLayout(0, 1)\` put everything below each other. \`GridLayout(0, 2)\` gives you two columns. The building blocks fill the cells in the order of the \`add\` lines, always left first, then right: + +| left | right | +|---|---| +| First number: | text field | +| Second number: | text field | +| + | - | +| \\* | / | +| Result: | ? | + +You won't need the labels on the left later. So you can build them directly inside \`add\`, without a variable: + +\`\`\`java +window.add(new JLabel("First number:")); +window.add(field1); +\`\`\` + +## The window with the first button + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Calculator { + public static void main(String[] args) { + JFrame window = new JFrame("Calculator"); + window.setSize(280, 220); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new GridLayout(0, 2)); + + JTextField field1 = new JTextField(); + JTextField field2 = new JTextField(); + JButton plus = new JButton("+"); + JButton minus = new JButton("-"); + JButton times = new JButton("*"); + JButton divide = new JButton("/"); + JLabel result = new JLabel("?"); + + plus.addActionListener(e -> { + int a = Integer.parseInt(field1.getText()); + int b = Integer.parseInt(field2.getText()); + result.setText("" + (a + b)); + }); + + window.add(new JLabel("First number:")); + window.add(field1); + window.add(new JLabel("Second number:")); + window.add(field2); + window.add(plus); + window.add(minus); + window.add(times); + window.add(divide); + window.add(new JLabel("Result:")); + window.add(result); + window.setVisible(true); + } +} +\`\`\` + +Type 3 and 4 and click +. The result shows 7. + +::: ludwig +Watch the brackets in \`"" + (a + b)\`. Without them Java works from left to right: \`"" + a\` gives the text “3”, and \`"3" + b\` appends the 4. You get “34” instead of 7. The bracket makes sure the calculation happens first. +::: + +## The other three buttons + +The buttons -, \\* and / work the same way. Only the operator in the last line changes: + +\`\`\`java +minus.addActionListener(e -> { + int a = Integer.parseInt(field1.getText()); + int b = Integer.parseInt(field2.getText()); + result.setText("" + (a - b)); +}); +\`\`\` + +/ has two special features: + +- With \`int\`, Java cuts off the decimal places when dividing. 7 / 2 gives 3. +- If the second number is 0, Java throws an \`ArithmeticException\`, as in the task “Dividing safely” in lesson 22. + +## Catching division by 0 + +\`\`\`java +divide.addActionListener(e -> { + int a = Integer.parseInt(field1.getText()); + int b = Integer.parseInt(field2.getText()); + try { + result.setText("" + (a / b)); + } catch (ArithmeticException error) { + result.setText("Not by 0!"); + } +}); +\`\`\` + +::: angeberwissen +With \`double\` and \`Double.parseDouble(…)\` you get decimal places: 7 / 2 gives 3.5. In return, Java throws no exception when dividing decimal numbers by 0. The result is then \`Infinity\`. +::: + +## Expert knowledge: a method of your own + +This is not in the curriculum, but it makes the code shorter. + +::: angeberwissen +Every listener reads the same two fields. You can move this repetition into a method of your own, a subprogram like in lesson 18. It goes in the class next to \`main\`: + +\`static int number(JTextField field) { return Integer.parseInt(field.getText()); }\` + +The listener then just says \`result.setText("" + (number(field1) + number(field2)));\`. +::: + +## Game: What does the calculator show? + +::: spiel frage +titel: Game: What does the calculator show? +intro: Ludwig has been tinkering with the calculator. Read the listener and predict what the result shows. Six rounds. + +runde: + plus.addActionListener(e -> { + int a = Integer.parseInt(field1.getText()); + int b = Integer.parseInt(field2.getText()); + result.setText("" + a + b); + }); +frage: You type 3 and 4 and click +. What does the result show? +- 7 +- [x] 34 +- 12 +> Without brackets Java works from left to right: \`"" + 3\` is the text "3", and \`+ 4\` adds the 4 to the end. + +runde: + times.addActionListener(e -> { + int a = Integer.parseInt(field1.getText()); + int b = Integer.parseInt(field2.getText()); + result.setText("" + a * b); + }); +frage: You type 3 and 4 and click *. What does the result show? +- 34 +- [x] 12 +- 7 +> Multiplication comes before addition here too: Java first works out 3 * 4, then adds the 12 to the text. Plus doesn't get this priority, which is why it needs the brackets. + +runde: + divide.addActionListener(e -> { + int a = Integer.parseInt(field1.getText()); + int b = Integer.parseInt(field2.getText()); + result.setText("" + (a / b)); + }); +frage: You type 7 and 2 and click /. What does the result show? +- 3.5 +- [x] 3 +- 4 +> With \`int\` Java cuts off the decimal places. It doesn't round. + +runde: + divide.addActionListener(e -> { + int a = Integer.parseInt(field1.getText()); + int b = Integer.parseInt(field2.getText()); + try { + result.setText("" + (a / b)); + } catch (ArithmeticException error) { + result.setText("Not by 0!"); + } + }); +frage: You type 8 and 0 and click /. What does the result show? +- 0 +- [x] Not by 0! +- Infinity +> With \`int\`, dividing by 0 throws an ArithmeticException, and \`catch\` writes the hint. + +runde: + divide.addActionListener(e -> { + double a = Double.parseDouble(field1.getText()); + double b = Double.parseDouble(field2.getText()); + result.setText("" + (a / b)); + }); +frage: You type 7 and 2 and click /. What does the result show? +- 3 +- [x] 3.5 +- 3.0 +> With \`double\` the decimal places are kept. + +runde: + divide.addActionListener(e -> { + double a = Double.parseDouble(field1.getText()); + double b = Double.parseDouble(field2.getText()); + try { + result.setText("" + (a / b)); + } catch (ArithmeticException error) { + result.setText("Not by 0!"); + } + }); +frage: You type 8 and 0 and click /. What does the result show? +- Not by 0! +- [x] Infinity +- 0.0 +> With \`double\` there is no exception. The result is \`Infinity\`, and the \`catch\` never gets its turn. +::: + +## Task: calculator + +Finish the calculator: + +- all four buttons calculate, +- / reports “Not by 0!” instead of crashing, +- if a field contains “abc” or nothing, “Please enter two numbers” appears. + +Extra: a fifth button **C** empties both fields and sets the result back to “?”. + +::: ludwig +For “abc” every listener needs a try/catch with \`NumberFormatException\`. A \`try\` may also be followed by two \`catch\` blocks, one for \`NumberFormatException\` and one for \`ArithmeticException\`. By the way, an empty field gives the text \`""\`, and that isn't a number either. +::: + +## 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. + +::: checkliste +- I can build two columns with GridLayout(0, 2). → Two columns +- I can explain why "" + (a + b) needs brackets. → The window with the first button +- I can program all four arithmetic buttons. → The other three buttons +- I can build a calculator that doesn't crash with 0 or “abc”. → Task: calculator +::: + +## Quiz + +::: quiz +? a is 3 and b is 4. What does "" + a + b give? +→ The window with the first button +- [ ] 7 +- [x] 34 +- [ ] An error +> Java works from left to right: first the text "3" is created, then the 4 is appended. + +? What does 7 / 2 give with int? +→ The other three buttons +- [ ] 3.5 +- [x] 3 +- [ ] 4 + +? In which order does GridLayout(0, 2) fill the cells? +→ Two columns +- [x] Row by row, left first, then right +- [ ] Column by column, starting top to bottom on the far left +- [ ] Randomly +::: +`,L4=`--- +titel: Guess the number +bereich: Windows with Swing +kurz: A game with a random number, a counter for the guesses and a button that switches itself off at the end. +--- + +## Skills I will gain now + +::: kompetenzen +- create a random whole number from 1 to 100 with Math.random +- decide which variables belong in the class +- switch a button off with setEnabled +- build a guessing game with a “New game” button +::: + +## The goal + +Time for a game: the computer thinks of a number from 1 to 100. You guess, and the window tells you “too small” or “too big”. Once you have found it, it tells you how many guesses you needed. + +New this time are **random numbers** and a button that **switches itself off** at the end. + +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## A random number + +\`Math.random()\` gives a random decimal number from 0 to just under 1, for example 0.4173. Three steps turn it into a whole number from 1 to 100: + +\`\`\`java +int secret = (int) (Math.random() * 100) + 1; +\`\`\` + +| Step | Example | +|---|---| +| \`Math.random()\` | 0.4173 | +| \`* 100\` | 41.73 | +| \`(int)\` cuts off the decimal places | 41 | +| \`+ 1\` | 42 | + +Without \`+ 1\` you would get 0 to 99. + +Try it in the [Code](#zeige-codelive) area: \`int secret = (int) (Math.random() * 100) + 1;\` and \`System.out.println(secret);\`. Every run gives a different number. + +::: angeberwissen +Computers can't actually roll dice. \`Math.random()\` uses a formula to calculate a long sequence of numbers that only **look** random. They are called pseudo-random numbers. For games that is perfectly fine. +::: + +## What the game remembers + +The game has to remember two things across all clicks: the secret number and the number of guesses. As with the click counter from lesson 32, both go in the class: + +\`\`\`java +static int secret = (int) (Math.random() * 100) + 1; +static int guesses = 0; +\`\`\` + +## The whole program + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class GuessTheNumber { + static int secret = (int) (Math.random() * 100) + 1; + static int guesses = 0; + + public static void main(String[] args) { + JFrame window = new JFrame("Guess the number"); + window.setSize(320, 180); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new GridLayout(0, 1)); + + JLabel hint = new JLabel("I'm thinking of a number from 1 to 100."); + JTextField field = new JTextField(); + JButton button = new JButton("Guess"); + + button.addActionListener(e -> { + int guess = Integer.parseInt(field.getText()); + guesses++; + if (guess < secret) { + hint.setText(guess + " is too small."); + } else if (guess > secret) { + hint.setText(guess + " is too big."); + } else { + hint.setText("Correct! You needed " + guesses + " guesses."); + button.setEnabled(false); + } + field.setText(""); + }); + + window.add(hint); + window.add(field); + window.add(button); + window.setVisible(true); + } +} +\`\`\` + +- \`field.setText("")\` empties the text field after each guess, so you can type the next one straight away. +- \`button.setEnabled(false)\` switches the button off. It turns grey and can't be clicked any more. The game is over. + +::: ludwig +\`setEnabled(true)\` switches a button back on. That way you can, for example, only allow a button once something has been entered. +::: + +## Expert knowledge: winning in 7 guesses + +::: angeberwissen +If you guess cleverly, you never need more than 7 guesses. Always guess the middle of the range that is left: first 50, then 25 or 75 and so on. Each guess halves the range: 100, 50, 25, 13, 7, 4, 2, 1. That is the **binary search** from lesson 19. Because 2 to the power of 7 = 128 is bigger than 100, 7 guesses are enough. +::: + +## Task: guess the number + +Rebuild the game and improve it: + +- An input like “abc” doesn't count as a guess and shows the hint “Please enter a number”. +- A second button **New game** thinks of a new number, sets the guesses to 0, switches the Guess button back on and resets the hint. + +Extra: after 7 wrong guesses the game is lost. The window then reveals the secret number. + +::: ludwig +For “doesn't count as a guess”, \`guesses++\` must come **after** \`Integer.parseInt\`, both in the \`try\` block. If \`parseInt\` throws an exception, the line with \`guesses++\` is skipped. +::: + +## 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. + +::: checkliste +- I can create a random whole number from 1 to 100 with Math.random. → A random number +- I can decide which variables belong in the class. → What the game remembers +- I can switch a button off with setEnabled. → The whole program +- I can build a guessing game with a “New game” button. → Task: guess the number +::: + +## Quiz + +::: quiz +? Which numbers does (int) (Math.random() * 100) + 1 give? +→ A random number +- [ ] 0 to 100 +- [x] 1 to 100 +- [ ] 1 to 101 + +? What does button.setEnabled(false) do? +→ The whole program +- [ ] It removes the button from the window. +- [x] The button turns grey and can't be clicked any more. +- [ ] It changes the text on the button. + +? With binary search, how many guesses do you need at most for 1 to 100? +→ Task: guess the number +- [ ] 50 +- [ ] 10 +- [x] 7 +> Each guess halves the range, and 2 to the power of 7 = 128 is bigger than 100. +::: +`,E4=`--- +titel: Many buttons, one listener +bereich: Windows with Swing +kurz: One listener for many buttons, and finding out with getActionCommand and getSource which button was clicked. +--- + +## Skills I will gain now + +::: kompetenzen +- store a listener in a variable of type ActionListener and sign it up at several buttons +- explain what getActionCommand and getSource return +- put buttons onto a JPanel in a loop +- build a code lock that only opens with the right code +::: + +## The goal + +Since the business with the cake, Ludwig wants to lock his stable. He builds a **code lock**: nine digit keys, a zero, **C** to clear and **OK** to check. Only someone who types 1234 gets "Gate open!". + +That's twelve buttons. Until now every button had its own listener, as with the calculator in lesson 35. Today you learn how **one** listener is enough for all buttons. + +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## Nine almost identical listeners + +With one listener per key it would look like this: + +\`\`\`java +one.addActionListener(e -> display.setText(display.getText() + "1")); +two.addActionListener(e -> display.setText(display.getText() + "2")); +three.addActionListener(e -> display.setText(display.getText() + "3")); +// ... and so on up to 9 +\`\`\` + +The lines only differ in the digit. If you want to change a small detail, you have to do it nine times and are bound to forget one line. + +## A listener as a variable + +A listener can also be stored in a **variable**. Its data type is \`ActionListener\`, the contract from lesson 30. Then you sign up the same listener at several buttons: + +\`\`\`java +ActionListener digit = e -> display.setText(display.getText() + e.getActionCommand()); + +one.addActionListener(digit); +two.addActionListener(digit); +three.addActionListener(digit); +\`\`\` + +\`ActionListener\` is in the package \`java.awt.event\`. So you need \`import java.awt.event.*;\` at the top. + +Now the code exists only once. But how does the listener know which digit to add? + +## Who clicked? + +The \`e\` before the arrow is the **event**, an object of type \`ActionEvent\`. The button passes it along with every click, and it contains what happened: + +| Call | Returns | Example | +|---|---|---| +| \`e.getActionCommand()\` | the caption of the clicked button, as text | \`"7"\` | +| \`e.getSource()\` | the clicked button itself | the button \`ok\` | + +- \`getActionCommand()\` is handy when the caption already says what to do, as with the digits. +- You compare \`getSource()\` with a button using \`==\`: \`if (e.getSource() == ok)\`. Here \`==\` is right, because it is about exactly this one object, not about a text. + +::: ludwig +You compare texts with \`equals\` and buttons with \`==\`. If you want to decide by the caption, you write \`e.getActionCommand().equals("OK")\`. That works too, but breaks as soon as someone changes the caption to "Open". \`e.getSource() == ok\` stays correct. +::: + +## Buttons in a loop + +With a shared listener you can even build the digit keys in a loop. So that they line up neatly in a grid, they go onto a **JPanel**. A JPanel is an area in the window with its own layout: + +\`\`\`java +JPanel keys = new JPanel(new GridLayout(0, 3)); +for (int i = 1; i <= 9; i++) { + JButton digit = new JButton("" + i); + digit.addActionListener(key); + keys.add(digit); +} +\`\`\` + +- \`"" + i\` turns the number \`i\` into the text for the caption. +- Each pass creates a new button. All of them get the same listener \`key\`. +- \`window.add(keys, BorderLayout.CENTER)\` puts the whole area with all the keys into the window. + +## The whole program + +\`\`\`java +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class CodeLock { + public static void main(String[] args) { + JFrame window = new JFrame("Code lock"); + window.setSize(240, 300); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new BorderLayout()); + + JLabel display = new JLabel("", SwingConstants.CENTER); + JPanel keys = new JPanel(new GridLayout(0, 3)); + JButton clear = new JButton("C"); + JButton ok = new JButton("OK"); + + ActionListener key = e -> { + if (e.getSource() == clear) { + display.setText(""); + } else if (e.getSource() == ok) { + if (display.getText().equals("1234")) { + display.setText("Gate open!"); + } else { + display.setText("Wrong"); + } + } else { + display.setText(display.getText() + e.getActionCommand()); + } + }; + + for (int i = 1; i <= 9; i++) { + JButton digit = new JButton("" + i); + digit.addActionListener(key); + keys.add(digit); + } + JButton zeroKey = new JButton("0"); + zeroKey.addActionListener(key); + clear.addActionListener(key); + ok.addActionListener(key); + keys.add(clear); + keys.add(zeroKey); + keys.add(ok); + + window.add(display, BorderLayout.NORTH); + window.add(keys, BorderLayout.CENTER); + window.setVisible(true); + } +} +\`\`\` + +- \`clear\` and \`ok\` are created **before** the listener, because the listener compares with them. +- The listener first checks the two special buttons. All the others are digits and add their caption. + +::: angeberwissen +The keypad on a phone has the 1 at the top left, the one on a calculator and a computer keyboard has the 7 at the top left. Why? When push-button phones came along, there were tests with people who had to dial with them. With the 1 at the top they were faster, and calculating machines had their layout long before that. Ludwig's lock does it like the phone. +::: + +## Game: Who clicked? + +::: spiel zuhoerer +titel: Game: Who clicked? +intro: In every round **one** listener listens at several buttons. Ludwig shows you code, the window and the clicks. What does the display say at the end? Afterwards Ludwig plays the clicks. +frage: What does the display say after the clicks? + +runde: + JFrame window = new JFrame("Letters"); + JLabel display = new JLabel(""); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + ActionListener z = e -> display.setText(display.getText() + e.getActionCommand()); + a.addActionListener(z); + b.addActionListener(z); +klicks: A, B, A +- A +- AB +- [x] ABA +> One listener, two buttons. Each time, \`e.getActionCommand()\` returns the caption of the clicked button, and it is added at the end. + +runde: + JFrame window = new JFrame("Counter"); + static int number = 0; + JLabel display = new JLabel("0"); + JButton plus = new JButton("+"); + JButton minus = new JButton("-"); + ActionListener z = e -> { + if (e.getSource() == plus) { + number++; + } else { + number--; + } + display.setText("" + number); + }; + plus.addActionListener(z); + minus.addActionListener(z); +klicks: +, +, - +- 3 +- [x] 1 +- -1 +> \`e.getSource()\` tells you which button it was. Plus twice, minus once: 0 + 1 + 1 - 1 = 1. + +runde: + JFrame window = new JFrame("Letters"); + JLabel display = new JLabel(""); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + JButton c = new JButton("C"); + ActionListener z = e -> display.setText(display.getText() + e.getActionCommand()); + a.addActionListener(z); + b.addActionListener(z); +klicks: A, C, B +- ACB +- [x] AB +- A +> The listener is only signed up at A and B. Nobody is listening when C is clicked. + +runde: + JFrame window = new JFrame("Keys"); + JLabel display = new JLabel(""); + JButton one = new JButton("1"); + JButton two = new JButton("2"); + JButton del = new JButton("C"); + ActionListener z = e -> { + if (e.getActionCommand().equals("C")) { + display.setText(""); + } else { + display.setText(display.getText() + e.getActionCommand()); + } + }; + one.addActionListener(z); + two.addActionListener(z); + del.addActionListener(z); +klicks: 1, 2, C, 1 +- 121 +- 12 +- [x] 1 +> After 1 and 2 the display says "12". C clears everything, and the last 1 stands alone. + +runde: + JFrame window = new JFrame("Lock"); + JLabel display = new JLabel(""); + JButton four = new JButton("4"); + JButton two = new JButton("2"); + JButton ok = new JButton("OK"); + ActionListener z = e -> { + if (e.getSource() == ok) { + if (display.getText().equals("42")) { + display.setText("Gate open!"); + } else { + display.setText("Wrong"); + } + } else { + display.setText(display.getText() + e.getActionCommand()); + } + }; + four.addActionListener(z); + two.addActionListener(z); + ok.addActionListener(z); +klicks: 2, 4, OK +- Gate open! +- [x] Wrong +- 24OK +> "24" was typed, but the secret is "42". The order of the clicks matters. +::: + +## Task: Code lock + +Build the code lock and try it out. + +Then make it better: + +- After three wrong attempts, **OK** switches itself off, like the button in Guess the number in lesson 36. Count the attempts in a \`static int\` variable in the class. +- Extra: the display shows \`*\` instead of the digits. Remember the real input in a \`static String input = "";\` and only add a star to the display. + +::: ludwig +For the calculator from lesson 35, one listener is enough for +, -, \\* and / too. Check inside it with \`e.getActionCommand().equals("+")\` which operator was clicked. +::: + +## 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. + +::: checkliste +- I can store a listener in a variable of type ActionListener and sign it up at several buttons. → A listener as a variable +- I can explain what getActionCommand and getSource return. → Who clicked? +- I can put buttons onto a JPanel in a loop. → Buttons in a loop +- I can build a code lock that only opens with the right code. → Task: Code lock +::: + +## Quiz + +::: quiz +? What does e.getActionCommand() return for a click on the button new JButton("7")? +→ Who clicked? +- [ ] the number 7 +- [x] the text "7" +- [ ] the button itself + +? How do you check whether the button ok was clicked? +→ Who clicked? +- [x] e.getSource() == ok +- [ ] e.getSource().equals("ok") +- [ ] ok.getActionCommand() +> getSource returns the button itself, and you compare it with ==. + +? Why is a listener stored in a variable? +→ A listener as a variable +- [ ] So that it runs faster. +- [x] So that you can sign it up at several buttons and write the code only once. +- [ ] Because lambdas aren't allowed otherwise. + +? Match. +→ Who clicked? += ActionListener -> data type of a listener += ActionEvent -> the event e with the information about the click += JPanel -> an area with its own layout +::: +`,W4=`--- +titel: Inner classes +bereich: Windows with Swing +kurz: Write a listener as a named inner class, as an anonymous class and as a lambda, and know who can see what. +--- + +## Skills I will gain now + +::: kompetenzen +- write a listener as a named inner class +- write a listener as an anonymous class +- explain what is left out in a lambda +- explain which way of writing sees which variables +- build a counter with three buttons written in three ways +::: + +## The goal + +You already know the click counter from lesson 32. Today you write its listener in **three ways**, all of which do exactly the same: + +1. as a **named inner class**, the way it was mostly done before Java 8, +2. as an **anonymous class**, which you know from the expert knowledge in lesson 30, +3. as a **lambda** with the arrow, as before. + +In other people's code, in books and on the internet you will meet all three. After this lesson you will recognise them. + +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## Reminder: the contract + +A listener is anything that fulfils the contract \`ActionListener\`. It contains exactly one method: + +\`\`\` +public void actionPerformed(ActionEvent e) +\`\`\` + +The button calls it with every click. The three ways of writing are three ways of providing this one method. + +## 1. The named inner class + +An **inner class** is a class inside another class. It has a name, here \`Plus\`, and fulfils the contract with \`implements ActionListener\`: + +\`\`\`java +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class Counter { + static int count = 0; + static JLabel number = new JLabel("0", SwingConstants.CENTER); + + static class Plus implements ActionListener { + public void actionPerformed(ActionEvent e) { + count++; + number.setText("" + count); + } + } + + public static void main(String[] args) { + JFrame window = new JFrame("Click counter"); + window.setSize(250, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new GridLayout(0, 1)); + + JButton plus = new JButton("+1"); + JButton again = new JButton("Also +1"); + plus.addActionListener(new Plus()); + again.addActionListener(new Plus()); + + window.add(number); + window.add(plus); + window.add(again); + window.setVisible(true); + } +} +\`\`\` + +- \`new Plus()\` creates an object of the class \`Plus\`. That is the listener the button gets. +- Because the class has a name, you can use it for several buttons, here for \`plus\` and \`again\`. +- The class is **outside** \`main\`. So it only sees what is in the class \`Counter\`: \`count\` and \`number\`. That's why \`number\` is a variable of the class this time and not of \`main\`. +- You need \`static class\` because \`main\` is static. Without \`static\`, javac reports "non-static variable this cannot be referenced from a static context". + +## 2. The anonymous class + +If you only need the listener in one place, you can write the class right where the object is needed. Then it gets no name: + +\`\`\`java +plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + count++; + number.setText("" + count); + } +}); +\`\`\` + +- \`new ActionListener() { … }\` means: "a new object that fulfils the contract ActionListener, like this: …". +- At the end there is \`});\`: the curly bracket closes the class, the round one closes the call to \`addActionListener\`. +- The anonymous class is **inside** \`main\`. So it also sees the variables of \`main\`, as long as they don't change any more. + +## 3. The lambda + +The lambda is the short form of the anonymous class, since Java 8: + +\`\`\`java +plus.addActionListener(e -> { + count++; + number.setText("" + count); +}); +\`\`\` + +Everything Java knows anyway is left out: \`new ActionListener()\`, the name \`actionPerformed\`, \`public void\` and the type \`ActionEvent\`. What remains is the parameter \`e\`, the arrow and the body. This only works because the contract has exactly **one** method. + +## The three compared + +| | named inner class | anonymous class | lambda | +|---|---|---|---| +| has a name | yes, e.g. \`Plus\` | no | no | +| stands | in the class, outside \`main\` | right at the button | right at the button | +| for several buttons | yes, \`new Plus()\` | no | yes, in a variable (lesson 37) | +| sees variables of \`main\` | no | yes, if they don't change | yes, if they don't change | +| length | longest | medium | shortest | + +::: ludwig +If a variable of \`main\` should change in the listener, like \`count++\`, it has to go into the class, whichever way you write the listener. That was the problem from lesson 32. +::: + +::: angeberwissen +After compiling, look into the folder with the \`.class\` files. javac creates one file for every class: \`Counter.class\`, \`Counter$Plus.class\` for the inner class and \`Counter$1.class\` for the anonymous class. As it has no name, it gets a number. A lambda gets no file of its own, Java only builds it when the program starts. +::: + +## Game: Which way of writing? + +::: spiel frage +titel: Game: Which way of writing? +intro: Ludwig shows you listeners from other people's programs. Which way of writing is it? Six rounds. +frage: Which way of writing is this? +antworten: named inner class | anonymous class | lambda + +runde: + button.addActionListener(e -> text.setText("Hello")); +richtig: lambda +> The arrow \`->\` gives the lambda away. + +runde: + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + text.setText("Hello"); + } + }); +richtig: anonymous class +> \`new ActionListener() {\` followed by a whole method: a class without a name is being written here. + +runde: + static class Greeting implements ActionListener { + public void actionPerformed(ActionEvent e) { + text.setText("Hello"); + } + } +richtig: named inner class +> The class is called \`Greeting\` and fulfils the contract with \`implements ActionListener\`. + +runde: + button.addActionListener(new Greeting()); +richtig: named inner class +> \`new Greeting()\` creates an object of the class \`Greeting\`. The class itself is somewhere else and has a name. + +runde: + ActionListener key = e -> { + display.setText(display.getText() + e.getActionCommand()); + }; +richtig: lambda +> A lambda in a variable, as with the code lock in lesson 37. The arrow gives it away. + +runde: + ActionListener key = new ActionListener() { + public void actionPerformed(ActionEvent e) { + display.setText(display.getText() + e.getActionCommand()); + } + }; +richtig: anonymous class +> An anonymous class can be stored in a variable too. Then it can be signed up at several buttons, just like the lambda. +::: + +## Task: One counter, three ways + +Build the click counter with three buttons: + +- **+1** gets the named inner class \`Plus\`. +- **-1** gets an anonymous class. +- **Reset** gets a lambda. + +Check that all three buttons count as expected. Then remove the \`static\` from the class \`Plus\` and read javac's error message. + +## 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. + +::: checkliste +- I can write a listener as a named inner class. → 1. The named inner class +- I can write a listener as an anonymous class. → 2. The anonymous class +- I can explain what is left out in a lambda. → 3. The lambda +- I can explain which way of writing sees which variables. → The three compared +- I can build a counter with three buttons written in three ways. → Task: One counter, three ways +::: + +## Quiz + +::: quiz +? Why does the short form with the arrow work for ActionListener? +→ 3. The lambda +- [ ] Because ActionListener is a class. +- [x] Because the contract has exactly one method. +- [ ] Because the button demands it. + +? Which way of writing can you use with new Plus() for several buttons without storing it in a variable? +→ 1. The named inner class +- [x] the named inner class +- [ ] the anonymous class +- [ ] the lambda + +? Why is there static in front of class Plus? +→ 1. The named inner class +- [ ] So that the class is faster. +- [x] Because main is static and couldn't create an object of Plus otherwise. +- [ ] Because every class has to be static. + +? Match. +→ The three compared += class Plus implements ActionListener -> named inner class += new ActionListener() { … } -> anonymous class += the arrow after e -> lambda +::: +`,N4=`--- +titel: Two tabs +bereich: Windows with Swing +kurz: Build a window with two tabs, bring data from one tab to the other and save the list as a text file. +--- + +## Skills I will gain now + +::: kompetenzen +- build a window with two tabs +- add lines to a JTextArea with append +- explain why a listener can use building blocks on both tabs +- save a file inside a listener with try and catch +- build a shopping list that counts how many things are on it +::: + +## The goal + +Ludwig's shopping list from lesson 23 gets a window. It has two **tabs**, like the tabs in a browser: + +- In the tab **Input** you type what you need and click **Add**. +- The tab **List** shows everything you have entered. A button **Save** writes the list into a text file. + +New are the tabs (\`JTabbedPane\`), a text area with several lines (\`JTextArea\`) and saving from inside a listener. + +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## Tabs with JTabbedPane + +Each tab shows its own area. The areas are JPanels, like the keypad of the code lock in lesson 37: + +\`\`\`java +JTabbedPane tabs = new JTabbedPane(); +JPanel input = new JPanel(new GridLayout(0, 1)); +JPanel list = new JPanel(new BorderLayout()); + +tabs.addTab("Input", input); +tabs.addTab("List", list); +window.add(tabs); +\`\`\` + +| Call | Meaning | +|---|---| +| \`addTab("Input", input)\` | a new tab with the caption "Input", it shows the JPanel \`input\` | +| \`setSelectedIndex(1)\` | switches to the second tab, counting starts at 0 | +| \`setTitleAt(1, "List (3)")\` | changes the caption of the second tab | + +At the start, the tab that was added first is open. + +## A text area with several lines + +A \`JTextField\` has only one line. For the list you need a \`JTextArea\`: + +\`\`\`java +JTextArea area = new JTextArea(); +area.setEditable(false); +area.append("Hay\\n"); +\`\`\` + +- \`append\` adds text at the end. The \`"\\n"\` then starts a new line, as when splitting with \`split("\\n")\` in lesson 24. +- \`setEditable(false)\` stops people from typing into the list itself. +- \`getText()\` returns the whole text with all lines. + +## From one tab to the other + +The button **Add** is on the tab Input, the text area on the tab List. Still, the listener can use both. All building blocks are variables in \`main\`, and the lambda sees all of them, no matter on which tab they are shown later: + +\`\`\`java +add.addActionListener(e -> { + area.append(field.getText() + "\\n"); + info.setText(field.getText() + " is on the list."); + field.setText(""); +}); +\`\`\` + +::: ludwig +A building block can only lie on **one** area. If you add the same button first to \`input\` and then to \`list\`, Swing takes it away from \`input\`. It only shows up on the tab List. +::: + +## Saving inside the listener + +To save, you use the \`PrintWriter\` from lesson 23. Inside the listener there is a catch, though: the way out with \`throws Exception\` from lesson 23 doesn't exist here. The lambda is a method of its own, \`actionPerformed\`, and according to the contract it must not pass on a \`FileNotFoundException\`. That's why saving goes into try and catch: + +\`\`\`java +save.addActionListener(e -> { + try { + PrintWriter out = new PrintWriter("shoppinglist.txt"); + out.print(area.getText()); + out.close(); + info.setText("Saved in shoppinglist.txt"); + tabs.setSelectedIndex(0); + } catch (FileNotFoundException ex) { + info.setText("Saving didn't work."); + } +}); +\`\`\` + +- The exception is called \`ex\` here, because the name \`e\` is already taken by the event. +- After saving, the window jumps back to the tab Input with \`setSelectedIndex(0)\`, where the message is. +- VisuStruct shows the saved file below the console as soon as you have clicked Save. + +## The whole program + +\`\`\`java +import javax.swing.*; +import java.awt.*; +import java.io.*; + +public class ShoppingList { + public static void main(String[] args) { + JFrame window = new JFrame("Shopping list"); + window.setSize(300, 250); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JTabbedPane tabs = new JTabbedPane(); + + JPanel input = new JPanel(new GridLayout(0, 1)); + JTextField field = new JTextField(); + JButton add = new JButton("Add"); + JLabel info = new JLabel("Nothing on the list yet."); + input.add(new JLabel("What do you need?")); + input.add(field); + input.add(add); + input.add(info); + + JPanel list = new JPanel(new BorderLayout()); + JTextArea area = new JTextArea(); + area.setEditable(false); + JButton save = new JButton("Save"); + list.add(area, BorderLayout.CENTER); + list.add(save, BorderLayout.SOUTH); + + tabs.addTab("Input", input); + tabs.addTab("List", list); + + add.addActionListener(e -> { + area.append(field.getText() + "\\n"); + info.setText(field.getText() + " is on the list."); + field.setText(""); + }); + + save.addActionListener(e -> { + try { + PrintWriter out = new PrintWriter("shoppinglist.txt"); + out.print(area.getText()); + out.close(); + info.setText("Saved in shoppinglist.txt"); + tabs.setSelectedIndex(0); + } catch (FileNotFoundException ex) { + info.setText("Saving didn't work."); + } + }); + + window.add(tabs); + window.setVisible(true); + } +} +\`\`\` + +Type Hay, click Add, then Apples and Add again. Switch to the tab List and click Save. + +## Game: Where does it end up? + +::: spiel frage +titel: Game: Where does it end up? +intro: Ludwig builds windows with tabs. Read the code and predict what you see. Six rounds. + +runde: + tabs.addTab("Input", input); + tabs.addTab("List", list); +frage: Which tab is open at the start? +- [x] Input +- List +- none +> At the start, the tab that was added first is open. + +runde: + tabs.addTab("List", list); + tabs.addTab("Input", input); +frage: Which tab is open at the start? +- Input +- [x] List +- both +> This time List comes first. The order of \`addTab\` decides the order of the tabs. + +runde: + tabs.addTab("Input", input); + tabs.addTab("List", list); + tabs.addTab("Help", help); + tabs.setSelectedIndex(1); +frage: Which tab is open? +- Input +- [x] List +- Help +> Counting starts at 0: 0 is Input, 1 is List, 2 is Help. + +runde: + add.addActionListener(e -> { + area.append(field.getText() + "\\n"); + field.setText(""); + }); + // You type Hay, click Add, type Apples, click Add. +frage: What is on the tab List afterwards? +- Apples +- HayApples +- [x] Hay\\nApples +> \`append\` adds at the end, and each \`"\\n"\` starts a new line. + +runde: + JButton button = new JButton("OK"); + input.add(button); + list.add(button); +frage: Where does the button OK show up? +- on both tabs +- only on the tab Input +- [x] only on the tab List +> A building block can only lie on one area. With the second \`add\`, Swing takes it away from \`input\`. + +runde: + save.addActionListener(e -> { + area.setText(""); + tabs.setTitleAt(1, "List (empty)"); + tabs.setSelectedIndex(0); + }); + // The button save is on the tab List. +frage: What do you see after the click? +- the empty tab List +- [x] the tab Input, and the second tab is called "List (empty)" +- the tab Input, the second tab is still called "List" +> The listener empties the area, renames the tab and switches to tab 0. All of it happens with one click. +::: + +## Task: Shopping list with tabs + +Build the program and try it out. + +Then make it better: + +- Empty inputs don't go onto the list. Check \`field.getText().isEmpty()\` first (lesson 17). +- The tab List shows in its title how many things are on the list: "List (3)". Count along in a \`static int\` variable and use \`setTitleAt\`. +- Extra: a third tab **Help** with a JLabel that explains how the program works. + +## 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. + +::: checkliste +- I can build a window with two tabs. → Tabs with JTabbedPane +- I can add lines to a JTextArea with append. → A text area with several lines +- I can explain why a listener can use building blocks on both tabs. → From one tab to the other +- I can save a file inside a listener with try and catch. → Saving inside the listener +- I can build a shopping list that counts how many things are on it. → Task: Shopping list with tabs +::: + +## Quiz + +::: quiz +? Which tab is open after tabs.setSelectedIndex(0)? +→ Tabs with JTabbedPane +- [x] the first one +- [ ] the second one +- [ ] none + +? Why is saving inside the listener in try and catch? +→ Saving inside the listener +- [ ] Because PrintWriter only works inside try. +- [x] Because actionPerformed must not pass on a FileNotFoundException. +- [ ] Because main has no throws. + +? What is the difference between JTextField and JTextArea? +→ A text area with several lines +- [ ] There is none. +- [x] JTextArea can show several lines. +- [ ] You can't write into a JTextField. + +? Match. +→ Tabs with JTabbedPane += JTabbedPane -> an area with tabs += JPanel -> the area of a tab += JTextArea -> a text area with several lines +::: +`,F4=`--- +titel: Model View Controller +bereich: Windows with Swing +kurz: Split the click counter into model, view and controller and understand who talks to whom. +--- + +## Skills I will gain now + +::: kompetenzen +- say what model, view and controller each do +- write a model without Swing and test it without a window +- explain what new Counter() builds and why there is no static +- name the four messages after a click +- add a second view without changing the model +- build a counter with −1, Reset and limits in the model +::: + +## The goal + +Big programs with windows almost always share the same structure. It is called **Model View Controller**, **MVC** for short: + +- The **model** holds the data and knows its rules. +- The **view** only shows the data. +- The **controller** reacts to clicks and passes the word on. + +You learn MVC with the click counter from lesson 32. It is split into three parts, step by step. In the end it shows the same count twice: as a number and as a bar. + +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). + +## Everything in one class + +This is what the click counter looked like so far, everything sits in \`main\` and in one variable of the class: + +\`\`\`java +static int count = 0; + +public static void main(String[] args) { + // ... build the window ... + JLabel number = new JLabel("0", SwingConstants.CENTER); + JButton plus = new JButton("+1"); + plus.addActionListener(e -> { + count++; + number.setText("" + count); + }); +} +\`\`\` + +That works. But imagine the count should also show up as a bar, later in a second window and in a file as well. Then every listener has to think of every display. Counting and showing are tied up in a knot, and with every display the knot gets bigger. + +MVC unties the knot: every job gets its own class. + +## The model + +The model is the counter itself, without any Swing: + +\`\`\`java +class Counter { + int value = 0; + + void increase() { + value++; + } + + int getValue() { + return value; + } +} +\`\`\` + +- This time there is no \`static\` in front of \`value\` and the methods. That makes them belong to an **object**: \`new Counter()\` builds a counter with its own \`value\`, just as \`new JButton("+1")\` builds a button with its own caption. +- \`model.increase()\` calls the method of this one counter, just like \`button.setText(…)\`. +- Whoever wants to know the value asks with \`getValue()\`. It can only be changed through \`increase()\`. + +As the model needs no window, you can try it out without a window at all: + +\`\`\`java +public class CounterTest { + public static void main(String[] args) { + Counter model = new Counter(); + model.increase(); + model.increase(); + System.out.println(model.getValue()); + } +} + +class Counter { + int value = 0; + + void increase() { + value++; + } + + int getValue() { + return value; + } +} +\`\`\` + +The output is 2. Several classes may stand in one file. Only one of them is \`public\`, and that one contains \`main\`. + +## The view + +The view shows the value and does nothing else. It doesn't calculate, and it doesn't know where the number comes from: + +\`\`\`java +class NumberView { + JLabel number = new JLabel("0", SwingConstants.CENTER); + + void update(int value) { + number.setText("" + value); + } +} +\`\`\` + +- The view is handed the value with \`update(int value)\` and writes it into its JLabel. +- You build the window and the button in \`main\`, as always. \`window.add(view.number)\` puts the view's JLabel into the window. + +## The controller + +The controller is the listener at the button. It connects model and view: + +\`\`\`java +Counter model = new Counter(); +NumberView view = new NumberView(); + +plus.addActionListener(e -> { + model.increase(); + view.update(model.getValue()); +}); +\`\`\` + +- First it changes the model, then it fetches the new value and hands it to the view. +- The problem from lesson 32 is gone: the variable \`model\` never changes, it always points to the same counter. Only the \`value\` inside it changes. That's why the lambda may use \`model\`, without any \`static\`. + +## Who talks to whom? + +With every click four messages run, always in the same order: + +::: grafik mvc-klick.svg +The arrows light up one after the other. The model counts up at the second arrow, the display only at the fourth. +::: + +1. The button reports the click to the controller (\`actionPerformed\`). +2. The controller tells the model: \`increase()\`. +3. The controller asks the model for the new value: \`getValue()\`. +4. The controller hands the value to the view: \`update(value)\`. + +The model talks to nobody. It waits until it is asked. + +::: ludwig +Remember: the model knows nothing about windows. In \`Counter\` there isn't a single \`JLabel\` and no \`import javax.swing\`. If you need Swing there, the code belongs in the view. +::: + +## The pay-off: a second view + +Now the count should also show up as a bar. For that a second view joins in. A \`JProgressBar\` is a bar that fills up, here from 0 to 10: + +\`\`\`java +class BarView { + JProgressBar bar = new JProgressBar(0, 10); + + void update(int value) { + bar.setValue(value); + } +} +\`\`\` + +The controller gets one more line. The model stays exactly as it was: + +\`\`\`java +plus.addActionListener(e -> { + model.increase(); + view.update(model.getValue()); + bar.update(model.getValue()); +}); +\`\`\` + +That is exactly the pay-off of MVC: you can add or swap displays without touching the model. + +## The whole program + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +class Counter { + int value = 0; + + void increase() { + value++; + } + + int getValue() { + return value; + } +} + +class NumberView { + JLabel number = new JLabel("0", SwingConstants.CENTER); + + void update(int value) { + number.setText("" + value); + } +} + +class BarView { + JProgressBar bar = new JProgressBar(0, 10); + + void update(int value) { + bar.setValue(value); + } +} + +public class ClickCounter { + public static void main(String[] args) { + Counter model = new Counter(); + NumberView view = new NumberView(); + BarView bar = new BarView(); + + JFrame window = new JFrame("Click counter"); + window.setSize(250, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new GridLayout(0, 1)); + + JButton plus = new JButton("+1"); + plus.addActionListener(e -> { + model.increase(); + view.update(model.getValue()); + bar.update(model.getValue()); + }); + + window.add(view.number); + window.add(bar.bar); + window.add(plus); + window.setVisible(true); + } +} +\`\`\` + +Click +1 a few times and watch the number and the bar grow together. + +::: angeberwissen +MVC was invented in 1979 by the Norwegian Trygve Reenskaug, at the research centre Xerox PARC in California. Back then there were already computers with windows and a mouse there. In the same year Steve Jobs visited the lab and was so excited that Apple went on to build computers with windows and a mouse. +::: + +## Game: Where does the code belong? + +::: spiel frage +titel: Game: Where does the code belong? +intro: Ludwig has thrown code from an MVC program onto a pile. Sort every piece. Eight rounds. +frage: Where does this code belong? +antworten: Model | View | Controller + +runde: + int value = 0; +richtig: Model +> The count is the data. Data lives in the model. + +runde: + number.setText("" + value); +richtig: View +> Showing something on the screen is the view's job. + +runde: + plus.addActionListener(e -> model.increase()); +richtig: Controller +> Reacting to a click and telling the model: that's what the controller does. + +runde: + void increase() { + value++; + } +richtig: Model +> The model itself knows how to change its data. + +runde: + bar.setValue(value); +richtig: View +> A bar that fills up only shows something. So: view. + +runde: + void increase() { + if (value < 10) { + value++; + } + } +richtig: Model +> "At most 10" is a rule for the data. Rules belong in the model, then they hold for every button and every view. + +runde: + view.update(model.getValue()); +richtig: Controller +> Fetching the value from the model and handing it to the view: that's the controller in the middle. + +runde: + JLabel number = new JLabel("0", SwingConstants.CENTER); +richtig: View +> A JLabel is a building block of the screen. There is no Swing in the model. +::: + +## Game: Whose turn is it? + +::: spiel reihenfolge +titel: Game: Whose turn is it? +intro: After a click, model, view and controller talk to each other, but it only works in one order. Put the steps in the right order. Five rounds. + +runde: +frage: You click +1 in the click counter. What happens, one after the other? +- You click +1. +- The controller gets \`actionPerformed\`. +- The controller calls \`model.increase()\`. +- The model counts \`value\` up. +- The controller fetches \`model.getValue()\`. +- The view shows the new number. +> Click, controller, change the model, fetch the value, show it. Those are the four arrows from the picture, with counting up in the middle. + +runde: + plus.addActionListener(e -> { + model.increase(); + view.update(model.getValue()); + bar.update(model.getValue()); + }); +frage: What happens after a click on +1, one after the other? +- The click on +1 +- \`model.increase()\` +- The number shows the new value. +- The bar grows. +> The listener works through its lines from top to bottom: first the model, then the number, then the bar. + +runde: +frage: Put the controller in the right order so that the view shows the new number. +- \`plus.addActionListener(e -> {\` +- \`model.increase();\` +- \`view.update(model.getValue());\` +- \`});\` +> First change, then show. The other way round, the view still shows the old value. + +runde: + reset.addActionListener(e -> { + model.reset(); + view.update(model.getValue()); + }); +frage: The counter is at 5. You click Reset. What happens, one after the other? +- You click Reset. +- The model sets \`value\` to 0. +- \`model.getValue()\` returns 0. +- The view shows 0. +> Reset also runs through the controller into the model. The view only learns about the new value at the very end. + +runde: +frage: A test without a window should print 1. In which order do the lines stand in main? +- \`Counter model = new Counter();\` +- \`model.increase();\` +- \`System.out.println(model.getValue());\` +> First build the object, then work with it, and look at the result last. The model can be tested without any window. +::: + +## Task: A counter with limits + +Build the whole program and try it out. + +Then make it better: + +- A button **−1** counts down. The model gets a method \`decrease()\` for it, the controller a second listener. +- A button **Reset** sets the counter back to 0 with \`reset()\`. +- The model itself takes care of the limits: never below 0 and never above 10, because then the bar is full. +- Extra: a third view \`ConsoleView\` whose \`update\` prints "New value: 3" with \`System.out.println\`. A view doesn't have to be a window. + +## 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. + +::: checkliste +- I can say what model, view and controller each do. → The goal +- I can write a model without Swing and test it without a window. → The model +- I can explain what new Counter() builds and why there is no static. → The model +- I can name the four messages after a click. → Who talks to whom? +- I can add a second view without changing the model. → The pay-off: a second view +- I can build a counter with −1, Reset and limits in the model. → Task: A counter with limits +::: + +## Quiz + +::: quiz +? Where does the rule "The counter never goes above 10" belong? +→ The model +- [x] in the model +- [ ] in the view +- [ ] in the controller +> Rules about the data belong in the model. Then they hold no matter which button is pressed. + +? What does the view do? +→ The goal +- [ ] It calculates the new value. +- [x] It shows the value it is given. +- [ ] It listens for clicks. + +? Why may the lambda use model, even though model is a variable of main? +→ Who talks to whom? +- [ ] Because Counter is public. +- [x] Because model always points to the same counter; only the value inside it changes. +- [ ] Because lambdas may change any variable. + +? What do you have to change in the model when a second view joins in? +→ The pay-off: a second view +- [x] nothing +- [ ] a second method increase +- [ ] a second JLabel + +? Match. +→ The goal += Counter with value and increase() -> model += NumberView with update(int value) -> view += the listener at the button -> controller +::: +`,J4=`Technical terms for the learning area. When a term appears in a step, it is marked there once and shows its explanation +on hover or tap. If it is in bold in that step, it is being explained right there and is not marked. +\`also:\` lists other forms that are recognised too. Upper and lower case matter. + +### Algorithm +also: algorithm, algorithms, Algorithms +Exact step-by-step instructions for solving a task. Every step is clear. + +### Structure chart +also: structure chart, structure charts, Structure charts, Nassi-Shneiderman diagram, Nassi-Shneiderman diagrams +An algorithm drawn as a picture made of boxes. You read it from top to bottom. It is also called a Nassi-Shneiderman diagram. + +### Flowchart +also: flowchart, flowcharts, Flowcharts +An algorithm drawn as symbols joined by arrows (DIN 66001 / ISO 5807). A diamond is a decision. + +### Pseudocode +also: pseudocode +An algorithm written as text in plain language with fixed words such as IF and WHILE. The indentation shows what belongs together. + +### Statement +also: statement, statements, Statements +A single step in the structure chart, for example a calculation, an input or an output. + +### Sequence +also: sequence, sequences, Sequences +Steps that run one after another from top to bottom, each exactly once. + +### Branch +also: branch, branches, Branches, conditional statement, conditional statements +A block that uses a condition to decide which of two paths runs. It is also called a conditional statement. + +### Path +also: path, paths +One of the two ways through a branch: left for true, right for false. + +### Loop +also: loop, loops, Loops, iteration, repetition +A block that repeats steps as long as a condition holds. + +### Loop body +also: loop body +The inside of a loop, that is, the steps that are repeated. + +### Pass +also: passes +Running the inside of a loop once. + +### Condition +also: condition, conditions, Conditions +A question that can only be answered with yes (true) or no (false), for example age >= 18. + +### Placeholder +also: placeholder, placeholders +An empty box with the sign ø. If you drag an element onto it, the element replaces it. + +### Object Inspector +The area below the diagram. Here you edit the text and settings of the box you just clicked. + +### Simulation +also: simulation +Runs your structure chart in the editor, step by step if you like. That way you see what happens. + +### Variable +also: variable, variables, Variables +A labelled box for a value. It has a name, a data type and a value. + +### camelCase +also: CamelCase +A way of writing names made of several words: written together, every further word starts with a capital, e.g. \`priceWithTax\`. + +### Constant +also: constant, constants, Constants +A variable whose value stays the same once it is set. You write \`const\` in front of it, e.g. \`const double VAT = 0.19\`. + +### Data type +also: data type, data types, Data types +Says what kind of value fits into a variable: int (whole number), double (decimal number), String (text), boolean (true or false) or char (a single character). + +### Assignment +also: assignment, assignments, Assignments +The sign =. It works out the right-hand side and stores the result in the variable on the left. + +### Temporary variable +also: temporary variable, temporary variables, helper variable +An extra variable that keeps a value for a short time, for example when swapping. + +### IPO model +also: input-process-output +Input, process, output: first ask for values, then calculate, then show the result. + +### Problem analysis +also: problem analysis +You read a task carefully and work out what is given, what you are looking for and how to get from one to the other. + +### Comparison operator +also: comparison operator, comparison operators, Comparison operators +A sign that compares two values, for example == or <. The result is true or false. + +### Switch +also: switch, multiple selection +A block that runs exactly one of several cases, depending on the value of a variable. It is also called multiple selection. + +### Pre-test loop +also: pre-test loop, pre-test loops, head-controlled +The loop checks its condition before every pass. If the condition is false right at the start, the loop does not run even once. + +### Post-test loop +also: post-test loop, post-test loops, foot-controlled +The loop checks its condition only after every pass. So it always runs at least once. + +### Counter variable +also: counter variable, counter variables, counter +A variable that counts along in a loop, usually i. + +### Endless loop +also: endless loop, endless loops, infinite loop, infinite loops +A loop whose condition never becomes false. It never stops by itself. + +### Array +also: array, arrays, Arrays +A row of slots with one shared name and the same data type. + +### Index +also: index, indices, indexes +The number of a slot in an array. Counting starts at 0. + +### char +The data type for a single character. It goes in single quotation marks, e.g. 'C'. "C" with double quotation marks, on the other hand, is a String. + +### Character code +also: character code, character codes, ASCII code, ASCII table +The number behind a character. In the ASCII table A has the code 65, B 66 and so on. In Java (int) turns a character into its code and (char) turns a code into the character. + +### String +also: strings, Strings +A text, that is, a row of characters. In Java the data type is called String. The characters are counted from 0. + +### 2D array +also: 2D arrays, two-dimensional array, two-dimensional arrays +An array with rows and columns, like a table. A slot needs two indices, e.g. \`seats[1][2]\`. + +### Subprogram +also: subprogram, subprograms, Subprograms, method, methods, Methods, procedure, procedures, function, functions, Functions +A structure chart of its own for part of a task. It runs when it is called. In Java it is called a method; depending on its kind also a procedure or a function. + +### Parameter +also: parameter, parameters, Parameters +A variable in the header line of a subprogram. When it is called, it gets the value from the parentheses. + +### Spaghetti code +also: spaghetti code +A program that jumps around so wildly that you can hardly follow what happens. Structure charts prevent that. + +### Call by value +also: call by value +A subprogram gets a copy of the value. If it changes its parameter, the caller's variable stays the same. + +### Call by reference +also: call by reference +A subprogram gets a reference to the same data, e.g. to an array. If it changes a slot, the caller sees the change too. + +### Return value +also: return value, return values, Return values +The result that a subprogram hands back to the call with return. + +### Break +A block that leaves the loop it is in straight away. Then the program continues below the loop. + +### Desk check +also: desk check, desk checks, Desk checks +You run a structure chart on paper and write down the values of the variables after every step. + +### Linear search +also: linear search +A way of searching that compares all values one after another with the value you are looking for. It also works with unsorted values. + +### Binary search +also: binary search +A way of searching sorted values. It looks at the middle and keeps searching only in the matching half. + +### Bubble sort +also: bubble sort, Bubblesort +A simple way of sorting. It always compares two neighbours and swaps them if they are the wrong way round. + +### Event +also: event, events, Events +Something a person does in a window program, for example clicking a button. The program reacts to it with a listener (ActionListener). + +### Interface +also: Interfaces +A kind of contract in Java: it states which methods a class must have. \`ActionListener\` is an interface with the method \`actionPerformed\`. + +### Exception +also: exception, exceptions, Exceptions +An error that only happens while the program runs, for example an index outside the array. If no \`catch\` catches it, the program stops. + +### Scanner +A ready-made Java building block that reads input from the keyboard, for example a number with \`scanner.nextInt()\`. It needs \`import java.util.Scanner;\` at the very top. + +### comment +auch: comments, Comment, Comments +A note in the code for people. Java skips it when it runs. \`//\` lasts until the end of the line, \`/* … */\` can span several lines. + +### import +A line at the very top of Java code that fetches a ready-made building block from a package, for example \`import java.util.Scanner;\`. Without it, Java doesn't know the name. +`,R4=`## Basics + +### Statement + +A single step. You use it to create variables or to calculate. + +\`\`\` +int number = 5 +double price = 2.5 +String name = "Ada" +number = number + 1 +\`\`\` + +### Data types + +The data type comes before the name of the variable. + +| Data type | Meaning | Example | +|---|---|---| +| \`int\` | whole number | \`int count = 3\` | +| \`double\` | decimal number (with a point) | \`double price = 2.5\` | +| \`String\` | text in double quotation marks | \`String name = "Ada"\` | +| \`boolean\` | truth value | \`boolean done = false\` | +| \`char\` | a single character in single quotation marks | \`char grade = 'C'\` | + +\`'C'\` is a \`char\`, \`"C"\` is a String. You get a character from a text with \`charAt\`: \`char first = name.charAt(0)\`. Every character has a character code: \`(int) 'A'\` is 65, \`(char) 66\` is \`'B'\`. + +### Input + +Asks for a value while the chart runs and stores it in a variable. The text in quotation marks is the question. + +\`\`\` +input: int age "How old are you?" +input: double price "Enter a price" +input: String name "What is your name?" +\`\`\` + +### Output + +Shows a text or a value. Texts go in quotation marks; you join text and variables with \`+\`. + +\`\`\` +output: "Hello" +output: sum +output: "You are " + age + " years old." +\`\`\` + +> In an output, \`+\` always joins the parts together: with 3 and 4, \`output: a + b\` shows 34. So calculate in a variable first, e.g. \`int sum = a + b\`, and then output \`sum\`. + +## Branches + +### Branch + +Checks a condition. If it is true, the left path (true) runs, otherwise the right one (false). + +\`\`\` +age >= 18 +number % 2 == 0 +grade < 1 || grade > 6 +\`\`\` + +### Switch + +Picks one of several cases, depending on the value of a variable. If no case fits, \`default\` applies. You add cases on the right with **Add Case**. + +## Loops + +### While loop + +Repeats its inside **as long as** the condition is true. The condition is checked before every pass. + +\`\`\` +number != 1 +i < 10 +\`\`\` + +### Do-while loop + +Runs its inside **at least once** and checks the condition only afterwards. + +### For loop + +Counts a variable from a start value up to a limit. The three fields are Init, Condition and Step. + +\`\`\` +int i = 0 +i < 5 +i++ +\`\`\` + +### Endless loop + +Repeats its inside without a condition. A **Break** inside it lets you leave it. + +### Break + +Leaves the loop around it (\`break\`). + +## Subprograms + +### Call + +Stands for a subprogram, e.g. \`calculateSum()\`. With parameters and a return value, the subprogram has a header line as its title: + +\`\`\` +int square(int x) header line of the subprogram +return x * x hands back the result +int q = square(5) call, q gets 25 +showSum(3, 4) call of a void subprogram +\`\`\` + +## Calculating and comparing + +### Operators and comparisons + +- \`+ - * /\` the four basic operations +- \`%\` remainder of a division (\`7 % 2\` is 1) +- \`==\` equal, \`!=\` not equal +- \`<\` \`<=\` \`>\` \`>=\` less than, less than or equal, greater than, greater than or equal +- \`&&\` and, \`||\` or + +## Arrays + +### Arrays + +Several values under one name. Counting starts at 0. + +\`\`\` +int[] numbers = {3, 7, 1} +output: numbers[0] +int[] empty = new int[5] +\`\`\` + +A **2D array** is a table with rows and columns: + +\`\`\` +boolean[][] seats = new boolean[3][5] +seats[1][4] = true +output: seats.length + " rows, " + seats[0].length + " seats" +\`\`\` + +## Java + +### Comments + +Notes in the code. Java skips them, the structure chart stays the same. + +\`\`\`java +/* + * Task: add the numbers from 1 to 10 + * (multi-line comment) + */ +// Process (single-line comment) +int sum = 0; +for (int i = 1; i <= 10; i++) { + sum = sum + i; // comment after the code +} // end for +\`\`\` + +Good for: the task, dividing the code into input, process and output, an explanation, the end of a block after \`}\`, the expected output and notes for next time. +`,G4=`--- +titel: O que é um estrutograma? +bereich: Primeiros passos +kurz: Mostrar e ler algoritmos como uma série de passos claros. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar o que é um algoritmo +- ler um estrutograma +- reconhecer os três blocos básicos: sequência, decisão e ciclo +- ler um fluxograma (em inglês *flowchart*) e construir um sozinho +- explicar porque é que os saltos num fluxograma levam a erros +- ler um algoritmo simples em pseudocódigo +::: + +## Um algoritmo é uma instrução exata + +Um **algoritmo** descreve passo a passo como resolver uma tarefa. Cada passo tem de ser tão claro que qualquer um o consiga executar sem perguntar, tanto uma pessoa como um computador. + +Conheces algoritmos do dia a dia: uma receita, o caminho para um sítio ou as instruções para montar um roupeiro. + +::: diagramm l1-tee.visustruct +Fazer chá como estrutograma: cada bloco é um passo. +::: + +## Como se lê um estrutograma + +Um estrutograma lê-se **de cima para baixo**. Cada bloco é um passo. Só quando um passo termina é que começa o seguinte. + +Esta forma de desenhar foi inventada por **Isaac Nassi e Ben Shneiderman** (1973). Por isso também se chama diagrama de Nassi-Shneiderman. Na Alemanha está normalizado como DIN 66261. + +::: bild ike-nassi.jpg ben-shneiderman.jpg +À esquerda: Isaac “Ike” Nassi (foto: [Ed Schipul](https://commons.wikimedia.org/wiki/File:Me_with_Ike_Nassi!!!!!_%286893328729%29.jpg), [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/), recortada), à direita: Ben Shneiderman (foto: [Robert Kosara](https://commons.wikimedia.org/wiki/File:Ben_Shneiderman_at_UNCC_%283x4_cropped%29.jpg), CC0). +::: + +> Um estrutograma tem sempre exatamente um início (em cima) e um fim (em baixo). Não há setas nem saltos para todo o lado. Programas que saltam para todo o lado chamam-se **código esparguete**, porque o seu fluxo se enrola como massa no prato. Mais sobre isto no passo 10. + +::: angeberwissen +Méééé, ouve bem! Em 1972, Nassi e Shneiderman ainda eram doutorandos na Universidade de Stony Brook, perto de Nova Iorque. Shneiderman tinha uns 25 anos e Nassi uns 23. Ou seja, dois estudantes que escreveram história da informática nas horas vagas. +::: + +## Bloco básico 1: a sequência + +Qualquer algoritmo pode ser construído com apenas **três blocos básicos**: **sequência**, [**decisão**]{.blau} e [**ciclo**]{.rosa}. As cores ajudam-te a associá-los: as [instruções]{.gelb} são amarelas, as decisões azuis, os ciclos cor-de-rosa. A sequência não tem cor própria, é simplesmente a fila de instruções umas por baixo das outras. Vês as mesmas cores no editor e mais tarde no código. Podes desligá-las nas definições em “Blocos coloridos”. Neste passo e nos dois seguintes vais conhecê-los um a um. + +A **sequência** é o bloco mais simples: várias instruções são executadas **uma a seguir à outra**, cada uma exatamente uma vez. + +É assim que se parece: + +- Cada instrução é um **retângulo simples**. +- Os retângulos ficam **uns por cima dos outros**, sem espaço entre eles. +- São executados de cima para baixo, uma instrução depois da outra. + +::: diagramm l1-sequenz.visustruct +Quatro instruções em sequência. Primeiro levantas-te, depois lavas os dentes, e assim por diante. +::: + +> O exemplo do chá lá em cima também é uma sequência. + +::: angeberwissen +15 minutos! Foi o tempo de que Shneiderman precisou para o primeiro esboço com sequência, decisão e ciclo. Eu preciso de mais tempo do que isso para escolher entre feno e trevo. +::: + +## Bloco básico 2: a decisão + +Muitas vezes o passo seguinte depende de uma **condição**. Uma condição é uma pergunta a que só se pode responder com **sim ou não**, por exemplo *Está a chover?* No VisuStruct, sim é **true** e não é **false**. + +Para decisões destas existe a **decisão**. É assim que se parece: + +- Em cima, a condição fica dentro de um **triângulo**. +- Por baixo, o bloco divide-se em **duas colunas**: à esquerda o ramo para **true**, à direita o ramo para **false**. +- Só é executado **um** dos dois ramos. Depois, os dois ramos continuam juntos por baixo da decisão. + +::: diagramm l1-verzweigung.visustruct +Se estiver a chover, é executado o ramo da esquerda, senão o da direita. Depois, os dois casos continuam com “Sair”. +::: + +> Se num dos casos não deve acontecer nada, esse ramo fica vazio. O sinal **ø** indica isso. + +::: angeberwissen +Alerta de ortografia! Escreve-se Shneiderman, sem c. Quem escrever “Schneiderman” leva um empurrãozinho dos meus chifres. Ele próprio conta que as pessoas estão sempre a meter um c no nome dele. +::: + +## Bloco básico 3: o ciclo + +Se uma coisa deve acontecer **várias vezes**, não a escreves várias vezes. Em vez disso usas um **ciclo**, também chamado repetição. + +É assim que se parece: + +- Em cima está a condição, por exemplo *Prato não vazio*. +- Os passos que se repetem ficam **recuados** por baixo dela. Em cima e à esquerda, o bloco forma um **L invertido** à volta deles. +- Antes de cada iteração, a condição é verificada. Enquanto for **true**, os passos dentro do L invertido são executados mais uma vez. Se for **false**, o programa continua por baixo do ciclo. + +::: diagramm l1-wiederholung.visustruct +Enquanto o prato não estiver vazio, dás uma garfada. Depois, o prato é levantado. +::: + +> Há mais tipos de ciclos. Vais conhecê-los nas próximas lições. + +## Os três juntos + +Os blocos básicos tornam-se realmente úteis quando os combinas. Este diagrama contém os três: uma sequência de cima para baixo, uma [decisão]{.blau} e um [ciclo]{.rosa}. As caixas amarelas são [instruções]{.gelb} simples. As instruções dentro de uma decisão ou de um ciclo também são amarelas. Em rigor, o diagrama todo é uma sequência, porque a decisão e o ciclo também estão na fila de cima para baixo. + +::: diagramm l1-grundbausteine.visustruct +Reconheces a decisão pelo triângulo e o ciclo pelo L invertido. Tudo junto forma uma sequência. +::: + +Os blocos também podem ser **encaixados** uns dentro dos outros: um ciclo ou um ramo pode voltar a conter sequências, decisões e ciclos. + +::: angeberwissen +Consolo para quem correu mal um teste: a famosa revista *Communications of the ACM* rejeitou o artigo sobre estrutogramas. Segundo Nassi, o revisor até disse que deviam juntar todas as cópias e queimá-las. Ai! O artigo saiu em 1973 numa revista mais pequena e hoje é citado milhares de vezes. Ha! +::: + +## Outras formas de desenhar: o fluxograma + +Há mais duas formas de representar um algoritmo: o **fluxograma** e o **pseudocódigo**. Vais conhecer as duas nas aulas. Em inglês, o fluxograma chama-se **flowchart**. Esta palavra aparece muitas vezes, por exemplo em programas e na internet. + +Aqui vês outra vez o nosso estrutograma para beber chá de “Os três juntos”. A seguir vamos ver o fluxograma, com o mesmo exemplo. + +::: diagramm l1-grundbausteine.visustruct +O exemplo do chá como estrutograma: primeiro a chávena, depois a decisão para o açúcar e depois o ciclo. +::: + +### O mesmo algoritmo como fluxograma + +::: grafik l01-pap.svg +O exemplo do chá como fluxograma. A seta de “Esperar 1 minuto” para cima forma o ciclo. +::: + +### Os símbolos + +Um fluxograma é feito de poucos símbolos ligados por **setas**. Está normalizado como DIN 66001 (ISO 5807). + +- **Oval:** início ou fim. Cada fluxograma tem exatamente um início e um fim. +- **Retângulo:** uma instrução, por exemplo *Pôr uma chávena na mesa*. +- **Losango:** uma decisão. No losango está uma pergunta, e dele saem duas setas: **sim** e **não**. +- **Paralelogramo:** uma entrada ou saída. No exemplo do chá não aparece. +- **Seta:** mostra qual é o passo seguinte. + +Um ciclo não tem símbolo próprio no fluxograma. Reconheces um ciclo por uma seta que volta **para cima**. + +### As vantagens + +- **Muito fácil de ler**, mesmo para quem nunca viu um fluxograma. Basta seguir as setas com o dedo. +- Os fluxogramas não se usam só na programação, mas em todo o lado onde se explica um processo: em manuais de instruções, na procura de avarias (“A lâmpada acende? Não: a ficha está ligada?”) ou nas empresas para os processos de trabalho. + +## Exercício: Fazer um bolo como fluxograma + +Agora és tu que constróis um fluxograma. O Ludwig faz um bolo assim: + +Põe os ingredientes na tigela e mexe a massa. Se a massa ainda não estiver lisa, continua a mexer. Quando está lisa, deita a massa na forma e coze o bolo durante 30 minutos. Depois testa com um palito: se ainda tiver massa agarrada, coze mais 5 minutos e testa outra vez. Quando o palito sai limpo, tira o bolo e diz: “O bolo está pronto!” + +::: pap +titel: Exercício: Fazer um bolo como fluxograma +auftrag: Os lugares no fluxograma estão vazios. Põe cada elemento no seu lugar. A forma do lugar ajuda-te. +start: Início +anweisung: Pôr os ingredientes na tigela +anweisung: Mexer a massa +frage: Massa lisa? | nein -> Mexer a massa +anweisung: Deitar a massa na forma +anweisung: Cozer 30 minutos +frage: Palito limpo? | nein: Cozer mais 5 minutos +anweisung: Tirar o bolo do forno +ausgabe: “O bolo está pronto!” +ende: Fim +erklärung: Dois ciclos, duas setas para cima: ao mexer, a seta volta a “Mexer a massa”; ao cozer, vai de “Cozer mais 5 minutos” de volta à pergunta. A saída fica no paralelogramo. +legende: ja +::: + +## Desvantagens do fluxograma: saltos + +Uma seta num fluxograma pode ir de qualquer símbolo para qualquer outro. Parece prático, mas é perigoso. + +Antigamente, os programas escreviam-se exatamente assim. Cada linha tinha um **número**, e o comando **GOTO**, em português “ir para”, saltava para um número de linha. Cada IR PARA é uma seta do fluxograma. O nosso exemplo do chá ficava assim: + +\`\`\` +10 Pôr uma chávena na mesa +20 SE não quer açúcar, IR PARA 40 +30 Juntar açúcar +40 SE chá não demasiado quente, IR PARA 70 +50 Esperar 1 minuto +60 IR PARA 40 +70 Beber o chá +\`\`\` + +### Mais uma linha, e os saltos ficam errados + +Agora melhoras o algoritmo: depois do açúcar, o saquinho de chá deve sair. Acrescentas a nova linha 40, e todas as linhas abaixo avançam um número. Mas os saltos continuam a apontar para os números antigos: + +\`\`\` +10 Pôr uma chávena na mesa +20 SE não quer açúcar, IR PARA 40 +30 Juntar açúcar +40 Tirar o saquinho de chá +50 SE chá não demasiado quente, IR PARA 70 +60 Esperar 1 minuto +70 IR PARA 40 +80 Beber o chá +\`\`\` + +Experimenta: a linha 70 já não te manda para a verificação da linha 50, mas para o saquinho. E quando o chá já está frio o suficiente, a linha 50 salta para a linha 70 em vez de *Beber o chá*. Ou seja, tiras o saquinho vezes sem conta e nunca bebes. A cada alteração tens de verificar todos os IR PARA. Num programa grande, com centenas de saltos, é fácil algo correr mal. + +### Para todo o lado: código esparguete + +Com setas também se pode saltar do meio de um ciclo para fora, ou de fora para o meio de um ciclo. Estes saltos tornam o fluxograma confuso muito depressa. Com muitos saltos, as setas cruzam-se até o fluxograma parecer um prato de esparguete. Por isso chama-se **código esparguete**. Mal se consegue seguir o fluxo, e os erros escondem-se bem. + +Um estrutograma não tem setas. Se acrescentares um bloco, tudo o que está abaixo desce com ele, e nenhum salto pode apontar para o sítio errado. Para sair de um ciclo mais cedo existe lá um bloco próprio e arrumado, a interrupção. Vais conhecê-la na lição 18. + +::: angeberwissen +Em 1968, o informático Edsger Dijkstra escreveu uma carta famosa: “Go To Statement Considered Harmful”, ou seja, “o GOTO é considerado prejudicial”. Desde então, os programas são construídos só com sequência, decisão e ciclo. Em Java, \`goto\` ainda hoje é uma palavra reservada, mas não a podes usar. Mééé, prefiro comer esparguete a programá-lo. +::: + +## Pseudocódigo e comparação + +**Pseudocódigo** é texto que parece um programa, mas está escrito em linguagem corrente. Palavras fixas como SE e ENQUANTO mostram os blocos, e a **indentação** mostra o que pertence a eles. Aqui também não há saltos. Este é o nosso exemplo do chá: + +\`\`\` +Pôr uma chávena na mesa +SE quer açúcar ENTÃO + Juntar açúcar +FIM SE +ENQUANTO chá ainda demasiado quente + Esperar 1 minuto +FIM ENQUANTO +Beber o chá +\`\`\` + +O pseudocódigo **não tem uma forma fixa**. Há quem escreva CASO em vez de SE, quem use uma seta para a atribuição (\`numero ← 5\`) ou quem não escreva as linhas FIM. Tudo isso é permitido. O importante é que qualquer pessoa o perceba sem explicação. Por isso, o pseudocódigo não é mais uma linguagem de programação que tens de aprender. + +::: angeberwissen +O pseudocódigo parece-te familiar? A linguagem de programação Python é muito parecida, e isso é de propósito: o seu criador, Guido van Rossum, queria que os programas se lessem quase como texto normal. O Python também usa a indentação para mostrar o que pertence junto. Mas atenção: o Python é uma linguagem de programação a sério, com regras fixas. Um espaço a mais e o computador reclama. O pseudocódigo é mais descontraído, tal como eu ao pequeno-almoço. +::: + +### Comparação + +- **Estrutograma:** blocos dentro de blocos, o ciclo é um L invertido. Vês a estrutura num relance, e saltos malucos são impossíveis. +- **Fluxograma:** símbolos com setas, o ciclo é uma seta que volta para cima. Muito fácil de imaginar, mas os fluxogramas grandes ficam depressa confusos, e são possíveis saltos para todo o lado. +- **Pseudocódigo:** texto com indentação, o ciclo fica entre ENQUANTO e FIM ENQUANTO. Rápido de escrever e já perto do código de um programa. + +> Os três descrevem o mesmo algoritmo. Quando sabes ler uma das formas, aprendes as outras depressa. + +::: angeberwissen +Nassi e Shneiderman estavam em guerra com as setas! O artigo deles de 1973 chamava-se “Flowchart Techniques for Structured Programming”. Com setas pode-se saltar para todo o lado até o fluxograma parecer um prato de esparguete. Num estrutograma isso é simplesmente impossível. Mééé, é assim que eu gosto: arrumado, como o meu estábulo. +::: + +## Primeiro a estrutura, depois o código + +Quando programas, acontecem duas coisas ao mesmo tempo: tens de pensar nos passos e prestar atenção à forma como a linguagem de programação se escreve. Um estrutograma permite-te separar as duas coisas. + +1. Primeiro pensas na **lógica**: que passos, que condições, que repetições? +2. Depois traduzes a estrutura pronta para **Java, Python ou JavaScript**. O VisuStruct até consegue gerar o código por ti. + +Com a **simulação** também podes executar o teu estrutograma passo a passo e verificar se ele faz mesmo o que deve. + +## Jogo: Que bloco básico? + +::: spiel frage +titel: Jogo: Que bloco básico? +intro: O Ludwig descreve coisas do seu dia a dia. Que bloco básico se esconde em cada uma? Oito rondas. +antworten: sequência | decisão | ciclo + +runde: +frage: "Pasta na escova, lavar os dentes, bochechar." +richtig: sequência +> Três passos, cada um exatamente uma vez e sempre por esta ordem. + +runde: +frage: "Se chover, levo o guarda-chuva, senão os óculos de sol." +richtig: decisão +> Uma condição decide qual dos dois caminhos é seguido. + +runde: +frage: "Mexer até a massa ficar lisa." +richtig: ciclo +> Mexe-se repetidamente enquanto a massa ainda não estiver lisa. + +runde: +frage: "Correr dez voltas ao campo de desporto." +richtig: ciclo +> A mesma volta é corrida dez vezes. + +runde: +frage: "Calçar os sapatos, vestir o casaco, abrir a porta, e lá vamos." +richtig: sequência +> Um passo a seguir ao outro, nada é saltado nem repetido. + +runde: +frage: "Se o semáforo estiver verde, atravessas a rua." +richtig: decisão +> Mesmo sem "senão" é uma decisão. O ramo senão fica simplesmente vazio. + +runde: +frage: "Lançar o dado até sair um seis." +richtig: ciclo +> Não se sabe antes quantas vezes. Lança-se até a condição se cumprir. + +runde: +frage: "Se alguém disser 'Entra', entras. Senão, esperas à porta." +richtig: decisão +> A resposta decide entre dois caminhos: entrar ou esperar. +::: + +## 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. + +::: checkliste +- Consigo explicar o que é um algoritmo. → Um algoritmo é uma instrução exata +- Consigo ler um estrutograma de cima para baixo. → Como se lê um estrutograma +- Consigo nomear os três blocos básicos: sequência, decisão e ciclo. → Bloco básico 1: a sequência +- Consigo reconhecer cada bloco básico num estrutograma pela sua forma. → Os três juntos +- Consigo nomear os símbolos de um fluxograma e ler um fluxograma simples. → Outras formas de desenhar: o fluxograma +- Consigo construir sozinho um algoritmo simples como fluxograma. → Exercício: Fazer um bolo como fluxograma +- Consigo explicar porque é que os saltos com GOTO levam a erros e a código esparguete. → Desvantagens do fluxograma: saltos +- Consigo ler um algoritmo simples em pseudocódigo. → Pseudocódigo e comparação +::: + +## Teste de conhecimentos + +::: quiz +? Em que direção se lê um estrutograma? +→ Como se lê um estrutograma +- [ ] Da esquerda para a direita +- [x] De cima para baixo +- [ ] De baixo para cima +> Cada bloco é um passo, e os passos seguem-se de cima para baixo. + +? Qual destes NÃO é um dos três blocos básicos? +→ Bloco básico 1: a sequência +- [ ] Sequência +- [ ] Decisão +- [x] Salto +- [ ] Ciclo +> Num estrutograma não há saltos. Sequência, decisão e ciclo chegam para qualquer algoritmo. + +? Como reconheces uma decisão num estrutograma? +→ Os três juntos +- [ ] Por um L invertido +- [x] Por um triângulo com a condição e duas colunas por baixo +- [ ] Por vários retângulos uns por cima dos outros +> O L invertido pertence ao ciclo, e retângulos uns por cima dos outros são uma sequência. + +? Quando é que o interior de um ciclo é executado mais uma vez? +→ Os três juntos +- [x] Enquanto a condição for verdadeira +- [ ] Só se a condição for falsa +- [ ] Sempre exatamente duas vezes +> A condição é verificada antes de cada iteração. Se for falsa, o programa continua por baixo do ciclo. + +? O que é um algoritmo? +→ Um algoritmo é uma instrução exata +- [x] Instruções claras, passo a passo, para resolver uma tarefa +- [ ] Um determinado programa em Java +- [ ] Uma imagem que explica um programa +> Um algoritmo não depende de nenhuma linguagem de programação. Um estrutograma é uma forma de o escrever. + +? Como reconheces um ciclo num fluxograma? +→ Outras formas de desenhar: o fluxograma +- [ ] Por um L invertido +- [x] Por uma seta que volta para cima +- [ ] Pela palavra ENQUANTO +> O L invertido pertence ao estrutograma, e ENQUANTO ao pseudocódigo. + +? Associa cada símbolo do fluxograma ao seu significado. +→ Outras formas de desenhar: o fluxograma += Oval -> Início ou fim += Retângulo -> Instrução += Losango -> Decisão += Paralelogramo -> Entrada ou saída +> O losango tem duas saídas: sim e não. + +? Como se diz fluxograma em inglês? +→ Outras formas de desenhar: o fluxograma +- [x] Flowchart +- [ ] Structure chart +- [ ] Pseudocode +> Structure chart é o estrutograma. + +? Acrescentas uma nova linha a um programa com GOTO. O que pode acontecer? +→ Desvantagens do fluxograma: saltos +- [x] Os saltos apontam para as linhas erradas, porque os números mudaram +- [ ] Nada, os saltos ajustam-se sozinhos +- [ ] O programa fica automaticamente mais rápido +> Cada IR PARA aponta para um número de linha fixo. Se as linhas descem, o programa salta para o sítio errado. + +? No pseudocódigo, o que mostra que linhas pertencem a um ciclo? +→ Pseudocódigo e comparação +- [ ] A cor +- [x] A indentação e o FIM ENQUANTO +- [ ] Uma seta +> Tudo o que está entre ENQUANTO e FIM ENQUANTO está recuado e é repetido. +::: +`,H4=`--- +titel: O editor +bereich: Primeiros passos +kurz: Inserir elementos, escrever texto, mover e eliminar. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- inserir um elemento da área Elementos e substituir um marcador +- alterar o texto de um bloco e mudar entre Instrução, Entrada e Saída +- mover, copiar e eliminar blocos e anular passos +::: + +## O ecrã + +O VisuStruct tem dois editores: o [editor de estrutogramas](#zeige-editor), de que trata esta lição, e à direita a área [Código](#zeige-codelive) para código Java (a partir da lição 4). Se o editor de estrutogramas estiver recolhido, esta lição abre-o sozinha. As palavras azuis mostram-te as áreas, mesmo que estejam recolhidas: passa o rato por cima de uma, e a área abre-se ao lado da área de aprendizagem e acende-se. Se clicares nela (ou tocares nela), fica aberta. + +O editor de estrutogramas tem várias áreas. Passa o rato por cima de uma palavra azul ou toca nela, e essa área acende-se no editor; as áreas recolhidas, como os Elementos, abrem-se. + +- **Mesmo em cima, a [barra de ferramentas](#zeige-leiste):** Novo, Abrir e Guardar. À direita, a roda dentada das [Definições](#zeige-einstellungen): tamanho do texto e idioma. +- **Por baixo, as [ferramentas](#zeige-werkzeuge)** por cima dos elementos e do estrutograma: Anular, Cortar, Copiar, Colar, Eliminar, Exportar, Código e Simulação. Os botões só mostram ícones. Se puseres o rato por cima de um, aparece o nome. +- **À esquerda, os [Elementos](#zeige-elemente):** Aqui estão todos os blocos que podes arrastar para o estrutograma. Há quem chame a esta área a paleta. +- **Ao meio, o [estrutograma](#zeige-struktogramm):** Um diagrama novo contém apenas um marcador vazio, assinalado com **ø**. +- **Em baixo, o [Inspetor de objetos](#zeige-objektinspektor):** Aqui editas o texto do elemento selecionado. + +> Podes recolher esta área de aprendizagem a qualquer momento com o [ícone da barra lateral](#zeige-lernen) no topo desta área. Fica só a barra estreita “🎓 Aprender” à esquerda; um clique abre-a de novo. Ela fica aberta ao lado do editor, para poderes experimentar logo o que lês. Da mesma forma, há à esquerda a coluna [📁 Ficheiros](#zeige-dateien) para os teus programas guardados (lição 3) e à direita a área [Código](#zeige-codelive) para Java (a partir da lição 4). + +## Inserir um elemento + +Arrasta um elemento da área **Elementos** para o estrutograma. Enquanto arrastas, uma linha azul mostra onde ele vai ficar: + +- **Sobre o marcador ø:** O elemento substitui o marcador. +- **Sobre a metade de cima de um bloco:** O elemento fica antes dele. +- **Sobre a metade de baixo de um bloco:** O elemento fica depois dele. + +::: grafik l02-einfuegen.svg +O sítio onde largas decide onde fica o novo elemento. +::: + +Também funciona sem arrastar: **clica** num elemento da área Elementos (ou toca nele). Ele é então inserido depois do bloco selecionado. Se o marcador **ø** estiver selecionado, substitui-o. + +Com o teclado, usa a tecla **Tab** para saltar para um elemento e prime **Enter**. O novo elemento também fica depois do bloco selecionado. + +::: angeberwissen +Agarrar blocos e arrastá-los de um lado para o outro, tal como estás a fazer agora, tem um nome pomposo: **manipulação direta**. Foi Ben Shneiderman quem inventou o termo em 1982. Sim, o senhor dos estrutogramas. Aquele homem trabalhava mais do que eu quando estou a pastar. +::: + +## Escrever texto + +Clica num bloco. Ele fica com um contorno azul, e o seu texto aparece no Inspetor de objetos por baixo do diagrama. O que escreveres lá aparece logo no diagrama. + +O bloco da área Elementos chama-se **Instrução**. Em cima, no Inspetor de objetos, escolhes de que tipo deve ser: + +- **Instrução:** calcular ou definir alguma coisa, p. ex. \`int numero = 5\`. Vais aprender como na lição 4. +- **Entrada:** pedir um valor enquanto o estrutograma é executado. Isso vem na lição 6. +- **Saída:** mostrar alguma coisa. No diagrama fica com \`output:\` à frente, p. ex. \`output: "Olá"\`. + +Para começar, só precisas de Saída. Os textos que devem aparecer exatamente como estão ficam entre **aspas**. + +::: diagramm l2-ausgabe.visustruct +Duas saídas, uma a seguir à outra. Abre o diagrama no editor e inicia a simulação para veres a saída. +::: + +## Mover, copiar, eliminar + +- **Mover:** Arrasta um bloco existente com o rato para um novo sítio. +- **Copiar e colar:** Seleciona um bloco e prime Ctrl+C e Ctrl+V (no Mac ⌘C e ⌘V). A cópia fica depois do bloco selecionado. +- **Eliminar:** Seleciona um bloco e prime Del, ou clica no [caixote do lixo](#zeige-loeschen) „Eliminar seleção“ nas ferramentas. +- **Anular:** Ctrl+Z anula o último passo, Ctrl+Shift+Z refá-lo (no Mac ⌘Z e ⌘⇧Z). + +## Exercício: Olá Mundo + +::: übung l2-hallo +titel: Olá Mundo +auftrag: Constrói um estrutograma que mostre **Olá Mundo**. +Arrasta uma **Instrução** dos Elementos para o marcador **ø** e clica no bloco. No Inspetor de objetos, por baixo do estrutograma, há três botões em cima: Instrução, Entrada e Saída. Clica em **Saída**. Depois escreve \`"Olá Mundo"\` no campo de texto por baixo, com aspas. +test: - -> Olá Mundo +braucht: anweisung +tipp: Só precisas de um único bloco. O texto que deve aparecer vai para o campo de texto do Inspetor de objetos. +tipp: Atenção às aspas. Sem elas, o VisuStruct procura uma variável chamada Olá. +lösung: l2-hallo-loesung.visustruct +::: + +Clica em **Verificar** quando terminares. O VisuStruct executa o teu estrutograma e compara a saída. + +## Exercício: Duas linhas + +::: übung l2-zwei-zeilen +titel: Duas linhas +auftrag: Mostra primeiro **Olá** e depois **Estou a aprender estrutogramas**, cada um na sua linha. +test: - -> Olá | Estou a aprender estrutogramas +tipp: Duas linhas significa duas saídas. Os blocos ficam uns por cima dos outros e são executados de cima para baixo. +tipp: Cada saída é um bloco próprio. Arrasta a segunda Instrução para a metade de baixo da primeira. +lösung: l2-zwei-zeilen-loesung.visustruct +::: + +## Jogo: Profissional do editor + +::: spiel frage +titel: Jogo: Profissional do editor +intro: O Ludwig testa se dominas o editor. Sete rondas. + +runde: +frage: Arrastas uma instrução para o marcador **ø**. O que acontece? +- [x] A instrução substitui o marcador. +- A instrução fica depois do marcador. +- Nada, não se pode largar nada sobre ø. +> O marcador só guarda o lugar. O novo elemento ocupa-o. + +runde: +frage: Arrastas um elemento para a metade **de cima** de um bloco. Onde fica? +- [x] antes dele +- depois dele +- Substitui o bloco. +> Metade de cima quer dizer antes, metade de baixo quer dizer depois. A linha azul mostra-te enquanto arrastas. + +runde: +frage: Arrastas um elemento para a metade **de baixo** de um bloco. Onde fica? +- antes dele +- [x] depois dele +- no fim do estrutograma +> Metade de baixo quer dizer: logo a seguir a este bloco. + +runde: +frage: Apagaste um bloco sem querer. O que o traz de volta? +- Ctrl+C / ⌘C +- [x] Ctrl+Z / ⌘Z +- Ctrl+V / ⌘V +> Ctrl+Z / ⌘Z anula o último passo. Ctrl+C / ⌘C copia, Ctrl+V / ⌘V cola. + +runde: +frage: Ao executar deve aparecer exatamente **Olá**. O que está no bloco? +- [x] output: "Olá" +- output: Olá +- "Olá" +> Um texto que deve aparecer tal e qual fica entre aspas. O editor põe \`output:\` à frente quando escolhes o tipo Saída. + +runde: +frage: Onde alteras o texto do bloco selecionado? +- na área Elementos +- [x] no Inspetor de objetos +- na barra de ferramentas lá em cima +> O Inspetor de objetos por baixo do diagrama mostra o texto do bloco selecionado. + +runde: +frage: Clicas num elemento da área Elementos, sem arrastar. Onde fica? +- [x] depois do bloco selecionado +- no início +- no fim +> Sem arrastar (clique, ou Tab e Enter), o novo elemento fica depois do bloco que está selecionado nesse momento. +::: + +## 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. + +::: checkliste +- Consigo inserir um elemento da área Elementos e substituir um marcador. → Inserir um elemento +- Consigo alterar o texto de um bloco e mudar entre Instrução, Entrada e Saída. → Escrever texto +- Consigo mover, copiar e eliminar blocos e anular passos. → Mover, copiar, eliminar +::: + +## Teste de conhecimentos + +::: quiz +? O que significa o sinal ø num bloco? +→ Inserir um elemento +- [ ] O bloco contém um erro. +- [x] Aqui ainda há um marcador vazio. +- [ ] O programa termina aqui. +> Um marcador é substituído quando arrastas um elemento para cima dele. + +? Arrastas uma Instrução para a metade de baixo de um bloco. Onde é que ela fica? +→ Inserir um elemento +- [ ] Antes dele +- [x] Depois dele +- [ ] O bloco é substituído. + +? Como mostras o texto Bom dia exatamente como está? +→ Escrever texto +- [ ] output: Bom dia +- [x] output: "Bom dia" +- [ ] input: "Bom dia" +> Sem aspas, Bom dia é entendido como o nome de uma variável. +::: +`,V4=`--- +titel: Guardar, abrir, exportar +bereich: Primeiros passos +kurz: Guardar os teus ficheiros em segurança, usar o teu espaço de trabalho, abrir vários diagramas e partilhá-los como imagem ou PDF. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- dar um título a um diagrama +- guardar um diagrama como ficheiro .visustruct e voltar a abri-lo +- exportar um diagrama como imagem (PNG) ou PDF +- abrir um segundo diagrama num novo separador +- criar o meu espaço de trabalho \`VisuStruct-Ficheiros\` +- guardar um programa no meu espaço de trabalho +::: + +## O ficheiro .visustruct + +Os estrutogramas são guardados como ficheiros **.visustruct**. Todas as versões do VisuStruct usam o mesmo formato: no navegador, no Mac, iPad e iPhone, e a app Java no computador. Assim podes começar no navegador na escola e continuar na app em casa. + +::: angeberwissen +Quando Nassi era estudante, não havia ficheiros para guardar. Havia cartões perfurados. Nassi conta que um encontro ao sábado à noite era assim: a futura mulher dele sentava-se com ele no centro de computação e perfurava-lhe os cartões. Romance à moda da informática! +::: + +::: grafik l03-lochkarte.svg l03-lochkarte-beschriftet.svg +Era assim um cartão perfurado. Cada cartão tinha uma linha de programa, aqui \`PRINT *, 'OLA MUNDO'\` na linguagem Fortran. Cada coluna é um carácter, e os furos são o seu código. Um programa inteiro era uma pilha destes cartões. Se caísse ao chão, era preciso voltar a ordenar tudo. +::: + +## Guardar e abrir + +- **[Guardar](#zeige-speichern)** (Ctrl+S, no Mac ⌘S): O diagrama é guardado como ficheiro. Se a coluna **Ficheiros** estiver configurada (ver abaixo), fica lá. Caso contrário, o navegador pergunta onde o guardar ou põe o ficheiro na pasta de transferências. +- **[Abrir](#zeige-oeffnen)** (Ctrl+O, no Mac ⌘O): Voltar a carregar um ficheiro guardado. Também podes simplesmente arrastar um ficheiro para a janela do navegador. + +> O navegador memoriza os teus exercícios automaticamente. Mas isso só funciona neste navegador, neste dispositivo. Por isso, guarda sempre também os trabalhos importantes como ficheiro. + +## A coluna Ficheiros + +À esquerda da área de aprendizagem encontras a coluna [📁 Ficheiros](#zeige-dateien). Aí reúnes todos os teus programas num só sítio, o teu **espaço de trabalho**. + +**A tua vez:** Configura já o teu espaço de trabalho, antes de continuares a ler. A partir de hoje guardas lá todos os teus programas. + +1. Cria um espaço de trabalho: abre a coluna e clica em **Escolher pasta**. Na janela, vai aos teus **Documentos**, cria aí com **Nova pasta** uma pasta chamada \`VisuStruct-Ficheiros\` e seleciona-a. Permite que o VisuStruct use a pasta. Isto funciona no Chrome e no Edge. No iPad e noutros navegadores, clica antes em **Guardar no navegador**. +2. Guarda como de costume. No teu espaço de trabalho, o VisuStruct cria automaticamente uma pasta com a data de hoje, por exemplo \`2026-10-23\`, e guarda lá o programa. O nome do ficheiro vem do título. + +O teu espaço de trabalho fica assim: + +\`\`\`text +VisuStruct-Ficheiros ← espaço de trabalho +└── 2026-10-23 ← dia + └── Fatorial.visustruct +\`\`\` + +Um clique num programa da coluna volta a abri-lo. Assim encontras depressa cada aula mais tarde. + +Também o teu **progresso** fica no espaço de trabalho: o ficheiro \`learnProgress.json\` guarda as lições e os exercícios que já concluíste. Se abrires o espaço de trabalho noutro navegador, o teu progresso volta a estar lá. + +> Porquê uma pasta real? O teu progresso e os teus programas ficam lá guardados como ficheiros. Podes levar a pasta contigo, por exemplo numa pen USB ou na tua pasta na nuvem, como o OneDrive. Assim continuas em casa, noutro computador, exatamente onde paraste. Se guardares só no navegador, tudo fica apenas neste navegador, neste dispositivo. Se alguém apagar os dados do navegador, o teu progresso também desaparece. + +## Vários diagramas em separadores + +Por cima do estrutograma vês os [separadores](#zeige-reiter). Com **+** ou [Novo](#zeige-neu) abres mais um diagrama vazio. Um ponto • antes do nome mostra que há alterações não guardadas. + +O [título](#zeige-titel) de um diagrama escreve-se no campo por cima do estrutograma. Também aparece quando exportas e é sugerido como nome do ficheiro. + +## Partilhar: imagem, PDF ou ficheiro + +Com [Exportar](#zeige-exportieren) nas ferramentas (ícone com uma seta para cima) podes partilhar o teu estrutograma: + +- **Imagem (PNG):** para pôr numa ficha de trabalho ou numa apresentação +- **Gráfico vetorial (SVG):** fica nítido em qualquer tamanho +- **PDF (A4):** uma página para entregar ou imprimir +- **Ficheiro VisuStruct (.visustruct):** para passar a alguém que deva abrir e continuar a editar o teu estrutograma no VisuStruct, por exemplo por e-mail ou pela plataforma de aprendizagem +- **Imprimir** (Ctrl+P, no Mac ⌘P): diretamente para a impressora + +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. + +## Jogo: Como o partilhas? + +::: spiel frage +titel: Jogo: Como o partilhas? +intro: O Ludwig quer partilhar o seu estrutograma. Que formato serve melhor? Seis rondas. +frage: Que formato serve? +antworten: .visustruct | PNG | SVG | PDF + +runde: +frage: Amanhã queres continuar a trabalhar no teu estrutograma. +richtig: .visustruct +> Só o ficheiro .visustruct pode voltar a ser aberto e editado no VisuStruct. + +runde: +frage: O estrutograma deve entrar numa apresentação como imagem. +richtig: PNG +> Uma imagem PNG pode ser posta em qualquer apresentação e em qualquer ficha de trabalho. + +runde: +frage: O teu professor quer imprimir o teu trabalho numa página A4. +richtig: PDF +> O PDF é exatamente uma página A4 para entregar ou imprimir. + +runde: +frage: O estrutograma vai para um cartaz e deve ficar nítido mesmo em tamanho enorme. +richtig: SVG +> Um gráfico vetorial fica nítido em qualquer tamanho. Um PNG fica com pixéis quando o aumentas. + +runde: +frage: A tua amiga deve alterar o estrutograma na app VisuStruct do iPad dela. +richtig: .visustruct +> Todas as versões do VisuStruct abrem o mesmo ficheiro .visustruct: no browser, no Mac, no iPad e no iPhone. + +runde: +frage: Queres enviar depressa uma imagem para um chat. +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: + +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. + +::: checkliste +- Consigo dar um título a um diagrama. → Experimenta +- Consigo guardar um diagrama como ficheiro .visustruct e voltar a abri-lo. → Guardar e abrir +- Consigo exportar um diagrama como imagem (PNG) ou PDF. → Partilhar: imagem, PDF ou ficheiro +- Consigo abrir um segundo diagrama num novo separador. → Vários diagramas em separadores +- Consigo criar o meu espaço de trabalho \`VisuStruct-Ficheiros\`. → A coluna Ficheiros +- Consigo guardar um programa no meu espaço de trabalho. → A coluna Ficheiros +::: + +## Teste de conhecimentos + +::: quiz +? Que ficheiro podes voltar a abrir na app para Mac e na app Java? +→ Guardar e abrir +- [x] O ficheiro .visustruct +- [ ] A imagem PNG exportada +- [ ] O PDF exportado +> As imagens e os PDF servem só para ver. Só o ficheiro .visustruct pode continuar a ser editado. + +? O navegador memoriza os teus exercícios. Porque deves guardar mesmo assim? +→ Guardar e abrir +- [ ] Porque senão os exercícios não são verificados +- [x] Porque o navegador só guarda os dados neste dispositivo e eles podem perder-se +- [ ] Porque não se pode exportar sem guardar + +? Hoje guardas um programa no teu espaço de trabalho. Onde fica? +→ A coluna Ficheiros +- [ ] Na pasta de transferências +- [x] No espaço de trabalho, dentro de uma pasta com a data de hoje +- [ ] Diretamente no espaço de trabalho, sem subpasta +> O VisuStruct cria automaticamente uma pasta com a data de cada dia. Assim os programas ficam ordenados por aula. +::: +`,q4=`--- +titel: Variáveis e tipos de dados +bereich: Fundamentos +kurz: Guardar valores, conhecer os tipos de dados int, double, String e boolean, e fazer contas. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- criar uma variável com tipo de dados, nome e valor +- distinguir os tipos de dados int, double, String e boolean +- explicar que = é uma atribuição e não uma comparação +- fazer contas com + - * / % e usar a divisão inteira +- criar e mostrar variáveis em Java +::: + +## O que é uma variável? + +Uma **variável** é como uma caixa com etiqueta. Tem um **nome**, um **tipo de dados** e um **valor**. + +\`\`\` +int idade = 14 +\`\`\` + +Aqui a variável chama-se \`idade\`, o seu tipo de dados é \`int\` (número inteiro) e o seu valor é 14. Mais tarde podes voltar a usar o valor através do nome. + +::: grafik l04-variable.svg +A variável como caixa: o nome na etiqueta, o tipo de dados como autocolante, o valor lá dentro. +::: + +> Os nomes de variáveis começam por uma **letra minúscula** e não têm espaços. Bons nomes dizem o que está lá dentro: \`preco\` é melhor do que \`p\`. Evita acentos e cedilhas nos nomes: escreve \`preco\` e não \`preço\`. + +::: angeberwissen +Em setembro de 1999 perdeu-se a sonda Mars Climate Orbiter. Uma equipa calculava a força de impulso em unidades americanas (libras), a outra esperava unidades métricas (newtons). Nos dados só estava o número, não a unidade. A sonda voou demasiado baixo na atmosfera de Marte e ardeu, um prejuízo de cerca de 125 milhões de dólares. Um nome que diz o que guarda, como \`impulsoEmNewtonSegundos\`, teria evitado a confusão. Já agora, eu escrevo sempre \`fenoEmQuilos\` na minha caixa de feno. +::: + +Se um nome tiver várias palavras, escreves-as juntas e começas cada palavra seguinte com maiúscula: \`precoComIva\`, \`numeroDeAlunos\`. Esta forma de escrever chama-se **camelCase**. + +::: angeberwissen +O camelCase tem este nome porque as maiúsculas no meio saem da palavra como as bossas de um camelo: \`precoComIva\` tem duas bossas. Eu, como bode, tenho zero bossas, mas dois chifres. Infelizmente ainda ninguém inventou a escrita BodeCase. +::: + +::: grafik l04-camelcase.svg +As maiúsculas C e I sobressaem como as duas bossas do camelo. +::: + +## Os quatro tipos de dados + +O tipo de dados diz que tipo de valor pode ser guardado na variável. + +- **int:** números inteiros, p. ex. \`int quantidade = 3\` ou \`int temperatura = -5\` +- **double:** números decimais, p. ex. \`double preco = 2.5\`. Escreves um **ponto**, nunca uma vírgula. +- **String:** texto, p. ex. \`String nome = "Inês"\`. O texto fica entre aspas. +- **boolean:** valores lógicos, só \`true\` ou \`false\` + +Há mais tipos de dados. Um deles vais precisar em breve: \`char\` para um **único caractere**, p. ex. \`char nota = 'C'\`. Um \`char\` fica entre aspas **simples**. Vais conhecê-lo melhor na lição 17. + +::: diagramm l05-datentypen.visustruct +Três variáveis com tipos de dados diferentes. Abre o diagrama e inicia a simulação. +::: + +Os valores lógicos aparecem sobretudo em **condições**: \`idade >= 18\` é \`true\` ou \`false\`. É disso que trata a lição 8. Uma variável do tipo \`boolean\` recebe simplesmente \`true\` ou \`false\`: + +\`\`\` +boolean adulto = false +\`\`\` + +::: angeberwissen +A 4 de junho de 1996, o foguetão Ariane 5 explodiu apenas 37 segundos depois da descolagem. A culpa foi de uma única linha: um número decimal para a velocidade foi metido numa variável inteira demasiado pequena para valores tão grandes. O tipo de dados não é um pormenor, pode custar meio milhar de milhões de euros. +::: + +## Atribuição com = + +O sinal \`=\` chama-se **atribuição**. Não quer dizer “é igual a” como na matemática. Quer dizer: calcula o lado direito e guarda o resultado na variável da esquerda. + +\`\`\` +int pontos = 10 +pontos = pontos + 5 +\`\`\` + +Na matemática, a segunda linha estaria errada, porque nenhum número é igual a si próprio mais 5. Na programação lê-se assim: pega no valor antigo 10, soma 5 e guarda 15 em \`pontos\`. O tipo de dados só se escreve da primeira vez, quando a variável é criada. + +::: grafik l04-zuweisung.svg +Primeiro calcula-se o lado direito, depois o resultado vai para a variável da esquerda. +::: + +## Fazer contas + +Podes fazer contas com números: + +- \`+\` mais, \`-\` menos, \`*\` vezes, \`/\` a dividir por +- \`%\` resto de uma divisão (diz-se “módulo”), p. ex. \`17 % 5\` dá 2 + +A **divisão com resto** conheces da escola primária, quando ainda não sabias números decimais: 17 : 5 = 3 e sobram 2. O 5 cabe três vezes no 17, o que dá 15. Até 17 faltam ainda 2: esse é o resto. O computador calcula com números inteiros exatamente assim: \`/\` dá o resultado sem o resto, \`%\` dá só o resto. + +| Escola primária | com \`/\` | com \`%\` | +|---|---|---| +| 17 : 5 = 3, resto 2 | \`17 / 5\` dá 3 | \`17 % 5\` dá 2 | +| 20 : 5 = 4, resto 0 | \`20 / 5\` dá 4 | \`20 % 5\` dá 0 | +| 3 : 5 = 0, resto 3 | \`3 / 5\` dá 0 | \`3 % 5\` dá 3 | + +Se o resto for 0, a divisão é exata. Mais tarde usas isto para ver se um número é par: nos números pares, \`numero % 2\` dá 0. + +**A multiplicação e a divisão vêm antes da adição e da subtração**, e os parênteses calculam-se primeiro: \`2 * (3 + 4)\` dá 14. + +## Exercício: Retângulo + +::: übung l05-rechteck +titel: Calcular um retângulo +auftrag: Um retângulo tem 7 de comprimento e 4 de largura. Cria as variáveis \`comprimento\` e \`largura\`. Calcula a área e o perímetro em variáveis próprias e mostra os dois assim: +\`Área: 28\` e na linha seguinte \`Perímetro: 22\`. +test: - -> Área: 28 | Perímetro: 22 +braucht: anweisung +tipp: Pensa primeiro de que variáveis precisas: duas para as medidas e duas para os resultados. São todas números inteiros. +tipp: A área é o comprimento vezes a largura, o perímetro é 2 vezes (comprimento mais largura). Para a saída escreves p. ex. \`output: "Área: " + area\`. O \`+\` junta o texto e o valor da variável. +lösung: l05-rechteck-loesung.visustruct +::: + +## Divisão inteira + +Se dividires dois números inteiros e guardares o resultado numa variável \`int\`, tudo o que vem depois da vírgula desaparece. **Não é arredondado.** + +\`\`\` +int x = 7 / 2 dá 3 +int r = 7 % 2 dá 1 (o resto) +double d = 7.0 / 2 dá 3.5 +\`\`\` + +Com \`/\` e \`%\` juntos podes fazer boas conversões, por exemplo de minutos para horas e minutos: + +::: diagramm l05-division.visustruct +135 minutos são 2 horas (135 / 60) e sobram 15 minutos (135 % 60). +::: + +## Exercício: Converter segundos + +::: übung l05-sekunden +titel: Converter segundos +auftrag: 200 segundos devem ser mostrados em minutos e segundos. A primeira e a última instrução já lá estão. Insere entre elas instruções que calculem \`minutos\` e \`resto\`. +start: l05-sekunden-start.visustruct +test: - -> 3 minutos e 20 segundos +braucht: anweisung +tipp: Quantos minutos inteiros cabem em 200 segundos, e quantos segundos sobram? Calcula primeiro de cabeça. +tipp: Um minuto tem 60 segundos. Usa \`/\` para os minutos inteiros e \`%\` para o resto. As duas variáveis são do tipo \`int\`. +lösung: l05-sekunden-loesung.visustruct +::: + +## Exercício: Compras + +::: übung l05-einkauf +titel: Compras +auftrag: Compras 3 cadernos a 2.5 euros cada. Cria \`quantidade\` como \`int\` e \`preco\` como \`double\`, calcula o preço total numa variável \`precoTotal\` e mostra \`Total: 7.5 euros\`. +test: - -> Total: 7.5 euros +braucht: anweisung +tipp: A quantidade vezes o preço dá o preço total. Para cada variável, pensa se é um número inteiro ou um número decimal. +tipp: O preço total é um número decimal, por isso \`precoTotal\` precisa do tipo \`double\`. +lösung: l05-einkauf-loesung.visustruct +::: + +## Agora em Java + +Um estrutograma é um plano. Em **Java** torna-se um programa que o computador executa. As tuas compras do exercício ficam assim: + +\`\`\`java +int quantidade = 3; +double preco = 2.5; +double precoTotal = quantidade * preco; +System.out.println("Total: " + precoTotal + " euros"); +\`\`\` + +- Primeiro o tipo de dados, depois o nome, depois o valor, tal como no bloco. +- Cada instrução termina com um **ponto e vírgula** \`;\`. +- Em Java, uma saída escreve-se \`System.out.println(…)\`. + +::: angeberwissen +O Java chamava-se primeiro **Oak** (carvalho), por causa da árvore em frente à janela do escritório de James Gosling. A partir de 1991, a sua equipa na Sun Microsystems queria programar pequenos aparelhos, como boxes de televisão. Mas o nome Oak já pertencia a outra empresa. Assim, em 1995 passou a chamar-se **Java**, como o café da ilha de Java. É por isso que o logótipo é uma chávena a fumegar. +::: + +## Texto em Java + +As variáveis não guardam só números. Para texto existe o tipo de dados \`String\`: + +\`\`\`java editor +String nome = "Inês"; +int idade = 14; +double altura = 1.62; +System.out.println(nome + " tem " + idade + " anos."); +System.out.println("Altura: " + altura + " m"); +\`\`\` + +- O texto fica entre aspas. +- \`String\` escreve-se com maiúscula, \`int\`, \`double\` e \`boolean\` com minúscula. O Java distingue-os. +- Com \`+\` juntas texto e números. + +Escreves Java na área [Código](#zeige-codelive). O estrutograma constrói-se sozinho enquanto escreves. “Abrir no editor” leva o exemplo para a área Código. Clica aí em “Executar”, depois muda o nome, a idade ou a altura e experimenta outra vez. + +::: übung l04-java-steckbrief +titel: Ficha em Java +code: java +auftrag: Escreve a ficha do Ludwig, o bode. Cria três variáveis: o nome **Ludwig**, a idade **7** e a altura **1.2**. Depois mostra estas duas linhas: + **Ludwig tem 7 anos.** e **Altura: 1.2 m** + “Abrir no editor” abre também a área Código à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. +test: - -> Ludwig tem 7 anos. | Altura: 1.2 m +braucht: anweisung +tipp: Precisas de uma \`String\`, um \`int\` e um \`double\`. Cada linha termina com ponto e vírgula. +tipp: \`String nome = "Ludwig";\`, \`int idade = 7;\` e \`double altura = 1.2;\`. Juntas a saída com \`+\`: \`System.out.println(nome + " tem " + idade + " anos.");\` +lösung: l04-java-steckbrief-loesung.visustruct +::: + +## Preenche os espaços: tipos de dados + +::: lückentext +titel: Ficha em Java +auftrag: Preenche as palavras que faltam. Por fora está a moldura de que qualquer programa Java precisa num ficheiro próprio. As variáveis ficam lá dentro. +\`\`\`java +[[public]] class Ficha { + public static [[void]] main(String[] args) { + [[int]] idade = 14; + [[double]] altura = 1.62; + [[String]] nome = "Mia"; + [[boolean]] temAnimal = true; + System.out.[[println]](nome + " tem " + idade + " anos."); + } +} +\`\`\` +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”. +::: + +## Encontra o erro: segundos + +::: übung l04-java-fehler +titel: Corrigir os segundos +code: java +auftrag: O programa deve converter 200 segundos em minutos e segundos e mostrar **3 min 20 s**. Mas mostra **20 min 3 s**. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l04-java-fehler-start.visustruct +test: - -> 3 min 20 s +braucht: anweisung +tipp: \`/\` divide sem resto, \`%\` dá o resto. Qual dos dois precisas para os minutos e qual para os segundos que sobram? +tipp: Os dois operadores estão trocados: \`int minutos = segundos / 60;\` e \`int resto = segundos % 60;\` +lösung: l04-java-fehler-loesung.visustruct +::: + +## Jogo: Que tipo de dados? + +::: spiel frage +titel: Jogo: Que tipo de dados? +intro: O Ludwig juntou valores. Que tipo de dados serve para cada valor? Oito rondas. +antworten: int | double | String | boolean + +runde: +frage: Que tipo de dados serve para \`17\`? +richtig: int +> Um número inteiro sem ponto decimal é um \`int\`. + +runde: +frage: Que tipo de dados serve para \`3.5\`? +richtig: double +> Números com ponto decimal são \`double\`. + +runde: +frage: Que tipo de dados serve para \`"Olá"\`? +richtig: String +> Texto entre aspas é uma \`String\`. + +runde: +frage: Que tipo de dados serve para \`true\`? +richtig: boolean +> \`true\` e \`false\` são os dois valores lógicos, tipo de dados \`boolean\`. + +runde: +frage: Que tipo de dados serve para \`"17"\`? +richtig: String +> Atenção às aspas! Aqui 17 é um texto com o qual não se pode calcular. + +runde: +frage: Que tipo de dados serve para \`-4\`? +richtig: int +> Os números inteiros negativos também são \`int\`. + +runde: +frage: Que tipo de dados serve para \`0.0\`? +richtig: double +> O ponto torna-o um número decimal, mesmo que a seguir só esteja um 0. + +runde: +frage: Que tipo de dados serve para \`"false"\`? +richtig: String +> Entre aspas, false também é só um texto. O valor lógico não tem aspas. +::: + +## 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. + +::: checkliste +- Consigo criar uma variável com tipo de dados, nome e valor. → O que é uma variável? +- Consigo distinguir os tipos de dados int, double, String e boolean. → Os quatro tipos de dados +- Consigo explicar que = é uma atribuição e não uma comparação. → Atribuição com = +- Consigo fazer contas com + - * / % e usar a divisão inteira. → Fazer contas +- Consigo criar e mostrar variáveis em Java. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? Que tipo de dados serve para o valor 3.75? +→ Os quatro tipos de dados +- [ ] int +- [x] double +- [ ] String +- [ ] boolean +> Os números decimais são do tipo double. No VisuStruct escrevem-se com ponto. + +? Que valor tem x depois de \`int x = 17 / 5\`? +→ Fazer contas +- [ ] 3.4 +- [x] 3 +- [ ] 4 +> Com números inteiros, tudo o que vem depois da vírgula desaparece. Não é arredondado. + +? Quanto dá \`17 % 5\`? +→ Fazer contas +- [x] 2 +- [ ] 3 +- [ ] 3.4 +> 17 a dividir por 5 dá 3, resto 2. O operador % dá o resto. + +? No início, \`int pontos = 10\`. O que fica em pontos depois de \`pontos = pontos * 2\`? +→ Atribuição com = +- [ ] 10 +- [ ] 12 +- [x] 20 +> O lado direito é calculado com o valor antigo 10, e o resultado 20 é guardado em pontos. + +? Que linha cria corretamente um número decimal em Java? +→ Agora em Java +- [ ] double preco = 2,5; +- [x] double preco = 2.5; +- [ ] Double preco = 2.5 +> Os números decimais escrevem-se com ponto, e no fim há um ponto e vírgula. +::: +`,Q4=`--- +titel: Sequência +bereich: Fundamentos +kurz: Executar passos um a seguir ao outro, prestar atenção à ordem e trocar valores. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar que uma sequência é executada de cima para baixo +- explicar porque é que a ordem dos passos conta +- trocar dois valores com uma variável auxiliar +- escrever uma sequência em Java +::: + +## Passo a passo + +Uma **sequência** é uma série de passos que são executados exatamente uma vez e exatamente por esta ordem. No estrutograma, os blocos ficam simplesmente uns por cima dos outros. + +Cada bloco só começa quando o bloco de cima terminou. Nada é saltado e nada é repetido. + +::: diagramm l05-sequenz.visustruct +Uma sequência de quatro blocos: primeiro \`comprimento\` e \`largura\` recebem os seus valores, depois a área é calculada e, no fim, é apresentada. Cada bloco é executado exatamente uma vez, de cima para baixo. Saída: 15. +::: + +> A sequência é o mais simples dos três blocos básicos. Quase todos os estrutogramas são feitos sobretudo de sequências. + +## A ordem conta + +Quando fazes chá, notas logo se a ordem estiver errada. Com contas é igual, só que é mais difícil de ver. + +::: diagramm l04-rechnen.visustruct +Primeiro duplicar, depois somar 1: o resultado é 7. Se trocares os dois blocos do meio, dá 8. +::: + +A instrução \`numero = numero * 2\` quer dizer: pega no valor de \`numero\`, multiplica-o por 2 e volta a guardar o resultado em \`numero\`. Por isso, o que está em \`numero\` depende do que aconteceu antes. + +::: angeberwissen +Os estrutogramas não são só coisa da escola. Segundo Shneiderman, empresas como a IBM e a Siemens também planeavam os seus programas com eles. Ou seja, aqui estás a aprender coisas de profissionais. Mééé-ravilha! +::: + +## Exercício: Pôr por ordem + +::: übung l04-reihenfolge +titel: Pôr por ordem +auftrag: O diagrama inicial tem os blocos certos, mas pela ordem errada. Move-os de modo que no fim seja mostrado **20**. +start: l04-reihenfolge-start.visustruct +test: - -> 20 +braucht: anweisung +tipp: Lê cada bloco e pergunta-te: de que variável precisa, e onde é que essa variável recebe o seu valor? +tipp: Uma variável tem de ser criada antes de fazeres contas com ela. A saída vem mesmo no fim. Confirma de cabeça: (2 + 3) · 4 = 20. +lösung: l04-reihenfolge-loesung.visustruct +::: + +## Trocar dois valores + +Imagina dois copos: um com sumo, outro com água. Se quiseres trocar o que está lá dentro, precisas de um terceiro copo, vazio. + +Com variáveis é exatamente igual. Se escreveres simplesmente \`a = b\` e depois \`b = a\`, o valor antigo de \`a\` já se perdeu. No fim, as duas variáveis têm o mesmo valor. + +A solução é uma **variável auxiliar** que guarda o valor antigo durante pouco tempo: + +::: grafik l05-tauschen.svg +Três passos com um copo vazio: primeiro o sumo para aux, depois a água para a esquerda, depois o sumo de aux para a direita. +::: + +::: diagramm l04-tauschen.visustruct +Primeiro guarda-se a em aux. Depois a recebe o valor de b, e b recebe o valor guardado em aux. +::: + +## Exercício: Trocar copos + +::: übung l04-glaeser-tauschen +titel: Trocar copos +auftrag: O copo da esquerda tem sumo, o da direita tem água. Troca o conteúdo das variáveis \`esquerda\` e \`direita\` antes de serem mostradas. +Não alteres os dois primeiros blocos. Insere novas instruções entre eles. +start: l04-tauschen-start.visustruct +test: - -> Esquerda: água | Direita: sumo +braucht: anweisung +tipp: Como trocas dois copos cheios na vida real? Precisas de um terceiro copo, vazio. +tipp: Cria uma variável auxiliar com \`String aux = esquerda\`. Depois disso precisas de mais duas atribuições. +lösung: l04-tauschen-loesung.visustruct +::: + +## Agora em Java + +Tal como na lição 4, também podes escrever uma sequência diretamente em Java. A troca de cima fica assim: + +\`\`\`java +int a = 5; +int b = 9; +int aux = a; +a = b; +b = aux; +System.out.println("a = " + a); +System.out.println("b = " + b); +\`\`\` + +- Cada bloco passa a ser uma linha. As linhas correm de cima para baixo, tal como os blocos. +- No fim de cada instrução há um **ponto e vírgula** \`;\`. +- Uma saída chama-se \`System.out.println(…)\` em Java. Atenção ao S maiúsculo de \`System\`: o Java distingue maiúsculas de minúsculas. + +Escreves Java na área [Código](#zeige-codelive), à direita do estrutograma. Enquanto escreves, o VisuStruct constrói o estrutograma ao mesmo tempo. Assim vês logo que bloco pertence a que linha. + +::: übung l05-java-kino +titel: Bilhetes de cinema em Java +code: java +auftrag: Um bilhete de cinema custa 9 euros. Escreve um programa em Java que calcula o preço de 3 bilhetes e mostra **Total: 27**. + “Abrir no editor” abre também a área Código à direita. Escreve lá o teu código; o estrutograma constrói-se sozinho. Depois clica em Verificar. +test: - -> Total: 27 +braucht: anweisung +tipp: Precisas de três variáveis: o preço, a quantidade e o resultado. Cada linha termina com ponto e vírgula. +tipp: \`int preco = 9;\` e \`int quantidade = 3;\` criam as variáveis. \`int total = preco * quantidade;\` calcula, e \`System.out.println("Total: " + total);\` mostra o resultado. +lösung: l05-java-kino-loesung.visustruct +::: + +## Preenche os espaços: trocar os copos + +::: lückentext +titel: Trocar dois valores +auftrag: Os valores de \`a\` e \`b\` devem ser trocados. Preenche as palavras que faltam. +\`\`\`java +int a = 3; +int b = 8; +[[int]] aux = [[a]]; +a = [[b]]; +b = [[aux]]; +System.out.println("a = " + a + ", b = " + b); +\`\`\` +erklärung: Primeiro guardas \`a\` na variável auxiliar, depois \`a\` recebe o valor de \`b\` e, por fim, \`b\` recebe o valor guardado. Saída: **a = 8, b = 3** +::: + +## Encontra o erro: saldo + +::: übung l05-java-fehler +titel: Corrigir o saldo +code: java +auftrag: O cartão da cantina tem 20 euros. Uma refeição custa 7 euros. O programa deve mostrar o saldo **depois** de pagar, ou seja, **Resta: 13**. Mas mostra **Resta: 20**. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l05-java-fehler-start.visustruct +test: - -> Resta: 13 +braucht: anweisung +tipp: Todas as linhas estão certas, só a ordem não. Quando é mostrado o saldo e quando se paga? +tipp: Troca as duas últimas linhas: primeiro \`saldo = saldo - preco;\`, depois a saída. +lösung: l05-java-fehler-loesung.visustruct +::: + +## Jogo: Ordenar os blocos + +::: spiel reihenfolge +titel: Jogo: Ordenar os blocos +intro: O Ludwig baralhou os blocos. Põe-nos pela ordem certa. Quatro rondas. + +runde: +frage: No fim deve aparecer **7**. +- \`int numero = 3\` +- \`numero = numero * 2\` +- \`numero = numero + 1\` +- \`output: numero\` +> Primeiro duplicar, depois somar 1: 3 · 2 + 1 = 7. Ao contrário dava (3 + 1) · 2 = 8. + +runde: +frage: No fim deve aparecer **8**. +- \`int numero = 3\` +- \`numero = numero + 1\` +- \`numero = numero * 2\` +- \`output: numero\` +> Os mesmos blocos, outra ordem, outro resultado: (3 + 1) · 2 = 8. + +runde: + int a = 3 + int b = 5 +frage: a e b devem trocar os seus valores. +- \`int aux = a\` +- \`a = b\` +- \`b = aux\` +- \`output: a + " " + b\` +> Primeiro guarda-se a em aux. Senão o valor antigo perde-se assim que a recebe o valor de b. + +runde: +frage: O Ludwig faz chá. +- Encher a chaleira com água +- Ligar a chaleira +- Esperar até a água ferver +- Deitar a água sobre o saquinho de chá +- Deixar o chá em infusão +> Cada passo precisa do anterior. Tal como num estrutograma. +::: + +## 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. + +::: checkliste +- Consigo explicar que uma sequência é executada de cima para baixo. → Passo a passo +- Consigo explicar porque é que a ordem dos passos conta. → A ordem conta +- Consigo trocar dois valores com uma variável auxiliar. → Trocar dois valores +- Consigo escrever uma sequência em Java. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? Quantas vezes é executado cada bloco de uma sequência? +→ Passo a passo +- [ ] Até uma condição ser falsa +- [x] Exatamente uma vez +- [ ] Nenhuma, se estiver vazio +> Numa sequência nada é repetido e nada é saltado. Para repetir existem os ciclos. + +? No início a = 5 e b = 9. Depois é executado \`a = b\` e a seguir \`b = a\`. O que está nas variáveis no fim? +→ Trocar dois valores +- [ ] a = 9 e b = 5 +- [x] a = 9 e b = 9 +- [ ] a = 5 e b = 5 +> Depois de \`a = b\`, o valor antigo 5 perdeu-se. \`b = a\` só copia o 9 de volta. + +? Porque precisas de uma variável auxiliar para trocar valores? +→ Trocar dois valores +- [x] Para um valor não ser escrito por cima antes de ser preciso +- [ ] Para o estrutograma ficar mais comprido +- [ ] Porque senão não se podem mostrar variáveis + +? O que mostra a sequência \`int x = 4\`, \`x = x + 1\`, \`x = x * 3\`, \`output: x\`? +→ A ordem conta +- [ ] 13 +- [x] 15 +- [ ] 4 +> Primeiro x passa a 5, depois a 15. + +? Com que termina cada instrução em Java? +→ Agora em Java +- [ ] Com um ponto . +- [x] Com um ponto e vírgula ; +- [ ] Com dois pontos : +> Se faltar o ponto e vírgula, o VisuStruct mostra uma indicação por baixo do código. +::: +`,U4=`--- +titel: Entrada e saída +bereich: Fundamentos +kurz: Pedir valores, mostrar resultados e usar o modelo EPS. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar o modelo EPS +- escrever uma entrada com tipo de dados, nome e pergunta +- juntar texto e variáveis numa saída com + +- calcular primeiro um resultado e guardá-lo numa variável, depois mostrar essa variável, p. ex. \`int soma = a + b\`, depois \`output: soma\` +- identificar a entrada, o processamento e a saída numa tarefa +- ler números em Java com o scanner +- escrever comentários com \`//\` e \`/* */\` e usá-los para organizar e explicar o meu código +::: + +## O modelo EPS + +Muitos programas funcionam em três partes: + +1. **Entrada:** O programa pede valores, p. ex. dois números. +2. **Processamento:** Faz contas com os valores. +3. **Saída:** Mostra o resultado. + +As primeiras letras dão **EPS**. Até agora, os valores estavam fixos no estrutograma. Com uma entrada, pode ser usado um valor diferente de cada vez que o estrutograma é executado. + +::: diagramm l06-eva.visustruct +Entrada em cima, processamento ao meio, saída em baixo. Inicia a simulação e experimenta números diferentes. +::: + +## Entrada com input: + +Uma entrada pede um valor enquanto o estrutograma é executado e guarda-o numa variável. Escreves o **tipo de dados**, o **nome** e uma **pergunta** entre aspas: + +\`\`\` +input: int idade "Quantos anos tens?" +input: double preco "Preço em euros?" +input: String nome "Como te chamas?" +\`\`\` + +No editor escolhes o tipo **Entrada** em cima, numa Instrução. A palavra \`input:\` já fica à frente, e só escreves \`int idade "Quantos anos tens?"\`. + +> O tipo de dados decide o que pode ser introduzido. Com \`int\`, a simulação dá erro se alguém escrever 2.5 ou Olá. + +## Saída com output: + +Uma saída mostra texto e valores. O texto fica entre aspas, as variáveis não. Com \`+\` **juntas** as partes: + +\`\`\` +output: "Olá " + nome + "!" +output: "Tens " + idade + " anos." +\`\`\` + +Atenção aos espaços dentro das aspas. Sem eles fica tudo colado, e vês \`OláInês!\` em vez de \`Olá Inês!\`. + +## Exercício: Cumprimento + +::: übung l06-begruessung +titel: Cumprimento +auftrag: Pede um nome e cumprimenta a pessoa. Quando se escreve Ada, deve ser mostrado **Olá Ada!**. +test: Ada -> Olá Ada! +test: Rui -> Olá Rui! +braucht: anweisung +tipp: Primeiro vem uma entrada para o nome, depois uma saída que usa o nome. +tipp: O nome é texto, por isso a entrada precisa do tipo \`String\`. Na saída juntas \`"Olá "\`, a variável e \`"!"\` com \`+\`. +lösung: l06-begruessung-loesung.visustruct +::: + +## Cuidado com o + numa saída + +Numa saída, o \`+\` junta **sempre** as partes, mesmo com números. Se \`a\` for 3 e \`b\` for 4, então + +\`\`\` +output: a + b +\`\`\` + +não mostra 7, mas **34**. Por isso calcula primeiro numa variável e depois mostra a variável: + +\`\`\` +int soma = a + b +output: "Soma: " + soma +\`\`\` + +Isso também encaixa no modelo EPS: calculas na parte do processamento, não na saída. + +## Da tarefa ao estrutograma + +Antes de arrastares o primeiro bloco, lê a tarefa com atenção e desmonta-a. A isto chama-se **análise do problema**. Três perguntas ajudam-te: + +1. **O que é dado?** Esses valores tornam-se a **entrada**. Pensa também no tipo de dados. +2. **O que procuras?** Isso torna-se a **saída**. +3. **Como chegas do que é dado ao que procuras?** Isso é o **processamento**, muitas vezes uma fórmula. + +Um exemplo: *Um bilhete de cinema custa 9 euros. O programa pergunta quantos bilhetes alguém compra e mostra o preço total.* + +- Dado: o número de bilhetes → \`input: int quantidade "Quantos bilhetes?"\` +- Procurado: o preço total → \`output: "Preço total: " + total\` +- Caminho: quantidade vezes 9 → \`int total = quantidade * 9\` + +Agora só tens de pôr as três partes umas por cima das outras, pela ordem E, P, S. + +> Procura palavras-sinal na tarefa: *pergunta*, *lê* ou *introduz* apontam para uma entrada. *Mostra*, *escreve* ou *indica* apontam para uma saída. + +## Exercício: Calculadora + +::: übung l06-rechner +titel: Soma e produto +auftrag: Pede dois números inteiros. Depois mostra a soma e o produto deles, cada um na sua linha. +Com 3 e 4 fica assim: \`Soma: 7\` e \`Produto: 12\`. +test: 3, 4 -> Soma: 7 | Produto: 12 +test: 10, -2 -> Soma: 8 | Produto: -20 +test: 0, 5 -> Soma: 5 | Produto: 0 +braucht: anweisung +tipp: Planeia a ordem: primeiro ler os dois números, depois calcular, depois mostrar. +tipp: Precisas de duas entradas, duas instruções para calcular e duas saídas. Calcula a soma numa variável própria, senão o \`+\` junta os números. +lösung: l06-rechner-loesung.visustruct +::: + +## Exercício: Média + +::: übung l06-mittelwert +titel: Média +auftrag: Pede dois números, que também podem ser números decimais. Mostra a média deles, ou seja, para 2 e 3 é \`Média: 2.5\`. +test: 2, 3 -> Média: 2.5 +test: 4, 6 -> Média: 5.0 +test: 1.5, 2 -> Média: 1.75 +braucht: anweisung +tipp: A média de dois números obtém-se somando-os e dividindo o resultado ao meio. +tipp: Para números decimais usas o tipo \`double\`. A média é a soma a dividir por 2. Não te esqueças dos parênteses: \`(x + y) / 2\`. +lösung: l06-mittelwert-loesung.visustruct +::: + +## Agora em Java + +O exemplo EPS do início fica assim em Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Primeiro número?"); +int a = scanner.nextInt(); +System.out.println("Segundo número?"); +int b = scanner.nextInt(); +int soma = a + b; +System.out.println("Soma: " + soma); +\`\`\` + +- Para entradas, o Java precisa de um **Scanner**. Escreves as duas primeiras linhas uma vez lá em cima e depois podes ler quantas vezes quiseres. +- \`scanner.nextInt()\` lê um número inteiro, \`scanner.nextDouble()\` um número decimal e \`scanner.next()\` uma palavra. +- A pergunta ao utilizador é uma saída normal logo antes. O VisuStruct junta as duas linhas num bloco de entrada. + +::: angeberwissen +O Java foi pensado para controlar pequenos aparelhos, e ainda o faz: em muitos cartões SIM de telemóvel e cartões bancários corre uma mini versão chamada **Java Card**. É bem possível que tenhas Java no bolso neste momento. +::: + +::: übung l06-java-tage +titel: Idade em dias +code: java +auftrag: Escreve um programa em Java que pergunta a idade em anos e mostra quantos dias são, mais ou menos. Conta 365 dias por ano. Para 2 anos aparece **São cerca de 730 dias.** +test: 2 -> São cerca de 730 dias. +test: 10 -> São cerca de 3650 dias. +test: 1 -> São cerca de 365 dias. +braucht: anweisung +tipp: Primeiro as duas linhas do scanner, depois a pergunta e a entrada, depois o cálculo, depois a saída. +tipp: \`int anos = scanner.nextInt();\` lê. \`int dias = anos * 365;\` calcula, e \`System.out.println("São cerca de " + dias + " dias.");\` mostra. +lösung: l06-java-tage-loesung.visustruct +::: + +## Comentários no código + +Podes escrever notas no teu código. Chamam-se **comentários** (em inglês *comments*). O Java salta-os ao executar, por isso o programa e o estrutograma ficam iguais. Há dois tipos: + +- \`//\` transforma o resto da linha num comentário. É um **comentário de uma linha**. +- \`/*\` começa um **comentário de várias linhas** e \`*/\` termina-o. Tudo o que está entre os dois faz parte do comentário, seja quantas linhas forem. O Java não precisa dos asteriscos no início das linhas do meio, só ficam arrumados. + +Em programas acabados às vezes também vês \`/** … */\` com dois asteriscos no início. É um **comentário Javadoc**, a partir do qual o Java consegue criar uma descrição do programa. Para ti, chegam \`//\` e \`/* */\`. + +O exemplo EPS com comentários fica assim: + +\`\`\`java editor +/* + * Tarefa: O programa pede dois números + * e mostra a sua soma. + */ +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +// Entrada +System.out.println("Primeiro número?"); +int a = scanner.nextInt(); +System.out.println("Segundo número?"); +int b = scanner.nextInt(); + +// Processamento +int soma = a + b; // somar os dois números + +// Saída +System.out.println("Soma: " + soma); // com 3 e 4 espero: Soma: 7 + +// Da próxima vez: permitir também números decimais +\`\`\` + +Para que servem os comentários: + +- **A tarefa:** o comentário de várias linhas lá em cima diz o que o programa deve fazer. +- **Organização:** \`// Entrada\`, \`// Processamento\` e \`// Saída\` dividem o código segundo o modelo EPS. +- **Explicação:** um comentário depois de uma linha diz o que o teu algoritmo faz ali. +- **Expectativa:** escreve que saída esperas. Ao testar, comparas. +- **Associar chavetas:** mais tarde vais ter blocos entre chavetas \`{ }\`. Aí, p. ex. \`} // fim do for\` mostra que chaveta fecha o quê. +- **Guardar ideias:** de que te tens de lembrar quando continuares da próxima vez? + +Clica em **Abrir no editor**, muda um comentário ou acrescenta um novo. O estrutograma fica igual e o VisuStruct guarda os teus comentários. + +> Não escrevas um comentário depois de cada linha. Explica o que o teu algoritmo faz e porquê, não cada carácter. + +::: angeberwissen +Os dois tipos são muito mais antigos do que o Java: \`/* … */\` vem da linguagem PL/I, de 1964, e \`//\` da BCPL, de 1967. O Java herdou-os através do C e do C++. +::: + +## Preenche os espaços: comentários + +::: lückentext +titel: Completar os comentários +auftrag: Completa os caracteres para que lá em cima fique um comentário de várias linhas com a tarefa e as outras duas notas sejam comentários de uma linha. +\`\`\`java +[[/*]] + * Tarefa: O programa converte euros em cêntimos. + [[*/]] +int euros = 3; +[[//]] Processamento +int centimos = euros * 100; +[[//]] Saída, esperado: 300 +System.out.println(centimos); +\`\`\` +erklärung: \`/*\` abre o comentário de várias linhas e \`*/\` fecha-o. \`//\` só vale até ao fim da linha, por isso cada nota precisa do seu próprio \`//\`. +::: + +## Preenche os espaços: entrada + +::: lückentext +titel: Ler um nome e uma idade +auftrag: Preenche as palavras que faltam para que o programa leia um nome e uma idade. +\`\`\`java +import java.util.[[Scanner]]; +Scanner scanner = [[new]] Scanner(System.[[in]]); + +System.out.println("Como te chamas?"); +[[String]] nome = scanner.[[next]](); +System.out.println("Que idade tens?"); +int idade = scanner.[[nextInt]](); +System.out.println("Olá " + nome + ", para o ano vais ter " + [[(idade + 1)]] + " anos."); +\`\`\` +erklärung: \`scanner.next()\` lê uma palavra, \`scanner.nextInt()\` um número inteiro. Os parênteses à volta de \`idade + 1\` são importantes: sem eles, o Java junta primeiro \`idade\` e depois \`1\` ao texto, e 14 passaria a **141**. +::: + +## Encontra o erro: soma + +::: übung l06-java-fehler +titel: Corrigir a soma +code: java +auftrag: O programa lê dois números e deve mostrar a soma. Mas com 3 e 4 aparece **Soma: 34** em vez de **Soma: 7**. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l06-java-fehler-start.visustruct +test: 3, 4 -> Soma: 7 +test: 10, 5 -> Soma: 15 +test: 0, 9 -> Soma: 9 +braucht: anweisung +tipp: Lê a saída da esquerda para a direita: o que dá \`"Soma: " + a\`? E o que acontece quando ainda vem \`+ b\` a seguir? +tipp: Põe parênteses para o Java calcular primeiro: \`System.out.println("Soma: " + (a + b));\` +lösung: l06-java-fehler-loesung.visustruct +::: + +## Jogo: O que aparece? + +::: spiel frage +titel: Jogo: O que aparece? +intro: O Ludwig construiu entradas e saídas. Diz antes o que acontece. Sete rondas. + +runde: + int a = 3 + int b = 4 + output: a + b +frage: O que aparece? +- 7 +- [x] 34 +- a + b +> Numa saída, o \`+\` junta sempre as partes, mesmo números. + +runde: + int a = 3 + int b = 4 + int soma = a + b + output: "Soma: " + soma +frage: O que aparece? +- [x] Soma: 7 +- Soma: 34 +- Soma: soma +> O cálculo acontece antes, numa variável. A saída só junta o texto e o resultado. + +runde: + input: String nome "Como te chamas?" + output: "Olá" + nome + "!" +frage: Escreves Mia. O que aparece? +- Olá Mia! +- [x] OláMia! +- Olá nome! +> O texto \`"Olá"\` não tem espaço no fim. Por isso fica tudo colado. + +runde: + input: int idade "Quantos anos tens?" +frage: Escreves 2.5. O que acontece? +- idade fica 2. +- idade fica 2.5. +- [x] A simulação mostra um erro. +> O tipo de dados \`int\` só aceita números inteiros. + +runde: + input: double preco "Preço em euros?" +frage: A que parte do modelo EPS pertence este bloco? +- [x] Entrada +- Processamento +- Saída +> \`input:\` pede um valor. Isso é a entrada. + +runde: + double media = (a + b) / 2.0 +frage: A que parte do modelo EPS pertence este bloco? +- Entrada +- [x] Processamento +- Saída +> Aqui calcula-se alguma coisa. Isso é o processamento. + +runde: + output: "Média: " + media +frage: A que parte do modelo EPS pertence este bloco? +- Entrada +- Processamento +- [x] Saída +> \`output:\` mostra o resultado. Isso é a saída. +::: + +## 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. + +::: checkliste +- Consigo explicar o modelo EPS. → O modelo EPS +- Consigo escrever uma entrada com tipo de dados, nome e pergunta. → Entrada com input: +- Consigo juntar texto e variáveis numa saída com +. → Cuidado com o + numa saída +- Consigo calcular primeiro um resultado e guardá-lo numa variável, depois mostrar essa variável, p. ex. \`int soma = a + b\`, depois \`output: soma\`. → Cuidado com o + numa saída +- Consigo identificar a entrada, o processamento e a saída numa tarefa. → Da tarefa ao estrutograma +- Consigo ler números em Java com o scanner. → Agora em Java +- Consigo escrever comentários com \`//\` e \`/* */\` e usá-los para organizar e explicar o meu código. → Comentários no código +::: + +## Teste de conhecimentos + +::: quiz +? O que quer dizer EPS? +→ O modelo EPS +- [x] Entrada, processamento, saída +- [ ] Entrada, programa, sequência +- [ ] Editar, partilhar, sair +> Muitos programas pedem primeiro valores, processam-nos e depois mostram o resultado. + +? As variáveis a e b têm os valores 3 e 4. O que mostra \`output: a + b\`? +→ Cuidado com o + numa saída +- [ ] 7 +- [x] 34 +- [ ] a + b +> Numa saída, o + junta as partes. Calcula primeiro a soma numa variável. + +? Que entrada serve se for introduzido um preço como 4.99? +→ Entrada com input: +- [ ] input: int preco "Preço?" +- [x] input: double preco "Preço?" +- [ ] input: String "Preço?" +> 4.99 é um número decimal, portanto double. Além disso, cada entrada precisa de um nome de variável. + +? O que mostra \`output: "Idade: " + idade\` se idade tiver o valor 12? +→ Cuidado com o + numa saída +- [x] Idade: 12 +- [ ] "Idade: " + 12 +- [ ] Idade: idade + +? Tarefa: *O programa pede o raio de um círculo e mostra o seu perímetro.* Associa cada parte do texto ao seu lugar no modelo EPS. +→ Da tarefa ao estrutograma += pede o raio -> Entrada += perímetro = 2 * 3.14 * raio -> Processamento += mostra o seu perímetro -> Saída +> O raio é dado, o perímetro é o que procuras. A fórmula liga os dois. + +? O que lê \`scanner.nextInt()\`? +→ Agora em Java +- [x] Um número inteiro +- [ ] Um número decimal +- [ ] Uma frase inteira +> Para números decimais há \`scanner.nextDouble()\`, para uma palavra \`scanner.next()\`. + +? O que faz o Java com um comentário? +→ Comentários no código +- [ ] Mostra-o como texto. +- [x] Salta-o. +- [ ] Indica um erro. +> Os comentários são notas para pessoas. O programa corre exatamente igual com ou sem eles. + +? Onde termina um comentário que começa com \`/*\`? +→ Comentários no código +- [x] Em \`*/\` +- [ ] No fim da linha +- [ ] Na próxima linha vazia +> Por isso um comentário com \`/*\` pode ocupar várias linhas. Já um comentário com \`//\` termina no fim da linha. +::: +`,$4=`--- +titel: Simulação e teste de secretária +bereich: Fundamentos +kurz: Executar um estrutograma passo a passo, segui-lo à mão e encontrar erros. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- iniciar a simulação, fazer pausa, executar passos individuais e pará-la +- ler as variáveis, a saída e o último passo durante a simulação +- fazer um teste de secretária à mão, em forma de tabela +- encontrar um erro comparando os valores com o que espero +- acompanhar código Java com Passo a passo e pontos de paragem +::: + +## Iniciar a simulação + +Antes de chegarem as decisões e os ciclos, vais conhecer a tua ferramenta mais importante. A partir de agora podes usar a simulação para verificar sozinho cada exercício. + +Com o botão [▶︎ Iniciar simulação](#zeige-simulation) à direita nas ferramentas, o VisuStruct executa o teu estrutograma. Enquanto a simulação está a correr, não podes editar o diagrama. O mesmo botão chama-se então **■ Terminar simulação** e leva-te de volta à edição. + +À direita aparecem os **Controlos**: + +- **Reproduzir** executa o diagrama automaticamente, passo a passo. Quanto tempo espera entre dois passos defines em **Pausa por passo**. +- **Pausa** para por um momento. Depois continuas com Reproduzir ou Passo. +- **Passo** executa exatamente um passo. Assim podes observar com calma. +- **Parar** cancela e põe tudo de volta ao início. + +Abre o diagrama seguinte no editor e percorre-o com **Passo**: + +::: diagramm sim-tausch.visustruct +Os valores de a e b são trocados. A variável aux guarda um dos valores entretanto. +::: + +## O que a simulação mostra + +- **Destaque:** Um bloco do diagrama fica colorido. Com **Último passo** é o bloco que acabou de ser executado. Com **Próximo passo** é o bloco que vem a seguir. +- **Entrada:** Se o diagrama pedir um valor, escreves aqui e confirmas com **OK**. +- **Último passo:** Aqui vês o que acabou de acontecer, p. ex. \`a = 5 -> 5\` depois do bloco \`a = b\`. À esquerda, as variáveis já foram substituídas pelos seus valores; à direita da seta está o resultado. +- **Variáveis:** Todas as variáveis com os seus valores atuais. +- **Saída:** Tudo o que foi mostrado com \`output:\`. + +Se a área [Código](#zeige-codelive) estiver aberta à direita, a [consola](#zeige-konsole) também acompanha lá. É limpa no início e depois mostra as saídas e entradas tal como apareceriam no programa real. + +No fim aparece **Simulação terminada.** Se algo correr mal, a simulação para no bloco com erro e mostra uma mensagem, p. ex. **Variável desconhecida: total**. + +## O teste de secretária + +Num **teste de secretária** és tu o computador. Percorres o estrutograma com papel e caneta e anotas os valores das variáveis depois de cada passo. O melhor é fazer uma tabela: uma coluna para o passo, uma para cada variável e uma para a saída. + +Para o diagrama de cima, a tabela fica assim: + +| Passo | a | b | aux | Saída | +|---|---|---|---|---| +| \`int a = 3\` | 3 | – | – | | +| \`int b = 5\` | 3 | 5 | – | | +| \`int aux = a\` | 3 | 5 | 3 | | +| \`a = b\` | 5 | 5 | 3 | | +| \`b = aux\` | 5 | 3 | 3 | | +| \`output: "a = " + a\` | 5 | 3 | 3 | a = 5 | +| \`output: "b = " + b\` | 5 | 3 | 3 | b = 3 | + +Depois compara a tua tabela com a simulação. Os valores em **Variáveis** coincidem com a tua linha depois de cada passo? + +> Um teste de secretária é especialmente útil nos testes escritos. Aí não tens computador, mas mesmo assim podes mostrar o que o teu estrutograma faz. + +## Encontrar erros + +Se um estrutograma mostrar algo errado, faz assim: + +1. **Escreve o que esperas:** O que deve sair para uma determinada entrada? +2. **Executa passo a passo:** Inicia a simulação com **Passo** e observa as variáveis. +3. **Encontra o sítio:** Onde é que um valor fica pela primeira vez diferente do que esperavas? É exatamente aí que está o erro. + +Erros frequentes numa sequência são: + +- A **ordem** está errada: uma variável é usada antes de ter um valor. +- Um valor é **escrito por cima** antes de ser preciso. +- Faltam **parênteses**: \`a + b / 2\` não é o mesmo que \`(a + b) / 2\`. +- São divididos dois números inteiros: \`7 / 2\` dá \`3\`, porque com \`int\` tudo o que vem depois da vírgula desaparece. + +> Mais tarde chegam as decisões e os ciclos. Aí a simulação também te mostra que ramo é seguido e quantas vezes um ciclo é executado. + +::: angeberwissen +A 9 de setembro de 1947, a equipa de Grace Hopper encontrou uma traça verdadeira presa entre dois contactos do computador Harvard Mark II. Colaram-na no diário de bordo e escreveram: “Primeiro caso real de um bug encontrado.” Hoje a traça está num museu em Washington. +::: + +## Exercício: Corrigir a troca + +::: übung sim-tausch +titel: Corrigir a troca +auftrag: O estrutograma deve ler dois números e mostrá-los trocados. Ou seja, com 3 e 5 deve aparecer primeiro **5** e depois **3**. Mas mostra 5 duas vezes. + Faz um teste de secretária ou usa **Passo** e corrige o erro. +start: sim-tausch-start.visustruct +test: 3, 5 -> 5 | 3 +test: 1, 2 -> 2 | 1 +test: 7, 7 -> 7 | 7 +braucht: anweisung +tipp: Percorre o diagrama com **Passo** e anota os valores de a e b depois de cada passo. Onde é que o 3 desaparece? +tipp: Olha para a depois do passo \`a = b\`. Para onde foi o valor antigo de a? Guarda-o primeiro numa variável auxiliar, como no exemplo de cima. +lösung: sim-tausch-loesung.visustruct +::: + +## Exercício: Corrigir os bilhetes de cinema + +::: übung sim-kino +titel: Corrigir os bilhetes de cinema +auftrag: Um bilhete de cinema custa 8.50 euros. O estrutograma deve pedir o número de bilhetes e mostrar o preço total, ou seja, para 2 bilhetes \`Total: 17.0\`. + Inicia a simulação. Ela para com uma mensagem de erro. Descobre porquê e corrige o estrutograma. +start: sim-kino-start.visustruct +test: 2 -> Total: 17.0 +test: 3 -> Total: 25.5 +test: 0 -> Total: 0.0 +braucht: anweisung +tipp: Lê com atenção a mensagem de erro da simulação. Que variável é que ela ainda não conhece? +tipp: A simulação executa os blocos de cima para baixo. O total já tem um valor quando chega a saída? Podes mover os blocos com o rato. +lösung: sim-kino-loesung.visustruct +::: + +> Se uma simulação nunca mais acabar, clica em **Parar**. Quando **Verificas** um exercício, o VisuStruct para sozinho depois de um número muito grande de passos. + +## Agora em Java + +Também podes executar código Java passo a passo. Na área [Código](#zeige-codelive), a ferramenta para isso chama-se **depurador** (debugger): + +- Clica num número de linha à esquerda. Aparece um ponto vermelho: é um **ponto de paragem**. [▶︎ Executar](#zeige-ausfuehren) para antes dessa linha. +- O botão [Passo a passo](#zeige-einzelschritt) executa exatamente uma linha, como **Passo** na simulação. +- Por baixo do código vês o valor atual de cada variável. É o teu teste de secretária, só que é o computador que escreve. + +::: übung l07-java-pizza +titel: Corrigir a encomenda de pizzas +code: java +auftrag: Uma pizza custa 8 euros, o queijo extra 2 euros. Para 3 pizzas com queijo extra, o programa deve mostrar **Total: 30**. Mas mostra 14. + Percorre o código Java com Passo a passo e observa \`total\`. Encontra o erro e corrige-o no código. +start: l07-java-pizza-start.visustruct +test: - -> Total: 30 +braucht: anweisung +tipp: Que valor está em \`total\` depois da quarta linha? Faz as contas de cabeça: o que é que o Java calcula primeiro? +tipp: Como na matemática, a multiplicação vem antes da soma: \`preco + queijo * quantidade\` é \`8 + 6\`. Põe parênteses: \`(preco + queijo) * quantidade\`. +lösung: l07-java-pizza-loesung.visustruct +::: + +## Preenche os espaços: teste de secretária + +::: lückentext +titel: O que está nas variáveis? +auftrag: Faz um teste de secretária de cabeça. Escreve depois de cada linha o valor que a variável tem a seguir e, na última linha, o que é mostrado. +\`\`\`java +int a = 5; +int b = 2; +a = a + b; // a vale agora [[7]] +b = a * 2; // b vale agora [[14]] +a = b - a; // a vale agora [[7]] +System.out.println(a + b); // saída: [[21]] +\`\`\` +erklärung: Cada linha calcula com os valores que estão nesse momento nas variáveis: a = 5 + 2 = 7, b = 7 · 2 = 14, a = 14 − 7 = 7, saída 7 + 14 = 21. Podes confirmar com Passo a passo na área Código. +::: + +## Encontra o erro: pontuação + +::: übung l07-java-fehler +titel: Corrigir a pontuação +code: java +auftrag: Num jogo, o Ludwig ganha primeiro 10 pontos, depois 5 pontos e depois perde 3 pontos. No fim deve aparecer **Pontos: 12**. Mas aparece **Pontos: 3**. + Percorre o código com Passo a passo e observa \`pontos\`. Corrige a linha errada e carrega em Verificar. +start: l07-java-fehler-start.visustruct +test: - -> Pontos: 12 +braucht: anweisung +tipp: Depois de que linha é que \`pontos\` passa de repente a valer 3? O que devia acontecer nessa linha? +tipp: O Ludwig perde 3 pontos, por isso tira-se 3 ao valor antigo: \`pontos = pontos - 3;\` +lösung: l07-java-fehler-loesung.visustruct +::: + +## Jogo: Desativar a bomba + +::: spiel bombe +titel: Jogo: Desativar a bomba +intro: Cada programa tem **exatamente um erro**, e a bomba está a fazer tique-taque. Faz o teste de secretária de cabeça e toca na linha errada antes de o tempo acabar. Os programas estão em Java, mas cada linha é um bloco como no estrutograma. Seis rondas, 30 segundos cada. +zeit: 30 + +runde: + int a = 3; + int b = 5; + int aux = a; + a = b; + b = a; +frage: Deve trocar os valores de a e b. +fehler: 5 +besser: b = aux; +> a já tem o valor de b. O valor antigo de a está em aux. + +runde: + int a = 4; + int b = 6; + double media = a + b / 2; + System.out.println(media); +frage: Deve mostrar a média 5.0. +fehler: 3 +besser: double media = (a + b) / 2.0; +> Sem parênteses, a divisão vem primeiro: 4 + 6 / 2 = 7. + +runde: + int bilhetes = 3; + double preco = 8.5; + double total = bilhetes + preco; + System.out.println("Total: " + total); +frage: Deve mostrar o preço de 3 bilhetes de cinema a 8,50 € cada. +fehler: 3 +besser: double total = bilhetes * preco; +> Para o preço total multiplica-se, não se soma. + +runde: + int minutos = 135; + int horas = minutos / 60; + int resto = minutos / 60; + System.out.println(horas + " h " + resto + " min"); +frage: Deve mostrar 2 h 15 min. +fehler: 3 +besser: int resto = minutos % 60; +> \`%\` dá o resto de uma divisão. Com \`/\`, resto também ficava com 2. + +runde: + String nome = "Ada"; + System.out.println("Olá " + "nome" + "!"); +frage: Deve mostrar "Olá Ada!". +fehler: 2 +besser: System.out.println("Olá " + nome + "!"); +> Entre aspas, nome é só um texto. A variável não tem aspas. + +runde: + double preco = 100; + preco = preco * 0.1; + System.out.println(preco); +frage: Deve aumentar o preço em 10 %, ou seja, mostrar 110.0. +fehler: 2 +besser: preco = preco + preco * 0.1; +> Vezes 0.1 dá só os 10 %, ou seja, 10.0. Isso ainda tem de ser somado ao preço antigo. +::: + +## 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. + +::: checkliste +- Consigo iniciar a simulação, fazer pausa, executar passos individuais e pará-la. → Iniciar a simulação +- Consigo ler as variáveis, a saída e o último passo durante a simulação. → O que a simulação mostra +- Consigo fazer um teste de secretária à mão, em forma de tabela. → O teste de secretária +- Consigo encontrar um erro comparando os valores com o que espero. → Encontrar erros +- Consigo acompanhar código Java com Passo a passo e pontos de paragem. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? Que botão executa exatamente um passo? +→ Iniciar a simulação +- [ ] Reproduzir +- [x] Passo +- [ ] Parar +> Reproduzir continua automaticamente, Passo executa só um passo. + +? O que anotas depois de cada passo num teste de secretária? +→ O teste de secretária +- [ ] Só a saída no fim +- [x] Os valores atuais de todas as variáveis +- [ ] O código Java gerado +> Assim vês exatamente onde um valor é diferente do que esperavas. + +? Primeiro \`int a = 3\`, depois \`int b = 5\`, depois \`a = b\`. Que valores têm a e b a seguir? +→ O teste de secretária +- [ ] a = 5 e b = 3 +- [x] a = 5 e b = 5 +- [ ] a = 3 e b = 5 +> O valor antigo de a foi escrito por cima. É por isso que precisas de uma variável auxiliar para trocar valores. + +? O campo Último passo mostra \`preco = 4 * 2.5 -> 10.0\`. O que quer isso dizer? +→ O que a simulação mostra +- [ ] A variável preco tem agora o valor 4. +- [x] Foi calculado 4 * 2.5 e o resultado 10.0 foi guardado em preco. +- [ ] A simulação encontrou um erro. + +? A simulação indica **Variável desconhecida: soma**. Qual é uma razão provável? +→ Encontrar erros +- [x] soma é usada antes de lhe ter sido dado um valor. +- [ ] soma é demasiado grande. +- [ ] O estrutograma tem demasiados blocos. + +? O que faz um ponto vermelho antes de um número de linha na área Código? +→ Agora em Java +- [ ] Marca um erro. +- [x] O programa para antes dessa linha. +- [ ] A linha é saltada. +> É um ponto de paragem. Continuas com ▶︎ ou com Passo a passo. +::: +`,Y4=`--- +titel: Decisão +bereich: Fundamentos +kurz: Usar uma condição para decidir qual de dois ramos é executado. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar que é executado exatamente um ramo de uma decisão +- usar os operadores de comparação == != < <= > >= +- distinguir == de = +- construir uma decisão com um ramo vazio +- escrever uma decisão com if e else em Java +::: + +## Se, então, senão + +Até agora, todos os blocos eram sempre executados. Mas muitas vezes um programa deve **decidir**: se uma condição se verificar, faz uma coisa, senão faz a outra. + +É para isso que serve a **decisão**. A condição fica no triângulo em cima. Por baixo, o estrutograma divide-se em dois ramos: + +- **true** (esquerda): é executado se a condição for verdadeira +- **false** (direita): é executado se a condição for falsa + +É sempre executado **exatamente um** dos dois ramos. Depois, o programa continua por baixo da decisão. + +::: diagramm l07-alter-pruefen.visustruct +Consoante a idade introduzida, aparece uma mensagem ou a outra. Experimenta 17 e 18 na simulação. +::: + +## Inserir uma decisão + +Arrasta a **Decisão** da área Elementos para o estrutograma. Clica no triângulo e escreve a condição no Inspetor de objetos, p. ex. \`idade >= 18\`. A palavra \`if\` já está à frente. + +Cada ramo começa com um marcador ø. Arrasta instruções para lá. Um ramo também pode ter vários blocos uns por cima dos outros. + +## Operadores de comparação + +Uma condição é normalmente uma **comparação**. O seu resultado é sempre \`true\` ou \`false\`. + +- \`==\` igual, p. ex. \`numero == 0\` +- \`!=\` diferente, p. ex. \`resposta != 42\` +- \`<\` menor, \`<=\` menor ou igual +- \`>\` maior, \`>=\` maior ou igual + +> Não confundas \`==\` com \`=\`. Um só \`=\` é uma atribuição e guarda um valor. Para comparar precisas de dois sinais de igual. + +Com \`%\` verificas se um número é divisível por outro: \`numero % 2 == 0\` é verdadeiro se \`numero\` for par. + +## Exercício: Par ou ímpar + +::: übung l07-gerade +titel: Par ou ímpar +auftrag: Pede um número inteiro. Mostra **par** se for par, senão **ímpar**. +test: 4 -> par +test: 7 -> ímpar +test: 0 -> par +braucht: verzweigung +tipp: Aqui há duas possibilidades, por isso precisas de uma decisão. Como reconheces um número par? +tipp: Um número é par se não sobrar resto quando o divides por 2. A condição é \`numero % 2 == 0\`. +lösung: l07-gerade-loesung.visustruct +::: + +## Exercício: O número maior + +::: übung l07-maximum +titel: O número maior +auftrag: Pede dois números inteiros e mostra só o maior. Se os dois forem iguais, mostra esse número. +test: 3, 8 -> 8 +test: 9, 2 -> 9 +test: 5, 5 -> 5 +braucht: verzweigung +tipp: Uma decisão compara os dois números. Cada ramo tem exatamente uma saída. +tipp: Compara com \`a > b\`. No ramo true mostras \`a\`, no ramo false \`b\`. +lösung: l07-maximum-loesung.visustruct +::: + +## Um ramo vazio + +Às vezes uma coisa só deve acontecer se a condição for verdadeira e, caso contrário, não acontece nada. Então o ramo false fica **vazio**. No estrutograma mostra o marcador **ø**. + +::: diagramm l07-rabatt.visustruct +A partir de 50 euros tens 5 euros de desconto. Caso contrário não acontece nada; o ramo false está vazio. A saída em baixo é executada nos dois casos. +::: + +## Exercício: Valor absoluto + +::: übung l07-betrag +titel: Valor absoluto de um número +auftrag: Pede um número inteiro. Se for negativo, torna-o positivo. Depois mostra o número. Assim, -5 passa a 5, e 7 fica 7. +Usa uma decisão com um ramo vazio e só **uma** saída por baixo da decisão. +test: -5 -> 5 +test: 7 -> 7 +test: 0 -> 0 +test: -12 -> 12 +braucht: verzweigung +tipp: Só os números negativos têm de ser alterados. O que acontece a um número se o multiplicares por -1? +tipp: A condição é \`numero < 0\`. No ramo true trocas o sinal, p. ex. com \`numero = 0 - numero\`. O ramo false fica vazio. +lösung: l07-betrag-loesung.visustruct +::: + +## Agora em Java + +Esta é a verificação da idade do início desta lição em Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Quantos anos tens?"); +int idade = scanner.nextInt(); +if (idade >= 18) { + System.out.println("És maior de idade."); +} else { + System.out.println("Ainda não és maior de idade."); +} +\`\`\` + +- A condição fica depois de \`if\`, entre **parênteses curvos** \`( )\`. +- O ramo true fica entre **chavetas** \`{ }\`, o ramo false vem depois de \`else\`, nas suas próprias chavetas. Depois de uma chaveta não há ponto e vírgula. +- Se o ramo false estiver vazio, deixas simplesmente de fora \`else { }\`. +- O teu programa precisa das duas primeiras linhas uma vez, assim que lê alguma coisa. Depois, \`scanner.nextInt()\` lê um número inteiro. A pergunta antes disso é uma saída normal. + +::: angeberwissen +O Java também tem uma mascote: o **Duke**, um bonequinho preto e branco com um grande nariz vermelho. Foi desenhado pela equipa do Java em 1992 e desde então acena em conferências e t-shirts. O Ludwig acha que um bode teria ficado melhor. +::: + +::: übung l08-java-bestanden +titel: Aprovado em Java +code: java +auftrag: Escreve um programa em Java que pergunta pela pontuação. A partir de 50 pontos mostra **aprovado**, senão **reprovado**. + Escreve o código na área Código e depois clica em Verificar. +test: 50 -> aprovado +test: 49 -> reprovado +test: 100 -> aprovado +test: 0 -> reprovado +braucht: verzweigung +tipp: Começa pelas duas linhas do scanner. Depois perguntas pelos pontos, lês o valor e comparas com \`if\`. +tipp: A condição é \`pontos >= 50\`. Num ramo fica \`System.out.println("aprovado");\` e depois de \`else\` vem \`System.out.println("reprovado");\`. +lösung: l08-java-bestanden-loesung.visustruct +::: + +## Preenche os espaços: par ou ímpar + +::: lückentext +titel: Par ou ímpar +auftrag: Preenche as palavras e os sinais que faltam. O programa deve mostrar se um número é par. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Que número?"); +int numero = scanner.nextInt(); +[[if]] (numero [[%]] 2 [[==]] 0) [[{]] + System.out.println("par"); +[[}]] [[else]] { + System.out.println("ímpar"); +} +\`\`\` +erklärung: \`numero % 2\` é o resto da divisão por 2. Se for 0, o número é par. Para comparar precisas de \`==\`, um \`=\` sozinho é uma atribuição. Os dois ramos ficam entre chavetas. +::: + +## Encontra o erro: entrada + +::: übung l08-java-fehler +titel: Corrigir a entrada +code: java +auftrag: No jardim zoológico, as crianças com **menos** de 6 anos entram de graça, todos os outros pagam 4 euros. Mas o programa também deixa entrar de graça as crianças de seis anos. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l08-java-fehler-start.visustruct +test: 5 -> Entrada gratuita +test: 6 -> 4 euros +test: 10 -> 4 euros +test: 0 -> Entrada gratuita +braucht: verzweigung +tipp: Experimenta o programa com 6. Que operador de comparação ainda deixa passar o 6? +tipp: “Menos de 6” é \`idade < 6\`. \`<=\` significa “menor ou igual”. +lösung: l08-java-fehler-loesung.visustruct +::: + +## Jogo: Que caminho? + +::: spiel frage +titel: Jogo: Que caminho? +intro: O Ludwig escreveu decisões em Java. Avalia a condição de cabeça e diz o que aparece. Sete rondas. + +runde: + int x = 5; + if (x > 5) { + System.out.println("grande"); + } else { + System.out.println("pequeno"); + } +frage: O que aparece? +- grande +- [x] pequeno +- nada +> 5 > 5 é falso, porque 5 não é maior do que 5. Portanto, o ramo falso. + +runde: + int x = 5; + if (x >= 5) { + System.out.println("grande"); + } else { + System.out.println("pequeno"); + } +frage: O que aparece? +- [x] grande +- pequeno +- grande e pequeno +> \`>=\` quer dizer "maior ou igual". 5 >= 5 é verdadeiro. + +runde: + int numero = 7; + if (numero % 2 == 0) { + System.out.println("par"); + } else { + System.out.println("ímpar"); + } +frage: O que aparece? +- par +- [x] ímpar +- 1 +> 7 % 2 dá resto 1, portanto não 0. O número é ímpar. + +runde: + int x = -4; + if (x < 0) { + x = -x; + } + System.out.println(x); +frage: O que aparece? +- -4 +- [x] 4 +- nada +> -4 < 0 é verdadeiro, por isso o sinal é invertido. + +runde: + int x = 4; + if (x < 0) { + x = -x; + } + System.out.println(x); +frage: O que aparece? +- -4 +- [x] 4 +- nada +> 4 < 0 é falso. O ramo falso está vazio, o programa continua simplesmente por baixo. + +runde: + int nota = 3; + if (nota != 3) { + System.out.println("diferente"); + } else { + System.out.println("três"); + } +frage: O que aparece? +- diferente +- [x] três +- nada +> \`!=\` quer dizer "diferente de". 3 != 3 é falso. + +runde: + int a = 8; + int b = 12; + if (a > b) { + System.out.println(a); + } else { + System.out.println(b); + } +frage: O que aparece? +- 8 +- [x] 12 +- 20 +> O programa mostra o maior dos dois números. +::: + +## 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. + +::: checkliste +- Consigo explicar que é executado exatamente um ramo de uma decisão. → Se, então, senão +- Consigo usar os operadores de comparação == != < <= > >=. → Operadores de comparação +- Consigo distinguir == de =. → Operadores de comparação +- Consigo construir uma decisão com um ramo vazio. → Um ramo vazio +- Consigo escrever uma decisão com if e else em Java. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? Que ramo é executado se a condição for falsa? +→ Se, então, senão +- [ ] O ramo true +- [x] O ramo false +- [ ] Os dois ramos +- [ ] Nenhum, o programa termina +> Com false, é executado o ramo da direita. Depois, o programa continua por baixo da decisão. + +? Que condição verifica se idade é exatamente 18? +→ Operadores de comparação +- [ ] idade = 18 +- [x] idade == 18 +- [ ] idade >= 18 +> Um só = é uma atribuição. Para comparar precisas de ==. + +? O que significa ø num ramo? +→ Um ramo vazio +- [x] Neste caso não acontece nada. +- [ ] O programa termina aqui. +- [ ] A condição é falsa. + +? A condição é \`pontos >= 50\`. Para que valor é verdadeira? +→ Operadores de comparação +- [ ] 49 +- [x] 50 +- [ ] 0 +> >= quer dizer maior ou igual. Portanto o 50 está incluído. + +? Nos manuais, a decisão tem muitas vezes outro nome. Qual? +→ Se, então, senão +- [ ] Seleção múltipla +- [x] Instrução condicional +- [ ] Iteração +> As instruções de um ramo só são executadas sob uma condição. Por isso também se chama instrução condicional. + +? Onde fica em Java a condição de uma decisão? +→ Agora em Java +- [x] Entre parênteses curvos logo a seguir a if +- [ ] Entre chavetas depois de else +- [ ] Depois de um ponto e vírgula +> \`if (idade >= 18) { … }\`: os parênteses curvos pertencem à condição, as chavetas ao ramo. +::: +`,X4=`--- +titel: Combinar condições +bereich: Fundamentos +kurz: Juntar várias condições com e, ou e não, e verificar intervalos de valores. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar quando é que uma combinação com && é verdadeira +- explicar quando é que uma combinação com || é verdadeira +- inverter uma condição com ! +- verificar se um valor está num intervalo como de 1 a 5 +- ler a tabela de verdade de &&, || e ! +- guardar o resultado de uma condição numa variável boolean +- avaliar condições compostas com segurança +- ligar condições em Java com && e || +::: + +## E: && + +Às vezes uma só comparação não chega. Por exemplo, só tens direito a um bilhete jovem se tiveres **pelo menos 12 anos e menos de 18**. + +Com \`&&\` (e) juntas duas condições. O resultado só é \`true\` se **as duas** condições forem verdadeiras. + +::: diagramm l08-jugendticket.visustruct +As duas comparações têm de estar certas. Experimenta 11, 12, 17 e 18 na simulação. +::: + +## Ou: || + +Com \`||\` (ou), o resultado é \`true\` se **pelo menos uma** das condições for verdadeira. Também podem ser as duas. + +\`\`\` +dia == 6 || dia == 7 +\`\`\` + +Esta condição é verdadeira se \`dia\` tiver o valor 6 ou o valor 7, ou seja, ao sábado ou ao domingo. + +> Num teclado português, a barra vertical \`|\` escreve-se com Shift e a tecla à esquerda do 1. + +## Exercício: Fim de semana + +::: übung l08-wochenende +titel: Fim de semana +auftrag: Pede um dia da semana como número (1 é segunda-feira, 7 é domingo). Mostra **Fim de semana** se for sábado ou domingo, senão **Dia útil**. +test: 6 -> Fim de semana +test: 7 -> Fim de semana +test: 1 -> Dia útil +test: 5 -> Dia útil +braucht: verzweigung +tipp: É fim de semana se o dia for 6 **ou** 7. Para isso precisas de duas comparações numa só condição. +tipp: Sábado é 6, domingo é 7. Junta as duas comparações com \`||\`. +lösung: l08-wochenende-loesung.visustruct +::: + +## Verificar intervalos de valores + +No ensino básico em Portugal, as notas vão de 1 a 5 (5 é a melhor). Verificas se uma nota está **dentro do intervalo** com duas comparações e \`&&\`: + +\`\`\` +nota >= 1 && nota <= 5 +\`\`\` + +::: grafik l08-zahlenstrahl.svg +O intervalo verde de 1 a 5 é válido; as duas pontas estão incluídas. +::: + +Ao contrário, uma nota está **fora** do intervalo se for demasiado pequena **ou** demasiado grande: + +::: diagramm l08-note.visustruct +Não há notas menores do que 1 nem maiores do que 5. +::: + +> A forma como se escreve na matemática, \`1 <= nota <= 5\`, não funciona. Tens de a dividir em duas comparações e juntá-las com \`&&\`. + +## Exercício: Nota válida + +::: übung l08-note-gueltig +titel: Nota válida +auftrag: Pede uma nota como número inteiro. Mostra **válida** se estiver entre 1 e 5 (1 e 5 incluídos), senão **inválida**. +test: 1 -> válida +test: 5 -> válida +test: 3 -> válida +test: 0 -> inválida +test: 6 -> inválida +braucht: verzweigung +tipp: Uma nota válida tem de cumprir duas coisas ao mesmo tempo: não ser demasiado pequena **e** não ser demasiado grande. +tipp: A nota tem de ser maior ou igual a 1 e, ao mesmo tempo, menor ou igual a 5. +lösung: l08-gueltig-loesung.visustruct +::: + +## Não e parênteses + +Com \`!\` (não) inverte-se uma condição: \`true\` passa a \`false\` e vice-versa. + +\`\`\` +!(nota >= 1 && nota <= 5) +\`\`\` + +Isto é verdadeiro se a nota **não** estiver no intervalo, e quer dizer o mesmo que \`nota < 1 || nota > 5\`. + +Se \`&&\` e \`||\` aparecerem juntos, o \`&&\` é calculado primeiro, tal como a multiplicação antes da adição. É melhor usar **parênteses**; assim fica claro o que pertence ao quê: + +\`\`\` +(idade >= 12 && idade < 18) || estudante == 1 +\`\`\` + +## A tabela de verdade + +Uma **tabela de verdade** mostra de relance o que resulta de \`&&\`, \`||\` e \`!\`. À esquerda estão as quatro possibilidades para duas condições \`a\` e \`b\`, à direita o resultado: + +::: grafik l09-wahrheitstabelle.svg +Verde é true, vermelho é false. Com && só há uma linha verde, com || só uma vermelha. +::: + +Para fixar: + +- \`a && b\` só é verdadeiro se **ambas** forem verdadeiras. +- \`a || b\` só é falso se **ambas** forem falsas. +- \`!a\` inverte o valor. + +::: angeberwissen +O tipo de dados \`boolean\` tem o nome de **George Boole**. Este inglês mostrou já em 1847 que se pode calcular com verdadeiro e falso como com números, quase cem anos antes de existir o primeiro computador. Hoje a sua lógica está em todos os chips. +::: + +## Valores lógicos em variáveis + +O resultado de uma condição é um **valor lógico** do tipo \`boolean\`. Podes guardá-lo numa variável, tal como um número, e usá-lo mais tarde: + +\`\`\` +boolean fimDeSemana = dia == 6 || dia == 7 +\`\`\` + +Na decisão fica então só \`fimDeSemana\`. Lê-se quase como uma frase: "Se for fim de semana, então …". Não escrevas \`fimDeSemana == true\`, porque \`fimDeSemana\` já é true ou false. + +Com \`!fimDeSemana\` perguntas pelo contrário, ou seja, um dia útil. + +::: ludwig +Condições longas ficam mais claras se puseres partes delas em variáveis boolean com nomes claros, por exemplo \`boolean jovem = idade >= 12 && idade < 18\`. +::: + +## Jogo: Verdadeiro ou falso? + +Agora é a tua vez. Calcula cada condição de cabeça. Depois de cada resposta vês como o VisuStruct a avalia passo a passo. + +::: spiel +idade: 8..20 +dia: 1..7 +nota: 0..6 +estudante: boolean +fimDeSemana: boolean +? idade >= 18 +? dia == 6 +? nota != 3 +? idade >= 12 && idade < 18 +? dia == 6 || dia == 7 +? estudante && fimDeSemana +? !estudante +? nota >= 1 && nota <= 5 +? !(idade < 18) +? estudante || idade >= 18 +? (idade >= 12 && idade < 18) || estudante +? !(nota >= 1 && nota <= 5) +? !fimDeSemana && dia != 3 +? idade >= 12 && idade < 18 && !estudante +::: + +## Exercício: Ano bissexto + +::: übung l08-schaltjahr +titel: Ano bissexto +auftrag: Um ano é bissexto se for divisível por 4, mas não por 100. Os anos divisíveis por 400 são bissextos de qualquer forma. +Pede um ano e mostra **Ano bissexto** ou **Não é ano bissexto**. +test: 2024 -> Ano bissexto +test: 2023 -> Não é ano bissexto +test: 1900 -> Não é ano bissexto +test: 2000 -> Ano bissexto +braucht: verzweigung +tipp: Confirma primeiro a regra com exemplos: 2024 é bissexto, 1900 não é, 2000 é. “Divisível” quer dizer que o resto é 0. +tipp: Divisível por 4 é \`ano % 4 == 0\`, não divisível por 100 é \`ano % 100 != 0\`. Junta estas duas com \`&&\`, põe parênteses à volta e acrescenta o caso do 400 com \`||\`. +lösung: l08-schaltjahr-loesung.visustruct +::: + +## Agora em Java + +O bilhete jovem do início fica assim em Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Quantos anos tens?"); +int idade = scanner.nextInt(); +if (idade >= 12 && idade < 18) { + System.out.println("Bilhete jovem"); +} else { + System.out.println("Sem bilhete jovem"); +} +\`\`\` + +Os sinais \`&&\`, \`||\` e \`!\` são exatamente os que já usas no estrutograma. Vêm do Java. Como sempre, a condição inteira fica entre os parênteses curvos depois de \`if\`. + +::: übung l09-java-schule +titel: Escola ou tempo livre +code: java +auftrag: Escreve um programa em Java que pergunta a hora (0 a 23). Das 8 até às 15, inclusive, mostra **Escola**, senão **Tempo livre**. +test: 8 -> Escola +test: 15 -> Escola +test: 16 -> Tempo livre +test: 7 -> Tempo livre +braucht: verzweigung +tipp: A hora tem de cumprir duas condições ao mesmo tempo. Que operador quer dizer “e”? +tipp: \`if (hora >= 8 && hora <= 15) { … } else { … }\` +lösung: l09-java-schule-loesung.visustruct +::: + +## Preenche os espaços: condições + +::: lückentext +titel: Nota e fim de semana +auftrag: Preenche os operadores e as palavras que faltam. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Que nota?"); +int nota = scanner.nextInt(); +if (nota >= 1 [[&&]] nota [[<=]] 5) { + System.out.println("nota válida"); +} else { + System.out.println("nota inválida"); +} +System.out.println("Que dia (1 a 7)?"); +int dia = scanner.nextInt(); +[[boolean]] fimDeSemana = dia == 6 [[||]] dia == 7; +if ([[!]]fimDeSemana) { + System.out.println("dia de escola"); +} +\`\`\` +erklärung: Uma nota é válida quando **as duas** condições são verdadeiras, por isso \`&&\`. É fim de semana quando **uma** das duas é verdadeira, por isso \`||\`. O resultado cabe numa variável \`boolean\`, e \`!\` inverte-o. +::: + +## Encontra o erro: sem escola + +::: übung l09-java-fehler +titel: Corrigir o dia sem escola +code: java +auftrag: O programa deve mostrar **sem escola** para o dia 6 (sábado) e o dia 7 (domingo), e **escola** nos outros dias. Mas mostra sempre **escola**. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l09-java-fehler-start.visustruct +test: 6 -> sem escola +test: 7 -> sem escola +test: 3 -> escola +test: 1 -> escola +braucht: verzweigung +tipp: \`dia\` pode ser 6 **e** 7 ao mesmo tempo? +tipp: Basta que uma das duas condições seja verdadeira: \`dia == 6 || dia == 7\`. +lösung: l09-java-fehler-loesung.visustruct +::: + +## 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. + +::: checkliste +- Consigo explicar quando é que uma combinação com && é verdadeira. → E: && +- Consigo explicar quando é que uma combinação com || é verdadeira. → Ou: || +- Consigo inverter uma condição com !. → Não e parênteses +- Consigo verificar se um valor está num intervalo como de 1 a 5. → Verificar intervalos de valores +- Consigo ler a tabela de verdade de &&, || e !. → A tabela de verdade +- Consigo guardar o resultado de uma condição numa variável boolean. → Valores lógicos em variáveis +- Consigo avaliar condições compostas com segurança (pelo menos 8 de 10 certas no jogo). → Jogo: Verdadeiro ou falso? +- Consigo ligar condições em Java com && e ||. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? Quando é que \`a && b\` é verdadeiro? +→ E: && +- [ ] Se a ou b for verdadeiro +- [x] Só se a e b forem ambos verdadeiros +- [ ] Se exatamente um deles for verdadeiro +> Com && as duas partes têm de estar certas. Se uma for falsa, o todo é falso. + +? A variável dia tem o valor 6. Quanto dá \`dia == 6 || dia == 7\`? +→ Ou: || +- [x] true +- [ ] false +> Com || basta que um dos lados seja verdadeiro. + +? Que condição verifica se numero está entre 10 e 20 (ambos incluídos)? +→ Verificar intervalos de valores +- [ ] 10 <= numero <= 20 +- [ ] numero >= 10 || numero <= 20 +- [x] numero >= 10 && numero <= 20 +> Com || todos os números seriam permitidos, porque qualquer número é maior do que 10 ou menor do que 20. + +? Quanto dá \`!(5 > 3)\`? +→ Não e parênteses +- [ ] true +- [x] false +> 5 > 3 é verdadeiro, e o ! inverte isso. + +? Como escreves em Java “idade é pelo menos 12 e menor do que 18”? +→ Agora em Java +- [ ] if (12 <= idade < 18) +- [x] if (idade >= 12 && idade < 18) +- [ ] if (idade >= 12 || idade < 18) +> Cada comparação fica sozinha, ligada com \`&&\`. +::: +`,K4=`--- +titel: Seleção +bereich: Fundamentos +kurz: Executar um de vários casos, consoante o valor de uma variável. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- inserir uma seleção, acrescentar casos e alterar os nomes dos casos +- explicar quando é executado o caso default +- decidir se serve melhor uma seleção ou uma decisão +- escrever uma seleção múltipla em Java com switch +::: + +## Muitas possibilidades, uma variável + +Uma máquina de bebidas tem três botões: 1 para água, 2 para sumo, 3 para chocolate quente. Com decisões precisas de três blocos encaixados uns nos outros. Isso fica depressa largo e confuso. + +::: diagramm l09-verschachtelt.visustruct +A máquina com três decisões encaixadas. Cada decisão volta a verificar a mesma variável escolha. +::: + +Sempre que comparas **uma variável** com **vários valores fixos**, há uma forma mais simples: a **seleção**. + +## Como se constrói uma seleção + +Em cima, no bloco, está a variável que decide. Por baixo há uma coluna própria para cada caso. Por cima de cada coluna está o valor a que ela pertence. + +::: diagramm l09-automat.visustruct +A mesma máquina como seleção. Se escolha tiver o valor 2, só é executada a coluna 2. +::: + +- A simulação procura o caso cujo nome corresponde exatamente ao valor. +- Se nenhum caso corresponder, é executado o **default**. Este caso fica sempre na ponta da direita. +- Depois, o programa continua por baixo da seleção. Só é executado **um** caso. + +> Uma seleção nova tem os casos 1, 2 e default. Clica num caso para alterar o seu **Nome do caso** no Inspetor de objetos. Com **Adicionar caso** ganhas uma nova coluna antes do default. + +## Casos com texto + +Os casos não têm de ser números. Também podes escolher pelo conteúdo de uma variável \`String\`. Então escreves o texto como nome do caso, por exemplo \`vermelho\`. + +::: diagramm l09-ampel.visustruct +Um semáforo: consoante a cor introduzida, aparece uma mensagem diferente. Na simulação, experimenta também uma cor que não existe. +::: + +Maiúsculas e minúsculas contam: \`Vermelho\` não corresponde ao caso \`vermelho\`. + +## Exercício: Nota por extenso + +::: übung l09-note +titel: Nota por extenso +auftrag: Pede uma nota como número inteiro e mostra-a por extenso: 1 muito insuficiente, 2 insuficiente, 3 suficiente, 4 bom, 5 muito bom. + Para qualquer outro número deve aparecer **Nota inválida**. +test: 5 -> muito bom +test: 3 -> suficiente +test: 1 -> muito insuficiente +test: 9 -> Nota inválida +braucht: fallauswahl +tipp: Para muitos valores fixos, uma seleção é mais clara do que muitas decisões. Cada nota tem um caso próprio. +tipp: Usa “Adicionar caso” até teres os casos 1 a 5 e default. Em cima, na seleção, escreves \`nota\`. +lösung: l09-note-loesung.visustruct +::: + +## Exercício: Calculadora + +::: übung l09-rechner +titel: Calculadora +auftrag: Pede, um a seguir ao outro, um número inteiro \`a\`, um operador como \`String\` e um segundo número inteiro \`b\`. + Para \`+\`, \`-\` e \`*\` mostras o resultado. Para qualquer outro sinal aparece **Operador desconhecido**. +test: 3, +, 4 -> 7 +test: 10, -, 4 -> 6 +test: 6, *, 7 -> 42 +test: 1, x, 2 -> Operador desconhecido +braucht: fallauswahl +tipp: Primeiro lê os três valores. Depois, uma seleção sobre o operador decide o que é calculado. +tipp: Antes da seleção, cria \`int resultado = 0\`. Em cada caso calculas, por exemplo, \`resultado = a + b\` e depois mostras \`resultado\`. Os nomes dos casos são simplesmente \`+\`, \`-\` e \`*\`. +lösung: l09-rechner-loesung.visustruct +::: + +## Seleção ou decisão? + +A seleção só verifica se um valor é **exatamente igual** a um nome de caso. Portanto: + +- **Seleção:** uma variável, vários valores fixos. Exemplos: escolher num menu, dia da semana como número, notas. +- **Decisão:** intervalos e condições combinadas. Exemplos: \`idade >= 18\`, \`temperatura < 0 || temperatura > 30\`. + +Por isso, para “idade 18 ou mais” continuas a precisar da decisão. Não podes criar um caso próprio para cada idade possível. + +## Agora em Java + +A máquina de bebidas fica assim em Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("1 água, 2 sumo, 3 chocolate quente"); +int escolha = scanner.nextInt(); +switch (escolha) { + case 1 -> { + System.out.println("Aqui está a tua água."); + } + case 2 -> { + System.out.println("Aqui está o teu sumo."); + } + case 3 -> { + System.out.println("Aqui está o teu chocolate quente."); + } + default -> { + System.out.println("Este botão não existe."); + } +} +\`\`\` + +- Depois de \`switch\`, a variável que é comparada fica entre parênteses curvos. +- Cada caso começa com \`case\`, o valor e uma seta \`->\`. Depois, entre chavetas, fica o que deve acontecer. +- \`default\` é o caso “senão”. Corre quando nenhum valor serve. + +::: angeberwissen +A seta \`case 1 ->\` só existe em Java desde 2020 (Java 14). Antes escrevia-se \`case 1:\` e era preciso terminar cada caso com \`break;\`. Quem se esquecia, continuava simplesmente para o caso seguinte. A seta poupou muitos problemas a muitos programadores. +::: + +::: übung l10-java-wuerfel +titel: Dado por extenso +code: java +auftrag: Escreve um programa em Java com \`switch\` que lê um número. Para 1 mostra **um**, para 2 **dois**, para 3 **três** e senão **não conheço**. +test: 1 -> um +test: 2 -> dois +test: 3 -> três +test: 7 -> não conheço +braucht: fallauswahl +tipp: Precisas de três casos \`case\` e um caso \`default\`. +tipp: \`switch (numero) { case 1 -> { System.out.println("um"); } … default -> { System.out.println("não conheço"); } }\` +lösung: l10-java-wuerfel-loesung.visustruct +::: + +## Preenche os espaços: switch + +::: lückentext +titel: Meses por extenso +auftrag: Preenche as palavras e os sinais que faltam na seleção múltipla. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Que mês (1 a 3)?"); +int mes = scanner.nextInt(); +[[switch]] (mes) { + [[case]] 1 -> { + System.out.println("janeiro"); + } + case 2 [[->]] { + System.out.println("fevereiro"); + } + [[case]] 3 -> { + System.out.println("março"); + } + [[default]] -> { + System.out.println("Não conheço"); + } +} +\`\`\` +erklärung: Depois de \`switch\` vem a variável entre parênteses. Cada caso começa com \`case\`, o valor e a seta \`->\`. \`default\` é executado quando nenhum caso serve. +::: + +## Encontra o erro: calculadora + +::: übung l10-java-fehler +titel: Corrigir a calculadora +code: java +auftrag: A calculadora lê dois números e uma opção: 1 mais, 2 menos, 3 vezes. Com 7, 3 e a opção 2 devia dar **4**, mas dá **-4**. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l10-java-fehler-start.visustruct +test: 7, 3, 2 -> 4 +test: 7, 3, 1 -> 10 +test: 7, 3, 3 -> 21 +test: 7, 3, 5 -> Não existe +test: 10, 4, 2 -> 6 +braucht: fallauswahl +tipp: Mais e vezes estão certos. Olha com atenção para o \`case 2\`. +tipp: No menos, a ordem conta: \`a - b\` em vez de \`b - a\`. +lösung: l10-java-fehler-loesung.visustruct +::: + +## Jogo: Que caso? + +::: spiel frage +titel: Jogo: Que caso? +intro: O Ludwig carrega em botões da máquina de bebidas e de outras seleções. O que acontece? Seis rondas. + +runde: + int escolha = 2; + switch (escolha) { + case 1 -> { System.out.println("água"); } + case 2 -> { System.out.println("sumo"); } + case 3 -> { System.out.println("chocolate quente"); } + default -> { System.out.println("Esse botão não existe."); } + } +frage: O que aparece? +- água +- [x] sumo +- Esse botão não existe. +> escolha é 2, por isso corre exatamente o \`case 2\`. + +runde: + int escolha = 4; + switch (escolha) { + case 1 -> { System.out.println("água"); } + case 2 -> { System.out.println("sumo"); } + case 3 -> { System.out.println("chocolate quente"); } + default -> { System.out.println("Esse botão não existe."); } + } +frage: O que aparece? +- chocolate quente +- nada +- [x] Esse botão não existe. +> Nenhum caso serve para 4, por isso corre o \`default\`. + +runde: + String dia = "segunda"; + switch (dia) { + case "Segunda" -> { System.out.println("Matemática"); } + case "Terça" -> { System.out.println("Educação Física"); } + default -> { System.out.println("livre"); } + } +frage: O que aparece? +- Matemática +- Educação Física +- [x] livre +> Nos textos conta cada letra: "segunda" com s minúsculo não é "Segunda". + +runde: + int nota = 0; + switch (nota) { + case 1 -> { System.out.println("muito bom"); } + case 2 -> { System.out.println("bom"); } + case 3 -> { System.out.println("suficiente"); } + } +frage: O que aparece? +- muito bom +- [x] nada +- suficiente +> Nenhum caso serve e não há \`default\`. Então simplesmente não acontece nada. + +runde: +frage: Queres verificar se \`idade >= 18\`. O que serve melhor? +- [x] uma decisão +- uma seleção +> Uma seleção só compara com valores fixos. Para "maior ou igual" precisas de uma decisão. + +runde: +frage: Um dado mostra de 1 a 6, e para cada número deve aparecer uma palavra diferente. O que serve melhor? +- uma decisão +- [x] uma seleção +> Uma variável, seis valores fixos: é exatamente para isso que serve a seleção. +::: + +## 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. + +::: checkliste +- Consigo inserir uma seleção, acrescentar casos e alterar os nomes dos casos. → Como se constrói uma seleção +- Consigo explicar quando é executado o caso default. → Como se constrói uma seleção +- Consigo decidir se serve melhor uma seleção ou uma decisão. → Seleção ou decisão? +- Consigo escrever uma seleção múltipla em Java com switch. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? A variável dia tem o valor 5. Existem os casos 1, 2, 3 e default. O que é executado? +→ Como se constrói uma seleção +- [ ] Nada +- [ ] O caso 3 +- [x] O caso default +> Nenhum nome de caso corresponde a 5, por isso aplica-se o default. + +? Quantos casos são executados de cada vez que a seleção é executada? +→ Como se constrói uma seleção +- [x] Exatamente um +- [ ] Todos os casos a partir do que corresponde +- [ ] Todos os casos +> Depois do caso que corresponde, o programa continua logo por baixo da seleção. + +? Para que é que uma seleção NÃO serve? +→ Seleção ou decisão? +- [ ] Escolher a opção 1, 2 ou 3 de um menu +- [x] Verificar se uma temperatura está acima dos 30 graus +- [ ] Tratar uma cor como vermelho, amarelo ou verde +> “Acima dos 30” é um intervalo. Para isso precisas de uma decisão com uma comparação. + +? No semáforo escreves \`Vermelho\`, e o caso chama-se \`vermelho\`. O que acontece? +→ Como se constrói uma seleção +- [ ] É executado o caso vermelho. +- [x] É executado o caso default. +- [ ] A simulação indica um erro. +> Maiúsculas e minúsculas contam. Vermelho e vermelho são textos diferentes. + +? Com que nome também encontras a seleção nos manuais? +→ Como se constrói uma seleção +- [ ] Instrução condicional +- [ ] Sequência +- [x] Seleção múltipla +> É escolhido um de muitos casos. Por isso também se chama seleção múltipla. + +? Como se chama em Java o caso “senão” de um switch? +→ Agora em Java +- [ ] else +- [x] default +- [ ] case 0 +::: +`,ev=`--- +titel: Ciclo while +bereich: Fundamentos +kurz: Repetir passos enquanto uma condição for verdadeira. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar que o ciclo while verifica a sua condição antes de cada iteração +- usar uma variável contadora com valor inicial, condição e alteração +- notar quando um ciclo nunca acaba e corrigir o erro +- seguir um ciclo iteração a iteração num teste de secretária +- escrever um ciclo while em Java +::: + +## Repetir enquanto algo se verificar + +Muitas vezes um programa deve fazer uma coisa várias vezes. Em vez de escreveres o mesmo bloco cinco vezes, usas um **ciclo**. + +O **ciclo while** repete o seu interior **enquanto** a sua condição for verdadeira. A condição fica em cima, na cabeça do bloco. O interior fica recuado por baixo, enquadrado por um parêntese à esquerda. + +::: diagramm l10-countdown.visustruct +Uma contagem decrescente: enquanto numero for maior do que 0, numero é mostrado e diminui 1. Depois aparece Partida! +::: + +## Primeiro a condição + +O ciclo while é um **ciclo pré-teste**. Antes de **cada** iteração, a condição é verificada: + +1. Verificar a condição. +2. Se for verdadeira, executar o interior uma vez e recomeçar no 1. +3. Se for falsa, o programa continua por baixo do ciclo. + +::: grafik l10-kopfgesteuert.svg +Depois de cada iteração volta-se à condição. Só quando ela é falsa é que o programa continua por baixo do ciclo. +::: + +Na contagem decrescente, a condição é verificada quatro vezes: com 3, 2 e 1 é verdadeira, com 0 é falsa. + +> Se a condição já for falsa da primeira vez que é verificada, o interior **não é executado nem uma vez**. Começa a contagem com \`int numero = 0\` e só aparece Partida! + +## Uma variável contadora + +Muitos ciclos vão contando. Para isso precisas de três coisas: + +- **Um valor inicial antes do ciclo**, p. ex. \`int i = 1\` +- **Uma condição na cabeça**, p. ex. \`i <= 5\` +- **Uma alteração no interior**, p. ex. \`i = i + 1\` (abreviado: \`i++\`) + +Se faltar uma destas partes, o ciclo conta mal ou nem sequer conta. + +::: angeberwissen +Os ciclos de contagem são antiquíssimos! No artigo de 1973, Nassi e Shneiderman mostraram a sua ideia, entre outras coisas, com o **fatorial**: 5! = 1 · 2 · 3 · 4 · 5 = 120. Aqui está a minha versão caprina. Experimenta-a com **Passo** na simulação e vê o \`fatorial\` a crescer. Mééé, isto vai depressa! +::: + +::: diagramm l10-fakultaet.visustruct +O fatorial com uma variável contadora \`i\`, reconstruído a partir de um exemplo do artigo de 1973. +::: + +## Exercício: Contar até n + +::: übung l10-bis-n +titel: Contar até n +auftrag: Pede um número inteiro \`n\` e mostra todos os números de 1 a \`n\`, cada um na sua linha. +test: 3 -> 1 | 2 | 3 +test: 5 -> 1 | 2 | 3 | 4 | 5 +test: 1 -> 1 +braucht: whileSchleife +tipp: Precisas de uma variável contadora que começa em 1 e aumenta 1 em cada iteração. +tipp: Antes do ciclo, cria \`int i = 1\`. A condição é \`i <= n\`. No interior mostras \`i\` e depois aumentas \`i\` em 1. +lösung: l10-bis-n-loesung.visustruct +::: + +## Atenção: ciclo infinito + +Se nada no interior do ciclo alterar a condição, ela fica verdadeira para sempre. O ciclo nunca para. A isto chama-se **ciclo infinito**. + +::: diagramm l10-endlos.visustruct +Aqui falta numero = numero - 1. O ciclo mostra 3 uma e outra vez e nunca chega a Partida! +::: + +Pergunta-te em cada ciclo: **O que é que no interior garante que a condição acaba por ficar falsa?** Quando um exercício é verificado, o VisuStruct para depois de um número muito grande de passos e indica um possível ciclo infinito. + +## Exercício: Duplicar até 100 + +::: übung l10-verdoppeln +titel: Duplicar até 100 +auftrag: Pede um número inteiro. Duplica-o até ele ser pelo menos 100. + No fim, mostra **quantas vezes** o duplicaste. +test: 10 -> 4 +test: 30 -> 2 +test: 1 -> 7 +test: 100 -> 0 +braucht: whileSchleife +tipp: O ciclo é executado enquanto o número ainda for demasiado pequeno. Vai contando quantas vezes foi executado. +tipp: Precisas de uma segunda variável \`int passos = 0\`. A condição é \`numero < 100\`. No interior duplicas o número com \`numero = numero * 2\` e aumentas \`passos\` em 1. Se o número já for 100, o ciclo nem chega a ser executado. +lösung: l10-verdoppeln-loesung.visustruct +::: + +## Ciclos num teste de secretária + +Com um ciclo, o **teste de secretária** é especialmente valioso. Vês exatamente quantas vezes o ciclo é executado e com que valor para. Cada verificação da condição tem uma linha própria. + +::: diagramm l16-schreibtisch.visustruct +Um ciclo while soma os números 1, 2 e 3. +::: + +| Passo | soma | i | Saída | +|---|---|---|---| +| \`int soma = 0\` | 0 | – | | +| \`int i = 1\` | 0 | 1 | | +| \`i <= 3\` → true | 0 | 1 | | +| \`soma = soma + i\` | 1 | 1 | | +| \`i = i + 1\` | 1 | 2 | | +| \`i <= 3\` → true | 1 | 2 | | +| \`soma = soma + i\` | 3 | 2 | | +| \`i = i + 1\` | 3 | 3 | | +| \`i <= 3\` → true | 3 | 3 | | +| \`soma = soma + i\` | 6 | 3 | | +| \`i = i + 1\` | 6 | 4 | | +| \`i <= 3\` → false | 6 | 4 | | +| \`output: soma\` | 6 | 4 | 6 | + +Erros frequentes em ciclos são: + +- O ciclo é executado **uma vez a mais ou uma vez a menos**, p. ex. \`<\` em vez de \`<=\`. +- Uma variável **não é alterada** no ciclo, ou é alterada no sentido errado. Então o ciclo nunca acaba. +- Uma variável recebe o seu valor inicial **dentro** do ciclo em vez de antes dele e é reposta em cada iteração. + +## Exercício: Corrigir a contagem decrescente + +::: übung l16-countdown +titel: Corrigir a contagem decrescente +auftrag: A contagem decrescente deve contar para trás a partir do valor inicial e mostrar **Já!** no fim. Ou seja, com 3: 3, 2, 1, Já! + O diagrama inicial tem dois erros. Encontra e corrige os dois. +start: l16-countdown-start.visustruct +test: 3 -> 3 | 2 | 1 | Já! +test: 1 -> 1 | Já! +test: 0 -> Já! +tipp: Há dois erros. Um tem a ver com a contagem, o outro com a saída no fim. +tipp: Inicia a simulação com o valor inicial 3 e observa i em Variáveis. O i diminui? Compara também com atenção a última saída com a tarefa. +lösung: l16-countdown-loesung.visustruct +::: + +## Agora em Java + +A contagem decrescente do início desta lição fica assim em Java: + +\`\`\`java +int numero = 3; +while (numero > 0) { + System.out.println(numero); + numero = numero - 1; +} +System.out.println("Partida!"); +\`\`\` + +- Depois de \`while\`, a condição fica entre parênteses curvos, como em \`if\`. +- Tudo o que se repete fica entre chavetas. É o corpo do ciclo. +- O corpo está recuado. Assim vês, como no estrutograma, o que pertence ao ciclo. + +::: übung l11-java-gerade +titel: Números pares em Java +code: java +auftrag: Escreve um programa em Java que lê um número inteiro \`n\` e, com um ciclo while, mostra todos os números pares de 2 até no máximo \`n\`. Para 7, são 2, 4 e 6. +test: 7 -> 2 | 4 | 6 +test: 8 -> 2 | 4 | 6 | 8 +test: 2 -> 2 +braucht: whileSchleife +tipp: Precisas de uma variável contadora que começa em 2. O ciclo corre enquanto ela não for maior do que \`n\`. +tipp: \`int numero = 2;\` antes do ciclo, depois \`while (numero <= n) { … }\`. No corpo mostras \`numero\` e aumentas com \`numero = numero + 2;\`. +lösung: l11-java-gerade-loesung.visustruct +::: + +## Preenche os espaços: while + +::: lückentext +titel: Soma de 1 a 10 +auftrag: O programa deve somar os números de 1 a 10. Preenche as palavras e os sinais que faltam. +\`\`\`java +int soma = 0; +int numero = 1; +[[while]] (numero [[<=]] 10) [[{]] + soma = soma + [[numero]]; + [[numero]] = numero + 1; +} +System.out.println("Soma: " + soma); +\`\`\` +erklärung: O ciclo repete-se enquanto \`numero\` for no máximo 10. Em cada volta, \`numero\` é somado à soma e depois \`numero\` aumenta 1. Sem essa linha seria um ciclo infinito. Saída: **Soma: 55** +::: + +## Encontra o erro: poupar + +::: übung l11-java-fehler +titel: Corrigir o plano de poupança +code: java +auftrag: O Ludwig poupa 5 euros por semana. O programa pergunta o objetivo e deve mostrar ao fim de quantas semanas ele o atinge. Para 50 euros são 10 semanas, mas o programa diz **Semanas: 11**. + Percorre o código com Passo a passo e observa \`dinheiro\` e \`semanas\`. Corrige o erro e carrega em Verificar. +start: l11-java-fehler-start.visustruct +test: 50 -> Semanas: 10 +test: 12 -> Semanas: 3 +test: 5 -> Semanas: 1 +test: 1 -> Semanas: 1 +braucht: whileSchleife +tipp: Quanto dinheiro tem o Ludwig quando o ciclo se repete pela última vez? Precisa mesmo de poupar mais uma semana? +tipp: Só se poupa enquanto o objetivo **ainda não foi atingido**: \`while (dinheiro < objetivo)\`. +lösung: l11-java-fehler-loesung.visustruct +::: + +## Jogo: Quantas vezes? + +::: spiel frage +titel: Jogo: Quantas vezes? +intro: O Ludwig escreveu ciclos while. Faz o teste de secretária de cabeça. Seis rondas. + +runde: + int numero = 3; + while (numero > 0) { + System.out.println(numero); + numero = numero - 1; + } + System.out.println("Já!"); +frage: O que aparece? +- [x] 3\\n2\\n1\\nJá! +- 3\\n2\\n1\\n0\\nJá! +- Já! +> Quando numero é 0, \`numero > 0\` é falso, por isso o 0 já não aparece. + +runde: + int i = 10; + while (i < 5) { + System.out.println(i); + i = i + 1; + } +frage: O que aparece? +- [x] nada +- 10 +- de 10 a 4 +> A condição é verificada primeiro. 10 < 5 é falso, o corpo não corre nem uma vez. + +runde: + int i = 1; + while (i <= 3) { + System.out.println(i); + } +frage: O que acontece? +- Aparecem 1, 2 e 3. +- [x] O ciclo nunca para. +- Não aparece nada. +> i nunca aumenta no corpo. A condição fica sempre verdadeira: um ciclo infinito. + +runde: + int numero = 1; + while (numero < 100) { + numero = numero * 2; + } + System.out.println(numero); +frage: O que aparece? +- 64 +- 100 +- [x] 128 +> 1, 2, 4, 8, 16, 32, 64, 128. Só com 128 é que \`numero < 100\` é falso. + +runde: + int i = 0; + while (i < 5) { + i = i + 2; + } + System.out.println(i); +frage: O que aparece? +- 4 +- 5 +- [x] 6 +> i passa por 0, 2, 4, 6. Com 6, \`i < 5\` é falso. O 5 é saltado. + +runde: + int i = 1; + while (i <= 10) { + i = i + 3; + } +frage: Quantas vezes corre o corpo? +- 3 vezes +- [x] 4 vezes +- 10 vezes +> O corpo corre com i = 1, 4, 7 e 10. Depois i fica 13. +::: + +## 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. + +::: checkliste +- Consigo explicar que o ciclo while verifica a sua condição antes de cada iteração. → Primeiro a condição +- Consigo usar uma variável contadora com valor inicial, condição e alteração. → Uma variável contadora +- Consigo notar quando um ciclo nunca acaba e corrigir o erro. → Atenção: ciclo infinito +- Consigo seguir um ciclo iteração a iteração num teste de secretária. → Ciclos num teste de secretária +- Consigo escrever um ciclo while em Java. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? O que quer dizer ciclo pré-teste? +→ Primeiro a condição +- [x] A condição é verificada antes de cada iteração. +- [ ] A condição é verificada depois de cada iteração. +- [ ] O ciclo é sempre executado exatamente uma vez. +> A cabeça com a condição está em cima e é avaliada primeiro. + +? \`int i = 5\`, depois um ciclo while com a condição \`i < 3\`. Quantas vezes é executado o interior? +→ Primeiro a condição +- [x] Nenhuma +- [ ] Uma vez +- [ ] Três vezes +> Logo da primeira vez que é verificado, 5 < 3 é falso. + +? Porque é que um ciclo com a condição \`numero > 0\` nunca acaba se o interior só tiver \`output: numero\`? +→ Atenção: ciclo infinito +- [ ] Porque a saída aumenta o número +- [x] Porque numero nunca muda e a condição fica sempre verdadeira +- [ ] Porque a condição está mal escrita +> No interior tem de acontecer algo que acabe por tornar a condição falsa. + +? Que outros nomes têm os ciclos nos manuais? +→ Primeiro a condição +- [x] Iteração ou repetição +- [ ] Decisões +- [ ] Subprogramas +> Um ciclo repete instruções. Por isso também se chama iteração ou estrutura de repetição. + +? Um ciclo deve contar de 1 a 5, mas só vai até 4. Qual é o erro provável? +→ Uma variável contadora +- [x] A condição diz i < 5 em vez de i <= 5. +- [ ] O ciclo é um ciclo while. +- [ ] A variável i tem o nome errado. + +? Que linha começa corretamente um ciclo while em Java? +→ Agora em Java +- [ ] while numero > 0 { +- [x] while (numero > 0) { +- [ ] while (numero > 0); +> A condição fica entre parênteses curvos, depois \`{\` abre o corpo. +::: +`,tv=`--- +titel: Ciclo do-while +bereich: Fundamentos +kurz: Primeiro executar, depois verificar: ciclos com pelo menos uma iteração. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar que o ciclo do-while só verifica a sua condição depois do interior +- explicar porque é que o interior é executado pelo menos uma vez +- repetir uma entrada até ela ser válida +- escrever um ciclo do-while em Java +::: + +## Primeiro fazer, depois verificar + +O **ciclo do-while** é um **ciclo pós-teste**. A condição fica em baixo, no pé do bloco. É executado assim: + +1. Executar o interior uma vez. +2. Verificar a condição. +3. Se for verdadeira, recomeçar no 1. Se for falsa, o programa continua por baixo do ciclo. + +::: grafik l11-vergleich.svg +À esquerda, o ciclo while verifica primeiro; à direita, o ciclo do-while executa primeiro. +::: + +Em cima, no bloco, está \`do\`, e a condição fica no pé. Quando clicas no ciclo, a palavra \`while\` está à frente do campo de texto no Inspetor de objetos: a condição quer dizer “repete enquanto …”. + +> Tal como no ciclo while, a condição diz **quando é que o ciclo se repete**. Enquanto for verdadeira, o ciclo continua. + +::: angeberwissen +O Python não tem ciclo do-while. Quem lá quer “primeiro fazer, depois verificar” escreve \`while True:\` e sai do ciclo com \`break\`. Java, C e JavaScript, pelo contrário, têm \`do … while\` há décadas. +::: + +## Pelo menos uma iteração + +Como a condição só é verificada no fim, o interior **é sempre executado pelo menos uma vez**. Essa é a diferença mais importante em relação ao ciclo while. + +::: diagramm l11-einmal.visustruct +i vale 10 e, portanto, não é menor do que 5. Mesmo assim, 10 é mostrado uma vez, porque a verificação só vem depois. +::: + +Com um ciclo while e a mesma condição \`i < 5\`, aqui não seria mostrado nada. + +## Uso típico: repetir uma entrada + +O ciclo do-while serve sempre que alguma coisa tem de acontecer primeiro para a poderes verificar. O melhor exemplo é uma entrada: só depois de alguém ter escrito alguma coisa é que sabes se é válida. + +::: diagramm l11-eingabe-pruefen.visustruct +A pergunta repete-se até ser introduzido um número de 1 a 10. Na simulação, experimenta primeiro 0 e depois 12. +::: + +Aqui a condição descreve a entrada **inválida**: \`numero < 1 || numero > 10\`. Enquanto a entrada for inválida, a pergunta é feita outra vez. + +## Exercício: Nota válida + +::: übung l11-note +titel: Nota válida +auftrag: Pede uma nota. Se não estiver entre 1 e 5, pergunta outra vez. Se for válida, mostra-a, por exemplo **A tua nota: 3**. +test: 3 -> A tua nota: 3 +test: 0, 6, 2 -> A tua nota: 2 +test: 9, 5 -> A tua nota: 5 +test: -1, 1 -> A tua nota: 1 +braucht: doUntilSchleife +tipp: A nota é pedida pelo menos uma vez. Depois, a condição decide se se pergunta outra vez. +tipp: Antes do ciclo, cria \`int nota = 0\`. A entrada \`input: nota "Nota de 1 a 5"\` fica dentro do ciclo. A condição é \`nota < 1 || nota > 5\`. +lösung: l11-note-loesung.visustruct +::: + +## Exercício: Somar até 0 + +::: übung l11-summe +titel: Somar até 0 +auftrag: Pede números até ser introduzido um 0. Depois mostra a soma de todos os números introduzidos. +test: 3, 4, 0 -> 7 +test: 10, 0 -> 10 +test: 5, 5, 5, 0 -> 15 +test: 0 -> 0 +braucht: doUntilSchleife +tipp: Precisas de uma variável para a soma que começa em 0 antes do ciclo. Em cada iteração, o novo número é somado. +tipp: Antes do ciclo, cria \`int soma = 0\` e \`int numero = 0\`. No ciclo pedes \`numero\` e calculas \`soma = soma + numero\`. Somar o 0 não faz mal. O ciclo continua enquanto \`numero != 0\`. +lösung: l11-summe-loesung.visustruct +::: + +## Agora em Java + +O ciclo que corre mesmo assim uma vez fica assim em Java: + +\`\`\`java +int i = 10; +do { + System.out.println(i); + i = i + 1; +} while (i < 5); +\`\`\` + +- O corpo fica entre \`do {\` e \`}\`, a condição só vem depois. +- Aqui, depois de \`while (…)\`, há um **ponto e vírgula**. É diferente do ciclo while. + +::: übung l12-java-verdoppeln +titel: Duplicar pelo menos uma vez +code: java +auftrag: Escreve um programa em Java que lê um número inicial. Um ciclo do-while duplica-o e mostra-o enquanto for menor do que 100. Um número a partir de 100 também é duplicado pelo menos uma vez: 200 passa a 400. +test: 30 -> 60 | 120 +test: 200 -> 400 +test: 13 -> 26 | 52 | 104 +braucht: doUntilSchleife +tipp: No corpo duplicas o número e mostras. A condição fica no fim. +tipp: \`do { numero = numero * 2; System.out.println(numero); } while (numero < 100);\` +lösung: l12-java-verdoppeln-loesung.visustruct +::: + +## Preenche os espaços: do-while + +::: lückentext +titel: Triplicar +auftrag: O número é triplicado e mostrado enquanto for menor do que 100. Preenche as palavras e os sinais que faltam. +\`\`\`java +int numero = 1; +[[do]] { + numero = numero * 3; + System.out.println(numero); +} [[while]] (numero [[<]] 100)[[;]] +\`\`\` +erklärung: O corpo fica entre \`do {\` e \`}\`, a condição só vem depois. No ciclo do-while há um ponto e vírgula depois de \`while (…)\`. Saída: 3, 9, 27, 81 e 243. +::: + +## Encontra o erro: dividir ao meio + +::: übung l12-java-fehler +titel: Corrigir a divisão ao meio +code: java +auftrag: O programa lê um número inicial e, com um ciclo do-while, divide-o repetidamente por 2 (divisão inteira). Cada resultado é mostrado até chegar a **0**. Para 10 são 5, 2, 1 e 0. Mas falta o 0. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l12-java-fehler-start.visustruct +test: 10 -> 5 | 2 | 1 | 0 +test: 1 -> 0 +test: 7 -> 3 | 1 | 0 +test: 20 -> 10 | 5 | 2 | 1 | 0 +braucht: doUntilSchleife +tipp: Que valor tem \`numero\` depois de o 1 ser mostrado? O ciclo ainda se repete mais uma vez? +tipp: O ciclo deve continuar enquanto o número for maior do que 0: \`while (numero > 0);\` +lösung: l12-java-fehler-loesung.visustruct +::: + +## Jogo: Pelo menos uma vez? + +::: spiel frage +titel: Jogo: Pelo menos uma vez? +intro: While ou do-while? O Ludwig mostra-te ciclos. Diz antes o que acontece. Seis rondas. + +runde: + int i = 10; + do { + System.out.println(i); + i = i + 1; + } while (i < 5); +frage: O que aparece? +- nada +- [x] 10 +- de 10 a 4 +> Primeiro fazer, depois verificar: o corpo corre uma vez, depois 11 < 5 é falso. + +runde: + int i = 10; + while (i < 5) { + System.out.println(i); + i = i + 1; + } +frage: O que aparece? +- [x] nada +- 10 +- 11 +> No ciclo while a condição vem primeiro. 10 < 5 é falso, por isso não corre nada. + +runde: + int numero = 200; + do { + numero = numero * 2; + } while (numero < 100); + System.out.println(numero); +frage: O que aparece? +- 200 +- [x] 400 +- 800 +> Duplica-se uma vez de certeza. Depois 400 < 100 é falso. + +runde: + int numero = 30; + do { + numero = numero * 2; + System.out.println(numero); + } while (numero < 100); +frage: O que aparece? +- 60 +- [x] 60\\n120 +- 60\\n120\\n240 +> Depois de 60, 60 < 100 é verdadeiro, continua. Depois de 120 acaba. + +runde: +frage: Que linha termina corretamente um ciclo do-while em Java? +- [x] \`} while (i < 5);\` +- \`} while (i < 5)\` +- \`while (i < 5) {\` +> Depois do \`while (…)\` do ciclo do-while há um ponto e vírgula. + +runde: +frage: Para que se usa tipicamente um ciclo do-while? +- [x] repetir uma entrada até ser válida +- contar de 1 a 10 +- trocar dois valores +> A pergunta é feita pelo menos uma vez. Só depois se sabe se a entrada era válida. +::: + +## 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. + +::: checkliste +- Consigo explicar que o ciclo do-while só verifica a sua condição depois do interior. → Primeiro fazer, depois verificar +- Consigo explicar porque é que o interior é executado pelo menos uma vez. → Pelo menos uma iteração +- Consigo repetir uma entrada até ela ser válida. → Uso típico: repetir uma entrada +- Consigo escrever um ciclo do-while em Java. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? O que quer dizer ciclo pós-teste? +→ Primeiro fazer, depois verificar +- [ ] A condição é verificada antes de cada iteração. +- [x] A condição é verificada depois de cada iteração. +- [ ] O ciclo não tem condição. +> A condição fica no pé, em baixo, e é avaliada depois do interior. + +? A condição de um ciclo do-while é falsa desde o início. Quantas vezes é executado o interior? +→ Pelo menos uma iteração +- [ ] Nenhuma +- [x] Exatamente uma vez +- [ ] Para sempre +> O interior é executado primeiro. Só depois o ciclo nota que deve parar. + +? Queres pedir um número de 1 a 10. Que condição fica no pé? +→ Uso típico: repetir uma entrada +- [ ] \`numero >= 1 && numero <= 10\` +- [x] \`numero < 1 || numero > 10\` +- [ ] \`numero == 10\` +> O ciclo repete-se enquanto a entrada for inválida, ou seja, menor do que 1 ou maior do que 10. + +? Quando é que um ciclo do-while é melhor do que um ciclo while? +→ Pelo menos uma iteração +- [x] Quando o interior tem de ser executado pelo menos uma vez, p. ex. numa entrada +- [ ] Quando o ciclo talvez nem precise de ser executado +- [ ] Quando queres contar exatamente até 10 + +? O que fica no fim de um ciclo do-while em Java? +→ Agora em Java +- [ ] } while (condicao) { +- [x] } while (condicao); +- [ ] } until (condicao); +> Depois da condição vem um ponto e vírgula. +::: +`,nv=`--- +titel: Ciclo for +bereich: Fundamentos +kurz: Contar um número fixo de iterações com Início, Condição e Passo. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- nomear as três partes Início, Condição e Passo do ciclo for +- explicar por que ordem são executadas as três partes +- contar para a frente, para trás e em passos maiores com um ciclo for +- escrever um ciclo for em Java e explicar os seus três campos +::: + +## Contar com um plano fixo + +No ciclo while já foste contando: um valor inicial antes do ciclo, uma condição na cabeça, uma alteração no interior. O **ciclo for** junta estas três partes na cabeça. Assim vês num relance como ele conta. + +Quando clicas num ciclo for, ele tem três campos à direita: + +- **Início:** \`int i = 1\` cria a variável contadora. +- **Condição:** \`i <= 5\` diz até quando se conta. +- **Passo:** \`i++\` aumenta \`i\` em 1 depois de cada iteração. + +::: diagramm l12-eins-bis-fuenf.visustruct +Um ciclo for que mostra os números de 1 a 5. +::: + +::: angeberwissen +Porque é que a variável de contagem se chama quase sempre \`i\`? Na matemática, \`i\` representa há muito tempo um índice. E em FORTRAN, uma das primeiras linguagens de programação, de 1957, todas as variáveis começadas por I a N eram automaticamente números inteiros. Os programadores ainda não perderam o hábito. +::: + +## Por que ordem? + +As três partes são executadas em momentos diferentes: + +1. O **Início** é executado exatamente uma vez, logo no começo. +2. A **Condição** é verificada antes de cada iteração. Se for falsa, o ciclo termina. +3. Depois do interior vem o **Passo**, depois outra vez a condição. + +::: grafik l12-for-ablauf.svg +O Início só é executado uma vez. Depois, a condição, o interior e o passo repetem-se. +::: + +Portanto, o ciclo for é um ciclo pré-teste, como o ciclo while. Percorre o exemplo na simulação com **Passo** e observa como \`i\` muda. + +> Usa o ciclo for quando sabes de antemão quantas vezes uma coisa deve acontecer. Se o fim depender de algo que só acontece durante o ciclo, por exemplo uma entrada, é melhor o ciclo while ou do-while. + +## Exemplo: soma de 1 a n + +Um ciclo for é bom para somar números. Antes do ciclo está \`int soma = 0\`. Em cada iteração soma-se o número atual \`i\`. + +::: diagramm l12-summe.visustruct +Com n = 4, o ciclo calcula 0 + 1 + 2 + 3 + 4. No fim é mostrado 10. +::: + +## Outros passos + +O passo nem sempre tem de ser \`i++\`: + +- \`i--\` conta para trás, por exemplo com Início \`int i = 10\` e Condição \`i >= 1\`. +- \`i = i + 2\` salta de dois em dois, por exemplo 0, 2, 4, 6. + +Garante que o Início, a Condição e o Passo combinam. Com Início \`int i = 1\`, Condição \`i >= 1\` e Passo \`i++\`, a condição nunca fica falsa. + +::: übung l12-countdown +titel: Contagem decrescente +auftrag: Pede um número inteiro \`n\`. Usa um ciclo for para contar para trás de \`n\` até 1 e mostra cada número. Depois mostra **Já!**. +test: 3 -> 3 | 2 | 1 | Já! +test: 5 -> 5 | 4 | 3 | 2 | 1 | Já! +test: 1 -> 1 | Já! +braucht: forSchleife +tipp: Desta vez o ciclo for conta para trás. Pensa onde começa, quando para e como conta. +tipp: O Início é \`int i = n\`, a condição \`i >= 1\` e o passo \`i--\`. A saída Já! fica por baixo do ciclo, não dentro dele. +lösung: l12-countdown-loesung.visustruct +::: + +## Exercício: Tabuada + +::: übung l12-einmaleins +titel: Tabuada +auftrag: Pede um número e mostra a sua tabuada de 1 a 10. Cada linha fica assim: **3 x 1 = 3**, **3 x 2 = 6** e assim por diante. +test: 3 -> 3 x 1 = 3 | 3 x 2 = 6 | 3 x 3 = 9 | 3 x 4 = 12 | 3 x 5 = 15 | 3 x 6 = 18 | 3 x 7 = 21 | 3 x 8 = 24 | 3 x 9 = 27 | 3 x 10 = 30 +test: 7 -> 7 x 1 = 7 | 7 x 2 = 14 | 7 x 3 = 21 | 7 x 4 = 28 | 7 x 5 = 35 | 7 x 6 = 42 | 7 x 7 = 49 | 7 x 8 = 56 | 7 x 9 = 63 | 7 x 10 = 70 +braucht: forSchleife +tipp: O ciclo conta de 1 a 10. Em cada iteração mostras uma linha da tabuada. +tipp: No interior, calcula primeiro \`int produto = numero * i\`. Depois mostra \`numero + " x " + i + " = " + produto\`. Não te esqueças dos espaços dentro das aspas. +lösung: l12-einmaleins-loesung.visustruct +::: + +## Exercício: Corrigir a soma + +::: übung l16-summe +titel: Corrigir a soma +auftrag: O estrutograma deve somar todos os números de 1 a n. Ou seja, com n = 4 o resultado deve ser 1 + 2 + 3 + 4 = **10**. Mas mostra 6. + Faz um teste de secretária ou usa **Passo** e corrige o erro. +start: l16-summe-start.visustruct +test: 4 -> 10 +test: 1 -> 1 +test: 5 -> 15 +braucht: forSchleife +tipp: Percorre o ciclo com n = 4 de cabeça ou com **Passo**. Que números são realmente somados? +tipp: Olha para o último valor de i com que o ciclo é executado. Com n = 4, também tem de ser somado i = 4. +lösung: l16-summe-loesung.visustruct +::: + +## Agora em Java + +A soma de 1 até n fica assim em Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Até que número?"); +int n = scanner.nextInt(); +int soma = 0; +for (int i = 1; i <= n; i++) { + soma = soma + i; +} +System.out.println(soma); +\`\`\` + +Nos parênteses curvos depois de \`for\` estão os três campos do ciclo for, separados por ponto e vírgula: + +| Campo | Em Java | Significado | +|---|---|---| +| Início | \`int i = 1\` | \`i\` começa em 1. | +| Condição | \`i <= n\` | O ciclo corre enquanto isto for verdade. | +| Passo | \`i++\` | Depois de cada iteração, \`i\` aumenta 1. | + +\`i++\` é a forma curta de \`i = i + 1\`. Para contar para trás usas \`i--\`. + +::: übung l13-java-quadrate +titel: Quadrados em Java +code: java +auftrag: Escreve um programa em Java que lê um número inteiro \`n\` e, com um ciclo for, mostra os quadrados de 1 até \`n\`, cada um na sua linha. Para 3, são 1, 4 e 9. +test: 3 -> 1 | 4 | 9 +test: 5 -> 1 | 4 | 9 | 16 | 25 +test: 1 -> 1 +braucht: forSchleife +tipp: O ciclo conta \`i\` de 1 até \`n\`. O quadrado de \`i\` é \`i * i\`. +tipp: \`for (int i = 1; i <= n; i++) { … }\` e no corpo \`System.out.println(i * i);\`. +lösung: l13-java-quadrate-loesung.visustruct +::: + +## Preenche os espaços: for + +::: lückentext +titel: Contar para cima e para baixo +auftrag: O primeiro ciclo soma os números de 1 a 5, o segundo conta de 10 até 0 para trás. Preenche as palavras e os sinais que faltam. +\`\`\`java +int soma = 0; +[[for]] ([[int]] i = 1; i [[<=]] 5; [[i++ | i += 1 | i = i + 1]]) { + soma = soma + i; +} +System.out.println("Soma: " + soma); +for (int i = 10; i [[>=]] 0; [[i-- | i -= 1 | i = i - 1]]) { + System.out.println(i); +} +\`\`\` +erklärung: Entre os parênteses ficam o valor inicial, a condição e o passo, separados por ponto e vírgula. \`i++\` conta para cima, \`i--\` conta para baixo. Ao contar para trás até 0, a condição é \`i >= 0\`. +::: + +## Encontra o erro: tabuada + +::: übung l13-java-fehler +titel: Corrigir a tabuada +code: java +auftrag: O programa pergunta que tabuada queres e deve mostrá-la de 1 vez até 10 vezes, para o 7 são 7, 14, … até 70. Mas falta o 70. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l13-java-fehler-start.visustruct +test: 7 -> 7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 +test: 3 -> 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 +braucht: forSchleife +tipp: Quantas vezes se repete o ciclo? Conta os valores que \`i\` toma. +tipp: \`i\` também deve tomar o valor 10: \`i <= 10\` em vez de \`i < 10\`. +lösung: l13-java-fehler-loesung.visustruct +::: + +## Jogo: Desativar a bomba + +::: spiel bombe +titel: Jogo: Desativar a bomba +intro: Cada programa esconde **exatamente um erro**, e a bomba está a fazer tiquetaque. Lê o que o programa deve fazer e toca na linha errada antes de o tempo acabar. Oito rondas, 25 segundos cada. +zeit: 25 + +runde: + for (int i = 1; i <= 3; i++) { + System.out.println(i) + } +frage: Deve mostrar 1, 2 e 3. +fehler: 2 +besser: System.out.println(i); +> Falta o ponto e vírgula no fim da instrução. + +runde: + for (int i = 1, i <= 5, i++) { + System.out.println(i); + } +frage: Deve mostrar de 1 a 5. +fehler: 1 +besser: for (int i = 1; i <= 5; i++) { +> Os três campos do ciclo for separam-se com ponto e vírgula, não com vírgulas. + +runde: + for (int i = 10; i >= 1; i++) { + System.out.println(i); + } +frage: Deve contar para trás de 10 até 1. +fehler: 1 +besser: for (int i = 10; i >= 1; i--) { +> Com \`i++\`, \`i\` fica sempre maior e a condição \`i >= 1\` continua verdadeira: um ciclo infinito. Para contar para trás usas \`i--\`. + +runde: + int soma = 0; + for (int i = 1; i <= 4; i++) { + soma = i; + } + System.out.println(soma); +frage: Deve mostrar a soma 1 + 2 + 3 + 4 = 10. +fehler: 3 +besser: soma = soma + i; +> \`soma = i\` substitui a soma em cada iteração. No fim fica lá só 4. + +runde: + for (int i = 0; i <= 5; i++) { + System.out.println("Mééé"); + } +frage: Deve mostrar Mééé exatamente cinco vezes. +fehler: 1 +besser: for (int i = 0; i < 5; i++) { +> De 0 até 5, inclusive, são seis iterações. Quem começa em 0 usa \`<\`. + +runde: + for (int i = 1; i <= 3; i++) { + system.out.println(i); + } +frage: Deve mostrar 1, 2 e 3. +fehler: 2 +besser: System.out.println(i); +> O Java distingue maiúsculas de minúsculas: \`System\` escreve-se com S maiúsculo. + +runde: + int numero = 7; + for (int i = 1; i <= 10; i++) { + System.out.println(numero + " x " + i + " = " + numero * numero); + } +frage: Deve mostrar a tabuada do 7: 7 x 1 = 7, 7 x 2 = 14 e assim por diante. +fehler: 3 +besser: System.out.println(numero + " x " + i + " = " + numero * i); +> \`numero * numero\` dá sempre 49. Tem de ser \`numero * i\`. + +runde: + for (int i = 2; i <= 10; i + 2) { + System.out.println(i); + } +frage: Deve mostrar os números pares 2, 4, 6, 8 e 10. +fehler: 1 +besser: for (int i = 2; i <= 10; i = i + 2) { +> \`i + 2\` só calcula e não guarda nada. Para \`i\` crescer mesmo, é preciso \`i = i + 2\`. +::: + +## 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. + +::: checkliste +- Consigo nomear as três partes Início, Condição e Passo do ciclo for. → Contar com um plano fixo +- Consigo explicar por que ordem são executadas as três partes. → Por que ordem? +- Consigo contar para a frente, para trás e em passos maiores com um ciclo for. → Outros passos +- Consigo escrever um ciclo for em Java e explicar os seus três campos. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? Quantas vezes é executado o Início de um ciclo for? +→ Por que ordem? +- [x] Exatamente uma vez +- [ ] Antes de cada iteração +- [ ] Depois de cada iteração +> O Início cria a variável contadora uma vez, no começo. + +? Início \`int i = 0\`, Condição \`i < 3\`, Passo \`i++\`. Que valores tem i dentro do ciclo? +→ Contar com um plano fixo +- [ ] 1, 2, 3 +- [x] 0, 1, 2 +- [ ] 0, 1, 2, 3 +> Com i = 3 a condição é falsa, por isso o interior já não é executado. + +? Início \`int i = 2\`, Condição \`i <= 10\`, Passo \`i = i + 2\`. Quantas vezes é executado o interior? +→ Outros passos +- [ ] 4 vezes +- [x] 5 vezes +- [ ] 10 vezes +> i toma os valores 2, 4, 6, 8 e 10. + +? Quando é que um ciclo for serve melhor? +→ Contar com um plano fixo +- [x] Quando sabes de antemão quantas vezes repetir +- [ ] Quando perguntas até uma entrada ser válida +- [ ] Quando só é verificado um único valor + +? O que significa \`i++\` num ciclo for? +→ Contar com um plano fixo +- [ ] i é duplicado. +- [x] i aumenta 1. +- [ ] i é mostrado. +> \`i++\` é a forma curta de \`i = i + 1\`. +::: +`,iv=`--- +titel: Encaixar +bereich: Fundamentos +kurz: Combinar decisões dentro de ciclos e ciclos dentro de ciclos. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- pôr uma decisão dentro de um ciclo +- pôr um ciclo dentro de outro ciclo +- explicar que o ciclo interior é executado do princípio ao fim em cada iteração do exterior +- escrever ciclos e decisões encaixados em Java +::: + +## Blocos uns dentro dos outros + +Já conheces todos os blocos importantes: sequência, decisão, seleção e três tipos de ciclos. Só juntos é que eles se tornam realmente poderosos. + +Cada ramo e cada corpo do ciclo é, ele próprio, uma sequência. Podes pôr lá qualquer elemento, incluindo mais decisões e ciclos. A isto chama-se **encaixar**. + +> Para isso, basta arrastares um elemento para o marcador ø dentro de um ciclo ou de um ramo. + +## Uma decisão dentro de um ciclo + +O ciclo percorre todos os números, e a decisão decide para cada número se acontece alguma coisa. Assim podes contar, por exemplo, quantos números pares há de 1 a n. + +::: diagramm l13-gerade-zaehlen.visustruct +Em cada iteração, a decisão verifica com i % 2 == 0 se i é par. Só nesse caso quantidade aumenta 1. O ramo false fica vazio. +::: + +Com n = 7 são os números 2, 4 e 6, portanto é mostrado 3. + +## Exercício: Contar entradas pares + +::: übung l13-gerade-eingaben +titel: Contar entradas pares +auftrag: Pede exatamente **cinco** números inteiros, um a seguir ao outro. Depois mostra quantos deles eram pares. +test: 1, 2, 3, 4, 5 -> 2 +test: 2, 4, 6, 8, 10 -> 5 +test: 1, 3, 5, 7, 9 -> 0 +test: 10, 11, 0, 7, 8 -> 3 +braucht: forSchleife, verzweigung +tipp: Fazer a mesma coisa cinco vezes significa: ciclo. Em cada iteração é lido e verificado um número. +tipp: Um ciclo for de 1 a 5. No interior vem primeiro a entrada \`input: int numero "Introduz um número"\`, por baixo uma decisão com \`numero % 2 == 0\`. No ramo true aumentas \`quantidade\` em 1. +lösung: l13-gerade-eingaben-loesung.visustruct +::: + +## Um ciclo dentro de um ciclo + +Se um ciclo estiver dentro de outro, o **ciclo interior é executado do princípio ao fim em cada iteração do exterior**. Com isto podes construir padrões de linhas e colunas. + +::: diagramm l13-dreieck.visustruct +O ciclo exterior conta as linhas. O interior acrescenta ao texto tantas estrelas quantas o número da linha indica. Com n = 3 obténs um triângulo de 1, 2 e 3 estrelas. +::: + +Com \`String texto = ""\` cada linha começa vazia. \`texto = texto + "*"\` acrescenta uma estrela. Só quando a linha está pronta é que é mostrada. + +## Exercício: Retângulo + +::: übung l13-rechteck +titel: Retângulo +auftrag: Pede uma largura e uma altura. Mostra um retângulo feito de \`#\`: tantas linhas como a altura, e em cada linha tantos \`#\` como a largura. +test: 3, 2 -> ### | ### +test: 1, 3 -> # | # | # +test: 4, 1 -> #### +test: 2, 2 -> ## | ## +braucht: forSchleife +tipp: Precisas de dois ciclos, um dentro do outro: um para as linhas e, lá dentro, um para os caracteres de uma linha. +tipp: Constrói-o como o triângulo. A diferença: o ciclo interior conta sempre até \`largura\`, não até ao número da linha. O ciclo exterior conta até \`altura\`. +lösung: l13-rechteck-loesung.visustruct +::: + +## Não perder o fio + +Nos diagramas encaixados, o desenho ajuda-te: o que está mais para dentro fica recuado e rodeado pelo seu ciclo ou ramo. + +- Lê de fora para dentro: o que se repete? O que é decidido em cada iteração? +- Dá nomes com significado às variáveis contadoras, como \`linha\` e \`coluna\`. Dois ciclos não podem alterar a mesma variável contadora. +- Percorre um exemplo na simulação com **Passo** e observa as variáveis. + +::: angeberwissen +Foi exatamente para isto que o estrutograma foi inventado. Shneiderman perguntou-se: se devemos passar sem GOTO, porque não passar também sem as setas do fluxograma? O resultado: nada de esparguete de setas, e cada bloco fica bem arrumado no seu cercado. +::: + +## Agora em Java + +Contar os números pares fica assim em Java: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Até que número?"); +int n = scanner.nextInt(); +int quantidade = 0; +for (int i = 1; i <= n; i++) { + if (i % 2 == 0) { + quantidade++; + } // fim do if +} // fim do for +System.out.println(quantidade); +\`\`\` + +O que no estrutograma está encaixado, em Java está encaixado entre chavetas. Cada nível fica quatro espaços mais para dentro. Se o teu código ficar desarrumado, ajuda o botão **Indentar** em cima na área Código. + +Com muitas chavetas de fecho \`}\` é fácil perder a noção: que chaveta pertence a que bloco? Um comentário a seguir diz-te, p. ex. \`} // fim do if\` e \`} // fim do for\`. Isto também ajuda quando continuares mais tarde. + +\`quantidade++\` é a forma curta de \`quantidade = quantidade + 1\`. + +::: übung l14-java-treppe +titel: Escada de estrelas +code: java +auftrag: Escreve um programa em Java que lê o número de degraus e mostra uma escada de asteriscos. Para 3 degraus são \`*\`, \`**\` e \`***\`, cada degrau na sua linha. +test: 3 -> * | ** | *** +test: 1 -> * +test: 4 -> * | ** | *** | **** +braucht: forSchleife +tipp: Um ciclo exterior conta os degraus. Em cada degrau, um ciclo interior junta um texto de asteriscos. +tipp: No ciclo exterior: \`String linha = "";\`, depois \`for (int j = 1; j <= i; j++) { linha = linha + "*"; }\` e a seguir \`System.out.println(linha);\`. +lösung: l14-java-treppe-loesung.visustruct +::: + +## Preenche os espaços: encaixar + +::: lückentext +titel: Retângulo de estrelas +auftrag: O programa mostra um retângulo de 3 linhas com 4 estrelas cada. Preenche as palavras e os sinais que faltam. +\`\`\`java +for (int linha = 1; linha <= 3; linha++) { + String texto = [[""]]; + [[for]] (int coluna = 1; coluna [[<=]] 4; [[coluna++ | coluna += 1 | coluna = coluna + 1]]) { + texto = texto [[+]] "*"; + } + System.out.[[println]](texto); +[[}]] +\`\`\` +erklärung: O ciclo de dentro constrói uma linha de 4 estrelas, o de fora repete isso três vezes. Cada linha começa com um texto vazio \`""\`. A última chaveta fecha o ciclo de fora. +::: + +## Encontra o erro: divisíveis por 3 + +::: übung l14-java-fehler +titel: Corrigir a contagem +code: java +auftrag: O programa deve contar quantos números de 1 a \`n\` são divisíveis por 3 e mostrar o resultado **uma vez**. Para 10 é só **Quantidade: 3**. Mas mostra linhas a mais. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l14-java-fehler-start.visustruct +test: 10 -> Quantidade: 3 +test: 3 -> Quantidade: 1 +test: 2 -> Quantidade: 0 +braucht: forSchleife, verzweigung +tipp: Repara nas chavetas: a saída está dentro do ciclo ou depois dele? +tipp: Passa a linha \`System.out.println("Quantidade: " + quantidade);\` para depois da chaveta que fecha o ciclo. +lösung: l14-java-fehler-loesung.visustruct +::: + +## Jogo: Dentro e fora + +::: spiel frage +titel: Jogo: Dentro e fora +intro: O Ludwig encaixou blocos uns nos outros. Lê de fora para dentro e diz antes o que acontece. Seis rondas. + +runde: + for (int i = 1; i <= 3; i++) { + for (int j = 1; j <= 2; j++) { + System.out.println("*"); + } + } +frage: Quantas estrelas aparecem? +- 3 +- 5 +- [x] 6 +> O ciclo interior corre por completo em cada uma das 3 voltas do ciclo exterior: 3 · 2 = 6. + +runde: + for (int i = 1; i <= 2; i++) { + for (int j = 1; j <= 3; j++) { + System.out.println(i + " " + j); + } + } +frage: Que linha aparece em quarto lugar? +- 1 4 +- [x] 2 1 +- 2 2 +> Primeiro j percorre tudo com i = 1: 1 1, 1 2, 1 3. Depois j recomeça em 1, agora com i = 2. + +runde: + int contagem = 0; + for (int i = 1; i <= 10; i++) { + if (i % 3 == 0) { + contagem++; + } + } + System.out.println(contagem); +frage: O que aparece? +- [x] 3 +- 10 +- 4 +> A decisão só conta o 3, o 6 e o 9. + +runde: + for (int i = 1; i <= 4; i++) { + if (i % 2 == 0) { + System.out.println("par"); + } else { + System.out.println(i); + } + } +frage: O que aparece? +- 1\\n2\\n3\\n4 +- [x] 1\\npar\\n3\\npar +- par\\npar +> Em cada número a decisão volta a decidir: os ímpares aparecem como número, os pares como palavra. + +runde: + for (int i = 1; i <= 3; i++) { + String linha = ""; + for (int j = 1; j <= i; j++) { + linha = linha + "*"; + } + System.out.println(linha); + } +frage: O que aparece? +- ***\\n***\\n*** +- [x] *\\n**\\n*** +- ***\\n**\\n* +> O ciclo interior vai até i. Por isso cada linha fica com mais uma estrela. + +runde: + for (int i = 1; i <= 3; i++) { + for (int i = 1; i <= 3; i++) { + System.out.println(i); + } + } +frage: O que acontece? +- Aparece 1 a 3 três vezes. +- Aparece 1 a 3 uma vez. +- [x] O Java indica um erro. +> Dois ciclos um dentro do outro precisam de duas variáveis de contagem diferentes, por exemplo \`linha\` e \`coluna\`. +::: + +## 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. + +::: checkliste +- Consigo pôr uma decisão dentro de um ciclo. → Uma decisão dentro de um ciclo +- Consigo pôr um ciclo dentro de outro ciclo. → Um ciclo dentro de um ciclo +- Consigo explicar que o ciclo interior é executado do princípio ao fim em cada iteração do exterior. → Um ciclo dentro de um ciclo +- Consigo escrever ciclos e decisões encaixados em Java. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? O ciclo exterior é executado 3 vezes, o interior 4 vezes. Quantas vezes é executado ao todo o interior do ciclo interior? +→ Um ciclo dentro de um ciclo +- [ ] 7 vezes +- [x] 12 vezes +- [ ] 4 vezes +> Em cada uma das 3 iterações exteriores, o ciclo interior é executado 4 vezes, portanto 3 · 4 = 12. + +? Como sabes se um número é par? +→ Uma decisão dentro de um ciclo +- [ ] \`numero / 2 == 0\` +- [x] \`numero % 2 == 0\` +- [ ] \`numero == 2\` +> O % dá o resto de uma divisão. Nos números pares, o resto da divisão por 2 é zero. + +? Há uma decisão dentro de um ciclo for. Quantas vezes é verificada a condição da decisão? +→ Uma decisão dentro de um ciclo +- [ ] Uma vez +- [x] Uma vez por iteração do ciclo +- [ ] Só se for verdadeira +> A decisão faz parte do interior e é executada em cada iteração. + +? Como reconheces em Java o que pertence a um ciclo? +→ Agora em Java +- [ ] Pela cor +- [x] Pelas chavetas e pela indentação +- [ ] Pelos pontos e vírgulas +::: +`,av=`--- +titel: Arrays +bereich: Fundamentos +kurz: Guardar muitos valores com um só nome, chegar a eles com o índice e percorrê-los com um ciclo. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- criar um array com valores ou com \`new int[5]\` +- explicar que o índice começa em 0 e que o último índice é \`length - 1\` +- percorrer e encher um array com um ciclo for +- calcular a soma e o máximo de um array +- criar um array em Java e percorrê-lo com um ciclo +::: + +## Muitos valores com um só nome + +Imagina que queres guardar os pontos de cinco testes. Com cinco variáveis \`pontos1\` a \`pontos5\` isso fica depressa confuso. Um **array** é uma fila de posições que têm todas o mesmo nome e o mesmo tipo de dados. + +Crias um array com uma instrução. Depois do tipo de dados escreves parênteses retos \`[]\`: + +\`\`\` +int[] numeros = {2, 4, 6, 8, 10} +String[] nomes = {"Ada", "Rui", "Inês"} +\`\`\` + +Os valores entre chavetas vão logo para as posições. Também podes criar um array vazio com um número fixo de posições: + +\`\`\` +int[] pontos = new int[5] +String[] nomes = new String[3] +\`\`\` + +Com \`new int[5]\`, as cinco posições têm zeros no início; com \`new String[3]\`, textos vazios. + +## O índice começa em 0 + +Cada posição tem um número, o **índice**. Começa-se a contar em **0**. Portanto, com \`int[] numeros = {2, 4, 6, 8, 10}\`: + +- \`numeros[0]\` é 2 +- \`numeros[1]\` é 4 +- \`numeros[4]\` é 10 + +::: grafik l14-array.svg +Cinco posições com os índices 0 a 4. O índice está por cima da posição, o valor lá dentro. +::: + +**Porquê começar em 0?** Na informática, o índice não é “que posição”, mas sim a **distância ao início**. A primeira posição está logo no início, portanto a 0 passos. A segunda está a 1 passo, a terceira a 2 passos. Conheces isto do elevador: o rés-do-chão é o **0**, e o primeiro andar fica um nível acima. + +Daqui sai uma regra que vale a pena decorar: com 5 posições, o **último índice é 4**, sempre um a menos do que o número de posições. + +::: angeberwissen +Contar a partir de 0 já é bem antigo. A linguagem de programação C, de 1972, já funciona assim: o computador sabe o endereço da primeira posição e, para \`numeros[i]\`, calcula simplesmente “início mais i posições”. Com i = 0 fica no início, o que poupa uma conta. Java, Python e JavaScript copiaram isto. Já agora, eu também conto os meus chifres a partir de 0: chifre 0 à esquerda, chifre 1 à direita. +::: + +Com o índice lês um valor ou escreves lá um novo: + +\`\`\` +output: numeros[0] +numeros[1] = 99 +\`\`\` + +> Um array com 5 posições tem os índices 0 a 4. \`numeros[5]\` não existe. A simulação indica então uma expressão inválida. + +## O comprimento de um array + +\`numeros.length\` diz-te quantas posições tem um array. Com cinco valores é 5. Por isso, o **último** índice é sempre \`numeros.length - 1\`: + +\`\`\` +output: numeros.length +output: numeros[numeros.length - 1] +\`\`\` + +A segunda linha mostra o último valor, seja qual for o comprimento do array. O VisuStruct também percebe \`numeros.length()\`. + +::: übung l14-erster-letzter +titel: Primeiro e último valor +auftrag: Cria o array \`int[] valores = {4, 8, 15, 16, 23, 42}\`. Depois mostra em três linhas: o primeiro valor, o último valor e o número de valores. + Para o último valor, usa o comprimento e não escrevas simplesmente o índice 5. +test: - -> 4 | 42 | 6 +braucht: anweisung +tipp: Começa-se a contar em 0, por isso a primeira posição tem o índice 0. E qual é o índice da última posição? +tipp: O primeiro valor é \`valores[0]\`. O último é \`valores[valores.length - 1]\`. O número de valores é \`valores.length\`. +lösung: l14-erster-letzter-loesung.visustruct +::: + +## Percorrer um array com um ciclo + +Um array mostra a sua força junto com um **ciclo for**. A variável contadora \`i\` vai de 0 até ao último índice e é usada como índice: + +\`\`\` +int i = 0 +i < numeros.length +i++ +\`\`\` + +Na primeira iteração \`i\` é 0, na última é 4. Como a condição é \`i < numeros.length\`, o ciclo serve para qualquer comprimento. + +::: diagramm l14-array-durchlaufen.visustruct +O ciclo for mostra os cinco valores um a seguir ao outro. Em Variáveis, na simulação, vê o i a contar de 0 a 4. +::: + +É também assim que enches um array vazio com entradas. Como destino da entrada escreves a posição \`nomes[i]\`: + +::: diagramm l14-namen-eingeben.visustruct +São pedidos três nomes, que são escritos nas posições 0, 1 e 2. +::: + +::: übung l14-rueckwaerts +titel: Mostrar ao contrário +auftrag: Cria um array para 4 números inteiros e lê os 4 números com um ciclo. Depois mostra-os pela ordem **inversa**, cada um na sua linha. +test: 1, 2, 3, 4 -> 4 | 3 | 2 | 1 +test: 7, 0, 5, 9 -> 9 | 5 | 0 | 7 +braucht: forSchleife +tipp: Precisas de dois ciclos: um para ler da frente para trás e outro para mostrar de trás para a frente. +tipp: Crias o array com \`int[] numeros = new int[4]\`. A entrada é \`input: numeros[i] "Introduz um número"\`. No segundo ciclo começas em \`int i = numeros.length - 1\`, verificas \`i >= 0\` e contas para trás com \`i--\`. +lösung: l14-rueckwaerts-loesung.visustruct +::: + +## Soma e máximo + +Há duas tarefas que aparecem sempre com arrays: + +- **Soma:** Começas com \`soma = 0\` e somas cada valor no ciclo. +- **Máximo:** Primeiro guardas o valor da posição 0 como o maior até agora. No ciclo verificas cada valor. Se for maior, passa a ser o novo máximo. + +::: diagramm l14-summe-maximum.visustruct +Soma e máximo numa única passagem. O máximo começa com pontos[0] e não com 0, para também estar certo com números negativos. +::: + +::: übung l14-summe-max +titel: Soma e máximo +auftrag: Lê 5 números inteiros para um array. Depois mostra **Soma: …** e na linha seguinte **Máximo: …**. +test: 3, 9, 2, 9, 1 -> Soma: 24 | Máximo: 9 +test: 10, 20, 30, 40, 50 -> Soma: 150 | Máximo: 50 +test: -5, -2, -9, -1, -3 -> Soma: -20 | Máximo: -1 +braucht: forSchleife, verzweigung +tipp: Percorre o array com um ciclo. Soma cada valor à soma e guarda o maior valor visto até agora. +tipp: Calcula a soma e o máximo em variáveis próprias e só os mostra no fim, p. ex. com \`output: "Soma: " + soma\`. Se o teu máximo começar em 0, o terceiro teste falha. +lösung: l14-summe-max-loesung.visustruct +::: + +## Agora em Java + +Percorrer um array fica assim em Java: + +\`\`\`java +int[] numeros = {2, 4, 6, 8, 10}; +for (int i = 0; i < numeros.length; i++) { + System.out.println(numeros[i]); +} +\`\`\` + +- \`int[]\` quer dizer “array de números inteiros”. Os valores ficam entre chavetas. +- Um array vazio com 5 posições cria-se com \`new int[5]\`. +- \`numeros[i]\` é a posição com o índice \`i\`, \`numeros.length\` é o comprimento. + +::: übung l15-java-noten +titel: Soma das notas em Java +code: java +auftrag: Cria em Java o array \`notas\` com os valores 2, 3, 1 e 4. Soma todas as notas com um ciclo for e mostra **Soma: 10**. +test: - -> Soma: 10 +braucht: forSchleife +tipp: Cria \`int soma = 0;\` antes do ciclo. O ciclo vai de 0 até \`notas.length - 1\`. +tipp: \`int[] notas = {2, 3, 1, 4};\`, depois \`for (int i = 0; i < notas.length; i++) { soma = soma + notas[i]; }\` e no fim \`System.out.println("Soma: " + soma);\`. +lösung: l15-java-noten-loesung.visustruct +::: + +## Preenche os espaços: arrays + +::: lückentext +titel: Procurar o máximo +auftrag: O programa procura o maior valor do array. Preenche as palavras e os sinais que faltam. +\`\`\`java +[[int]][] valores = {3, 7, 1, 9, 4}; +int max = valores[0]; +[[for]] (int i = 1; i < valores.[[length]]; i++) { + if (valores[i] [[>]] max) { + max = valores[i]; + } +} +System.out.println("Máximo: " + max); +\`\`\` +erklärung: \`int[]\` é um array de números inteiros, \`valores.length\` é o seu comprimento. \`max\` começa com o primeiro valor e o ciclo compara todos os outros com ele. Saída: **Máximo: 9** +::: + +## Encontra o erro: temperaturas + +::: übung l15-java-fehler +titel: Corrigir a temperatura mais alta +code: java +auftrag: Em janeiro mediram-se as temperaturas -5, -2, -8 e -3 graus. O programa deve mostrar a mais alta, ou seja, **Temperatura mais alta: -2**. Mas diz 0 graus, embora nunca tenha estado tão quente. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l15-java-fehler-start.visustruct +test: - -> Temperatura mais alta: -2 +braucht: forSchleife, verzweigung +tipp: Com que valor começa \`max\`? Alguma das temperaturas é maior do que esse valor inicial? +tipp: \`max\` tem de começar com um valor do array: \`int max = temperaturas[0];\` +lösung: l15-java-fehler-loesung.visustruct +::: + +## Jogo: Desativar a bomba + +::: spiel bombe +titel: Jogo: Desativar a bomba +intro: Cada programa tem **exatamente um erro** com arrays, e a bomba está a fazer tique-taque. Toca na linha errada antes de o tempo acabar. Seis rondas, 30 segundos cada. +zeit: 30 + +runde: + int[] numeros = {2, 4, 6, 8, 10}; + for (int i = 0; i <= numeros.length; i++) { + System.out.println(numeros[i]); + } +frage: Deve mostrar os cinco valores. +fehler: 2 +besser: for (int i = 0; i < numeros.length; i++) { +> Com \`<=\`, i vai até 5. A posição \`numeros[5]\` não existe. + +runde: + String[] nomes = {"Ada", "Ben", "Cem"}; + System.out.println(nomes[1]); +frage: Deve mostrar o primeiro nome, ou seja, Ada. +fehler: 2 +besser: System.out.println(nomes[0]); +> Conta-se a partir de 0. \`nomes[1]\` já é o Ben. + +runde: + int[] numeros = {2, 4, 6, 8, 10}; + System.out.println(numeros[numeros.length]); +frage: Deve mostrar o último valor, ou seja, 10. +fehler: 2 +besser: System.out.println(numeros[numeros.length - 1]); +> O último índice é sempre um a menos do que o comprimento. + +runde: + int[] pontos = {3, 9, 2}; + int soma = 0; + for (int i = 0; i < pontos.length; i++) { + soma = pontos[i]; + } + System.out.println(soma); +frage: Deve mostrar a soma 14. +fehler: 4 +besser: soma = soma + pontos[i]; +> Assim cada valor apaga o anterior, e no fim soma só tem 2. + +runde: + int[] pontos = {-5, -2, -9}; + int max = 0; + for (int i = 0; i < pontos.length; i++) { + if (pontos[i] > max) { + max = pontos[i]; + } + } + System.out.println(max); +frage: Deve mostrar o máximo -2. +fehler: 2 +besser: int max = pontos[0]; +> Nenhum dos números é maior do que 0, por isso max ficaria em 0. É por isso que o máximo começa com a primeira posição. + +runde: + int[] numeros = {2, 4, 6, 8, 10}; + for (int i = numeros.length; i >= 0; i--) { + System.out.println(numeros[i]); + } +frage: Deve mostrar os valores de trás para a frente, de 10 a 2. +fehler: 2 +besser: for (int i = numeros.length - 1; i >= 0; i--) { +> De trás para a frente começa-se no último índice, que é \`numeros.length - 1\`. +::: + +## 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. + +::: checkliste +- Consigo criar um array com valores ou com \`new int[5]\`. → Muitos valores com um só nome +- Consigo explicar que o índice começa em 0 e que o último índice é \`length - 1\`. → O índice começa em 0 +- Consigo percorrer e encher um array com um ciclo for. → Percorrer um array com um ciclo +- Consigo calcular a soma e o máximo de um array. → Soma e máximo +- Consigo criar um array em Java e percorrê-lo com um ciclo. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? O que mostra \`output: numeros[2]\` com \`int[] numeros = {5, 10, 15, 20}\`? +→ O índice começa em 0 +- [ ] 10 +- [x] 15 +- [ ] 20 +> Começa-se a contar em 0: numeros[0] é 5, numeros[1] é 10, numeros[2] é 15. + +? Um array tem 8 posições. Qual é o último índice? +→ O índice começa em 0 +- [ ] 8 +- [x] 7 +- [ ] 9 +> O último índice é sempre length - 1. + +? Que condição serve para um ciclo for que percorre todos os valores de \`numeros\` e começa em \`int i = 0\`? +→ Percorrer um array com um ciclo +- [x] i < numeros.length +- [ ] i <= numeros.length +- [ ] i > numeros.length +> Com <= o ciclo também leria numeros[length], e essa posição não existe. + +? Com que valor deve começar o máximo antes de o ciclo começar? +→ Soma e máximo +- [ ] Sempre com 0 +- [x] Com o primeiro valor do array +- [ ] Com o comprimento do array +> Se começar com 0, então só com números negativos o resultado seria 0, embora o 0 nem esteja no array. + +? O que mostra \`output: numeros.length\` com \`int[] numeros = {5, 10, 15, 20}\`? +→ Muitos valores com um só nome +- [ ] 3 +- [x] 4 +- [ ] 20 +> length é o número de posições, não o último índice nem o último valor. + +? Que linha cria em Java um array com três números? +→ Agora em Java +- [x] int[] numeros = {1, 2, 3}; +- [ ] int numeros = [1, 2, 3]; +- [ ] array numeros = (1, 2, 3); +::: +`,sv=`--- +titel: Arrays bidimensionais +bereich: Fundamentos +kurz: Guardar valores em linhas e colunas, como os lugares de um cinema, e percorrê-los com dois ciclos encaixados. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- criar um array 2D e explicar o que significam os dois números +- ler e escrever uma posição com fila e lugar +- distinguir \`lugares.length\` de \`lugares[0].length\` +- explicar por que ordem dois ciclos encaixados visitam as posições +- criar e percorrer um array bidimensional em Java +::: + +## Um cinema como tabela + +Um cinema tem várias **filas**, e cada fila tem vários **lugares**. Para cada lugar queremos saber se o bilhete já foi vendido. É uma pergunta de sim ou não, por isso serve o tipo de dados \`boolean\`: \`true\` quer dizer vendido, \`false\` quer dizer livre. + +Um array normal é uma só fila de posições. Para o cinema precisamos de uma **tabela** com linhas e colunas. Isso é um **array bidimensional**, abreviado array 2D. Para isso escreves dois pares de parênteses retos: + +\`\`\` +boolean[][] lugares = new boolean[3][5] +\`\`\` + +Isto dá 3 filas com 5 lugares cada, ou seja, 15 posições. No início, todas as posições têm \`false\`: todos os lugares estão livres. + +::: grafik kino-saal.svg +O primeiro índice é a fila, o segundo é o lugar. Os dois contam-se a partir de 0. +::: + +## Chegar a uma posição + +Para uma posição precisas agora de **dois** índices: primeiro a fila, depois o lugar. + +\`\`\` +lugares[1][2] = true +\`\`\` + +Agora o lugar 2 da fila 1 está vendido. Ler funciona da mesma maneira: \`lugares[1][2]\` é agora \`true\`. + +Também podes perguntar o tamanho: + +- \`lugares.length\` é o número de **filas**, aqui 3. +- \`lugares[0].length\` é o número de **lugares** da fila 0, aqui 5. + +::: diagramm kino-verkaufen.visustruct +São vendidos três bilhetes. Depois, o diagrama mostra o tamanho do cinema e se a fila 1, lugar 2, está vendido. Repara em Variáveis, na simulação: lugares é mostrado fila a fila. +::: + +> Tal como num array normal, não existe a posição \`lugares[3][0]\`, porque as filas se chamam 0, 1 e 2. A simulação indica então uma expressão inválida. + +## Dois ciclos um dentro do outro + +Para olhar para **todos** os lugares, precisas de dois ciclos for, um dentro do outro: + +- O **ciclo exterior** conta a fila: \`fila\` vai de 0 a 2. +- O **ciclo interior** conta o lugar: \`lugar\` vai de 0 a 4. + +::: grafik kino-schleifen.svg +Azul é o ciclo exterior, laranja o interior. Os números mostram a ordem pela qual os lugares aparecem. +::: + +Para cada fila, o ciclo interior é executado **do princípio ao fim** uma vez. Só quando \`lugar\` passou pelos cinco lugares é que o ciclo exterior avança \`fila\` em um. Depois, \`lugar\` recomeça em 0. Assim, todos os 3 · 5 = 15 lugares aparecem exatamente uma vez. + +As condições são \`fila < lugares.length\` e \`lugar < lugares[fila].length\`. Assim os ciclos servem para um cinema de qualquer tamanho. + +::: diagramm kino-saalplan.visustruct +A planta da sala: para cada fila é montada e mostrada uma linha de X (vendido) e O (livre). Percorre-a com Passo e vê como lugar recomeça sempre do início, enquanto fila só vai contando devagar. +::: + +::: angeberwissen +Cada foto do telemóvel é um array 2D! Uma foto com 4000 · 3000 píxeis tem 3000 linhas com 4000 posições cada, ou seja, 12 milhões de píxeis. Cada posição guarda a cor de um ponto. Quando pões uma foto mais clara, o telemóvel percorre todos os píxeis com dois ciclos encaixados. A minha foto de perfil, já agora, só tem uma posição: castanho. +::: + +## Exercício: Contar lugares livres + +::: übung kino-frei +titel: Contar lugares livres +auftrag: No diagrama inicial já foram vendidos três bilhetes. Usa dois ciclos encaixados para contar quantos lugares ainda estão **livres** e mostra p. ex. \`Livres: 12\`. +start: kino-frei-start.visustruct +test: - -> Livres: 12 +braucht: forSchleife, verzweigung +tipp: Tal como na planta da sala, percorres todos os lugares com dois ciclos. Em vez de mostrares alguma coisa, contas. +tipp: Antes dos ciclos, cria \`int livres = 0\`. Um lugar está livre se \`lugares[fila][lugar]\` for false. A condição para isso é \`!lugares[fila][lugar]\`. +lösung: kino-frei-loesung.visustruct +::: + +## Exercício: Vender um bilhete + +::: übung kino-karte +titel: Vender um bilhete +auftrag: O diagrama inicial pede uma fila e um lugar. Se o lugar já estiver vendido, mostra \`Já vendido\`. Caso contrário, marca-o como vendido e mostra p. ex. \`Vendido: fila 0, lugar 4\`. +start: kino-karte-start.visustruct +test: 1, 2 -> Já vendido +test: 0, 4 -> Vendido: fila 0, lugar 4 +test: 2, 0 -> Vendido: fila 2, lugar 0 +braucht: verzweigung +tipp: Verifica primeiro se o lugar está vendido. Consoante a resposta, acontece uma coisa diferente. +tipp: Aqui não precisas de ciclo. Basta uma decisão com a condição \`lugares[fila][lugar]\`. No ramo false pões a posição a \`true\`. +lösung: kino-karte-loesung.visustruct +::: + +## Exercício: Tabela da tabuada + +::: übung kino-einmaleins +titel: Tabela da tabuada +auftrag: Cria \`int[][] tabela = new int[10][10]\` e enche-a com a tabuada até 10 usando dois ciclos. Depois pede dois números de 1 a 10 e lê o resultado da tabela, p. ex. \`3 · 4 = 12\`. +test: 3, 4 -> 3 · 4 = 12 +test: 7, 8 -> 7 · 8 = 56 +test: 10, 10 -> 10 · 10 = 100 +braucht: forSchleife +tipp: Primeiro, dois ciclos encaixados enchem a tabela; depois lês só uma única posição. +tipp: Os índices vão de 0 a 9, mas os números de 1 a 10. Por isso, a posição \`tabela[i][j]\` tem o valor \`(i + 1) * (j + 1)\`, e para 3 · 4 lês \`tabela[a - 1][b - 1]\`. +lösung: kino-einmaleins-loesung.visustruct +::: + +## Agora em Java + +A sala de cinema fica assim em Java: + +\`\`\`java +boolean[][] lugares = new boolean[3][5]; +lugares[0][2] = true; +lugares[1][1] = true; +lugares[1][2] = true; +System.out.println("Filas: " + lugares.length); +System.out.println("Lugares por fila: " + lugares[0].length); +System.out.println("Fila 1, lugar 2 vendido? " + lugares[1][2]); +\`\`\` + +- Dois pares de parênteses retos \`[][]\` representam uma tabela: primeiro a fila, depois o lugar. +- \`lugares.length\` é o número de filas, \`lugares[0].length\` o número de lugares numa fila. +- Com valores fixos, escreves cada fila nas suas próprias chavetas: \`int[][] t = {{1, 2}, {3, 4}};\` + +::: übung l16-java-punkte +titel: Somar os pontos +code: java +auftrag: Três jogadores jogaram duas rondas cada um. Cria em Java a tabela \`pontos\` com as filas {3, 5}, {4, 1} e {2, 2}. Soma todos os pontos com dois ciclos for encaixados e mostra **Soma: 17**. +test: - -> Soma: 17 +braucht: forSchleife +tipp: O ciclo exterior percorre as filas, o interior os lugares de uma fila. +tipp: \`int[][] pontos = {{3, 5}, {4, 1}, {2, 2}};\` e no ciclo interior \`soma = soma + pontos[i][j];\`. O ciclo interior vai até \`pontos[i].length\`. +lösung: l16-java-punkte-loesung.visustruct +::: + +## Preenche os espaços: tabelas + +::: lückentext +titel: Somar todos os campos +auftrag: O programa soma todos os números da tabela. Preenche as palavras e os sinais que faltam. +\`\`\`java +[[int]][][] campo = {{1, 2, 3}, {4, 5, 6}}; +int soma = 0; +for (int l = 0; l < campo.[[length]]; l++) { + for (int c = 0; c < campo[l].[[length]]; c++) { + soma = soma [[+]] campo[l][c]; + } +} +System.out.println("Soma: " + soma); +\`\`\` +erklärung: \`int[][]\` é uma tabela. \`campo.length\` é o número de linhas (2), \`campo[l].length\` o número de campos na linha \`l\` (3). Saída: **Soma: 21** +::: + +## Encontra o erro: pontos + +::: übung l16-java-fehler +titel: Corrigir o jogador 2 +code: java +auftrag: Na tabela \`pontos\`, cada linha corresponde a um jogador. O programa deve somar os pontos do jogador 2 (linha 1), ou seja, **Jogador 2: 11**. Em vez disso, dá um erro. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l16-java-fehler-start.visustruct +test: - -> Jogador 2: 11 +braucht: forSchleife +tipp: Em \`pontos[a][b]\`, \`a\` é a linha e \`b\` o lugar na linha. Que número corresponde à linha do jogador 2? +tipp: Os índices estão trocados: \`pontos[1][j]\` em vez de \`pontos[j][1]\`. +lösung: l16-java-fehler-loesung.visustruct +::: + +## Jogo: Que lugar? + +::: spiel frage +titel: Jogo: Que lugar? +intro: O Ludwig vende bilhetes de cinema. Primeiro a fila, depois o lugar, ambos a partir de 0. Sete rondas. + +runde: + boolean[][] lugares = new boolean[3][5]; + System.out.println(lugares.length); +frage: O que aparece? +- [x] 3 +- 5 +- 15 +> \`lugares.length\` é o número de filas. + +runde: + boolean[][] lugares = new boolean[3][5]; + System.out.println(lugares[0].length); +frage: O que aparece? +- 3 +- [x] 5 +- 15 +> \`lugares[0]\` é a fila 0. O seu comprimento é o número de lugares nessa fila. + +runde: + int[][] tabela = new int[4][6]; +frage: Quantas posições tem a tabela? +- 10 +- [x] 24 +- 35 +> 4 filas com 6 lugares cada: 4 · 6 = 24. + +runde: + int[][] t = {{1, 2}, {3, 4}}; + System.out.println(t[1][0]); +frage: O que aparece? +- 2 +- [x] 3 +- 4 +> A fila 1 é \`{3, 4}\`, e o lugar 0 dela é o 3. + +runde: + boolean[][] lugares = new boolean[3][5]; + lugares[3][0] = true; +frage: O que acontece? +- O primeiro lugar da fila 3 fica vendido. +- O primeiro lugar da última fila fica vendido. +- [x] Há um erro, porque as filas são 0, 1 e 2. +> Tal como num array normal, o último índice é um a menos do que o comprimento. + +runde: + int[][] t = {{1, 2, 3}, {4, 5, 6}}; + int soma = 0; + for (int fila = 0; fila < t.length; fila++) { + for (int lugar = 0; lugar < t[fila].length; lugar++) { + soma = soma + t[fila][lugar]; + } + } + System.out.println(soma); +frage: O que aparece? +- 6 +- 15 +- [x] 21 +> Os dois ciclos passam pelas seis posições: 1 + 2 + 3 + 4 + 5 + 6 = 21. + +runde: +frage: Dois ciclos percorrem a sala \`new boolean[3][5]\`. Que posição vem logo a seguir a \`lugares[0][4]\`? +- \`lugares[0][5]\` +- [x] \`lugares[1][0]\` +- \`lugares[1][4]\` +> A fila 0 terminou. O ciclo exterior avança, e o lugar recomeça em 0. +::: + +## 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. + +::: checkliste +- Consigo criar um array 2D e explicar o que significam os dois números. → Um cinema como tabela +- Consigo ler e escrever uma posição com fila e lugar. → Chegar a uma posição +- Consigo distinguir \`lugares.length\` de \`lugares[0].length\`. → Chegar a uma posição +- Consigo explicar por que ordem dois ciclos encaixados visitam as posições. → Dois ciclos um dentro do outro +- Consigo criar e percorrer um array bidimensional em Java. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? Quantas posições tem \`boolean[][] lugares = new boolean[4][6]\`? +→ Um cinema como tabela +- [ ] 10 +- [x] 24 +- [ ] 46 +> 4 filas com 6 lugares cada: 4 · 6 = 24. + +? O que está em todas as posições depois de \`new boolean[3][5]\`? +→ Um cinema como tabela +- [ ] true +- [x] false +- [ ] Nada, as posições estão vazias +> Um array boolean novo é enchido com false. No cinema isso quer dizer: todos os lugares estão livres. + +? Dois ciclos encaixados percorrem 3 filas com 5 lugares. Quantas vezes é executado o interior do ciclo **interior**? +→ Dois ciclos um dentro do outro +- [ ] 3 vezes +- [ ] 8 vezes +- [x] 15 vezes +> Para cada uma das 3 filas, o ciclo interior é executado 5 vezes: 3 · 5 = 15. + +? Associa o que cada expressão significa no cinema. +→ Chegar a uma posição += lugares.length -> Número de filas += lugares[0].length -> Número de lugares da fila 0 += lugares[2][4] -> Fila 2, lugar 4 += lugares[1][0] = true -> O lugar 0 da fila 1 está vendido + +? O que dá \`lugares.length\` para \`new boolean[3][5]\`? +→ Chegar a uma posição +- [x] 3, o número de filas +- [ ] 5, o número de lugares +- [ ] 15, todos os lugares juntos +::: +`,rv=`--- +titel: Strings +bereich: Fundamentos +kurz: Trabalhar com texto: ler caracteres, recortar partes, pesquisar, comparar e dividir. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar que os caracteres de uma String também se contam a partir de 0 +- trabalhar com \`length()\` e \`charAt(i)\` +- distinguir um \`char\` de uma String e usar o código de caractere com \`(int)\` e \`(char)\` +- recortar uma parte de um texto com \`substring\` +- usar \`indexOf\`, \`contains\`, \`toUpperCase\` e \`equals\` +- percorrer um texto caractere a caractere com um ciclo +- dividir um texto num array de Strings com \`split\` +- ler um texto em Java e compará-lo com \`equals\` +- usar mais métodos, como \`lastIndexOf\`, \`replace\`, \`compareTo\` e \`Integer.parseInt\` +- dividir o texto de um ficheiro em linhas com \`split("\\n")\` +- consultar um método na API do Java e ler a sua descrição +::: + +## Um texto é uma fila de caracteres + +Já conheces \`String\`: \`String nome = "Ludwig"\`. Na informática, um texto destes chama-se **string** (em inglês, “fio”), porque os caracteres ficam pendurados uns a seguir aos outros como contas num fio. Também se diz **cadeia de caracteres**. Cada caractere tem um lugar com um índice, tal como num array. Também aqui **se começa a contar em 0**: o primeiro caractere está a 0 passos do início. + +::: grafik zk-zeichen.svg +Os dez caracteres de “Passatempo” com os seus índices de 0 a 9. +::: + +Uma String traz consigo **métodos**. Escreves o nome da variável, um ponto e o método: + +- \`palavra.length()\` dá o número de caracteres, aqui 10. +- \`palavra.charAt(0)\` dá o caractere com o índice 0, aqui \`'P'\`. + +> Nas Strings escreves \`length()\` **com** parênteses, nos arrays \`length\` **sem**. Infelizmente, o Java é mesmo assim. + +Tal como num array, o último caractere tem o índice \`length() - 1\`. + +## Um único caractere: char + +Para um único caractere, o Java tem um tipo de dados próprio: **char**, abreviatura do inglês *character* (caractere). Um \`char\` fica entre aspas **simples**, uma String entre aspas duplas: + +- \`'C'\` é um \`char\`: exatamente um caractere. +- \`"C"\` é uma String: um texto que só tem um caractere. +- Um \`char\` tem sempre exatamente um caractere. Não existe um \`char\` vazio como \`''\`, mas uma String vazia \`""\` existe. + +\`charAt\` dá-te um caractere destes a partir de um texto: + +\`\`\` +char primeiro = palavra.charAt(0) +char ultimo = palavra.charAt(palavra.length() - 1) +\`\`\` + +Dois \`char\` comparas com \`==\`: \`palavra.charAt(0) == 'P'\` é \`true\`. + +Por trás de cada caractere há um número, o seu **código de caractere**. Que número pertence a que caractere está na tabela ASCII: \`'A'\` tem o código 65, \`'B'\` 66, \`'C'\` 67 e assim por diante até \`'Z'\` com 90. Com \`(int)\` obténs o código de um caractere, com \`(char)\` um código volta a ser um caractere: + +\`\`\` +int codigo = (int) 'C' +codigo = codigo + 1 +char seguinte = (char) codigo +\`\`\` + +Depois disto, \`codigo\` vale 68 e \`seguinte\` é \`'D'\`. Assim deslocas uma letra no alfabeto, e é exatamente isso que vais precisar mais tarde na cifra de César. + +## Recortar partes + +Com \`substring\` recortas uma parte do texto: + +- \`palavra.substring(0, 5)\` dá os caracteres desde o índice 0 **até mesmo antes** do índice 5, ou seja, \`"Passa"\`. +- \`palavra.substring(5)\` dá tudo desde o índice 5 até ao fim, ou seja, \`"tempo"\`. + +O fim **não** está incluído. Dá jeito: \`substring(0, 5)\` dá exatamente 5 caracteres. + +::: diagramm zk-zeichen.visustruct +Todos os métodos desta lição num exemplo. Percorre-o na simulação e compara cada saída com a imagem. +::: + +## Pesquisar e comparar + +Mais métodos de que precisas muitas vezes: + +| Método | Significado | Exemplo com \`"Passatempo"\` | +|---|---|---| +| \`indexOf("tempo")\` | Onde começa o texto? | 5 | +| \`indexOf("x")\` | não encontrado | -1 | +| \`contains("sat")\` | O texto aparece? | true | +| \`toUpperCase()\` | tudo em maiúsculas | PASSATEMPO | +| \`toLowerCase()\` | tudo em minúsculas | passatempo | +| \`equals("Passatempo")\` | o mesmo texto? | true | + +> Em Java comparas duas Strings com \`equals\`, não com \`==\`. Já dois caracteres (\`char\`) comparas com \`==\`, p. ex. \`palavra.charAt(i) == 'a'\`. + +::: angeberwissen +Experimenta \`"Ludwig".equals("ludwig")\`. A resposta é false! Para um computador, L e l são caracteres completamente diferentes. Lá dentro, cada caractere é guardado como um número: L é 76 e l é 108. Esta numeração chama-se ASCII e é de 1963. Mééé, portanto, para um computador, Ludwig e ludwig são dois bodes diferentes. Eu sou o do L maiúsculo. +::: + +## Caractere a caractere + +Com um ciclo for percorres um texto caractere a caractere. O índice \`i\` vai de 0 a \`palavra.length() - 1\`, tal como num array: + +::: diagramm zk-zaehlen.visustruct +Conta quantas vezes aparece a letra a. Na simulação, experimenta “banana” e observa i e quantidade. +::: + +## Dividir com split + +Muitas vezes há várias informações numa só linha, separadas por um caractere, p. ex. \`"Ludwig;bode;7"\`. Com \`split\` cortas a linha nesse caractere. O resultado é um **array de Strings**: + +\`\`\` +String[] partes = linha.split(";") +\`\`\` + +Depois disso, \`partes[0]\` é \`"Ludwig"\`, \`partes[1]\` é \`"bode"\` e \`partes[2]\` é \`"7"\`. Com \`partes.length\` descobres quantas partes há. + +::: diagramm zk-split.visustruct +A linha é dividida no ponto e vírgula, e cada parte é mostrada com o seu índice. +::: + +> Os ficheiros CSV, que conheces das folhas de cálculo, são feitos da mesma maneira: uma linha por registo, com os valores separados por vírgula ou ponto e vírgula. + +## Exercício: Iniciais + +::: übung zk-initialen +titel: Iniciais +auftrag: Pede um nome próprio e um apelido e mostra as iniciais. Ou seja, para Ludwig Bode fica \`L. B.\` +test: Ludwig, Bode -> L. B. +test: Ada, Lovelace -> A. L. +test: Ben, Shneiderman -> B. S. +braucht: anweisung +tipp: A inicial é a primeira letra de um nome. Que método dá o caractere numa determinada posição? +tipp: \`nome.charAt(0)\` dá a primeira letra. A saída fica então \`nome.charAt(0) + ". " + apelido.charAt(0) + "."\` +lösung: zk-initialen-loesung.visustruct +::: + +## Exercício: Ao contrário + +::: übung zk-rueckwaerts +titel: Ao contrário +auftrag: Pede uma palavra e mostra-a ao contrário. Ludwig passa a \`giwduL\`. +test: Ludwig -> giwduL +test: Ana -> anA +test: a -> a +braucht: forSchleife +tipp: Percorre a palavra caractere a caractere, mas de trás para a frente, e vai construindo um novo texto. +tipp: Cria \`String invertida = ""\`. O ciclo começa no último índice \`palavra.length() - 1\` e conta para trás até 0 com \`i--\`. Em cada iteração acrescentas \`palavra.charAt(i)\` no fim. +lösung: zk-rueckwaerts-loesung.visustruct +::: + +## Exercício: Contar palavras + +::: übung zk-woerter +titel: Contar palavras +auftrag: Pede uma frase e mostra quantas palavras tem, p. ex. \`Palavras: 5\` para “O Ludwig é um bode”. As palavras estão separadas por exatamente um espaço. +test: O Ludwig é um bode -> Palavras: 5 +test: Olá -> Palavras: 1 +test: Eu gosto de cabras -> Palavras: 4 +braucht: anweisung +tipp: Entre as palavras há sempre um espaço. Que método divide um texto num caractere? +tipp: Divide a frase num array de Strings com \`frase.split(" ")\`. O seu comprimento é o número de palavras. +lösung: zk-woerter-loesung.visustruct +::: + +## Agora em Java + +Os métodos desta lição já são Java. Um programa completo com um texto fica assim: + +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Como te chamas?"); +String nome = scanner.next(); +System.out.println("Olá " + nome.toUpperCase() + "!"); +System.out.println("O teu nome tem " + nome.length() + " letras."); +\`\`\` + +- \`scanner.next()\` lê uma palavra, ou seja, texto até ao próximo espaço. Para números continuas a usar \`scanner.nextInt()\`. +- O texto fica entre aspas **duplas** \`"Ludwig"\`, um único carácter entre aspas **simples** \`'L'\`. +- Depois de \`length()\`, \`toUpperCase()\` e dos outros métodos há sempre parênteses curvos, mesmo quando não há nada lá dentro. +- Comparas dois textos com \`equals\`. Cada letra conta: \`"Ludwig".equals("ludwig")\` é false. + +::: übung l17-java-passwort +titel: Verificar a palavra-passe +code: java +auftrag: Escreve em Java um programa que pergunta pela palavra-passe. Se for **Ludwig**, mostra **Bem-vindo!**, senão **Palavra-passe errada**. + Atenção às maiúsculas e minúsculas: \`ludwig\` está errado. +test: Ludwig -> Bem-vindo! +test: ludwig -> Palavra-passe errada +test: Geißbock -> Palavra-passe errada +braucht: verzweigung +tipp: Lê a palavra-passe com \`scanner.next()\` para uma variável String. Depois comparas numa decisão. +tipp: A condição é \`entrada.equals("Ludwig")\`. Em Java, \`==\` não compara textos de forma fiável. +lösung: l17-java-passwort-loesung.visustruct +::: + +## Preenche os espaços: textos + +::: lückentext +titel: Analisar uma palavra +auftrag: Preenche os métodos e as palavras que faltam. +\`\`\`java +import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Uma palavra?"); +[[String]] palavra = scanner.next(); +System.out.println("Comprimento: " + palavra.[[length]]()); +System.out.println("Maiúsculas: " + palavra.[[toUpperCase]]()); +System.out.println("Primeira letra: " + palavra.[[charAt]](0)); +if (palavra.[[equals]]("Ludwig")) { + System.out.println("Olá Ludwig!"); +} +\`\`\` +erklärung: \`length()\` conta os carateres, \`toUpperCase()\` põe tudo em maiúsculas, \`charAt(0)\` dá o primeiro caráter. Textos comparas com \`equals\`, não com \`==\`. +::: + +## Encontra o erro: iniciais + +::: übung l17-java-fehler +titel: Corrigir as iniciais +code: java +auftrag: O programa lê o nome próprio e o apelido e deve mostrar as iniciais. Para Ludwig Geißbock é **L. G.** Mas mostra **u. e.** + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l17-java-fehler-start.visustruct +test: Ludwig, Geißbock -> L. G. +test: Mia, Meyer -> M. M. +test: Ada, Lovelace -> A. L. +braucht: anweisung +tipp: Em que índice começa o Java a contar? +tipp: O primeiro caráter tem o índice 0: \`nome.charAt(0)\` e \`apelido.charAt(0)\`. +lösung: l17-java-fehler-loesung.visustruct +::: + +## Ainda mais métodos + +Uma String sabe fazer muito mais. Também vais precisar muitas vezes destes métodos: + +| Método | Significado | Exemplo | Resultado | +|---|---|---|---| +| \`lastIndexOf("a")\` | Onde está o último a? | \`"Passatempo".lastIndexOf("a")\` | 4 | +| \`isEmpty()\` | O texto está vazio? | \`"".isEmpty()\` | true | +| \`equalsIgnoreCase(…)\` | o mesmo texto, sem contar maiúsculas e minúsculas? | \`"Passatempo".equalsIgnoreCase("PASSATEMPO")\` | true | +| \`replace(antigo, novo)\` | substitui todas as ocorrências | \`"Passatempo".replace("tempo", "porte")\` | Passaporte | +| \`repeat(n)\` | o texto n vezes seguidas | \`"Mé".repeat(3)\` | MéMéMé | +| \`concat(…)\` | junta texto no fim, como \`+\` | \`"Passa".concat("tempo")\` | Passatempo | +| \`compareTo(…)\` | Qual vem primeiro no alfabeto? | \`"Anna".compareTo("Ben")\` | -1 | + +\`compareTo\` devolve um número: **negativo** se o texto vem antes no alfabeto, **0** se os dois são iguais e **positivo** se vem depois. Assim podes ordenar nomes. + +Dois métodos não pertencem a um texto, mas a uma classe. Por isso, à frente fica o nome da classe: + +- \`Integer.parseInt("7")\` transforma o texto "7" no número 7. Com ele já podes fazer contas. +- \`String.valueOf(7)\` transforma o número 7 no texto "7". + +::: diagramm zk-mehr.visustruct +Todos os métodos novos num só exemplo. Percorre-o na simulação e compara cada saída com a tabela. +::: + +## Texto de um ficheiro + +Os programas recebem muitas vezes o texto de um **ficheiro**. A Princesa Zora escreveu uma carta ao Ludwig. Ela está pronta no ficheiro \`carta.txt\`: + +::: datei carta.txt +Querido Ludwig, +a raposa fechou-me na sua torre. +A porta tem um cadeado com uma palavra secreta. +Só encontras a palavra com Java. +Ajuda-me, por favor! +A tua Princesa Zora +::: + +Estas linhas leem o ficheiro inteiro para uma String: + +\`\`\` +import java.nio.file.*; + +String carta = Files.readString(Path.of("carta.txt")); +\`\`\` + +Como a leitura funciona ao certo, vais aprender mais tarde, numa lição só sobre ficheiros. Por agora basta: depois disto, a carta inteira está em \`carta\`, com todas as linhas. + +No fim de cada linha há um carácter invisível para a **mudança de linha**. Em Java escreve-se \`"\\n"\`. Por isso, \`carta.split("\\n")\` divide a carta nas suas linhas. + +::: übung l17-java-brief +titel: Onde está a raposa? +code: java +auftrag: O código inicial já lê a carta. Divide-a em linhas e mostra **Linhas:** e o número de linhas. Depois procura a linha onde está **raposa** e mostra **Raposa na linha** e o seu número. A primeira linha tem o número 1. +start: l17-java-brief-start.visustruct +test: - -> Linhas: 6 | Raposa na linha 2 +braucht: forSchleife, verzweigung +tipp: \`String[] linhas = carta.split("\\n");\` divide a carta. Depois, um ciclo for percorre todas as linhas. +tipp: No ciclo verificas \`linhas[i].contains("raposa")\`. O índice começa em 0, por isso mostras \`(i + 1)\`. Os parênteses são precisos para o Java fazer a conta em vez de juntar 1 ao texto. +lösung: l17-java-brief-loesung.visustruct +::: + +## A API do Java + +Ninguém sabe todos os métodos de cor, nem os profissionais. Eles consultam a **API do Java**. API significa Application Programming Interface. É a descrição de tudo o que o Java já traz consigo. + +Todos os métodos de String estão aqui: [String na API do Java](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/String.html) + +Desce até à tabela **Method Summary**. Cada linha descreve um método: + +| Coluna | Exemplo | Significado | +|---|---|---| +| Modifier and Type | \`int\` | O que o método devolve | +| Method | \`lastIndexOf(String str)\` | Nome e parâmetros com o seu tipo de dados | +| Description | Returns the index within this string of the last occurrence … | O que o método faz | + +A API está em inglês. O teu browser pode traduzir a página. Os nomes dos métodos ficam em inglês, porque é assim que os escreves em Java. + +::: ludwig +A página é muito comprida. Com Ctrl+F (no Mac ⌘+F) procuras o nome do método e chegas lá logo. +::: + +Consulta estes métodos. Não estão nesta lição: + +::: quiz +? Consulta \`strip()\`. O que faz o método? +- [ ] Remove todos os espaços do texto. +- [x] Remove os espaços no início e no fim. +- [ ] Corta o último carácter. +> Como \`trim()\`. Mas \`strip()\` também conhece espaços especiais de outras escritas. + +? Consulta \`isBlank()\`. O que devolve \`" ".isBlank()\`? +- [x] true +- [ ] false +- [ ] 3 +> isBlank verifica se o texto está vazio ou só tem espaços. Já \`" ".isEmpty()\` seria false. + +? Consulta \`toCharArray()\`. Que tipo de dados devolve o método? +- [ ] String +- [ ] String[] +- [x] char[] +> Um array com todos os caracteres do texto, uma posição para cada carácter. + +? Consulta \`indexOf\` com dois parâmetros. O que devolve \`"Passatempo".indexOf("a", 2)\`? +- [ ] 1 +- [x] 4 +- [ ] -1 +> A pesquisa só começa no índice 2. O primeiro a a partir daí está no índice 4. + +? Consulta \`startsWith\`. Que tipo de dados devolve o método? +- [x] boolean +- [ ] int +- [ ] String +> Na coluna “Modifier and Type” está boolean: a resposta é true ou false. +::: + +## Jogo: Salvar a princesa + +Agora ajudas o Ludwig. A raposa fechou a princesa Zora na sua torre, e o portão só abre com uma palavra secreta. + +::: spiel prinzessin +titel: Jogo: Salvar a princesa +intro: No caminho para a torre, o Ludwig passa por **seis estações**. Em cada uma há um pedaço de código Java, e sai um número. Com \`alphabet.charAt(numero)\` o número transforma-se numa letra, que vai para as **palavras cruzadas**. Resolve-as, e os quadrados amarelos formam a palavra secreta para o portão. + +station: No fosso + String nome = " Zora "; + int numero = nome.trim().length(); +frage: Que número fica em \`numero\`? +zahl: 4 +feld: 5 1 +tipp: \`trim()\` corta os espaços no início e no fim. Depois conta os caracteres. +> Depois do \`trim()\` fica só \`"Zora"\`, que tem 4 caracteres. + +station: Na floresta da raposa + String lugar = "A raposa"; + int numero = lugar.length(); +frage: Que número fica em \`numero\`? +zahl: 8 +feld: 4 4 +tipp: \`length()\` conta todos os caracteres, também o espaço. +> O A, o espaço e r-a-p-o-s-a dão 8 caracteres. + +station: Na rocha das cabras + String texto = "Ludwig o bode"; + int numero = texto.indexOf(" "); +frage: Que número fica em \`numero\`? +zahl: 6 +feld: 4 6 +tipp: \`indexOf\` devolve a posição do primeiro espaço. O L tem o índice 0. +> L u d w i g tem os índices 0 a 5, por isso o primeiro espaço está no índice 6. + +station: Na escada da torre + String palavra = "Princesa"; + int numero = palavra.indexOf("a", 5); +frage: Que número fica em \`numero\`? Procura \`indexOf(String str, int fromIndex)\` na API do Java. +zahl: 7 +feld: 6 6 +tipp: A pesquisa começa no índice 5. Escreve os índices por baixo das letras. +> P r i n c e s a tem os índices 0 a 7. A partir do índice 5, o primeiro “a” está no 7. + +station: Diante da toca da raposa + int numero = "Zora".compareTo("Zoe"); +frage: Que número fica em \`numero\`? +zahl: 13 +feld: 1 9 +tipp: \`compareTo\` procura a primeira posição em que os textos são diferentes e subtrai os códigos dos caracteres. \`'r'\` é 114, \`'e'\` é 101. +> “Zo” é igual, depois vem \`'r'\` contra \`'e'\`: 114 − 101 = 13. + +station: No portão da torre + int numero = Integer.parseInt("1" + "1") / 5; +frage: Que número fica em \`numero\`? +zahl: 2 +feld: 6 5 +tipp: Primeiro os textos são juntados, depois passam a número. Com \`int\`, a divisão deita fora o resto. +> \`"1" + "1"\` é \`"11"\`, o \`parseInt\` faz disso 11, e 11 / 5 dá 2 com números inteiros. + +kreuzwort: As letras azuis já as tens. Preenche os outros quadrados com termos do Java. Clica numa pista para saltar para a palavra. +- → 1 3 BOOLEAN: Tipo de dados para verdadeiro ou falso +- → 4 1 STRING: Tipo de dados para texto +- → 6 5 CHAR: Tipo de dados para um único carácter +- ↓ 1 6 LENGTH: Método que conta os caracteres de uma string +- ↓ 2 1 ELSE: A parte “senão” de uma decisão +- ↓ 3 3 BREAK: Sai imediatamente de um ciclo +lösung: 1 3, 4 3, 2 6, 6 7, 7 3 + +tor: O Ludwig está diante do portão. A fechadura compara a tua palavra com \`equals\`. Escreve a palavra secreta. + String palavra = "___"; + if (palavra.equals(palavraSecreta)) { + portao.abrir(); + } +ende: A Zora está livre, e a raposa fugiu a correr. A palavra secreta era \`BREAK\`: com \`break\` sai-se de qualquer ciclo, e a Zora sai da torre. +::: + +## 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. + +::: checkliste +- Consigo explicar que os caracteres de uma String também se contam a partir de 0. → Um texto é uma fila de caracteres +- Consigo trabalhar com \`length()\` e \`charAt(i)\`. → Um texto é uma fila de caracteres +- Consigo distinguir um \`char\` de uma String e usar o código de caractere com \`(int)\` e \`(char)\`. → Um único caractere: char +- Consigo recortar uma parte de um texto com \`substring\`. → Recortar partes +- Consigo usar \`indexOf\`, \`contains\`, \`toUpperCase\` e \`equals\`. → Pesquisar e comparar +- Consigo percorrer um texto caractere a caractere com um ciclo. → Caractere a caractere +- Consigo dividir um texto num array de Strings com \`split\`. → Dividir com split +- Consigo ler um texto em Java e compará-lo com \`equals\`. → Agora em Java +- Consigo usar mais métodos, como \`lastIndexOf\`, \`replace\`, \`compareTo\` e \`Integer.parseInt\`. → Ainda mais métodos +- Consigo dividir o texto de um ficheiro em linhas com \`split("\\n")\`. → Texto de um ficheiro +- Consigo consultar um método na API do Java e ler a sua descrição. → A API do Java +::: + +## Teste de conhecimentos + +::: quiz +? Quanto dá \`"Ludwig".charAt(1)\`? +→ Um texto é uma fila de caracteres +- [ ] L +- [x] u +- [ ] d +> Começa-se a contar em 0: L tem o índice 0, u o índice 1. + +? O que é \`'C'\`? +→ Um único caractere: char +- [x] um \`char\`, ou seja, exatamente um caractere +- [ ] uma String +- [ ] uma variável chamada C +> Aspas simples indicam um único caractere, um \`char\`. \`"C"\` entre aspas duplas seria uma String. + +? \`'A'\` tem o código de caractere 65. Quanto dá \`(char) 67\`? +→ Um único caractere: char +- [ ] 'B' +- [x] 'C' +- [ ] 67 +> 65 é A, 66 é B, 67 é C. Com \`(char)\` o código volta a ser um caractere. + +? Quanto dá \`"Estrutura".substring(0, 6)\`? +→ Recortar partes +- [x] Estrut +- [ ] Estrutu +- [ ] strutu +> Os caracteres com os índices 0 a 5. O fim 6 não está incluído. + +? Uma palavra tem 7 caracteres. Que índice tem o último caractere? +→ Um texto é uma fila de caracteres +- [ ] 7 +- [x] 6 +- [ ] 8 +> Tal como num array: sempre um a menos do que o comprimento. + +? Como comparas duas Strings quanto ao conteúdo em Java? +→ Pesquisar e comparar +- [ ] a == b +- [x] a.equals(b) +- [ ] a = b + +? Associa cada método ao que dá para \`"Passatempo"\`. +→ Pesquisar e comparar += length() -> 10 += charAt(0) -> P += indexOf("tempo") -> 5 += substring(5) -> tempo + +? Que condição verifica em Java se \`entrada\` contém o texto Ludwig? +→ Agora em Java +- [ ] entrada = "Ludwig" +- [ ] entrada == 'Ludwig' +- [x] entrada.equals("Ludwig") +> Comparas textos com equals. As aspas simples são só para um único carácter. + +? O que devolve \`Integer.parseInt("12") + 1\`? +→ Ainda mais métodos +- [ ] "121" +- [x] 13 +- [ ] uma mensagem de erro +> parseInt transforma o texto num número. Depois o Java faz a conta normalmente. +::: +`,ov=`--- +titel: Chamada e interrupção +bereich: Fundamentos +kurz: Dividir tarefas grandes em subprogramas e sair mais cedo dos ciclos. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- dividir uma tarefa grande em problemas mais pequenos +- inserir uma chamada e construir um subprograma num separador próprio +- passar valores a um subprograma com parâmetros +- devolver um valor de retorno com return e guardá-lo ao chamar +- explicar porque é que um subprograma não consegue alterar um número, mas consegue alterar um array +- explicar o que faz uma Interrupção e porque está numa decisão +- terminar um ciclo com uma Interrupção ou através da sua condição +- reconhecer um método em Java e sair de um ciclo com \`break\` +::: + +## Dividir tarefas grandes + +Os estrutogramas compridos ficam depressa confusos. Por isso divides uma tarefa grande em **problemas mais pequenos**. Cada problema mais pequeno tem um nome próprio e um estrutograma próprio, um **subprograma**. + +Um quiz, por exemplo, tem três partes: dar as boas-vindas, fazer as perguntas, mostrar o resultado. O programa principal só nomeia estas três partes: + +::: diagramm l15-hauptprogramm.visustruct +O programa principal é feito só de três chamadas. O que acontece em cada parte está num estrutograma próprio. +::: + +Assim vês num relance como o programa está construído. Os pormenores estão noutro sítio. + +## A chamada + +Uma **chamada** é um bloco com linhas verticais duplas à esquerda e à direita. Quer dizer: executa aqui o subprograma com este nome e depois continua. + +- Arrastas a **Chamada** da área Elementos e escreves lá o nome, p. ex. \`mostrarBoasVindas()\`. +- Os parênteses curvos no fim mostram que é um subprograma. É assim que também se escreve em Java, Python e JavaScript. +- O subprograma em si constróis como estrutograma próprio num novo separador. Como título escreves o mesmo nome. + +::: diagramm l15-unterprogramm.visustruct +O subprograma mostrarBoasVindas() como estrutograma próprio. +::: + +> **Na simulação:** Quando a simulação chega a uma chamada, procura entre os separadores abertos o estrutograma com este título e executa-o. Depois continua no programa principal. Enquanto o subprograma é executado, o bloco da chamada fica destacado. Um subprograma como este, só com um nome como título, partilha as suas variáveis com o programa principal. Daqui a pouco vais aprender como um subprograma tem variáveis próprias. Se não houver nenhum separador que corresponda, a simulação salta a chamada e mostra um aviso. + +::: angeberwissen +Porque é que o teu professor diz sempre “método” em Java e nunca “função” ou “procedimento”? Porque em Java cada subprograma tem de pertencer a uma classe, e os subprogramas de uma classe chamam-se métodos. Mas a diferença continua a existir: se um método devolve um resultado, na verdade é uma função. Se tiver \`void\` à frente, não devolve nada e na verdade é um procedimento. O Java simplifica e chama métodos aos dois. Eu também: o meu método chama-se Ruminar. +::: + +## Exercício: Acrescentar uma chamada + +::: übung l15-titel +titel: Cumprimento com chamada +auftrag: Imagina que o subprograma \`mostrarTitulo()\` já existe. Constrói o programa principal: primeiro chama \`mostrarTitulo()\`. Depois pede um nome e mostra **Olá** e o nome. + Ou seja, quando se escreve Ada, aparece **Olá Ada**. +test: Ada -> Olá Ada +test: Rui -> Olá Rui +braucht: aufruf +tipp: O programa principal tem três partes: a chamada, a entrada e a saída. +tipp: Arrasta uma Chamada da área Elementos lá para cima e escreve \`mostrarTitulo()\`. Por baixo vêm a entrada \`input: String nome "Como te chamas?"\` e a saída. +lösung: l15-titel-loesung.visustruct +::: + +## Passar valores: parâmetros + +Muitas vezes um subprograma deve trabalhar com valores que só se conhecem quando é chamado. Nesse caso tem uma **linha de cabeçalho** como título: + +\`\`\` +void mostrarSoma(int a, int b) +\`\`\` + +- \`void\` quer dizer: o subprograma não devolve nenhum resultado. +- \`mostrarSoma\` é o nome. +- Entre os parênteses estão os **parâmetros**: variáveis com tipo de dados que recebem os seus valores quando o subprograma é chamado. Vários separam-se com vírgulas. + +::: diagramm l15-zeige-summe.visustruct +O subprograma com a linha de cabeçalho como título. Faz contas com a e b como se fossem variáveis normais. +::: + +No bloco da chamada escreves os valores entre os parênteses, p. ex. \`mostrarSoma(3, 4)\`. O primeiro valor vai para \`a\`, o segundo para \`b\`. Em vez de números também podes usar variáveis e contas, como \`mostrarSoma(x, x + 1)\`. + +::: diagramm l15-zeige-summe-haupt.visustruct +O programa principal chama mostrarSoma duas vezes com valores diferentes. Abre os dois diagramas e inicia aqui a simulação. +::: + +> **Variáveis locais:** Os parâmetros e todas as variáveis criadas no subprograma pertencem só ao subprograma. Ele recebe **cópias** dos valores; mais sobre isso em baixo, em passagem por valor. Durante a chamada, a simulação só mostra as variáveis do subprograma. + +## Devolver um resultado: return + +Um subprograma também pode devolver um resultado, o **valor de retorno**. Nesse caso, a linha de cabeçalho tem o tipo de dados do resultado em vez de \`void\`: + +\`\`\` +int quadrado(int x) +\`\`\` + +A instrução \`return resultado\` devolve o valor e termina logo o subprograma. Quando o chamas, guardas o resultado numa variável: depois de \`int q = quadrado(5)\`, \`q\` tem o valor 25. + +::: diagramm l15-quadrat.visustruct +O subprograma quadrado calcula e devolve o resultado com return. +::: + +::: diagramm l15-quadrat-haupt.visustruct +O programa principal guarda o valor de retorno em q. Abre os dois diagramas e experimenta a simulação. +::: + +> Um subprograma com valor de retorno tem de terminar com \`return\`. Se faltar o return, a simulação indica um erro. + +Na **vista de código**, a linha de cabeçalho passa a ser um método Java (\`public static int quadrado(int x)\`), um \`def\` em Python e uma \`function\` em JavaScript. Se os subprogramas estiverem abertos noutros separadores, aparecem no código juntamente com o programa principal. + +## Exercício: Calcular a área + +::: übung l15-flaeche +titel: Calcular a área +auftrag: Constrói dois diagramas. O subprograma \`int area(int a, int b)\` devolve a área de um retângulo, ou seja, a vezes b. O programa principal pede o comprimento e a largura, chama \`area\` e mostra **Área:** e o resultado. + Com 3 e 4 aparece **Área: 12**. +test: 3, 4 -> Área: 12 +test: 5, 5 -> Área: 25 +test: 7, 0 -> Área: 0 +braucht: aufruf +tipp: Constróis dois diagramas: um subprograma que só calcula e devolve o resultado, e um programa principal para a entrada e a saída. +tipp: Abre um novo separador com **+** e dá-lhe o título \`int area(int a, int b)\`. Lá dentro basta uma instrução: \`return a * b\`. No programa principal escreves \`int f = area(comprimento, largura)\` no bloco da chamada. +lösung: l15-flaeche-loesung.visustruct +unterprogramm: l15-flaeche-unterprogramm-loesung.visustruct +::: + +## Cópia ou original: passagem por valor e passagem por referência + +O que acontece se um subprograma alterar o seu parâmetro? Depende do **que** é passado. + +**Passagem por valor:** Com \`int\`, \`double\`, \`boolean\`, \`char\` e \`String\`, o subprograma recebe uma **cópia** do valor. Se alterar o seu parâmetro, a variável de quem chamou fica como estava. + +**Passagem por referência:** Com um **array**, o subprograma não recebe uma cópia, mas uma referência para o mesmo array. Se alterar uma posição, a posição também fica alterada para quem chamou. A linha de cabeçalho para isso fica assim: + +\`\`\` +void limpar(boolean[] lugares) +\`\`\` + +::: grafik uebergabe.svg +Em cima, duplicar recebe uma cópia de numero. Em baixo, fila e lugares apontam para o mesmo array. +::: + +Experimenta as duas. Abre os três diagramas e inicia a simulação no programa principal: + +::: diagramm uebergabe-verdopple.visustruct +duplicar só altera a sua cópia x. +::: + +::: diagramm uebergabe-leeren.visustruct +limpar põe todos os lugares a false, por exemplo quando uma sessão é cancelada. +::: + +::: diagramm uebergabe-haupt.visustruct +numero continua a ser 5 depois da chamada. Já os lugares em fila ficam livres depois da chamada. +::: + +> Se quiseres receber um número de volta de um subprograma, usa \`return\`, p. ex. \`numero = duplicar(numero)\` com a linha de cabeçalho \`int duplicar(int x)\`. Um array, pelo contrário, pode ser alterado diretamente pelo subprograma. + +::: angeberwissen +Em rigor, o Java só conhece a passagem por valor. Mas, com um array, não é copiado o array inteiro, só o seu **endereço** na memória. Com o endereço copiado, o subprograma encontra o mesmo array. É como se eu te desse uma cópia da chave do meu cacifo: a chave é copiada, mas o feno no cacifo só existe uma vez. +::: + +## Exercício: Pontos de bónus + +::: übung uebergabe-bonus +titel: Pontos de bónus +auftrag: O programa principal chama \`bonus(pontos)\` e depois mostra todos os pontos. Constrói o subprograma \`void bonus(int[] pontos)\`, que aumenta em 1 cada pontuação do array. Em vez de 3, 5 e 8 vês então **4**, **6** e **9**. +start: uebergabe-bonus-start.visustruct +test: - -> 4 | 6 | 9 +braucht: aufruf +tipp: O programa principal já está pronto. Só constróis o subprograma num novo separador. +tipp: Abre um novo separador com **+** e o título \`void bonus(int[] pontos)\`. Lá dentro, um ciclo for percorre todas as posições e calcula \`pontos[i] = pontos[i] + 1\`. Não precisas de return, porque o array é alterado diretamente. +lösung: uebergabe-bonus-loesung.visustruct +unterprogramm: uebergabe-bonus-unterprogramm-loesung.visustruct +::: + +## A interrupção + +Às vezes um ciclo deve terminar **mais cedo**, a meio do seu corpo. É para isso que serve a **Interrupção**. Ela sai imediatamente do ciclo em que está. O programa continua no primeiro bloco depois do ciclo. Em Java, Python e JavaScript chama-se \`break\`. + +Reconheces a Interrupção pela ponta no seu lado esquerdo. Podes escrever um pequeno comentário no bloco, p. ex. \`Sair do ciclo\`. Ele aparece no código como comentário depois de \`break\`. + +Uma Interrupção está quase sempre numa **decisão**: só se sai do ciclo se uma condição se verificar. + +Um caso típico é o **ciclo infinito com Interrupção**. O ciclo em si não tem condição. É executado até se chegar à Interrupção: + +::: diagramm l15-endlos-aussprung.visustruct +O ciclo pede sempre um número. Com 0 salta para fora, senão soma o número à soma. +::: + +Sem Interrupção, um ciclo infinito nunca acabaria mesmo. + +## Interrupção na simulação + +A simulação executa a Interrupção como \`break\`: sai do ciclo mais interior e continua depois dele. Se uma Interrupção estiver fora de qualquer ciclo, o subprograma termina; no programa principal termina o programa todo. O \`return\` faz o mesmo. + +Muitas vezes podes passar completamente sem Interrupção: escreves a condição de paragem diretamente no ciclo. Normalmente até fica mais claro. + +## Exercício: Somar até 0 + +::: übung l15-bis-null +titel: Somar até 0 +auftrag: Reconstrói o programa “Somar até 0” **sem** Interrupção. Ele pede números inteiros até alguém escrever 0. Depois mostra **Soma:** e a soma de todos os números introduzidos. +test: 3, 4, 0 -> Soma: 7 +test: 0 -> Soma: 0 +test: 10, -2, 5, 0 -> Soma: 13 +tipp: Sem Interrupção, é a própria condição do ciclo que tem de verificar se foi escrito 0. +tipp: Pede o primeiro número antes do ciclo. O ciclo while é executado com a condição \`numero != 0\`. No corpo somas o número à soma e depois pedes o número seguinte. Na segunda entrada só escreves \`input: numero "…"\`, porque \`numero\` já existe. +lösung: l15-bis-null-loesung.visustruct +::: + +## Agora em Java + +Em Java, um subprograma chama-se **método**. O quadrado de cima fica assim: + +\`\`\`java +public static int quadrado(int x) { + int resultado = x * x; + return resultado; +} +\`\`\` + +O programa principal chama o método pelo nome e passa-lhe o valor entre parênteses curvos: + +\`\`\`java +int q = quadrado(numero); +System.out.println("O quadrado é " + q); +\`\`\` + +- No cabeçalho, antes do nome, fica o que o método devolve (\`int\`). Se não devolver nada, fica \`void\`. +- Os parâmetros ficam entre parênteses curvos, com o tipo de dados: \`(int x)\`. Separas vários com vírgulas. +- Na área Código escreves cada método no seu próprio separador, tal como cada subprograma tem o seu próprio estrutograma. +- Em Java, a saída chama-se \`break\`. Com \`while (true)\` constróis um ciclo que só termina com \`break\`. + +::: übung l18-java-kasse +titel: Caixa com break +code: java +auftrag: Escreve uma caixa registadora em Java. Pergunta repetidamente por um preço em euros inteiros. Com 0 sai do ciclo com \`break\`. Depois mostra quantos artigos foram e quanto custam ao todo. + Com 3, 4 e depois 0 aparece **Artigos: 2** e **Total: 7**. +test: 3, 4, 0 -> Artigos: 2 | Total: 7 +test: 0 -> Artigos: 0 | Total: 0 +test: 10, 2, 5, 0 -> Artigos: 3 | Total: 17 +braucht: endlosschleife, aussprung +tipp: Precisas de duas variáveis que começam em 0 antes do ciclo: uma para a soma e outra para a quantidade de artigos. +tipp: Dentro de \`while (true) { … }\` lês o preço. Logo a seguir verificas \`if (preco == 0) { break; }\`. Só depois somas o preço e aumentas os artigos em 1. +lösung: l18-java-kasse-loesung.visustruct +::: + +## Preenche os espaços: métodos e break + +::: lückentext +titel: Método e saída +auftrag: Preenche as palavras que faltam. Em cima está o método que calcula um quadrado. Por baixo está o programa principal, que o chama. Na área Código, cada um fica no seu separador. +\`\`\`java +public static [[int]] quadrado(int x) { + [[return]] x * x; +} +\`\`\` +\`\`\`java +int numero = 1; +while ([[true]]) { + int q = [[quadrado]](numero); + if (q > 50) { + [[break]]; + } + System.out.println(q); + numero = numero + 1; +} +\`\`\` +erklärung: \`int\` antes do nome do método quer dizer que o método devolve um número inteiro, com \`return\`. Se um método não devolver nada, aparece \`void\`. \`while (true)\` repete-se sem fim até \`break\` sair do ciclo. Saída: 1, 4, 9, 16, 25, 36 e 49. +::: + +## Encontra o erro: adivinhar + +::: übung l18-java-fehler +titel: Corrigir a contagem de tentativas +code: java +auftrag: Neste jogo de adivinhar, o número secreto é 7. O programa pede um palpite até aparecer o 7 e depois mostra o número de tentativas. Com 3, 5 e 7 foram 3 tentativas, mas o programa diz **Tentativas: 2**. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l18-java-fehler-start.visustruct +test: 3, 5, 7 -> Tentativas: 3 +test: 7 -> Tentativas: 1 +test: 1, 2, 3, 7 -> Tentativas: 4 +braucht: endlosschleife, aussprung +tipp: O que acontece com o palpite certo? Ainda é contado antes de \`break\` sair do ciclo? +tipp: Primeiro conta, depois verifica: \`tentativas = tentativas + 1;\` fica antes do \`if\` com o \`break\`. +lösung: l18-java-fehler-loesung.visustruct +::: + +## Jogo: O que é devolvido? + +::: spiel frage +titel: Jogo: O que é devolvido? +intro: O Ludwig chama métodos e sai de ciclos a meio. Diz antes o que aparece. Sete rondas. + +runde: + public static int quadrado(int x) { + return x * x; + } + + int q = quadrado(5); + System.out.println(q); +frage: O que aparece? +- 5 +- 10 +- [x] 25 +> A chamada põe 5 em x, e o return devolve 5 · 5. + +runde: + public static void mostrarSoma(int a, int b) { + System.out.println(a + b); + } + + int x = 2; + mostrarSoma(x, x + 1); +frage: O que aparece? +- [x] 5 +- 23 +- 3 +> O primeiro valor 2 vai para a, o segundo valor 3 para b. Em Java, \`a + b\` calcula com números normalmente. + +runde: +frage: O que devolve um método que tem \`void\` antes do nome? +- um número inteiro +- [x] nada +- sempre 0 +> \`void\` quer dizer: sem valor de retorno. Com \`int\` nesse lugar, é devolvido um número inteiro. + +runde: + public static void duplicar(int x) { + x = x * 2; + } + + int numero = 5; + duplicar(numero); + System.out.println(numero); +frage: O que aparece? +- [x] 5 +- 10 +- 0 +> Passagem por valor (call by value): duplicar recebe uma cópia. numero continua a ser 5. + +runde: + public static void limpar(boolean[] lugares) { + for (int i = 0; i < lugares.length; i++) { + lugares[i] = false; + } + } + + boolean[] fila = {true, true}; + limpar(fila); + System.out.println(fila[0]); +frage: O que aparece? +- true +- [x] false +> Num array, fila e lugares apontam para o mesmo array. Quem chama também vê a alteração. + +runde: + int soma = 0; + for (int i = 1; i <= 10; i++) { + if (i == 4) { + break; + } + soma = soma + i; + } + System.out.println(soma); +frage: O que aparece? +- [x] 6 +- 10 +- 55 +> Com i = 4, o \`break\` sai logo do ciclo. Só foram somados 1 + 2 + 3. + +runde: + int numero = 1; + while (true) { + numero = numero * 3; + if (numero > 20) { + break; + } + } + System.out.println(numero); +frage: O que aparece? +- 9 +- 20 +- [x] 27 +> 3, 9, 27. Só 27 é maior do que 20, e então o ciclo infinito termina com break. +::: + +## 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. + +::: checkliste +- Consigo dividir uma tarefa grande em problemas mais pequenos. → Dividir tarefas grandes +- Consigo inserir uma chamada e construir um subprograma num separador próprio. → A chamada +- Consigo passar valores a um subprograma com parâmetros. → Passar valores: parâmetros +- Consigo devolver um valor de retorno com return e guardá-lo ao chamar. → Devolver um resultado: return +- Consigo explicar porque é que um subprograma não consegue alterar um número, mas consegue alterar um array. → Cópia ou original: passagem por valor e passagem por referência +- Consigo explicar o que faz uma Interrupção e porque está numa decisão. → A interrupção +- Consigo terminar um ciclo com uma Interrupção ou através da sua condição. → Interrupção na simulação +- Consigo reconhecer um método em Java e sair de um ciclo com \`break\`. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? O que significa um bloco de chamada com o texto \`mostrarResultado()\`? +→ A chamada +- [ ] O programa termina aqui. +- [x] O subprograma mostrarResultado() é executado aqui, e depois o programa continua. +- [ ] A palavra mostrarResultado() é mostrada aqui. + +? Onde continua o programa depois de uma Interrupção? +→ A interrupção +- [ ] No início do ciclo +- [x] No primeiro bloco depois do ciclo +- [ ] Logo no início do programa +> A Interrupção sai do ciclo em que está. Em Java, Python e JavaScript chama-se break. + +? Porque é que uma Interrupção costuma estar numa decisão? +→ A interrupção +- [x] Para só se sair do ciclo se uma condição se verificar +- [ ] Porque senão uma Interrupção não pode ser guardada +- [ ] Porque uma decisão é ela própria um ciclo +> Sem decisão, sair-se-ia do ciclo logo na primeira iteração. + +? Onde encontra a simulação o subprograma de uma chamada \`mostrarResultado()\`? +→ A chamada +- [ ] Tem de estar no mesmo estrutograma. +- [x] Num separador aberto com o título mostrarResultado() +- [ ] A simulação não consegue executar subprogramas. +> Constrói cada subprograma num separador próprio e dá-lhe como título o nome da chamada. + +? O subprograma tem a linha de cabeçalho \`void mostrarSoma(int a, int b)\`. Que chamada serve? +→ Passar valores: parâmetros +- [ ] mostrarSoma() +- [x] mostrarSoma(3, 4) +- [ ] int s = mostrarSoma(3, 4) +> Dois parâmetros precisam de dois valores. E \`void\` quer dizer que não volta nada que pudesses guardar. + +? Depois de \`int q = quadrado(5)\`, q tem 25. O que está no fim do subprograma quadrado? +→ Devolver um resultado: return +- [ ] output: x * x +- [x] return x * x +- [ ] q = x * x +> Com return, o subprograma devolve o valor à chamada. Uma saída só o mostraria. + +? \`void duplicar(int x)\` calcula \`x = x * 2\`. O programa principal tem \`int numero = 5\` e depois a chamada \`duplicar(numero)\`. Que valor tem numero a seguir? +→ Cópia ou original: passagem por valor e passagem por referência +- [x] 5 +- [ ] 10 +- [ ] 0 +> Passagem por valor: duplicar só alterou uma cópia de numero. + +? \`void limpar(boolean[] lugares)\` põe todas as posições a false. O que é verdade para o array fila no programa principal depois de \`limpar(fila)\`? +→ Cópia ou original: passagem por valor e passagem por referência +- [ ] Não mudou, porque o subprograma recebe uma cópia. +- [x] Todas as posições são false, porque lugares e fila são o mesmo array. +- [ ] O array é apagado. +> Passagem por referência: um array é passado como referência. Quem chamou também vê as alterações nas posições. + +? Como se chama um subprograma em Java? +→ Agora em Java +- [ ] Classe +- [x] Método +- [ ] Ciclo +> Em Java, um subprograma é um método, por exemplo o método \`main\`. Consoante o tipo, também se chama procedimento ou função. + +? Muitos blocos têm um segundo nome nos manuais. Associa cada termo do VisuStruct ao seu outro nome. +→ Agora em Java += Decisão -> Instrução condicional += Seleção -> Seleção múltipla += Ciclo -> Iteração += Subprograma -> Método +> Os dois nomes querem dizer o mesmo. Se conheces um deles, também percebes o outro. + +? O que fica no cabeçalho de um método Java que não devolve nada? +→ Devolver um resultado: return +- [ ] int +- [x] void +- [ ] return +> void significa “vazio”: o método faz alguma coisa, mas não devolve nenhum valor. +::: +`,lv=`--- +titel: Pesquisar e ordenar +bereich: Fundamentos +kurz: Perceber com cartas de jogar como funcionam a pesquisa linear, a pesquisa binária e o bubble sort, e porque é que alguns métodos são muito mais rápidos. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar como a pesquisa linear percorre um array +- construir uma pesquisa linear como estrutograma +- explicar porque é que a pesquisa binária só funciona com valores ordenados +- explicar porque é que a pesquisa binária é muito mais rápida com muitos valores +- mostrar uma ronda de bubble sort com cartas de jogar +- percorrer um array em Java e contar resultados +::: + +## Procurar uma carta + +À tua frente está uma fila de cartas de jogar viradas para baixo. Procuras o 9. O que fazes? Viras uma carta a seguir à outra até encontrares o 9 ou teres virado todas as cartas. + +::: grafik ss-lineare-suche.svg +As cartas estão baralhadas. Cada carta que viras é uma comparação: é esta o 9? +::: + +É exatamente assim que funciona a **pesquisa linear**: percorre o array do índice 0 até ao fim e compara cada posição com o valor procurado. Funciona sempre, mesmo que os valores estejam baralhados. + +No array, as nossas cartas são números. Deixamos de fora o valete, a dama e o rei. + +::: diagramm ss-lineare-suche.visustruct +O ciclo é executado até a carta ser encontrada ou já não haver posições. A variável comparacoes conta quantas vezes se comparou. Na simulação, procura o 2, o 27 e o 4. +::: + +> Se a carta não estiver lá, \`posicao\` fica em **-1**. Não existe o índice -1, por isso aqui -1 quer dizer “não encontrado”. + +## Exercício: Encontrar uma carta + +::: übung ss-karte-suchen +titel: Encontrar uma carta +auftrag: Cria o array \`int[] cartas = {8, 4, 11, 4, 6}\` e pede uma carta. Mostra a posição da **primeira** carta que corresponde, p. ex. \`Posição: 1\` para o 4. Se a carta não estiver lá, mostra \`Não encontrado\`. +test: 4 -> Posição: 1 +test: 6 -> Posição: 4 +test: 8 -> Posição: 0 +test: 9 -> Não encontrado +braucht: whileSchleife, verzweigung +tipp: Percorre o array da frente para trás e compara cada carta com a que procuras. +tipp: Reconstrói o exemplo de cima. Aqui não precisas da variável comparacoes. O ciclo tem de parar assim que \`posicao\` deixar de ser -1, senão, para o 4, encontras o segundo em vez do primeiro. +lösung: ss-karte-suchen-loesung.visustruct +::: + +## Pesquisa binária: ordenado é mais rápido + +Agora as cartas estão à tua frente **ordenadas**, da mais pequena para a maior. Procuras o 27. Já não viras a primeira carta da frente, mas a do **meio**: + +- Se for a que procuras, terminaste. +- Se for mais pequena, a carta procurada só pode estar à direita. A metade esquerda inteira fica de fora. +- Se for maior, fica de fora a metade direita. + +Fazes o mesmo outra vez com o resto. Com cada comparação, o monte fica reduzido a metade. + +::: grafik ss-binaere-suche.svg +Três comparações em vez de catorze: com cada meio, metade das cartas que restam fica de fora. +::: + +No estrutograma, duas variáveis guardam a parte em que ainda se procura: \`esquerda\` e \`direita\`. O meio é \`(esquerda + direita) / 2\`. Como é uma divisão inteira, o resultado é sempre um índice inteiro. + +::: diagramm ss-binaere-suche.visustruct +O mesmo array da pesquisa linear. Na simulação, procura outra vez o 27 e compara a saída Comparações com a pesquisa linear. +::: + +> A pesquisa binária **só funciona com valores ordenados**. Com cartas baralhadas, depois de olhares para o meio não sabes em que metade continuar a procurar. + +::: angeberwissen +Penso num número de 1 a 100. Podes adivinhar, e eu só digo “maior” ou “menor”. Com a pesquisa binária precisas no máximo de **7** tentativas. Para um número até um milhão são no máximo 20, para mil milhões 30. Cada duplicação custa só mais uma tentativa. É assim que as bases de dados pesquisam milhões de registos numa fração de segundo. Eu, já agora, pesquiso de forma linear: como o prado da esquerda para a direita. +::: + +## Quão rápido é? + +A qualidade de um método mede-se pelo número de comparações de que precisa **no pior caso**. Na pesquisa linear, é o caso em que a carta está mesmo lá atrás ou não existe. + +::: grafik ss-vergleiche.svg +Com 100 cartas, a pesquisa linear precisa de até 100 comparações, a pesquisa binária no máximo de 7. +::: + +| Número de cartas | Pesquisa linear | Pesquisa binária | +|---|---|---| +| 10 | 10 | 4 | +| 100 | 100 | 7 | +| 1000 | 1000 | 10 | +| 1 000 000 | 1 000 000 | 20 | + +A pesquisa linear cresce ao mesmo ritmo que o número de cartas. Na pesquisa binária, o dobro das cartas acrescenta só **uma** comparação. + +## Ordenar com bubble sort + +Para a pesquisa binária, os valores têm de estar ordenados. Uma das formas mais simples de ordenar é o **bubble sort**. Percorres a fila da esquerda para a direita e comparas sempre **dois vizinhos**. Se a carta maior estiver à esquerda, trocas as duas. + +::: grafik ss-bubblesort.svg +Depois de uma ronda, a carta maior está na ponta da direita. +::: + +Depois da primeira ronda, a carta maior está na ponta da direita, como uma bolha de ar que sobe. Daí vem o nome (*bubble* quer dizer bolha). Depois repetes a ronda para as cartas que restam. Com 5 cartas precisas de 4 rondas. + +O estrutograma tem dois ciclos for, um dentro do outro. O exterior conta as rondas, o interior compara os vizinhos \`cartas[i]\` e \`cartas[i + 1]\`. Já sabes como trocar: precisas de uma **variável auxiliar**. + +::: diagramm ss-bubblesort.visustruct +O ciclo interior fica mais curto em cada ronda, porque as cartas maiores à direita já estão no sítio certo. Percorre-o na simulação com Passo e observa o array em Variáveis. +::: + +O bubble sort é fácil de perceber, mas lento. Com n cartas precisa de até n · (n − 1) / 2 comparações: com 10 cartas 45, com 100 cartas já 4950 e com 1000 cartas quase meio milhão. Mais tarde talvez conheças métodos mais rápidos, como o quicksort. + +## Exercício: Ordenar por ordem decrescente + +::: übung ss-absteigend +titel: Ordenar por ordem decrescente +auftrag: O diagrama inicial lê 5 cartas e ordena-as com bubble sort por ordem **crescente**, ou seja, da mais pequena para a maior. Altera-o de modo que as cartas sejam mostradas por ordem **decrescente**, a maior primeiro. +start: ss-absteigend-start.visustruct +test: 3, 1, 4, 1, 5 -> 5 | 4 | 3 | 1 | 1 +test: 10, 20, 30, 40, 50 -> 50 | 40 | 30 | 20 | 10 +test: 2, 9, 2, 7, 6 -> 9 | 7 | 6 | 2 | 2 +braucht: forSchleife, verzweigung +tipp: Olha para a condição na decisão. É ela que decide quando dois vizinhos são trocados. +tipp: Só precisas de alterar um único caractere. Quando devem ser trocados dois vizinhos, se a carta maior deve ir para a esquerda? +lösung: ss-absteigend-loesung.visustruct +::: + +## Agora em Java + +A pesquisa linear do exercício fica assim em Java: + +\`\`\`java +int[] cartas = {8, 4, 11, 4, 6}; +int procurada = 4; +int posicao = -1; +int i = 0; +while (posicao == -1 && i < cartas.length) { + if (cartas[i] == procurada) { + posicao = i; + } + i = i + 1; +} +System.out.println("Posição: " + posicao); +\`\`\` + +- \`&&\` significa “e”: o ciclo só corre enquanto não se encontrou nada **e** ainda há cartas. +- Se o ramo false estiver vazio, deixas simplesmente de fora \`else\`. +- A troca no bubble sort também precisa de uma variável auxiliar em Java: \`int aux = cartas[i];\` + +::: übung l19-java-zaehlen +titel: Contar cartas +code: java +auftrag: As cartas {8, 4, 11, 4, 6} estão num array. Escreve em Java um programa que pergunta por uma carta e conta quantas vezes aparece. Mostra **Quantidade:** e o número. + Com 4 aparece **Quantidade: 2**. +test: 4 -> Quantidade: 2 +test: 8 -> Quantidade: 1 +test: 9 -> Quantidade: 0 +braucht: forSchleife, verzweigung +tipp: Ao contrário da pesquisa, não paras no primeiro resultado. Um ciclo for percorre todas as cartas. +tipp: \`for (int i = 0; i < cartas.length; i++)\` e lá dentro \`if (cartas[i] == procurada) { quantidade = quantidade + 1; }\`. \`quantidade\` começa em 0 antes do ciclo. +lösung: l19-java-zaehlen-loesung.visustruct +::: + +## Preenche os espaços: bubble sort + +::: lückentext +titel: Ordenar cartas +auftrag: O programa ordena as cartas por ordem crescente com o bubble sort. Preenche as palavras e os sinais que faltam. +\`\`\`java +int[] cartas = {5, 2, 8, 1}; +for (int ronda = 0; ronda < cartas.[[length]] - 1; ronda++) { + for (int i = 0; i < cartas.length - 1; i++) { + if (cartas[i] [[>]] cartas[i + 1]) { + [[int]] aux = cartas[i]; + cartas[i] = cartas[i + 1]; + cartas[i + 1] = [[aux]]; + } + } +} +for (int i = 0; i < cartas.length; i++) { + System.out.println(cartas[i]); +} +\`\`\` +erklärung: Se uma carta for maior do que a vizinha da direita, as duas trocam de lugar, com uma variável auxiliar como ao trocar os copos. Depois de \`length - 1\` rondas está tudo ordenado: 1, 2, 5, 8. +::: + +## Encontra o erro: pesquisa + +::: übung l19-java-fehler +titel: Corrigir a pesquisa linear +code: java +auftrag: As cartas {8, 4, 11, 4, 6} estão num array. O programa deve mostrar a **primeira** posição da carta procurada, para o 4 é **Posição: 1**. Mas mostra **Posição: 3**. + “Abrir no editor” mostra o código na área Código. Encontra o erro, corrige-o e carrega em Verificar. +start: l19-java-fehler-start.visustruct +test: 4 -> Posição: 1 +test: 6 -> Posição: 4 +test: 9 -> Posição: -1 +test: 8 -> Posição: 0 +braucht: whileSchleife, verzweigung +tipp: O ciclo vai sempre até à última carta. O que acontece quando o 4 aparece uma segunda vez? +tipp: O ciclo deve parar assim que encontrar algo: \`while (posicao == -1 && i < cartas.length)\`. +lösung: l19-java-fehler-loesung.visustruct +::: + +## Jogo: Profissional da pesquisa + +::: spiel frage +titel: Jogo: Profissional da pesquisa +intro: O Ludwig procura e ordena cartas. Quão rápido é, e o que sai? Sete rondas. + +runde: + int[] cartas = {8, 4, 11, 4, 6}; + int procurada = 4; + int posicao = -1; + int i = 0; + while (posicao == -1 && i < cartas.length) { + if (cartas[i] == procurada) { + posicao = i; + } + i = i + 1; + } + System.out.println("Posição: " + posicao); +frage: O que aparece? +- [x] Posição: 1 +- Posição: 3 +- Posição: 2 +> A pesquisa para no primeiro 4. Está na posição 1, contando a partir de 0. + +runde: + int[] cartas = {8, 4, 11, 4, 6}; + int procurada = 7; +frage: Com a mesma pesquisa linear: o que fica em posicao? +- 0 +- 5 +- [x] -1 +> O 7 não está lá. posicao fica em -1, que quer dizer "não encontrado". + +runde: +frage: Com que cartas funciona a pesquisa binária? +- com todas +- [x] só com cartas ordenadas +- só com menos de 100 +> Só com as cartas ordenadas é que, depois de olhares para o meio, sabes em que metade continuar a procurar. + +runde: +frage: De quantas comparações precisa no máximo a pesquisa binária com 100 cartas? +- 50 +- [x] 7 +- 100 +> Cada comparação corta o monte a meio. Cortar 7 vezes chega para até 128 cartas, portanto também para 100. + +runde: +frage: Em vez de 1000 cartas agora são 2000. Quantas comparações a mais precisa no máximo a pesquisa binária? +- [x] uma +- o dobro +- 1000 +> A primeira comparação reduz 2000 a 1000. Depois continua como antes. + +runde: + int[] cartas = {5, 3, 8, 1}; +frage: Uma passagem do bubble sort compara sempre dois vizinhos, da esquerda para a direita. Como ficam as cartas depois? +- 1, 3, 5, 8 +- [x] 3, 5, 1, 8 +- 3, 5, 8, 1 +> 5 e 3 trocam, 5 e 8 ficam, 8 e 1 trocam. A carta maior fica na ponta da direita. + +runde: +frage: O bubble sort troca \`cartas[i]\` e \`cartas[i + 1]\`. De que precisa para isso? +- [x] de uma variável auxiliar +- de um segundo array +- de uma pesquisa binária +> Tal como ao trocar duas variáveis: \`int aux = cartas[i];\`, senão perde-se um valor. +::: + +## 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. + +::: checkliste +- Consigo explicar como a pesquisa linear percorre um array. → Procurar uma carta +- Consigo construir uma pesquisa linear como estrutograma. → Exercício: Encontrar uma carta +- Consigo explicar porque é que a pesquisa binária só funciona com valores ordenados. → Pesquisa binária: ordenado é mais rápido +- Consigo explicar porque é que a pesquisa binária é muito mais rápida com muitos valores. → Quão rápido é? +- Consigo mostrar uma ronda de bubble sort com cartas de jogar. → Ordenar com bubble sort +- Consigo percorrer um array em Java e contar resultados. → Agora em Java +::: + +## Teste de conhecimentos + +::: quiz +? De que precisa a pesquisa binária? +→ Pesquisa binária: ordenado é mais rápido +- [ ] O array tem de ter exatamente 100 posições. +- [x] Os valores têm de estar ordenados. +- [ ] O valor procurado tem de existir. +> Só com valores ordenados é que sabes, depois de olhares para o meio, em que metade continuar a procurar. + +? Um array ordenado tem 1000 valores. De quantas comparações precisa a pesquisa binária no máximo? +→ Quão rápido é? +- [ ] 500 +- [ ] 100 +- [x] 10 +> 1000 → 500 → 250 → 125 → 63 → 32 → 16 → 8 → 4 → 2 → 1: depois de cerca de 10 divisões a meio, resta um valor. + +? O que compara o bubble sort em cada passo? +→ Ordenar com bubble sort +- [ ] A primeira e a última carta +- [x] Duas cartas vizinhas +- [ ] Cada carta com a do meio +> Se a carta maior estiver à esquerda, os vizinhos são trocados. + +? Onde está a carta maior depois da primeira ronda do bubble sort? +→ Ordenar com bubble sort +- [ ] Na ponta da esquerda +- [ ] No meio +- [x] Na ponta da direita +> Vai sendo trocada em cada comparação e sobe para a direita como uma bolha. + +? O que quer dizer \`posicao = -1\` na pesquisa linear? +→ Procurar uma carta +- [x] A carta (ainda) não foi encontrada. +- [ ] A carta está mesmo lá atrás. +- [ ] O array está vazio. + +? Associa cada método à descrição certa. +→ Procurar uma carta += Pesquisa linear -> olhar para uma carta a seguir à outra += Pesquisa binária -> olhar para o meio e pôr de lado uma metade += Bubble sort -> comparar vizinhos e trocá-los + +? Porque usas um ciclo for para contar e não uma pesquisa que para no primeiro resultado? +→ Agora em Java +- [ ] Um ciclo for é sempre mais rápido. +- [x] Tens de ver todas as cartas, senão faltam resultados mais à frente. +- [ ] Um ciclo while não consegue percorrer arrays. +> A carta pode aparecer várias vezes. Por isso percorres todas as cartas até ao fim. +::: +`,uv=`--- +titel: Estrutograma e código +bereich: Do estrutograma ao código +kurz: Todos os elementos em Java num relance, gerar código, escrever Java na área Código, executá-lo e procurar erros. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- abrir a vista de código e escolher Java como linguagem +- reconhecer em Java a saída, a entrada, as decisões e os ciclos +- explicar a diferença entre Excerto e Classe +- reconstruir um programa Java curto como estrutograma +- escrever Java na área Código e ler o estrutograma que é construído +- executar um programa com ▶︎ e usar entradas e saídas na consola +- pôr pontos de paragem e seguir um programa passo a passo +::: + +## A vista de código + +Nas lições 4 a 19 já escreveste cada elemento em Java. Aqui vês tudo num relance e aprendes como o VisuStruct transforma um estrutograma inteiro num programa Java. + +Um estrutograma descreve um processo. Para um computador o executar, precisas de um programa numa linguagem de programação. O VisuStruct escreve esse código por ti. + +Clica em [Código](#zeige-code) nas ferramentas (ícone com parênteses angulares). À direita aparece o **Gerador de código**: + +- Em cima escolhes a linguagem: **Java**, **Python** ou **JavaScript**. +- Para Java escolhes ainda em **Saída Java** entre **Excerto** (só as instruções) e **Classe** (um ficheiro Java completo). +- **Texto do diagrama como comentários** escreve o texto de cada bloco como comentário por cima do código. +- **Copiar** põe o código na área de transferência, **Guardar Java…** guarda um ficheiro \`.java\`. + +O código muda logo sempre que alteras alguma coisa no estrutograma. + +::: angeberwissen +Mais tarde, Nassi trabalhou na linguagem de programação Ada e foi responsável pelo software na Apple. Portanto, quem inventa estrutogramas não acaba num curral de cabras, acaba na Apple. +::: + +::: diagramm l17-beispiel.visustruct +Um pequeno programa com uma entrada, um ciclo for e uma decisão. Abre-o e olha para o código Java correspondente. +::: + +## O exemplo em Java + +Para o diagrama de cima, o VisuStruct gera este código como **Excerto**: + +\`\`\` +// import java.util.Scanner; +Scanner scanner = new Scanner(System.in); + +System.out.println("Que tabuada?"); +int numero = scanner.nextInt(); +for (int i = 1; i <= 3; i++) { + int resultado = numero * i; + System.out.println(i + " vezes " + numero + " = " + resultado); +} +if (numero > 10) { + System.out.println("Esta foi difícil!"); +} else { + System.out.println("Esta foi fácil."); +} +\`\`\` + +Em Java, cada instrução termina com um **ponto e vírgula** \`;\`. O que está dentro de um bloco fica entre **chavetas** \`{ }\` em Java. A indentação mostra-te o que pertence ao quê. + +## Os elementos em Java + +| Elemento | Java | Lição | +|---|---|---| +| Instrução | \`int soma = 0;\` | 4, 5 | +| Saída | \`System.out.println(soma);\` | 6 | +| Entrada | \`int numero = scanner.nextInt();\` | 6 | +| Decisão | \`if (condição) { … } else { … }\` | 8, 9 | +| Seleção | \`switch (valor) { case 1 -> { … } default -> { … } }\` | 10 | +| Ciclo while | \`while (condição) { … }\` | 11 | +| Ciclo do-while | \`do { … } while (condição);\` | 12 | +| Ciclo for | \`for (int i = 0; i < 5; i++) { … }\` | 13 | +| Ciclo infinito | \`while (true) { … }\` | 11, 18 | +| Interrupção | \`break;\` | 18 | +| Chamada | \`calcular();\` | 18 | +| Array | \`int[] numeros = new int[5];\` | 15, 16 | +| Texto (String) | \`String nome = scanner.next();\` | 17 | + +Para entradas, \`import java.util.Scanner;\` e \`Scanner scanner = new Scanner(System.in);\` são escritos uma vez lá em cima. Antes de cada entrada, o VisuStruct mostra a pergunta com \`System.out.println(…)\`. + +Se o ramo false de uma decisão estiver vazio, o VisuStruct gera mesmo assim uma parte \`else\` que só contém o comentário \`// empty element\`. Se desligares **Gerar ramo else vazio no código**, a parte \`else\` vazia desaparece. + +## Excerto ou Classe + +Podes colar um **Excerto** no método \`main\` de um programa Java que já exista. Com **Classe** obténs um ficheiro completo que podes compilar e executar logo: + +\`\`\` +import java.util.Scanner; + +public class Tabuada { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + System.out.println("Que tabuada?"); + int numero = scanner.nextInt(); + ... + } // fim do main +} // fim da classe +\`\`\` + +Os comentários \`// fim do main\` e \`// fim da classe\` depois das duas últimas chavetas não são necessários, mas ajudam muito: vês logo que chaveta fecha o quê e não te esqueces de nenhuma. + +O nome da classe vem do **título** do diagrama. O ficheiro tem de ter exatamente o mesmo nome, aqui \`Tabuada.java\`. O **Guardar Java…** trata disso por ti. + +> O código gerado é um bom começo, mas confirma-o. Se primeiro criares uma variável e mais tarde a voltares a ler com uma entrada, o VisuStruct escreve mesmo assim \`int pin = scanner.nextInt();\`. O Java indica então que \`pin\` já existe. Basta apagares o \`int\` nessa linha. + +::: angeberwissen +Todos os ficheiros Java compilados (\`.class\`) começam com os mesmos quatro bytes, escritos em hexadecimal: \`CA FE BA BE\`. É assim que o computador reconhece que é Java. Foi James Gosling que inventou este “cafe babe”, a condizer com o café do nome. +::: + +## O modo de linguagem Java + +Na [roda dentada](#zeige-einstellungen) em cima à direita podes ativar as **Palavras-chave do código**. Então os blocos da área Elementos têm os mesmos nomes que os comandos em Java: \`if\`, \`switch\`, \`for\`, \`while\`, \`do\`, \`while(true)\`, \`break\` e \`call\`. O resto da interface fica no teu idioma. + +Isto ajuda-te a associar os blocos aos comandos Java. O teu diagrama em si fica igual. + +## Escrever Java diretamente + +Até agora desenhaste primeiro o estrutograma e depois viste o código. Na área [Código](#zeige-codelive) também funciona ao contrário. Clica na barra estreita **Código** à direita. Ao lado do estrutograma aparece uma coluna onde escreves tu mesmo o Java. + +- **Do estrutograma para o código:** Quando alteras alguma coisa no estrutograma, o código Java muda logo. +- **Do código para o estrutograma:** Quando escreves Java, o VisuStruct constrói o estrutograma enquanto escreves. Se ainda faltar alguma coisa, por exemplo uma chaveta de fecho \`}\`, aparece uma indicação por baixo do código. +- **Sugestões:** Enquanto escreves, o VisuStruct sugere modelos, por exemplo para \`if\`, \`for\` ou \`while\`. Com Enter aceitas um modelo. Substitui simplesmente os marcadores cinzentos pelo teu texto. +- **Indentar:** Se o teu código ficou desarrumado, clica no botão **Indentar** em cima na área Código. Cada nível fica então quatro espaços mais para dentro, como no Eclipse ou no IntelliJ. Se tiveres linhas selecionadas, o VisuStruct só indenta essas. + +Assim podes experimentar os dois caminhos. Desenhar primeiro o estrutograma é bom para planear um processo. Escrever o código diretamente é mais rápido quando já sabes o que queres. O estrutograma ajuda-te depois a verificar o teu código. + +## Executar o programa + +Em cima, na área Código, [▶︎ Executar](#zeige-ausfuehren) inicia o teu programa e **■ Parar** termina-o, por exemplo num ciclo infinito. O que o teu programa mostra aparece em baixo na [consola](#zeige-konsole). Se pedir uma entrada, escreve-a lá e carrega em Enter. + +Podes arrastar com o rato a fronteira entre o código e a consola para cima ou para baixo. + +> A área Código entende os comandos Java que também existem como blocos no estrutograma. Ainda não conhece classes próprias nem objetos. Janelas com Swing funcionam na mesma: liga o **Java verdadeiro (com Swing)** na roda dentada (lição “A tua primeira janela”). + +::: angeberwissen +Os profissionais chamam **IDE** (Integrated Development Environment) a um programa onde se escreve código, se executa e se procuram erros. Com a área Código, o VisuStruct é um pequeno IDE com estrutograma incluído. +::: + +## Encontrar erros com o depurador + +Às vezes um programa corre, mas calcula mal. Aí ajuda o **depurador** (debugger): executa o teu programa devagar e tu vês o que acontece. + +- **Ponto de paragem:** Clica num número de linha à esquerda. Aparece um ponto vermelho. [▶︎ Executar](#zeige-ausfuehren) para antes dessa linha. Outro clique tira o ponto. +- **Linha amarela:** É a próxima a ser executada. No estrutograma, o bloco correspondente fica selecionado. +- **Variáveis:** Por baixo do código vês o valor atual de cada variável. O que mudou desde a última paragem acende-se a amarelo por um momento. +- **Passo a passo:** O botão [Passo a passo](#zeige-einzelschritt) ao lado de ▶︎ executa exatamente uma linha e para outra vez. Sem ponto de paragem, inicia o programa e para antes da primeira linha. +- **Continuar:** ▶︎ corre até ao próximo ponto de paragem ou até ao fim. **■ Parar** termina. + +Experimenta com este programa. Põe um ponto de paragem na linha 3 e carrega várias vezes em ▶︎. Como crescem \`i\` e \`soma\`? + +\`\`\` +int soma = 0; +for (int i = 1; i <= 4; i++) { + soma = soma + i; +} +System.out.println("Soma: " + soma); +\`\`\` + +::: ludwig +É um teste de secretária, só que o computador toma notas por ti. Antes de cada passo, pensa no valor que a variável devia ter a seguir. Quando a tabela não bate com o que esperavas, encontraste o sítio do erro. +::: + +## Exercício: Primeiro o código, depois o estrutograma + +Desta vez não desenhas. Abre a área Código e escreve este código Java: + +\`\`\` +System.out.println("Número inicial?"); +int zahl = scanner.nextInt(); +while (zahl > 0) { + System.out.println(zahl); + zahl = zahl - 1; +} +System.out.println("Start!"); +\`\`\` + +::: übung l20-countdown +titel: Contagem decrescente +bereich: beide +auftrag: Escreve o código Java acima na área Código. Executa-o com ▶︎ e introduz um número inicial na consola. + Depois observa o estrutograma que foi construído e clica em Verificar. +test: 3 -> 3 | 2 | 1 | Start! +test: 1 -> 1 | Start! +test: 0 -> Start! +braucht: whileSchleife +tipp: Abre a área Código com a barra estreita mais à direita e começa simplesmente a escrever. +tipp: Atenção ao ponto e vírgula no fim de cada instrução e às chavetas do ciclo while. Por baixo do código aparece uma indicação quando ainda falta alguma coisa. +lösung: l20-countdown-loesung.visustruct +::: + +## Exercício: Java como estrutograma + +Agora ao contrário: aqui está um pedaço de código Java. Reconstrói-o como estrutograma. + +\`\`\` +System.out.println("Introduz um número"); +int n = scanner.nextInt(); +int fatorial = 1; +for (int i = 1; i <= n; i++) { + fatorial = fatorial * i; +} +System.out.println(fatorial); +\`\`\` + +::: übung l17-fakultaet +titel: Fatorial a partir de Java +bereich: beide +auftrag: Reconstrói o código Java de cima como estrutograma. O programa lê um número n e mostra o produto 1 · 2 · … · n. + No fim, confirma na vista de código se o teu código Java fica igual. +test: 3 -> 6 +test: 5 -> 120 +test: 1 -> 1 +braucht: forSchleife +tipp: Lê o código Java linha a linha e pensa que bloco serve para cada linha. +tipp: As duas primeiras linhas Java juntas são uma única entrada: \`input: int n "Introduz um número"\`. O ciclo for tem os três campos \`int i = 1\`, \`i <= n\` e \`i++\`. +lösung: l17-fakultaet-loesung.visustruct +::: + +## Exercício: else if + +Em Java, vários casos escrevem-se muitas vezes com \`else if\`: + +\`\`\` +if (idade < 6) { + System.out.println("Entrada gratuita"); +} else if (idade < 18) { + System.out.println("Bilhete de criança: 4 euros"); +} else { + System.out.println("Bilhete de adulto: 8 euros"); +} +\`\`\` + +Num estrutograma não existe \`else if\`. Aí, uma segunda decisão fica no ramo false da primeira. Se o ramo false tiver só essa decisão, o VisuStruct volta a transformá-la em \`else if\` quando gera o código, e em \`elif\` em Python. + +::: übung l17-ticket +titel: Preço do bilhete +auftrag: Pede a idade como número inteiro e reconstrói o código Java de cima como estrutograma. +test: 5 -> Entrada gratuita +test: 6 -> Bilhete de criança: 4 euros +test: 17 -> Bilhete de criança: 4 euros +test: 18 -> Bilhete de adulto: 8 euros +braucht: verzweigung +tipp: No código Java há outro \`if\` dentro de um \`else\`. No estrutograma isso é uma decisão dentro de um ramo. +tipp: Arrasta uma segunda decisão com a condição \`idade < 18\` para o ramo false da primeira decisão. +lösung: l17-ticket-loesung.visustruct +::: + +## Jogo: Que bloco é? + +::: spiel frage +titel: Jogo: Que bloco é? +intro: O Ludwig mostra-te Java. Que bloco do estrutograma está por trás? Oito rondas. +frage: Que bloco é este? + +runde: + do { + numero = numero * 2; + } while (numero < 100); +- Ciclo while +- [x] Ciclo do-while +- Ciclo for +> A condição está em baixo. Por isso o corpo corre pelo menos uma vez. + +runde: + switch (escolha) { + case 1 -> { System.out.println("água"); } + default -> { System.out.println("Esse botão não existe."); } + } +- Decisão +- [x] Seleção +- Chamada +> Uma variável é comparada com valores fixos: isso é a seleção. + +runde: + break; +- Chamada +- Ciclo infinito +- [x] Interrupção +> O \`break\` sai logo do ciclo onde está. + +runde: + calcular(); +- [x] Chamada +- Saída +- Instrução +> Um nome com parênteses: aqui é chamado um subprograma. + +runde: + int numero = scanner.nextInt(); +- Saída +- [x] Entrada +- Chamada +> O scanner lê um valor. Isso é uma entrada. + +runde: + while (true) { + System.out.println("Olá"); + } +- Ciclo while com condição +- [x] Ciclo infinito +- Ciclo do-while +> \`while (true)\` não tem uma condição verdadeira. Só um break o poderia terminar. + +runde: +frage: Queres um ficheiro Java completo que possas compilar e executar logo. O que escolhes na vista de código? +- Excerto +- [x] Classe +> Um excerto são só as instruções para o método \`main\`. Classe cria o ficheiro inteiro. + +runde: +frage: No depurador, uma linha está amarela. O que quer dizer? +- Tem um erro. +- [x] É a próxima a ser executada. +- Tem um ponto de paragem. +> Amarela é a próxima linha. Um ponto de paragem é um ponto vermelho no número da linha. +::: + +## 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. + +::: checkliste +- Consigo abrir a vista de código e escolher Java como linguagem. → A vista de código +- Consigo reconhecer em Java a saída, a entrada, as decisões e os ciclos. → Os elementos em Java +- Consigo explicar a diferença entre Excerto e Classe. → Excerto ou Classe +- Consigo reconstruir um programa Java curto como estrutograma. → Exercício: Java como estrutograma +- Consigo escrever Java na área Código e ler o estrutograma que é construído. → Escrever Java diretamente +- Consigo executar um programa com ▶︎ e usar entradas e saídas na consola. → Executar o programa +- Consigo pôr pontos de paragem e seguir um programa passo a passo. → Encontrar erros com o depurador +::: + +## Teste de conhecimentos + +::: quiz +? Como fica \`output: "Olá"\` em Java? +→ Os elementos em Java +- [ ] print("Olá") +- [x] System.out.println("Olá"); +- [ ] console.log("Olá"); +> print é Python, console.log é JavaScript. + +? De onde vem o nome da classe em Classe? +→ Excerto ou Classe +- [ ] Chama-se sempre Main. +- [x] Do título do diagrama +- [ ] Do primeiro bloco +> Sem título, a classe chama-se Main. + +? Que código Java pertence a um ciclo do-while? +→ Os elementos em Java +- [ ] while (condição) { … } +- [x] do { … } while (condição); +- [ ] for (;;) { … } +> No do-while a condição está no fim, por isso o corpo é executado pelo menos uma vez. + +? Em que se transforma uma Interrupção no código Java? +→ Os elementos em Java +- [x] break; +- [ ] return; +- [ ] exit(); + +? O que acontece num ponto vermelho antes do número da linha? +→ Encontrar erros com o depurador +- [ ] A linha é ignorada. +- [x] O programa para antes dessa linha. +- [ ] A linha tem um erro. +> É um ponto de paragem. Continua-se com ▶︎ ou com Passo a passo. +::: +`,cv=`--- +titel: Python e JavaScript +bereich: Do estrutograma ao código +kurz: Gerar código Python e JavaScript a partir do estrutograma e executar JavaScript diretamente no navegador. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- escolher e comparar Python e JavaScript na vista de código +- explicar que o Python forma blocos pela indentação e não precisa de tipos de dados +- explicar o que o VisuStruct ajusta ao traduzir para Python +- executar JavaScript com Testar no navegador +::: + +## O mesmo diagrama, três linguagens + +Na vista de código ([Código](#zeige-code) nas ferramentas) escolhes a linguagem em cima. O estrutograma fica igual; só muda a forma de escrever. Assim podes comparar as linguagens facilmente. + +::: diagramm l18-beispiel.visustruct +Um número é diminuído em 3 uma e outra vez até deixar de ser maior do que 0. +::: + +## Python + +Para o diagrama de cima, o VisuStruct gera este código Python: + +\`\`\` +numero = int(input("Valor inicial?")) +while numero > 0: + print(numero) + numero = numero - 3 +print("Fim") +\`\`\` + +O que é diferente em Python em relação ao Java: + +- **Não há ponto e vírgula** nem **chavetas**. O Python reconhece o que pertence a um ciclo ou a uma decisão só pela **indentação**. Depois de \`while\`, \`if\` e \`else\` vêm dois pontos. +- As variáveis **não têm tipo de dados**: \`int numero = 5\` passa a \`numero = 5\`. +- A saída chama-se \`print(…)\`, a entrada \`input(…)\`. Para um número, fica \`int(…)\` à volta. +- Em Python, os arrays chamam-se **listas**: \`int[] numeros = {2, 4, 6}\` passa a \`numeros = [2, 4, 6]\`, e \`numeros.length\` passa a \`len(numeros)\`. +- Um ciclo for simples como \`int i = 0\`, \`i < 5\`, \`i++\` passa a \`for i in range(5):\`. + +## Cuidados com o Python + +Em alguns sítios, o Python é mais rigoroso do que o Java. Por isso, o VisuStruct traduz a forma de escrever do Java quando exporta: + +- **Texto e número com +:** \`"Soma: " + soma\` passa a \`"Soma: " + str(soma)\`. Sem \`str(…)\`, o Python para com um erro. +- **Não existe i++:** passa a \`i += 1\`. +- **&&, || e !** chamam-se \`and\`, \`or\` e \`not\` em Python, e \`true\` e \`false\` passam a \`True\` e \`False\`. +- **Divisão inteira:** Em Python, \`7 / 2\` dá sempre 3.5. Se o estrutograma dividir dois valores \`int\`, o VisuStruct escreve \`7 // 2\`, que dá 3, tal como em Java. +- **Ciclos for:** Os ciclos de contagem passam a \`for … in range(…)\`, também com \`i <= n\`, a contar para trás ou com passos como \`i = i + 2\`. Se um ciclo não encaixar nesse padrão, passa a ciclo \`while\`. +- **Não existe do-while:** passa a \`while True:\` com \`if not (…): break\` no fim. + +Se um diagrama estiver marcado como **pseudocódigo**, só aparece um aviso por cima do código. Nesse caso o texto é um esboço e não um programa executável. + +## JavaScript + +O mesmo diagrama em JavaScript: + +\`\`\` +"use strict"; + +let numero = parseInt((prompt("Valor inicial?") ?? "0"), 10); +while (numero > 0) { + console.log(numero); + numero = numero - 3; +} +console.log("Fim"); +\`\`\` + +O JavaScript parece-se com o Java: chavetas, ponto e vírgula, \`while (…)\` e \`if (…)\`. As diferenças: + +- As variáveis criam-se com \`let\`, sem tipo de dados. As constantes com \`const\`. +- A saída chama-se \`console.log(…)\`, a entrada \`prompt(…)\`. O \`parseInt(…)\` transforma a entrada num número inteiro. +- Os arrays ficam entre parênteses retos: \`let numeros = [2, 4, 6];\`. +- \`"use strict";\` mesmo lá em cima faz o JavaScript queixar-se de erros de escrita nos nomes das variáveis. +- O JavaScript só tem um tipo de número. Se o estrutograma dividir dois valores \`int\`, o VisuStruct escreve \`Math.trunc(a / b)\`. Assim desaparecem os algarismos depois da vírgula, tal como em Java. + +::: angeberwissen +O JavaScript não tem quase nada a ver com o Java. Brendan Eich criou-o em 1995 em apenas dez dias para o navegador Netscape. Primeiro chamava-se Mocha, depois LiveScript. Como toda a gente andava entusiasmada com o Java, pouco antes do lançamento mudaram-lhe o nome para JavaScript, por razões de publicidade. Desde então, as duas linguagens são constantemente confundidas. Os programadores dizem que o Java e o JavaScript têm tanto em comum como um carro e uma carpete. +::: + +## Executar JavaScript no navegador + +O JavaScript é a linguagem dos navegadores. Por isso o VisuStruct consegue **executar o código logo**: + +::: angeberwissen +Já agora, porque é que as ligações no navegador são azuis? Em 1985, a equipa de Ben Shneiderman testou que cor se vê bem mas não atrapalha a leitura. Ganhou o azul-claro. O vermelho destacava-se mais, mas as pessoas lembravam-se pior do texto a seguir. +::: + +1. Escolhe **JavaScript** na vista de código. +2. Clica em **Testar no navegador**. +3. O que o \`console.log\` mostra aparece em **Saída**. Se o programa pedir um valor com \`prompt\`, escreve-o e clica em **OK**. +4. **Parar** cancela o programa. + +O VisuStruct para sozinho um ciclo infinito \`while (true)\` depois de 100 000 iterações e indica **Execução interrompida: possível ciclo infinito.** + +> No código JavaScript, uma **Chamada** precisa de um subprograma com esse nome, senão o JavaScript indica um erro. Ao contrário da simulação, o navegador não procura nos outros separadores. + +## Exercício: Python como estrutograma + +Este programa Python mostra todos os números pares de 0 até um limite: + +\`\`\` +limite = int(input("Até que número?")) +for i in range(0, limite + 1, 2): + print(i) +\`\`\` + +\`range(0, limite + 1, 2)\` quer dizer: começar em 0, parar antes de \`limite + 1\`, contar de dois em dois. + +::: übung l18-python +titel: Números pares +auftrag: Reconstrói o programa Python de cima como estrutograma com um ciclo for. Com o limite 7, mostra 0, 2, 4 e 6. +test: 7 -> 0 | 2 | 4 | 6 +test: 4 -> 0 | 2 | 4 +test: 0 -> 0 +braucht: forSchleife +tipp: \`range(0, limite + 1, 2)\` conta de 0 até ao limite de dois em dois. Isso é um ciclo for. +tipp: Os três campos do ciclo for são \`int i = 0\`, \`i <= limite\` e \`i = i + 2\`. +lösung: l18-python-loesung.visustruct +::: + +## Exercício: JavaScript como estrutograma + +\`\`\` +let idade = parseInt((prompt("Quantos anos tens?") ?? "0"), 10); +if (idade >= 18) { + console.log("Podes votar."); +} else { + let anos = 18 - idade; + console.log("Espera mais " + anos + " anos."); +} +\`\`\` + +::: übung l18-js +titel: Votar a partir dos 18 +auftrag: Reconstrói o código JavaScript de cima como estrutograma. Depois testa na vista de código, com **JavaScript** e **Testar no navegador**, se o teu código mostra o mesmo que a simulação. +test: 12 -> Espera mais 6 anos. +test: 18 -> Podes votar. +test: 15 -> Espera mais 3 anos. +test: 40 -> Podes votar. +braucht: verzweigung +tipp: Lê o código linha a linha. \`if\` e \`else\` passam a uma decisão. +tipp: \`prompt\` e \`parseInt\` juntos são uma entrada: \`input: int idade "Quantos anos tens?"\`. O ramo false tem dois blocos: primeiro \`int anos = 18 - idade\`, depois a saída. +lösung: l18-js-loesung.visustruct +::: + +## Jogo: Que linguagem? + +::: spiel frage +titel: Jogo: Que linguagem? +intro: O Ludwig misturou linhas de três linguagens. Reconheces de onde vem cada uma? Oito rondas. +frage: Em que linguagem está isto escrito? +antworten: Java | Python | JavaScript + +runde: + print(numero) +richtig: Python +> Em Python, a saída chama-se \`print(…)\`, sem ponto e vírgula. + +runde: + console.log(numero); +richtig: JavaScript +> \`console.log\` é a saída em JavaScript. + +runde: + System.out.println(numero); +richtig: Java +> A saída comprida com \`System.out\` só existe em Java. + +runde: + let numeros = [2, 4, 6]; +richtig: JavaScript +> \`let\` e parênteses retos: um array em JavaScript. + +runde: + for i in range(5): +richtig: Python +> Dois pontos em vez de chavetas, e \`range\`: típico de Python. + +runde: + int[] numeros = {2, 4, 6}; +richtig: Java +> Só o Java escreve o tipo de dados \`int[]\` à frente. + +runde: + numero = int(input("Valor inicial?")) +richtig: Python +> Sem tipo de dados antes da variável, sem ponto e vírgula, e \`int(…)\` à volta da entrada. + +runde: + let numero = parseInt(prompt("Valor inicial?"), 10); +richtig: JavaScript +> \`prompt\` pede um valor no browser, \`parseInt\` transforma-o num número. +::: + +## 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. + +::: checkliste +- Consigo escolher e comparar Python e JavaScript na vista de código. → O mesmo diagrama, três linguagens +- Consigo explicar que o Python forma blocos pela indentação e não precisa de tipos de dados. → Python +- Consigo explicar o que o VisuStruct ajusta ao traduzir para Python. → Cuidados com o Python +- Consigo executar JavaScript com Testar no navegador. → Executar JavaScript no navegador +::: + +## Teste de conhecimentos + +::: quiz +? Como reconhece o Python que linhas pertencem a um ciclo? +→ Python +- [ ] Pelas chavetas +- [x] Pela indentação +- [ ] Pelo ponto e vírgula no fim da linha + +? Como fica \`output: soma\` em JavaScript? +→ O mesmo diagrama, três linguagens +- [ ] print(soma) +- [ ] System.out.println(soma); +- [x] console.log(soma); + +? Que linguagem consegue o VisuStruct executar diretamente no navegador? +→ Executar JavaScript no navegador +- [ ] Java +- [ ] Python +- [x] JavaScript +> Qualquer navegador consegue executar JavaScript. Para Java e Python precisas de um programa próprio. + +? O que acontece em Python com \`print("Soma: " + soma)\` se soma for o número 7? +→ Cuidados com o Python +- [ ] É mostrado Soma: 7. +- [x] O Python indica um erro, porque texto e número não se podem juntar com +. +- [ ] É mostrado Soma:. +> str(soma) transforma o número em texto. +::: +`,mv=`--- +titel: Quando o programa falha: try e catch +bereich: Apanhar erros +kurz: Ler mensagens de erro com Java verdadeiro e apanhar falhas com try e catch. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- ligar o Java verdadeiro na área Código +- ler numa mensagem de erro a exceção e a linha +- apanhar uma exceção com try e catch +- transformar texto num número com Integer.parseInt e apanhar a NumberFormatException +- escrever um programa que divide em segurança, mesmo por 0 +::: + +## Falhou! + +Este programa deve escrever três notas. Escreve-o na área [Código](#zeige-codelive) e clica em [▶︎ Executar](#zeige-ausfuehren): + +\`\`\`java +int[] notas = {2, 3, 1}; +System.out.println("Primeira nota: " + notas[0]); +System.out.println("Quarta nota: " + notas[3]); +System.out.println("Pronto!"); +\`\`\` + +A primeira nota aparece e depois acabou. O VisuStruct indica “Expressão inválida: notas[3]”, e “Pronto!” nunca chega a aparecer. O array só tem as posições 0, 1 e 2; a posição 3 não existe. + +::: ludwig +Já te aconteceu? Um pequeno erro e o programa inteiro vai-se. A mim aconteceu-me tantas vezes que cheguei a chorar em frente ao ecrã. Mas há uma solução, e chama-se **try** e **catch**. +::: + +::: angeberwissen +Em 1947, a equipa de Grace Hopper encontrou no computador Mark II da Universidade de Harvard uma traça que tinha causado uma avaria. Colaram-na no diário de bordo e escreveram: “First actual case of bug being found”. Desde então, os erros de programa chamam-se **bugs** (inglês para insetos). +::: + +## Ligar o Java verdadeiro + +Normalmente a área Código calcula com a mesma simulação que o estrutograma. Quando há um erro, ela simplesmente para. Para veres o que faz o Java verdadeiro, liga o Java verdadeiro: + +1. Clica na [roda dentada](#zeige-einstellungen) em cima à direita e escolhe Java como **Linguagem de programação**. +2. Na secção Java, marca **Java verdadeiro (com Swing)**. + +Na primeira execução, o VisuStruct descarrega uma única vez cerca de 40 MB. Depois disso, o teu código é compilado e executado como num ambiente de desenvolvimento Java a sério. + +> Com o Java verdadeiro, as entradas pela consola (\`Scanner\`) ainda não funcionam. Por isso os nossos exemplos não precisam de entradas. + +Escreve agora o programa como uma classe completa, para que os números das linhas batam certo, e executa-o: + +\`\`\`java +public class Notas { + public static void main(String[] args) { + int[] notas = {2, 3, 1}; + System.out.println("Primeira nota: " + notas[0]); + System.out.println("Quarta nota: " + notas[3]); + System.out.println("Pronto!"); + } +} +\`\`\` + +Na [consola](#zeige-konsole) aparece agora: + +\`\`\` +Primeira nota: 2 +java.lang.ArrayIndexOutOfBoundsException: 3 + at Notas.main(Notas.java:5) +\`\`\` + +## Ler a mensagem de erro + +Uma mensagem destas assusta à primeira vista. Mas diz-te exatamente o que se passa: + +| Parte | Significado | +|---|---| +| \`ArrayIndexOutOfBoundsException\` | O tipo de erro: o índice está fora do array. | +| \`3\` | O índice errado. | +| \`Notas.java:5\` | A linha onde aconteceu: a linha 5. | + +O Java chama a um erro destes, durante a execução, uma **exceção** (em inglês *exception*). Diz-se: o Java *lança* uma exceção. Se ninguém a apanhar, o programa para. É por isso que “Pronto!” não aparece. + +::: ludwig +Lê as mensagens de erro sempre de cima: primeiro o nome da exceção, depois o número da linha. Na área Código, os números das linhas estão à esquerda do código. +::: + +## try e catch + +Com **try** e **catch** apanhas a exceção. Altera a linha com \`notas[3]\` assim: + +\`\`\`java +try { + System.out.println("Quarta nota: " + notas[3]); +} catch (ArrayIndexOutOfBoundsException e) { + System.out.println("Esta nota não existe."); +} +System.out.println("Pronto!"); +\`\`\` + +- \`try\` quer dizer “tenta”. O Java executa o bloco entre chavetas normalmente. +- Se uma linha lá dentro lançar uma exceção, o Java salta logo para o bloco \`catch\`. O resto do bloco \`try\` é saltado. +- Entre parênteses, depois de \`catch\`, está a exceção que é apanhada e um nome para ela, normalmente \`e\`. +- Depois, o programa continua normalmente. Agora também aparece “Pronto!”. + +Se tudo correr bem no bloco \`try\`, o bloco \`catch\` é simplesmente saltado. + +::: ludwig +try e catch são como a rede por baixo do trapézio no circo: enquanto tudo corre bem, nem dás por ela. Se alguém cair, a rede apanha-o e o espetáculo continua. +::: + +> No estrutograma não há nenhuma caixa para try e catch. Por isso o VisuStruct mostra o bloco inteiro como uma instrução. Só o podes executar com o Java verdadeiro. + +## Transformar texto num número + +Muitas vezes um número começa por ser texto, por exemplo mais tarde num campo de texto numa janela. \`Integer.parseInt\` transforma texto num número inteiro: + +\`\`\`java +String entrada = "doze"; +try { + int numero = Integer.parseInt(entrada); + System.out.println("Dobro: " + numero * 2); +} catch (NumberFormatException e) { + System.out.println("Isto não é um número: " + entrada); +} +\`\`\` + +O Java não consegue converter “doze” e lança uma \`NumberFormatException\`. O programa escreve “Isto não é um número: doze”. Muda a primeira linha para \`String entrada = "12";\` e executa outra vez: agora aparece “Dobro: 24”. + +## Saber de profissional: as exceções são objetos + +Isto não está no programa da disciplina, mas é útil saber. + +::: angeberwissen +Cada exceção é um objeto de uma classe própria, por exemplo \`ArithmeticException\` para a divisão por 0. \`e.getMessage()\` dá-te a sua mensagem, por exemplo \`/ by zero\`. + +Depois de um \`try\` podem vir vários blocos \`catch\`, um para cada tipo de erro. \`catch (Exception e)\` apanha todas as exceções, mas diz-te menos sobre o que aconteceu. E um bloco \`finally { … }\` no fim corre sempre, quer tenha havido erro quer não. +::: + +## Jogo: A rede apanha? + +::: spiel frage +titel: Jogo: A rede apanha? +intro: O Ludwig anda no trapézio. O try e o catch apanham-no, ou o programa vai abaixo? Sete rondas. + +runde: + int[] notas = {2, 3, 1}; + System.out.println(notas[3]); + System.out.println("Pronto!"); +frage: O que acontece com Java a sério? +- Aparece 1 e Pronto! +- Só aparece Pronto! +- [x] O programa vai abaixo com uma ArrayIndexOutOfBoundsException. +> A posição 3 não existe. Ninguém apanha a exceção, por isso Pronto! nunca chega a aparecer. + +runde: + int[] notas = {2, 3, 1}; + try { + System.out.println(notas[3]); + } catch (ArrayIndexOutOfBoundsException e) { + System.out.println("Esta nota não existe."); + } + System.out.println("Pronto!"); +frage: O que aparece? +- Pronto! +- [x] Esta nota não existe.\\nPronto! +- Esta nota não existe. +> O bloco catch apanha a exceção, e depois o programa continua normalmente. + +runde: + try { + System.out.println("A"); + System.out.println(10 / 0); + System.out.println("B"); + } catch (ArithmeticException e) { + System.out.println("C"); + } +frage: O que aparece? +- A\\nB\\nC +- [x] A\\nC +- C +> Em 10 / 0, o Java salta logo para o bloco catch. O resto do bloco try, o B, é saltado. + +runde: + String entrada = "12"; + try { + int numero = Integer.parseInt(entrada); + System.out.println("Dobro: " + numero * 2); + } catch (NumberFormatException e) { + System.out.println("Isto não é um número: " + entrada); + } +frage: O que aparece? +- [x] Dobro: 24 +- Isto não é um número: 12 +- Dobro: 1212 +> "12" pode ser convertido. Se tudo correr bem no bloco try, o catch é saltado. + +runde: +frage: Que exceção lança \`Integer.parseInt("2.5")\`? +- ArithmeticException +- [x] NumberFormatException +- nenhuma, o resultado é 2 +> parseInt só converte números inteiros. Com um ponto, o formato não é válido. + +runde: +frage: Que exceção lança \`12 / 0\` com \`int\`? +- [x] ArithmeticException +- NumberFormatException +- ArrayIndexOutOfBoundsException +> Dividir por 0 não funciona com números inteiros. A mensagem é \`/ by zero\`. + +runde: + try { + int fatias = 12 / 0; + } catch (NumberFormatException e) { + System.out.println("Erro!"); + } + System.out.println("Pronto!"); +frage: O que acontece? +- Aparece Erro! e Pronto! +- Só aparece Pronto! +- [x] O programa vai abaixo. +> O catch só apanha a exceção que está entre parênteses. Uma ArithmeticException cai pela rede. +::: + +## Tarefa: dividir em segurança + +Este programa falha: + +\`\`\`java +int bolo = 12; +int pessoas = 0; +System.out.println("Cada um recebe " + bolo / pessoas + " fatias."); +System.out.println("Bom apetite!"); +\`\`\` + +1. Executa-o com o Java verdadeiro e lê a mensagem de erro. Que exceção é? +2. Apanha-a com try e catch. Em vez da falha deve aparecer “Sem pessoas não se pode dividir.”, e “Bom apetite!” deve aparecer na mesma. +3. Põe \`pessoas\` a 4 e verifica que aparece “Cada um recebe 3 fatias.”. + +::: ludwig +A exceção chama-se \`ArithmeticException\`. Põe no bloco \`try\` só a linha que pode falhar. +::: + +## 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. + +::: checkliste +- Consigo ligar o Java verdadeiro na área Código. → Ligar o Java verdadeiro +- Consigo ler numa mensagem de erro a exceção e a linha. → Ler a mensagem de erro +- Consigo apanhar uma exceção com try e catch. → try e catch +- Consigo transformar texto num número com Integer.parseInt e apanhar a NumberFormatException. → Transformar texto num número +- Consigo escrever um programa que divide em segurança, mesmo por 0. → Tarefa: dividir em segurança +::: + +## Teste de conhecimentos + +::: quiz +? O que acontece quando uma exceção não é apanhada? +→ Ler a mensagem de erro +- [ ] O Java salta a linha e continua. +- [x] O programa para. +- [ ] O computador reinicia. +> É por isso que no primeiro exemplo “Pronto!” não aparece. + +? O que acontece no bloco try depois da linha que lança uma exceção? +→ try e catch +- [ ] As restantes linhas correm na mesma. +- [x] O resto é saltado e o Java salta para o bloco catch. +- [ ] O Java recomeça o bloco try. + +? Que exceção lança Integer.parseInt("doze")? +→ Transformar texto num número +- [ ] ArithmeticException +- [ ] ArrayIndexOutOfBoundsException +- [x] NumberFormatException +> “doze” não tem um formato de número que o Java entenda. + +? Associa cada exceção à sua causa. +→ Ler a mensagem de erro += ArrayIndexOutOfBoundsException -> índice fora do array += ArithmeticException -> divisão por 0 += NumberFormatException -> o texto não é um número +::: +`,dv=`--- +titel: Ler e guardar texto +bereich: Ficheiros +kurz: Ler um ficheiro de texto linha a linha com Scanner e guardar um ficheiro com PrintWriter. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar porque é que os programas guardam dados em ficheiros +- ler um ficheiro de texto linha a linha com Scanner, hasNextLine e nextLine +- explicar porque é que o Java exige try e catch ou throws com ficheiros +- escrever um ficheiro com PrintWriter e terminá-lo com close +- ler um ficheiro, completá-lo e voltar a guardá-lo numerado +::: + +## Porquê ficheiros? + +Tudo o que está em variáveis desaparece assim que o programa termina. Se um programa deve lembrar-se de alguma coisa, por exemplo uma pontuação, uma lista ou notas, guarda os dados num **ficheiro**. Na próxima vez que arranca, volta a ler o ficheiro. + +A Zora está livre, e o Ludwig está a preparar uma festa. A lista de compras dele está pronta no ficheiro \`compras.txt\`: + +::: datei compras.txt +Feno +Maçãs +Cenouras +Dentes-de-leão +::: + +Um ficheiro com a extensão \`.txt\` contém só texto, linha a linha. Podes abri-lo com qualquer editor, por exemplo o Bloco de Notas no Windows ou o TextEdit no Mac. + +## Ler um ficheiro com Scanner + +Já conheces o \`Scanner\`: \`new Scanner(System.in)\` lê do teclado. Se lhe deres um ficheiro em vez de \`System.in\`, ele lê do ficheiro: + +\`\`\`java +import java.io.*; +import java.util.Scanner; + +Scanner ficheiro = new Scanner(new File("compras.txt")); +while (ficheiro.hasNextLine()) { + String linha = ficheiro.nextLine(); + System.out.println(linha); +} +ficheiro.close(); +\`\`\` + +| Método | Significado | +|---|---| +| \`new File("compras.txt")\` | o ficheiro com este nome | +| \`hasNextLine()\` | Ainda há mais uma linha? \`true\` ou \`false\` | +| \`nextLine()\` | devolve a linha seguinte e avança uma linha | +| \`close()\` | fecha o ficheiro quando terminas | + +O ciclo repete-se enquanto houver mais uma linha. Em cada volta, \`nextLine()\` vai buscar a linha seguinte. \`File\` pertence ao pacote \`java.io\`, por isso precisas de \`import java.io.*;\`. + +::: diagramm dt-lesen.visustruct +É assim que a leitura fica num estrutograma. Experimenta na simulação. +::: + +::: ludwig +Imagina o Scanner como um dedo a apontar para uma linha. \`nextLine()\` lê a linha debaixo do dedo e desce o dedo uma linha. Quando o dedo já está abaixo da última linha, \`hasNextLine()\` devolve \`false\`. +::: + +## E se o ficheiro não existir? + +Se o ficheiro não existir, o Java não o consegue ler e lança uma \`FileNotFoundException\`. O Java exige que o teu programa conte com isso. Ou apanhas a exceção com try e catch, como na lição 22: + +\`\`\`java +try { + Scanner ficheiro = new Scanner(new File("compras.txt")); + // ... ler ... + ficheiro.close(); +} catch (FileNotFoundException e) { + System.out.println("Falta o ficheiro compras.txt!"); +} +\`\`\` + +Ou escreves \`throws Exception\` a seguir a \`main\`. Isso quer dizer: "Este método pode lançar uma exceção, eu não trato dela." Nesse caso, o programa para se o ficheiro não existir. + +\`\`\`java +public static void main(String[] args) throws Exception { +\`\`\` + +> O VisuStruct escreve \`throws Exception\` a seguir a \`main\` automaticamente assim que o teu programa trabalha com ficheiros. Na simulação, o VisuStruct indica um ficheiro em falta com "Não existe nenhum ficheiro chamado …". + +## Exercício: Numerar a lista de compras + +::: übung l23-java-nummern +titel: Numerar a lista de compras +code: java +auftrag: Lê \`compras.txt\` linha a linha e mostra cada linha com o seu número: **1. Feno**, **2. Maçãs** e assim por diante. +start: l23-java-nummern-start.visustruct +test: - -> 1. Feno | 2. Maçãs | 3. Cenouras | 4. Dentes-de-leão +braucht: whileSchleife +tipp: Antes do ciclo, cria \`int numero = 1;\` e aumenta o número no fim de cada volta. +tipp: A saída é \`System.out.println(numero + ". " + linha);\` +lösung: l23-java-nummern-loesung.visustruct +::: + +## Escrever num ficheiro com PrintWriter + +Para escrever existe o \`PrintWriter\`. Os seus métodos têm os mesmos nomes que os de \`System.out\`: + +\`\`\`java +PrintWriter saida = new PrintWriter("saudacao.txt"); +saida.println("Olá Zora!"); +saida.println("Até amanhã, Ludwig"); +saida.close(); +\`\`\` + +Depois disto, \`saudacao.txt\` contém: + +\`\`\` +Olá Zora! +Até amanhã, Ludwig +\`\`\` + +- \`println\` escreve o texto e começa depois uma nova linha, \`print\` escreve sem nova linha. +- Se o ficheiro já existir, é **substituído**. O conteúdo antigo desaparece. +- Depois da execução, o VisuStruct mostra por baixo da saída o que foi guardado no ficheiro. + +::: ludwig +Não te esqueças do \`close()\`! O PrintWriter junta primeiro o texto numa memória intermédia e só o escreve no ficheiro quando é fechado. Sem \`close()\` o ficheiro fica vazio. Já perdi assim uma história inteira. +::: + +## Exercício: Completar a lista de compras + +::: übung l23-java-ergaenzen +titel: Completar a lista de compras +code: java +auftrag: O Ludwig ainda precisa de bolo. Lê \`compras.txt\` e escreve cada linha no novo ficheiro \`compras-nova.txt\`. Depois acrescenta **Bolo** como última linha. No fim, mostra quantas linhas foram guardadas: **5 linhas guardadas**. +start: l23-java-ergaenzen-start.visustruct +test: - -> 5 linhas guardadas +datei: compras-nova.txt -> Feno | Maçãs | Cenouras | Dentes-de-leão | Bolo +braucht: whileSchleife +tipp: No ciclo, lês uma linha com \`ficheiro.nextLine()\` e escreve-la logo a seguir com \`saida.println(linha)\`. +tipp: Depois do ciclo vem \`saida.println("Bolo");\`. Fecha os dois ficheiros com \`close()\`, senão \`compras-nova.txt\` fica vazio. +lösung: l23-java-ergaenzen-loesung.visustruct +::: + +## Jogo: O que fica no ficheiro? + +::: spiel frage +titel: Jogo: O que fica no ficheiro? +intro: O Ludwig escreve ficheiros com o PrintWriter. Lê o código e prevê o que fica no ficheiro. Seis rondas. +frage: O que fica depois no ficheiro? + +runde: + PrintWriter saida = new PrintWriter("saudacao.txt"); + saida.println("Olá"); + saida.println("Zora"); + saida.close(); +- [x] Olá\\nZora +- OláZora +- Zora +> \`println\` começa uma nova linha depois de cada texto. + +runde: + PrintWriter saida = new PrintWriter("palavra.txt"); + saida.print("Bo"); + saida.print("la"); + saida.println("!"); + saida.close(); +- Bo\\nla\\n! +- [x] Bola! +- Bo la ! +> \`print\` continua a escrever sem nova linha, por isso as partes ficam coladas. + +runde: + PrintWriter saida = new PrintWriter("segredo.txt"); + saida.println("O tesouro está na torre"); +- O tesouro está na torre +- [x] Nada, o ficheiro fica vazio. +- O Java indica um erro. +> Sem \`close()\` o texto nunca chega ao ficheiro. Fica na memória intermédia. + +runde: + // Antes, nota.txt contém: Antigo + PrintWriter saida = new PrintWriter("nota.txt"); + saida.println("Novo"); + saida.close(); +- Antigo\\nNovo +- [x] Novo +- Novo\\nAntigo +> Um novo PrintWriter substitui o ficheiro. O conteúdo antigo desaparece. + +runde: + PrintWriter saida = new PrintWriter("numeros.txt"); + for (int i = 1; i <= 3; i++) { + saida.println(i * 2); + } + saida.close(); +- 1\\n2\\n3 +- 246 +- [x] 2\\n4\\n6 +> O ciclo escreve 2, 4 e 6, cada número na sua linha. + +runde: + // compras.txt contém: Feno, Maçãs (uma por linha) + Scanner ficheiro = new Scanner(new File("compras.txt")); + PrintWriter saida = new PrintWriter("grande.txt"); + while (ficheiro.hasNextLine()) { + saida.println(ficheiro.nextLine().toUpperCase()); + } + ficheiro.close(); + saida.close(); +- Feno\\nMaçãs +- [x] FENO\\nMAÇÃS +- FENOMAÇÃS +> Cada linha é lida, passada para maiúsculas e escrita na sua própria linha. +::: + +## 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. + +::: checkliste +- Consigo explicar porque é que os programas guardam dados em ficheiros. → Porquê ficheiros? +- Consigo ler um ficheiro de texto linha a linha com Scanner, hasNextLine e nextLine. → Ler um ficheiro com Scanner +- Consigo explicar porque é que o Java exige try e catch ou throws com ficheiros. → E se o ficheiro não existir? +- Consigo escrever um ficheiro com PrintWriter e terminá-lo com close(). → Escrever num ficheiro com PrintWriter +- Consigo ler um ficheiro, completá-lo e voltar a guardá-lo numerado. → Exercício: Completar a lista de compras +::: + +## Teste de conhecimentos + +::: quiz +? O que devolve hasNextLine()? +→ Ler um ficheiro com Scanner +- [ ] a linha seguinte +- [x] true se ainda houver uma linha, senão false +- [ ] o número de linhas +> Com hasNextLine() o ciclo verifica se continua. + +? O que acontece se chamares new PrintWriter("lista.txt") para um ficheiro que já existe? +→ Escrever num ficheiro com PrintWriter +- [ ] O texto novo é acrescentado no fim. +- [x] O ficheiro é substituído. +- [ ] O Java indica um erro. + +? Porque é que um ficheiro fica vazio, apesar de println ter sido chamado? +→ Escrever num ficheiro com PrintWriter +- [ ] Porque println só escreve na consola. +- [x] Porque falta o close(). +- [ ] Porque o nome do ficheiro termina em .txt. +> Só o close() escreve a memória intermédia no ficheiro. + +? Liga cada método à sua tarefa. +→ Ler um ficheiro com Scanner += nextLine() -> lê a linha seguinte += println(texto) -> escreve uma linha += close() -> fecha o ficheiro +::: +`,hv=`--- +titel: Linha a linha com BufferedReader +bereich: Ficheiros +kurz: Ler com BufferedReader e readLine até chegar null, e ler um ficheiro inteiro de uma vez com Files. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- ler um ficheiro com BufferedReader e readLine +- reconhecer o fim de um ficheiro, porque readLine aí devolve null +- contar quantas vezes uma palavra aparece num ficheiro +- ler um ficheiro inteiro com Files.readString e dividi-lo em linhas com split +- encontrar a entrada mais longa de um ficheiro +::: + +## O bolo desapareceu! + +Na manhã a seguir à festa, o bolo do Ludwig desapareceu. Felizmente, o castelo tem um diário. Cada linha começa com o dia e a hora: + +::: datei diario.txt +Seg 08:15 Ludwig alimenta as cabras +Seg 12:30 Zora lê na torre +Seg 18:00 Raposa passa às escondidas pelo portão +Ter 09:00 Ludwig faz um bolo +Ter 14:45 Lebre traz cenouras +Ter 16:20 Raposa pergunta pela receita +Ter 23:55 O bolo desapareceu +Qua 07:00 Zora encontra migalhas junto à toca da Raposa +::: + +Já o conseguias ler com o Scanner da lição 23. Mas, para ficheiros, os profissionais usam muitas vezes o **BufferedReader**. + +## Ler com BufferedReader + +\`\`\`java +import java.io.*; + +BufferedReader leitor = new BufferedReader(new FileReader("diario.txt")); +String linha = leitor.readLine(); +while (linha != null) { + System.out.println(linha); + linha = leitor.readLine(); +} +leitor.close(); +\`\`\` + +- \`new FileReader("diario.txt")\` abre o ficheiro, e \`new BufferedReader(…)\` põe-lhe uma memória intermédia à volta. Vai buscar o ficheiro em pedaços grandes e por isso é mais rápido com ficheiros longos. +- \`readLine()\` devolve a linha seguinte. Quando já não há linhas, devolve **null**. +- Por isso, o ciclo repete-se enquanto \`linha != null\`. No fim de cada volta lê a linha seguinte. + +::: diagramm dt-buffered.visustruct +Primeiro ler uma linha, depois verificar, e no fim da volta ler a seguinte. +::: + +**null** quer dizer "nada". Não é o texto vazio \`""\`, mas nenhum texto. Uma variável com \`null\` não tem métodos: \`linha.length()\` para então com uma \`NullPointerException\`. Por isso, verifica sempre primeiro \`linha != null\`. + +| | Scanner | BufferedReader | +|---|---|---| +| Criar | \`new Scanner(new File(…))\` | \`new BufferedReader(new FileReader(…))\` | +| Ainda há mais uma linha? | \`hasNextLine()\` | \`readLine()\` devolve \`null\` | +| Linha seguinte | \`nextLine()\` | \`readLine()\` | +| Ponto forte | também lê números (\`nextInt()\`) | rápido, mesmo com ficheiros grandes | + +::: ludwig +O ciclo é diferente do ciclo com o Scanner: a primeira linha é lida **antes** do ciclo, e cada uma das seguintes **no fim** da volta. Se te esqueceres da leitura no fim, o programa lê sempre a mesma linha e nunca para. +::: + +::: angeberwissen +O fim de uma linha não é igual em todo o lado: o Windows escreve dois carateres invisíveis, “retorno do carro” e “avanço de linha”, o Linux e o macOS só o avanço de linha. Os nomes vêm da máquina de escrever, em que o carro voltava atrás e o papel subia uma linha. O \`readLine()\` funciona com os dois. +::: + +## Exercício: Quantas vezes aparece a Raposa? + +::: übung l24-java-fuchs +titel: Quantas vezes aparece a Raposa? +code: java +auftrag: Lê o diário com o BufferedReader e conta as linhas onde aparece **Raposa**. No fim, mostra **Raposa:** e o número. +start: l24-java-fuchs-start.visustruct +test: - -> Raposa: 3 +braucht: whileSchleife, verzweigung +tipp: Antes do ciclo, cria \`int quantidade = 0;\`. No ciclo verificas \`linha.contains("Raposa")\`. +tipp: O \`linha = leitor.readLine();\` fica no fim do ciclo, depois do if. +lösung: l24-java-fuchs-loesung.visustruct +::: + +## Fechar automaticamente + +Para que o \`close()\` não seja esquecido, mesmo depois de uma exceção, existe uma forma curta do try: o que é criado entre os parênteses a seguir a \`try\` é fechado pelo Java sozinho no fim. + +\`\`\`java +try (BufferedReader leitor = new BufferedReader(new FileReader("diario.txt"))) { + String linha = leitor.readLine(); + while (linha != null) { + System.out.println(linha); + linha = leitor.readLine(); + } +} catch (IOException e) { + System.out.println("Falta o diário."); +} +\`\`\` + +Isto chama-se **try-with-resources**. \`IOException\` apanha todos os erros ao ler e escrever, incluindo um ficheiro em falta. + +> Tal como try e catch, o try-with-resources só funciona com Java verdadeiro (lição 22). Na simulação, escreves tu o \`close()\`. + +## O atalho: Files + +Desde o Java 11 é ainda mais curto. \`Files.readString\` lê o ficheiro inteiro de uma vez, como já conheces da lição 17. Com \`split("\\n")\` divides o texto num array de linhas: + +\`\`\`java +import java.nio.file.*; + +String texto = Files.readString(Path.of("diario.txt")); +String[] linhas = texto.split("\\n"); +for (int i = 0; i < linhas.length; i++) { + System.out.println(linhas[i]); +} +\`\`\` + +Agora todas as linhas estão no array. Podes vê-las pela ordem que quiseres, por exemplo de trás para a frente ou só uma sim, uma não. + +| Forma | Boa para | +|---|---| +| \`Scanner\` | ficheiros pequenos, ler números e palavras | +| \`BufferedReader\` | ficheiros grandes, linha a linha | +| \`Files.readString\` | ficheiros pequenos que cabem inteiros no programa | + +::: ludwig +Um ficheiro com um milhão de linhas é melhor lido linha a linha com o BufferedReader. Com \`Files.readString\`, o ficheiro inteiro teria de ir de uma vez para a memória. +::: + +## Exercício: A entrada mais longa + +::: übung l24-java-laengster +titel: A entrada mais longa +code: java +auftrag: No código inicial, as linhas do diário já estão no array \`linhas\`. Encontra a linha mais longa e mostra-a assim: **Entrada mais longa:** seguido da linha. +start: l24-java-laengster-start.visustruct +test: - -> Entrada mais longa: Qua 07:00 Zora encontra migalhas junto à toca da Raposa +braucht: forSchleife, verzweigung +tipp: Guarda a linha mais longa até agora em \`String maisLonga = linhas[0];\` e percorre as outras linhas com um ciclo for. +tipp: Se \`linhas[i].length() > maisLonga.length()\`, então \`linhas[i]\` passa a ser a mais longa. +lösung: l24-java-laengster-loesung.visustruct +::: + +## Jogo: Detetive de ficheiros + +::: spiel frage +titel: Jogo: Detetive de ficheiros +intro: Quem levou o bolo? Cada programa procura no **diário** a partir do início. Prevê o que mostra e junta as pistas. Cinco rondas. +frage: O que mostra o programa? + +runde: + String linha = leitor.readLine(); + linha = leitor.readLine(); + System.out.println(linha.substring(10)); +- Ludwig alimenta as cabras +- [x] Zora lê na torre +- Seg 12:30 Zora lê na torre +> O segundo \`readLine()\` devolve a segunda linha. O texto depois da hora começa no índice 10. + +runde: + int n = 0; + String linha = leitor.readLine(); + while (linha != null) { + if (linha.startsWith("Ter")) n++; + linha = leitor.readLine(); + } + System.out.println(n); +- 3 +- [x] 4 +- 8 +> Quatro entradas são de terça-feira. + +runde: + String linha = leitor.readLine(); + while (linha != null) { + if (linha.contains("bolo")) { + System.out.println(linha.substring(4, 9)); + } + linha = leitor.readLine(); + } +- [x] 09:00\\n23:55 +- 09:00 +- Ter\\nTer +> Há duas linhas com "bolo". \`substring(4, 9)\` recorta a hora. + +runde: + String linha = leitor.readLine(); + String ultima = ""; + while (linha != null) { + if (linha.contains("Raposa")) ultima = linha; + linha = leitor.readLine(); + } + System.out.println(ultima); +- Ter 16:20 Raposa pergunta pela receita +- [x] Qua 07:00 Zora encontra migalhas junto à toca da Raposa +- Seg 18:00 Raposa passa às escondidas pelo portão +> \`ultima\` é substituída a cada resultado. No fim fica lá o último. "toca da Raposa" também contém "Raposa". + +runde: + String linha = leitor.readLine(); + while (linha != null) { + if (linha.contains("migalhas")) { + int junto = linha.indexOf("junto à "); + System.out.println(linha.substring(junto + 8)); + } + linha = leitor.readLine(); + } +- [x] toca da Raposa +- junto à toca da Raposa +- migalhas +> As migalhas estão junto à toca da Raposa. A Raposa perguntou pela receita, e às 23:55 o bolo tinha desaparecido. Caso resolvido! +::: + +## 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. + +::: checkliste +- Consigo ler um ficheiro com BufferedReader e readLine. → Ler com BufferedReader +- Consigo reconhecer o fim de um ficheiro, porque readLine aí devolve null (linha != null). → Ler com BufferedReader +- Consigo contar quantas vezes uma palavra aparece num ficheiro. → Exercício: Quantas vezes aparece a Raposa? +- Consigo ler um ficheiro inteiro com Files.readString e dividi-lo em linhas com split. → O atalho: Files +- Consigo encontrar a entrada mais longa de um ficheiro. → Exercício: A entrada mais longa +::: + +## Teste de conhecimentos + +::: quiz +? O que devolve readLine() quando o ficheiro chegou ao fim? +→ Ler com BufferedReader +- [ ] "" +- [x] null +- [ ] -1 +> null quer dizer: já não há mais texto. + +? Porque é que no fim do ciclo há outra vez linha = leitor.readLine()? +→ Ler com BufferedReader +- [ ] Para fechar o ficheiro. +- [x] Senão linha fica sempre igual e o ciclo nunca para. +- [ ] Para mostrar a primeira linha duas vezes. + +? O que faz o try-with-resources? +→ Ler com BufferedReader +- [ ] Lê o ficheiro mais depressa. +- [x] Fecha o ficheiro sozinho no fim. +- [ ] Impede qualquer exceção. + +? Liga cada forma àquilo para que é boa. +→ O atalho: Files += BufferedReader -> ficheiros grandes, linha a linha += Files.readString -> ficheiros pequenos de uma vez += Scanner -> ler números e palavras +::: +`,gv=`--- +titel: Tabelas em CSV +bereich: Ficheiros +kurz: Ler uma tabela num ficheiro CSV, dividir cada linha com split e fazer contas com os números. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar como é feito um ficheiro CSV: cabeçalho, registos, separador +- dividir uma linha com split e fazer dela um número com Integer.parseInt +- saltar o cabeçalho antes de fazer contas +- calcular uma média a partir de uma coluna de um ficheiro CSV +- encontrar o melhor valor numa coluna de um ficheiro CSV +- nomear um ponto forte e um ponto fraco do CSV +::: + +## Uma tabela num ficheiro de texto + +A professora Cabra, da escola do castelo, guardou as notas da turma numa tabela. Como na Alemanha, 1 é a melhor nota e 6 a pior: + +| Nome | Matemática | Alemão | Inglês | +|---|---|---|---| +| Ludwig | 2 | 3 | 1 | +| Zora | 1 | 2 | 2 | +| Raposa | 4 | 3 | 5 | +| Lebre | 2 | 1 | 3 | + +No ficheiro, a tabela fica assim: + +::: datei turma.csv +Nome;Matemática;Alemão;Inglês +Ludwig;2;3;1 +Zora;1;2;2 +Raposa;4;3;5 +Lebre;2;1;3 +::: + +Isto é um **ficheiro CSV**. CSV quer dizer "Comma-Separated Values", ou seja, "valores separados por vírgulas". Cada linha é uma linha da tabela, e as colunas estão separadas por um carácter separador. Em Portugal e na Alemanha usa-se normalmente o **ponto e vírgula** \`;\`, porque a vírgula já aparece em números como \`2,5\`. + +- A primeira linha é o **cabeçalho**. Diz o que está em cada coluna. +- Cada uma das linhas seguintes é um **registo**, aqui um aluno ou uma aluna. +- O Excel, o LibreOffice e o Numbers abrem ficheiros CSV diretamente como tabela. + +## Dividir uma linha com split + +Já conheces o \`split(";")\` da lição 17. Divide um texto em cada ponto e vírgula e devolve um array: + +\`\`\`java +String linha = "Zora;1;2;2"; +String[] partes = linha.split(";"); +// partes[0] é "Zora", partes[1] é "1", partes[2] é "2", partes[3] é "2" +\`\`\` + +Depois disto, as notas ainda são **texto**. Só podes fazer contas com elas depois de as transformares num número com \`Integer.parseInt\`: + +\`\`\`java +int matematica = Integer.parseInt(partes[1]); +\`\`\` + +::: diagramm dt-csv.visustruct +Dividir uma linha CSV e ler a nota de Matemática como número. +::: + +## Ler o ficheiro inteiro + +Para o ficheiro inteiro, combinas o BufferedReader da lição 24 com \`split\`. O cabeçalho não tem notas, por isso lês essa linha antes do ciclo e saltas por cima dela: + +\`\`\`java +BufferedReader leitor = new BufferedReader(new FileReader("turma.csv")); +String linha = leitor.readLine(); // cabeçalho +linha = leitor.readLine(); // primeiro registo +while (linha != null) { + String[] partes = linha.split(";"); + System.out.println(partes[0] + ": Matemática " + partes[1]); + linha = leitor.readLine(); +} +leitor.close(); +\`\`\` + +::: ludwig +Sem o segundo \`readLine()\` antes do ciclo, o cabeçalho vai parar ao ciclo. Aí, \`Integer.parseInt("Matemática")\` tenta fazer um número a partir da palavra, e o Java para com uma \`NumberFormatException\`. +::: + +## Exercício: Média de Matemática + +::: übung l25-java-schnitt +titel: Média de Matemática +code: java +auftrag: Calcula a média das notas de Matemática. Salta o cabeçalho, soma as notas de Matemática (coluna 1) e divide pelo número de registos. Mostra **Média de Matemática:** e a média. +start: l25-java-schnitt-start.visustruct +test: - -> Média de Matemática: 2.25 +braucht: whileSchleife +tipp: Antes do ciclo, cria \`double soma = 0;\` e \`int quantidade = 0;\`. Com \`double\`, nada é cortado na divisão. +tipp: No ciclo: \`String[] partes = linha.split(";");\`, depois \`soma = soma + Integer.parseInt(partes[1]);\` e \`quantidade++;\`. +lösung: l25-java-schnitt-loesung.visustruct +::: + +## Exercício: Melhor nota a Inglês + +::: übung l25-java-beste +titel: Melhor nota a Inglês +code: java +auftrag: Quem tem a melhor nota a Inglês (coluna 3)? Mostra **Melhor nota a Inglês:**, o nome e, entre parênteses, a nota. +start: l25-java-beste-start.visustruct +test: - -> Melhor nota a Inglês: Ludwig (1) +braucht: whileSchleife, verzweigung +tipp: Guarda a melhor nota até agora em \`int melhorNota = 7;\` e o nome em \`String melhorNome = "";\`. Qualquer nota verdadeira é melhor do que 7. +tipp: Se \`nota < melhorNota\`, guardas a nova nota e \`partes[0]\` como nome. +lösung: l25-java-beste-loesung.visustruct +::: + +## Pontos fortes e fracos do CSV + +| Bom | Difícil | +|---|---| +| As tabelas ocupam pouco espaço. | Se o separador aparecer no texto, por exemplo \`Lebre;muito bem; esforçada\`, a linha parte-se em partes a mais. | +| O Excel e outros programas abrem o ficheiro diretamente. | Tudo é uma tabela plana. Se um animal tiver várias comidas preferidas, isso não cabe bem numa célula. | +| Qualquer programa o consegue ler com \`split\`. | O ficheiro não diz se \`1\` é um número ou um texto. | + +::: ludwig +O Excel guarda ficheiros CSV com ponto e vírgula em Portugal e na Alemanha, mas com vírgula em Inglaterra e nos EUA. Por isso, quem abre um ficheiro de outro país às vezes vê tudo numa única coluna. +::: + +## Jogo: Linha estragada + +::: spiel bombe +titel: Jogo: Linha estragada +intro: Em cada ficheiro CSV há **exatamente uma linha estragada**, e a bomba está a contar. Compara cada linha com o cabeçalho e toca na linha estragada antes que o tempo acabe. Cinco rondas, 20 segundos cada. +zeit: 20 +daten: csv + +runde: + Nome;Matemática;Alemão;Inglês + Ludwig;2;3;1 + Zora;1 + Raposa;4;3;5 +frage: Cada linha precisa de quatro colunas. +fehler: 3 +besser: Zora;1;2;2 +> Faltam duas notas à Zora. Então \`partes[3]\` não existe, e o Java para com uma \`ArrayIndexOutOfBoundsException\`. + +runde: + Nome;Nota;Comentário + Ludwig;2;trabalha bem em equipa + Lebre;1;muito bem; esforçada + Zora;1;lê muito +frage: Cada linha precisa de três colunas. +fehler: 3 +besser: Lebre;1;muito bem, esforçada +> O ponto e vírgula no comentário separa uma quarta coluna. O separador não pode aparecer no texto. + +runde: + Nome;Matemática;Alemão;Inglês + Ludwig;2;3;1 + Zora;1;2;2 + Raposa,4,3,5 +frage: O separador é o ponto e vírgula. +fehler: 4 +besser: Raposa;4;3;5 +> Aqui há vírgulas em vez de pontos e vírgulas. \`split(";")\` não encontra nenhum ponto e vírgula e devolve a linha inteira como uma única parte. + +runde: + Nome;Matemática;Alemão;Inglês + Lebre;2;1;3 + Raposa;quatro;3;5 + Ludwig;2;3;1 +frage: As notas são números. +fehler: 3 +besser: Raposa;4;3;5 +> \`Integer.parseInt("quatro")\` não consegue fazer um número a partir da palavra e lança uma \`NumberFormatException\`. + +runde: + Nome;Matemática;Alemão;Inglês + Zora;1;2;2 + Lebre;2;1;3 + Ludwig;2;;1 +frage: Nenhum campo pode estar vazio. +fehler: 4 +besser: Ludwig;2;3;1 +> Entre os dois pontos e vírgulas não há nada. \`Integer.parseInt("")\` lança uma \`NumberFormatException\`. +::: + +## 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. + +::: checkliste +- Consigo explicar como é feito um ficheiro CSV: cabeçalho, registos, separador. → Uma tabela num ficheiro de texto +- Consigo dividir uma linha com split e fazer dela um número com Integer.parseInt. → Dividir uma linha com split +- Consigo saltar o cabeçalho antes de fazer contas. → Ler o ficheiro inteiro +- Consigo calcular uma média a partir de uma coluna de um ficheiro CSV. → Exercício: Média de Matemática +- Consigo encontrar o melhor valor numa coluna de um ficheiro CSV. → Exercício: Melhor nota a Inglês +- Consigo nomear um ponto forte e um ponto fraco do CSV. → Pontos fortes e fracos do CSV +::: + +## Teste de conhecimentos + +::: quiz +? O que devolve "Lebre;2;1;3".split(";")[2]? +→ Dividir uma linha com split +- [ ] "2" +- [x] "1" +- [ ] 1 +> A contagem começa em 0. E o resultado é um texto, não um número. + +? Porque é que o programa chama readLine() duas vezes antes do ciclo? +→ Ler o ficheiro inteiro +- [ ] Para ler o ficheiro mais depressa. +- [x] A primeira linha é o cabeçalho, sem notas. É saltada. +- [ ] Porque readLine precisa sempre de duas linhas. + +? O que acontece com Integer.parseInt("Matemática")? +→ Dividir uma linha com split +- [ ] Devolve 0. +- [x] O Java lança uma NumberFormatException. +- [ ] Devolve o comprimento da palavra. + +? Liga. +→ Pontos fortes e fracos do CSV += cabeçalho -> diz o que está nas colunas += registo -> uma linha com valores += separador -> separa as colunas, muitas vezes ; +::: +`,pv=`--- +titel: Dados em JSON +bereich: Ficheiros +kurz: Perceber ficheiros JSON, tirar valores com indexOf e substring e escrever JSON tu mesmo. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- reconhecer objetos, chaves, valores e listas em JSON +- tirar um valor de uma linha JSON com indexOf e substring +- mostrar todos os valores de uma chave de um ficheiro JSON +- construir e guardar uma entrada JSON com + e \\" +- guardar dados num ficheiro JSON +- nomear um ponto forte e um ponto fraco do JSON +::: + +## Dados com nomes + +O zoo do castelo guarda os seus animais num ficheiro \`zoo.json\`: + +::: datei zoo.json +{ + "zoo": "Zoo do Castelo", + "animais": [ + {"nome": "Ludwig", "especie": "bode", "idade": 7}, + {"nome": "Zora", "especie": "cabra", "idade": 6}, + {"nome": "Raposa", "especie": "raposa-vermelha", "idade": 4}, + {"nome": "Lebre", "especie": "lebre", "idade": 2} + ] +} +::: + +Isto é **JSON**, a "JavaScript Object Notation". Quase todas as aplicações web e todos os jogos enviam e guardam dados assim. Ao contrário de um ficheiro CSV, antes de cada valor está o seu **nome**, a **chave**. + +| Carácter | Significado | Exemplo | +|---|---|---| +| \`{ … }\` | um **objeto**: pares de chave e valor | \`{"nome": "Zora", "idade": 6}\` | +| \`"chave": valor\` | um par, separado por dois pontos | \`"idade": 6\` | +| \`[ … ]\` | uma **lista** de valores, como um array | \`"animais": [ … ]\` | +| \`,\` | separa os pares e as entradas de uma lista | | +| \`"…"\` | um texto. Números e \`true\`/\`false\` ficam sem aspas. | \`"cabra"\`, \`6\` | + +Objetos e listas podem ser **encaixados** uns nos outros: o objeto do zoo contém a lista \`animais\`, e cada animal é outra vez um objeto. Tal como nos arrays, a lista conta a partir de 0: \`animais[1].nome\` é \`"Zora"\`. + +::: angeberwissen +Foi Douglas Crockford quem tornou o JSON conhecido no início dos anos 2000. Na licença do seu programa de JSON escreveu: “O software deve ser usado para o Bem, não para o Mal.” Por isso, a empresa IBM perguntou se o podia usar na mesma. Ele respondeu que a IBM e os seus clientes também o podiam usar para o Mal. +::: + +## Tirar um valor + +Os profissionais leem JSON com uma biblioteca, por exemplo o **Gson**. Ela não faz parte do Java e tem de ser adicionada primeiro. Para o nosso ficheiro do zoo chegam os métodos de String da lição 17, porque cada animal está na sua própria linha. + +Em Java, escreves umas aspas dentro de um texto como \`\\"\`. Assim, o texto \`"\\"nome\\": \\""\` é \`"nome": "\`, exatamente o que está antes de cada nome. + +\`\`\`java +String linha = "{\\"nome\\": \\"Zora\\", \\"especie\\": \\"cabra\\", \\"idade\\": 6},"; +int inicio = linha.indexOf("\\"nome\\": \\"") + 9; +int fim = linha.indexOf("\\"", inicio); +String nome = linha.substring(inicio, fim); +\`\`\` + +- \`indexOf("\\"nome\\": \\"")\` encontra o início de \`"nome": "\`. São 9 caracteres, por isso o nome começa 9 caracteres mais à frente. +- \`indexOf("\\"", inicio)\` procura as aspas seguintes **a partir de** \`inicio\`. É aí que o nome acaba. +- \`substring(inicio, fim)\` recorta o nome: \`Zora\`. + +::: diagramm dt-json.visustruct +Tirar o nome de uma linha JSON. +::: + +## Exercício: Todos os nomes do zoo + +::: übung l26-java-namen +titel: Todos os nomes do zoo +code: java +auftrag: Lê \`zoo.json\` linha a linha. Em cada linha que contém \`"nome"\`, mostra só o nome. +start: l26-java-namen-start.visustruct +test: - -> Ludwig | Zora | Raposa | Lebre +braucht: whileSchleife, verzweigung +tipp: Verifica com \`linha.contains("\\"nome\\"")\` se há um nome na linha. As outras linhas são saltadas. +tipp: Dentro do if: \`int inicio = linha.indexOf("\\"nome\\": \\"") + 9;\`, depois \`int fim = linha.indexOf("\\"", inicio);\` e \`System.out.println(linha.substring(inicio, fim));\`. +lösung: l26-java-namen-loesung.visustruct +::: + +## Escrever JSON + +Para escrever, juntas o texto com \`+\` e escreves-o no ficheiro com o PrintWriter da lição 23. Os textos em JSON precisam de aspas, portanto \`\\"\` no texto Java, os números não: + +\`\`\`java +String nome = "Zora"; +int pontos = 15; +String entrada = "{\\"nome\\": \\"" + nome + "\\", \\"pontos\\": " + pontos + "}"; +// entrada é {"nome": "Zora", "pontos": 15} +\`\`\` + +Numa lista há uma vírgula entre as entradas, mas **nenhuma** depois da última. Isso verificas com um if. + +::: ludwig +Umas aspas esquecidas ou uma vírgula a mais, e nenhum programa consegue ler o ficheiro. O JSON é rigoroso. Por isso, os profissionais também usam uma biblioteca para escrever. +::: + +## Exercício: Guardar pontos em JSON + +::: übung l26-java-schreiben +titel: Guardar pontos em JSON +code: java +auftrag: Guarda os pontos do torneio de perguntas como lista em \`pontos.json\`. Cada linha contém um objeto com **nome** e **pontos**, e entre os objetos há uma vírgula. No fim, mostra **3 entradas guardadas**. +start: l26-java-schreiben-start.visustruct +test: - -> 3 entradas guardadas +datei: pontos.json -> [ | {"nome": "Ludwig", "pontos": 12}, | {"nome": "Zora", "pontos": 15}, | {"nome": "Raposa", "pontos": 9} | ] +braucht: forSchleife, verzweigung +tipp: Percorre os arrays com \`for (int i = 0; i < nomes.length; i++)\`. Constrói a entrada com \`" {\\"nome\\": \\"" + nomes[i] + "\\", \\"pontos\\": " + pontos[i] + "}"\`. +tipp: Se \`i < nomes.length - 1\`, acrescentas ainda \`","\`. Depois do ciclo, escreve \`"]"\` e fecha o ficheiro. +lösung: l26-java-schreiben-loesung.visustruct +::: + +## Pontos fortes e fracos do JSON + +| Bom | Difícil | +|---|---| +| Cada valor tem um nome. Vê-se logo o que \`6\` quer dizer. | O ficheiro é mais longo do que um CSV, porque as chaves aparecem em todas as linhas. | +| Os dados podem ser encaixados, por exemplo uma lista dentro de um objeto. | O Java não lê JSON sozinho. É precisa uma biblioteca como o Gson. | +| O JSON é o padrão na web. Quase todas as linguagens de programação o conhecem. | Um carácter a mais ou a menos torna o ficheiro inteiro ilegível. | + +## Jogo: Qual é a chave? + +::: spiel frage +titel: Jogo: Qual é a chave? +intro: O Ludwig procura valores em ficheiros JSON. Lê o ficheiro e diz qual é o valor pedido. Cinco rondas. + +runde: + {"nome": "Zora", "especie": "cabra", "idade": 6} +frage: Qual é o valor de **idade**? +- "idade" +- [x] 6 +- "cabra" +> Antes dos dois pontos está a chave, depois está o valor. Os números ficam sem aspas. + +runde: + { + "animais": [ + {"nome": "Ludwig", "idade": 7}, + {"nome": "Zora", "idade": 6}, + {"nome": "Raposa", "idade": 4} + ] + } +frage: O que é **animais[1].nome**? +- Ludwig +- [x] Zora +- Raposa +> A lista conta a partir de 0, como um array. \`animais[1]\` é o segundo animal. + +runde: + { + "zoo": "Zoo do Castelo", + "chefe": {"nome": "Ludwig", "especie": "bode"} + } +frage: Como chegas a **bode**? +- [x] chefe.especie +- especie +- zoo.chefe.especie +> \`especie\` está dentro do objeto \`chefe\`. Por isso o caminho passa por \`chefe\`. + +runde: + { + "nome": "Lebre", + "comidaPreferida": ["cenouras", "trevo", "dentes-de-leão"] + } +frage: O que é **comidaPreferida[2]**? +- trevo +- cenouras +- [x] dentes-de-leão +> O índice 0 é cenouras, o 1 é trevo e o 2 é dentes-de-leão. Algo assim dificilmente cabe numa célula em CSV. + +runde: + {"nome": "Raposa", "idade": 4, "comFome": true} +frage: Que chave tem um valor lógico? +- nome +- idade +- [x] comFome +> \`true\` e \`false\` ficam sem aspas, como os números. Em Java isto seria um \`boolean\`. +::: + +## 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. + +::: checkliste +- Consigo reconhecer objetos, chaves, valores e listas em JSON. → Dados com nomes +- Consigo tirar um valor de uma linha JSON com indexOf e substring. → Tirar um valor +- Consigo mostrar todos os valores de uma chave de um ficheiro JSON. → Exercício: Todos os nomes do zoo +- Consigo construir e guardar uma entrada JSON com + e \\". → Escrever JSON +- Consigo guardar dados num ficheiro JSON. → Exercício: Guardar pontos em JSON +- Consigo nomear um ponto forte e um ponto fraco do JSON. → Pontos fortes e fracos do JSON +::: + +## Teste de conhecimentos + +::: quiz +? O que está em JSON antes de cada valor? +→ Dados com nomes +- [ ] o número da linha +- [x] a sua chave, por exemplo "nome" +- [ ] um ponto e vírgula +> A chave e o valor estão separados por dois pontos. + +? Como escreves umas aspas dentro de um texto Java? +→ Escrever JSON +- [ ] "" +- [x] \\" +- [ ] '"' + +? Em {"animais": [{"nome": "Ludwig"}, {"nome": "Zora"}]}, qual é o valor de animais[0].nome? +→ Dados com nomes +- [x] Ludwig +- [ ] Zora +- [ ] animais +> A lista conta a partir de 0. + +? Liga. +→ Pontos fortes e fracos do JSON += { } -> um objeto com chaves e valores += [ ] -> uma lista += : -> separa a chave do valor +::: +`,fv=`--- +titel: Comparar formatos +bereich: Ficheiros +kurz: Comparar os mesmos dados em txt, CSV e JSON, escolher o formato certo e converter um ficheiro noutro formato. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- reconhecer os mesmos dados em txt, CSV e JSON +- comparar pontos fortes e fracos de txt, CSV e JSON +- converter um ficheiro CSV em frases +- converter um ficheiro CSV em JSON +::: + +## Os mesmos animais três vezes + +O Ludwig guardou os animais do castelo em três ficheiros. Todos dizem o mesmo, só que escrito de outra maneira. + +Como texto, tal como se escreveria a uma pessoa: + +::: datei animais.txt +Ludwig (bode) tem 7 anos. +Zora (cabra) tem 6 anos. +Raposa (raposa-vermelha) tem 4 anos. +::: + +Como tabela em CSV: + +::: datei animais.csv +Nome;Espécie;Idade +Ludwig;bode;7 +Zora;cabra;6 +Raposa;raposa-vermelha;4 +::: + +Como JSON: + +::: datei animais.json +[ + {"nome": "Ludwig", "especie": "bode", "idade": 7}, + {"nome": "Zora", "especie": "cabra", "idade": 6}, + {"nome": "Raposa", "especie": "raposa-vermelha", "idade": 4} +] +::: + +## O que sabe fazer cada formato? + +| | txt | CSV | JSON | +|---|---|---|---| +| Fácil de ler para pessoas | sim | mais ou menos | mais ou menos | +| Ordem fixa para programas | não | sim, colunas | sim, chaves | +| O que quer dizer um valor? | está na frase | está no cabeçalho | está mesmo antes dele | +| Encaixar (uma lista dentro de uma entrada) | não | difícil | sim | +| Abrir no Excel | não | sim | não | +| Ler em Java | Scanner, BufferedReader | mais \`split\` | métodos de String ou uma biblioteca | +| Tamanho | pequeno | o mais pequeno | o maior | + +Em resumo: + +- **txt** para textos que pessoas leem: cartas, notas, um diário. +- **CSV** para tabelas: notas, medições, uma lista de recordes. Todas as linhas têm as mesmas colunas. +- **JSON** para dados com estrutura: jogos guardados, definições, tudo o que circula entre programas e na web. + +::: ludwig +Quando a tua aplicação de meteorologia vai buscar a temperatura, a resposta chega quase sempre em JSON. E quando um professor exporta as notas do programa da escola, recebe muitas vezes um ficheiro CSV. +::: + +## Exercício: De CSV para frases + +::: übung l27-java-saetze +titel: De CSV para frases +code: java +auftrag: Converte \`animais.csv\` em texto. Para cada animal, escreve uma frase como **Ludwig (bode) tem 7 anos.** no ficheiro \`frases.txt\`. No fim, mostra **3 frases guardadas**. +start: l27-java-saetze-start.visustruct +test: - -> 3 frases guardadas +datei: frases.txt -> Ludwig (bode) tem 7 anos. | Zora (cabra) tem 6 anos. | Raposa (raposa-vermelha) tem 4 anos. +braucht: whileSchleife +tipp: O código inicial já salta o cabeçalho. Divide cada linha com \`String[] partes = linha.split(";");\`. +tipp: A frase é \`partes[0] + " (" + partes[1] + ") tem " + partes[2] + " anos."\`. Conta com \`quantidade++\` e lê a linha seguinte no fim do ciclo. +lösung: l27-java-saetze-loesung.visustruct +::: + +## Exercício: De CSV para JSON + +::: übung l27-java-json +titel: De CSV para JSON +code: java +auftrag: Converte \`animais.csv\` em JSON e guarda-o em \`animais-novos.json\`, exatamente como \`animais.json\` acima. No fim, mostra **3 animais guardados**. +start: l27-java-json-start.visustruct +test: - -> 3 animais guardados +datei: animais-novos.json -> [ | {"nome": "Ludwig", "especie": "bode", "idade": 7}, | {"nome": "Zora", "especie": "cabra", "idade": 6}, | {"nome": "Raposa", "especie": "raposa-vermelha", "idade": 4} | ] +braucht: forSchleife, verzweigung +tipp: \`linhas[0]\` é o cabeçalho. Por isso, começa o ciclo for em \`i = 1\` e divide \`linhas[i]\` com \`split(";")\`. +tipp: Constrói a entrada com \`\\"\`, como na lição 26. A idade é um número e fica sem aspas. Só acrescentas uma vírgula se \`i < linhas.length - 1\`. +lösung: l27-java-json-loesung.visustruct +::: + +## Jogo: Que formato serve? + +::: spiel frage +titel: Jogo: Que formato serve? +intro: O Ludwig quer guardar dados e não sabe que formato usar. Ajuda-o. Seis rondas. +antworten: txt | CSV | JSON + +runde: +frage: As notas da turma inteira devem ser abertas no Excel. +richtig: CSV +> As notas são uma tabela, e o Excel abre ficheiros CSV diretamente. + +runde: +frage: O Ludwig escreve uma carta à Zora. +richtig: txt +> Uma carta é texto para pessoas. Não precisa de colunas nem de chaves. + +runde: +frage: Um jogo guardado com nome, nível e uma lista de todas as chaves apanhadas. +richtig: JSON +> Em JSON, uma lista pode ficar encaixada numa entrada. Em CSV dificilmente cabe numa célula. + +runde: +frage: Um aparelho de medição guarda a hora e a temperatura a cada minuto, durante um ano inteiro. +richtig: CSV +> Muitas linhas iguais com as mesmas colunas: para isto, o CSV é o mais pequeno. O JSON repetiria as chaves em todas as linhas. + +runde: +frage: Uma aplicação de meteorologia vai buscar a previsão a um servidor na internet. +richtig: JSON +> O JSON é o padrão na web. Quase todas as aplicações recebem os dados assim. + +runde: +frage: O diário do castelo, em que cada entrada é uma frase curta. +richtig: txt +> Cada linha é uma frase para pessoas. É lida linha a linha, como na lição 24. +::: + +## 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. + +::: checkliste +- Consigo reconhecer os mesmos dados em txt, CSV e JSON. → Os mesmos animais três vezes +- Consigo comparar pontos fortes e fracos de txt, CSV e JSON. → O que sabe fazer cada formato? +- Consigo converter um ficheiro CSV em frases. → Exercício: De CSV para frases +- Consigo converter um ficheiro CSV em JSON. → Exercício: De CSV para JSON +::: + +## Teste de conhecimentos + +::: quiz +? Que formato o Excel abre diretamente como tabela? +→ O que sabe fazer cada formato? +- [ ] txt +- [x] CSV +- [ ] JSON + +? Porque é que um ficheiro JSON é normalmente maior do que um CSV com os mesmos dados? +→ O que sabe fazer cada formato? +- [ ] Porque o JSON guarda mais números. +- [x] Porque as chaves se repetem em cada entrada. +- [ ] Porque o JSON não usa vírgulas. + +? Em que formato cada valor diz o que significa? +→ O que sabe fazer cada formato? +- [ ] txt +- [ ] CSV +- [x] JSON +> Em JSON a chave está mesmo antes do valor, por exemplo "idade": 7. + +? Liga cada objetivo a um formato. +→ O que sabe fazer cada formato? += uma carta à Zora -> txt += a pauta de notas da turma -> CSV += um jogo guardado com listas -> JSON +::: +`,bv=`--- +titel: A tua primeira janela +bereich: Janelas com Swing +kurz: Abrir uma janela tua com Java e Swing, explicado linha a linha. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- ligar o “Java verdadeiro” na área Código +- abrir uma janela com título e tamanho +- explicar o que faz cada linha do programa com janela +- explicar porque é que setVisible(true) fica no fim +::: + +## Programas com janelas + +Até agora os teus programas escreviam texto na consola. Mas a maioria dos programas que conheces tem **janelas** com botões e campos de texto. A isto chama-se uma interface gráfica. + +O Java traz uma caixa de ferramentas para isso: o **Swing**. No VisuStruct ligas o Swing assim: + +1. Abre à direita a área [Código](#zeige-codelive). +2. Clica na [roda dentada](#zeige-einstellungen) em cima à direita e escolhe Java como **Linguagem de programação**. +3. Por baixo, na secção Java, marca **Java verdadeiro (com Swing)**. + +Na primeira vez que clicas em [▶︎ Executar](#zeige-ausfuehren), o VisuStruct descarrega uma única vez cerca de 40 MB, o que demora um pouco. Depois disso o teu código corre como Java verdadeiro, e as tuas janelas aparecem na área Código na área **Janelas Java**, por cima da consola. + +> Com o “Java verdadeiro”, as entradas pela consola (\`Scanner\`) ainda não funcionam. Para programas com entradas, desliga outra vez a opção. + +::: angeberwissen +O Swing existe desde 1998. Antes disso, o Java só tinha o AWT, mais antigo, com uma classe \`Frame\`. Para ninguém confundir os blocos novos, quase todos os nomes no Swing começam por **J**: \`JFrame\`, \`JButton\`, \`JLabel\`. Pelo J reconheces logo o Swing. +::: + +## O programa completo + +Este é o programa mais pequeno que abre uma janela. Escreve-o na área Código e clica em [▶︎ Executar](#zeige-ausfuehren): + +\`\`\`java +import javax.swing.*; + +public class MinhaJanela { + public static void main(String[] args) { + JFrame janela = new JFrame("A minha primeira janela"); + janela.setSize(300, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setVisible(true); + } +} +\`\`\` + +Aparece uma janela cinzenta vazia com o título “A minha primeira janela”. Mais nada, mas é a tua própria janela! + +A moldura com \`public class\` e \`main\` já conheces da lição Java. Novas são a primeira linha e as quatro linhas dentro de \`main\`. Vamos vê-las uma a uma. + +::: ludwig +Olha para o estrutograma ao lado do código: cada linha em \`main\` é um bloco, todos uns por baixo dos outros. No início, um programa com janelas é então só uma sequência. +::: + +## Linha a linha + +| Linha | O que faz | +|---|---| +| \`import javax.swing.*;\` | Traz a caixa de ferramentas Swing para o programa. Sem esta linha o Java não conhece \`JFrame\`. | +| \`JFrame janela = new JFrame("A minha primeira janela");\` | Constrói uma janela nova. O texto entre parênteses é o título em cima, na moldura da janela. Depois falas com ela através da variável \`janela\`. | +| \`janela.setSize(300, 200);\` | A janela fica com 300 píxeis de largura e 200 píxeis de altura. | +| \`janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\` | Quando alguém fecha a janela, o programa também termina. | +| \`janela.setVisible(true);\` | Só agora a janela fica visível. | + +O ponto em \`janela.setSize(…)\` quer dizer: “Janela, faz isto!” Antes do ponto está quem deve fazer alguma coisa, depois do ponto o que deve fazer. + +> Sem \`setDefaultCloseOperation\`, o Java só esconde a janela quando ela é fechada. O programa continua a correr sem se ver. + +## Porque é que setVisible fica no fim + +\`setVisible(true)\` mostra a janela tal como ela está nesse momento. Por isso preparas tudo primeiro: título, tamanho e, mais tarde, também botões. Só mesmo no fim tornas a janela visível. + +O que só pões na janela depois de \`setVisible(true)\` muitas vezes não aparece. É que o Java não volta a desenhar a janela sozinho. Às vezes só aparece quando se muda o tamanho da janela. Erros destes são difíceis de encontrar. + +::: ludwig +Primeiro preparar, depois mostrar. Como no teatro: a cortina só sobe quando o palco está pronto. +::: + +Experimenta: apaga a linha com \`setVisible(true)\` e executa o programa outra vez. O programa corre, mas não vês nenhuma janela. + +## Saber de profissional: classes e objetos + +Isto não está no programa da disciplina, mas ajuda-te a perceber o Swing. + +::: angeberwissen +O Java é, na verdade, uma linguagem **orientada a objetos**. \`JFrame\` é uma classe, ou seja, uma planta para janelas. Com \`new JFrame(…)\` o Java constrói, segundo essa planta, uma janela a sério: um **objeto**. Com dois \`new\` podias construir duas janelas, ambas com a mesma planta. + +\`setSize\` e \`setVisible\` são métodos que qualquer objeto janela sabe fazer. Por isso escreves \`janela.setSize(…)\`: o objeto \`janela\` executa o seu método. O teu próprio programa também é uma classe, neste caso \`MinhaJanela\`. +::: + +## Jogo: O que acontece? + +::: spiel frage +titel: Jogo: O que acontece? +intro: O Ludwig andou a mexer no programa da janela. Lê as linhas e prevê o que acontece. Seis rondas. + +runde: + JFrame janela = new JFrame("Olá"); + janela.setSize(300, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); +frage: O que vês depois de executar? +- uma janela com o título "Olá" +- [x] nenhuma janela +- uma mensagem de erro +> Falta \`setVisible(true)\`. A janela está construída, mas fica invisível. + +runde: + JFrame janela = new JFrame("Olá"); + janela.setSize(200, 300); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setVisible(true); +frage: Como é a janela? +- mais larga do que alta +- [x] mais alta do que larga +- quadrada +> O primeiro número é a largura, o segundo a altura: 200 de largura, 300 de altura. + +runde: + JFrame janela = new JFrame("Olá"); + janela.setSize(300, 200); + janela.setVisible(true); +frage: Fechas a janela. O que acontece ao programa? +- Termina. +- [x] Continua a correr, invisível. +- A janela volta logo a abrir. +> Sem \`setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)\`, o Java só esconde a janela. + +runde: + JFrame janela = new JFrame(); + janela.setSize(300, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setVisible(true); +frage: O que aparece no topo da moldura da janela? +- janela +- JFrame +- [x] nada, o título está vazio +> Sem texto entre os parênteses, a janela não tem título. O nome da variável \`janela\` nunca aparece na janela. + +runde: + public class Teste { + public static void main(String[] args) { + JFrame janela = new JFrame("Teste"); + janela.setVisible(true); + } + } +frage: O que diz o javac? +- [x] cannot find symbol: class JFrame +- nada, a janela aparece +- missing return statement +> Falta a linha \`import javax.swing.*;\`. Sem ela, o Java não conhece \`JFrame\`. + +runde: + JFrame a = new JFrame("Uma"); + JFrame b = new JFrame("Duas"); + a.setSize(300, 200); + b.setSize(300, 200); + a.setVisible(true); +frage: O que vês? +- [x] uma janela com o título "Uma" +- duas janelas +- uma janela com o título "Duas" +> Duas janelas feitas com a mesma planta, mas só a \`a\` fica visível. +::: + +## Tarefa: a tua própria janela + +Altera o programa de forma que + +- o título diga “Olá” e o teu nome, +- a janela tenha 400 píxeis de largura e 300 píxeis de altura, +- o programa termine quando fechas a janela. + +Executa-o e verifica os três pontos. + +::: ludwig +Não te apetece escrever tanto? Com o “Java verdadeiro” podes escrever na área Código só as quatro linhas de \`main\`. O VisuStruct põe-nas sozinho dentro de uma classe e acrescenta as linhas \`import\`. Num ambiente de desenvolvimento Java a sério precisas, no entanto, do programa completo. +::: + +## 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. + +::: checkliste +- Consigo ligar o “Java verdadeiro” na área Código. → Programas com janelas +- Consigo abrir uma janela com título e tamanho. → O programa completo +- Consigo explicar o que faz cada linha do programa com janela. → Linha a linha +- Consigo explicar porque é que setVisible(true) fica no fim. → Porque é que setVisible fica no fim +::: + +## Teste de conhecimentos + +::: quiz +? Que linha torna a janela visível? +→ Porque é que setVisible fica no fim +- [ ] janela.setSize(300, 200); +- [x] janela.setVisible(true); +- [ ] new JFrame("Olá"); +> Sem setVisible(true) a janela fica invisível. + +? Onde fica melhor janela.setVisible(true)? +→ Porque é que setVisible fica no fim +- [ ] Mesmo no início de main +- [x] No fim, quando a janela já está preparada +- [ ] Tanto faz. +> O que vem depois de setVisible(true) muitas vezes não aparece. + +? O que faz setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)? +→ Linha a linha +- [ ] A janela fecha-se logo. +- [x] Quando se fecha a janela, o programa termina. +- [ ] A janela já não se pode fechar. + +? Como reconheces os blocos do Swing? +→ Linha a linha +- [x] O nome começa por J, p. ex. JFrame. +- [ ] Estão entre chavetas. +- [ ] Terminam em Window. +::: +`,xv=`--- +titel: Um botão na janela +bereich: Janelas com Swing +kurz: Pôr um botão na janela e arrumá-lo bem com um layout. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- construir um botão e pô-lo na janela com add +- explicar porque é que o botão entra antes de setVisible +- usar o FlowLayout para o botão ter o tamanho normal +- construir uma janela com um botão em que se pode carregar +::: + +## Construir um botão + +Uma janela vazia é aborrecida. Agora vai lá para dentro um botão. No Swing, um botão chama-se **JButton** (button é inglês para botão). + +Precisas de duas linhas novas: + +\`\`\`java +JButton botao = new JButton("Clica-me"); +janela.add(botao); +\`\`\` + +- \`new JButton("Clica-me")\` constrói um botão. O texto entre parênteses fica escrito no botão. +- \`janela.add(botao)\` põe o botão na janela. Sem \`add\` o botão existe, mas não está em lado nenhum e não o vês. + +## O programa completo + +As duas linhas ficam **antes** de \`setVisible(true)\`, porque a janela deve primeiro ficar pronta e só depois ser mostrada: + +\`\`\`java +import javax.swing.*; + +public class JanelaBotao { + public static void main(String[] args) { + JFrame janela = new JFrame("Botão"); + janela.setSize(300, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JButton botao = new JButton("Clica-me"); + janela.add(botao); + + janela.setVisible(true); + } +} +\`\`\` + +Executa o programa. Surpresa: o botão é enorme e enche a janela toda! + +::: ludwig +A ordem é a mesma da primeira janela: preparar, construir o botão, pô-lo na janela e só no fim mostrar. As linhas em branco no código ajudam-te a ver estas partes. +::: + +## O botão gigante + +A forma como uma janela arruma as suas partes é decidida pelo seu **layout**. Sem mais indicações, um \`JFrame\` põe tudo no meio e torna-o tão grande como a janela inteira. + +Com outro layout o botão fica com o tamanho normal. O **FlowLayout** põe tudo lado a lado, como palavras numa linha, só do tamanho necessário: + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class JanelaBotao { + public static void main(String[] args) { + JFrame janela = new JFrame("Botão"); + janela.setSize(300, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new FlowLayout()); + + JButton botao = new JButton("Clica-me"); + janela.add(botao); + + janela.setVisible(true); + } +} +\`\`\` + +O \`FlowLayout\` pertence à caixa de ferramentas AWT, mais antiga. Por isso há uma segunda linha em cima: \`import java.awt.*;\`. + +::: angeberwissen +No FlowLayout os blocos correm como texto: se um botão já não cabe na linha, passa para a seguinte. Torna a janela estreita e vê como os botões mudam de linha. Flow é inglês para fluxo. +::: + +## Clicar funciona, mas nada acontece + +Clica no botão. Ele fica um pouco mais escuro enquanto o carregas. O Swing mostra assim que foi carregado. Fora isso, não acontece nada. + +Isto não é um erro: ainda não disseste ao programa **o que** deve acontecer com um clique. Isso aprendes na próxima lição. + +## Jogo: Desativar a bomba + +::: spiel bombe +titel: Jogo: Desativar a bomba +intro: Em cada programa de janela há **exatamente um erro**, e a bomba está a contar. Lê o que o programa deve fazer e toca na linha errada antes de o tempo acabar. Seis rondas, 25 segundos cada. +zeit: 25 + +runde: + JFrame janela = new JFrame("Botão"); + janela.setSize(300, 200); + JButton botao = new JButton(Clica-me); + janela.add(botao); + janela.setVisible(true); +frage: Deve mostrar um botão "Clica-me". +fehler: 3 +besser: JButton botao = new JButton("Clica-me"); +> A legenda é um texto e precisa de aspas. + +runde: + JFrame janela = new JFrame("Botão"); + janela.setSize(300, 200); + JButton botao = new JButton("OK"); + janela.add(janela); + janela.setVisible(true); +frage: Deve pôr o botão "OK" na janela. +fehler: 4 +besser: janela.add(botao); +> Na janela entra o botão, não a própria janela. + +runde: + import java.swing.*; + import java.awt.*; +frage: Deve trazer o Swing e o FlowLayout para o programa. +fehler: 1 +besser: import javax.swing.*; +> O Swing está em \`javax.swing\`, com x. O FlowLayout vem de \`java.awt\`, sem x. + +runde: + JFrame janela = new JFrame("Botão"); + janela.setSize(300, 200); + janela.setLayout(new FlowLayout); + janela.add(new JButton("OK")); + janela.setVisible(true); +frage: Deve mostrar o botão no tamanho normal. +fehler: 3 +besser: janela.setLayout(new FlowLayout()); +> Depois de \`new\` e do nome vêm sempre parênteses, mesmo que não haja nada lá dentro. + +runde: + JFrame janela = new JFrame("Botão"); + janela.setSize(300, 200); + janela.setLayout(new FlowLayout()); + JButton botao = new Jbutton("OK"); + janela.add(botao); + janela.setVisible(true); +frage: Deve mostrar um botão "OK". +fehler: 4 +besser: JButton botao = new JButton("OK"); +> O Java distingue maiúsculas de minúsculas: \`JButton\` com B maiúsculo. + +runde: + JFrame janela = new JFrame("Botão"); + janela.setSize(300, 200); + janela.setLayout(new FlowLayout()); + janela.add(new JButton("OK")); + janela.setVisible(false); +frage: Deve mostrar a janela com o botão. +fehler: 5 +besser: janela.setVisible(true); +> Com \`false\`, a janela fica invisível. +::: + +## Tarefa: clica-me + +Constrói uma janela com o título “Teste do botão”, com 300 por 200 píxeis e um botão “Clica-me” de tamanho normal. Deve ser possível carregar no botão, mesmo que ainda não aconteça nada. + +Extra: põe um segundo botão “Eu também” ao lado. Por que ordem aparecem os botões? Troca as duas linhas \`add\` e experimenta outra vez. + +::: ludwig +Cada botão precisa da sua própria variável, por exemplo \`botao\` e \`botao2\`, e do seu próprio \`add\`. O FlowLayout põe os botões pela ordem das linhas \`add\`. +::: + +## 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. + +::: checkliste +- Consigo construir um botão e pô-lo na janela com add. → Construir um botão +- Consigo explicar porque é que o botão entra antes de setVisible(true). → O programa completo +- Consigo usar o FlowLayout para o botão ter o tamanho normal. → O botão gigante +- Consigo construir uma janela com um botão em que se pode carregar. → Tarefa: clica-me +::: + +## Teste de conhecimentos + +::: quiz +? O que faz janela.add(botao)? +→ Construir um botão +- [ ] Constrói um botão novo. +- [x] Põe o botão na janela. +- [ ] Torna o botão clicável. +> O botão é construído com new JButton(…). + +? Porque é que, sem FlowLayout, o botão enche a janela toda? +→ O botão gigante +- [ ] Porque o texto é demasiado comprido +- [x] Porque sem layout próprio a janela torna tudo tão grande como ela +- [ ] Porque falta o setSize + +? Que linha import precisas para o FlowLayout? +→ O botão gigante +- [ ] import javax.swing.*; +- [x] import java.awt.*; +- [ ] import java.util.*; +> O FlowLayout vem do AWT, mais antigo. + +? O que acontece nesta lição quando clicas no botão? +→ Tarefa: clica-me +- [ ] O programa termina. +- [x] O botão fica mais escuro por um momento, e mais nada. +- [ ] No botão aparece “Fui clicado”. +> O que deve acontecer com um clique aprendes na próxima lição. +::: +`,vv=`--- +titel: O botão reage +bereich: Janelas com Swing +kurz: Com um ActionListener decides o que acontece com um clique. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar o que é um evento +- usar addActionListener para decidir o que acontece com um clique +- executar várias instruções com um clique +- construir um botão que muda o seu texto depois do clique +::: + +## Um clique é um evento + +Na lição anterior podias carregar no botão, mas nada acontecia. Num programa com janelas é a pessoa que decide quando acontece alguma coisa: clica, escreve ou fecha uma janela. Cada ação destas chama-se **evento**. + +Por isso o teu programa tem de esperar pelo clique e dar por ele. Para isso registas no botão um ouvinte, um **ActionListener** (inglês para “ouvinte de ações”). A cada clique o botão chama o seu ouvinte, e o ouvinte executa o teu código. + +::: ludwig +Até agora o teu programa corria de cima para baixo, como no estrutograma. O código do ouvinte, pelo contrário, só corre mais tarde, sempre que alguém clica. Quantas vezes isso acontece, ninguém sabe de antemão. +::: + +## A linha com a seta + +É assim que registas o ouvinte: + +\`\`\`java +botao.addActionListener(e -> botao.setText("Fui clicado")); +\`\`\` + +Lido de fora para dentro: + +- \`botao.addActionListener( … )\` regista um ouvinte no botão. +- \`e\` é o evento. Contém, por exemplo, quando foi o clique. Aqui não precisas dele, mas o nome tem de estar lá. +- \`->\` lê-se “então faz”. +- \`botao.setText("Fui clicado")\` é o que acontece com o clique: o botão recebe um texto novo. + +A linha vem depois de \`new JButton(…)\`, porque o botão já tem de existir. E, como tudo o resto, vem antes de \`setVisible(true)\`. + +## O programa completo + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class ClicaMe { + public static void main(String[] args) { + JFrame janela = new JFrame("Clica-me"); + janela.setSize(300, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new FlowLayout()); + + JButton botao = new JButton("Clica-me"); + botao.addActionListener(e -> botao.setText("Fui clicado")); + janela.add(botao); + + janela.setVisible(true); + } +} +\`\`\` + +Executa-o e clica no botão. Agora diz “Fui clicado”. + +> Se o texto novo for mais comprido do que o antigo, o FlowLayout alarga o botão sozinho. + +## Várias instruções com um clique + +Se com um clique deve acontecer mais do que uma coisa, pões chavetas depois da seta. Lá dentro, cada instrução tem o seu ponto e vírgula, como no corpo de um ciclo: + +\`\`\`java +botao.addActionListener(e -> { + botao.setText("Fui clicado"); + janela.setTitle("Obrigado!"); + System.out.println("Clique!"); +}); +\`\`\` + +\`System.out.println\` escreve na [consola](#zeige-konsole), como de costume. Clica várias vezes: a cada clique aparece uma nova linha “Clique!”. Assim vês que o código do ouvinte corre mesmo a cada clique. + +::: ludwig +Atenção ao fim: primeiro \`}\` fecha o bloco, depois \`)\` fecha o parêntese de \`addActionListener\`, e só então vem o ponto e vírgula. Ou seja, \`});\`. Se faltar alguma coisa, aparece uma indicação por baixo do código. +::: + +## Jogo: Quem está a ouvir? + +::: spiel zuhoerer +titel: Jogo: Quem está a ouvir? +intro: O Ludwig mostra-te código e a janela correspondente. Por baixo vês que botões são clicados, um a seguir ao outro. O que acontece? Depois da tua resposta, o Ludwig reproduz os cliques: vês que ouvinte ouve o evento e que linhas correm a seguir. +frage: O que diz a etiqueta depois dos cliques? + +runde: + JFrame janela = new JFrame("Saudação"); + JLabel texto = new JLabel("Início"); + JButton botao = new JButton("Olá"); + botao.addActionListener(e -> texto.setText("Olá mundo")); +klicks: Olá +- Início +- [x] Olá mundo +- Olá +> O botão tem um ouvinte. Com o clique executa \`texto.setText("Olá mundo")\`, e a etiqueta mostra “Olá mundo”. + +runde: + JFrame janela = new JFrame("Fruta"); + JLabel texto = new JLabel("?"); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + a.addActionListener(e -> texto.setText("Maçã")); + b.addActionListener(e -> texto.setText("Pera")); +klicks: A, B +- Maçã +- [x] Pera +- Maçã Pera +> Cada botão tem o seu próprio ouvinte. Primeiro o A escreve “Maçã”, depois o B substitui-o por “Pera”. O \`setText\` troca o texto antigo, não acrescenta nada. + +runde: + JFrame janela = new JFrame("Fruta"); + JLabel texto = new JLabel("?"); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + a.addActionListener(e -> texto.setText("Maçã")); +klicks: B +- Maçã +- Pera +- [x] ? +> Ninguém se inscreveu no botão B: não há \`b.addActionListener\`. O clique é um evento, mas ninguém está a ouvir. Por isso o ponto de interrogação fica. + +runde: + JFrame janela = new JFrame("Cores"); + JLabel texto = new JLabel("nenhuma"); + JButton vermelho = new JButton("Vermelho"); + JButton azul = new JButton("Azul"); + vermelho.addActionListener(e -> texto.setText("Azul")); + azul.addActionListener(e -> texto.setText("Vermelho")); +klicks: Vermelho +- Vermelho +- [x] Azul +- nenhuma +> Atenção: o que acontece é decidido pelo código no ouvinte, não pela legenda do botão. O ouvinte do botão “Vermelho” escreve “Azul”. + +runde: + JFrame janela = new JFrame("Botão"); + JLabel texto = new JLabel("Clica, por favor"); + JButton botao = new JButton("Clica-me"); + botao.addActionListener(e -> { + botao.setText("Obrigado!"); + texto.setText("Clicado"); + }); +klicks: Clica-me +frage: O que diz o botão depois do clique? +- Clica-me +- [x] Obrigado! +- Clicado +> O bloco depois da seta tem duas instruções. As duas correm com o clique, uma a seguir à outra: o botão fica com “Obrigado!”, a etiqueta com “Clicado”. + +runde: + JFrame janela = new JFrame("Consola"); + JButton botao = new JButton("Vai"); + botao.addActionListener(e -> System.out.println("Clique!")); +klicks: Vai, Vai, Vai +frage: Quantas linhas “Clique!” há depois na consola? +- 1 +- [x] 3 +- 0 +> O ouvinte corre a **cada** clique, não só no primeiro. Três cliques, três linhas. +::: + +## Saber de profissional: ActionListener é uma interface + +Isto não está no programa da disciplina. Se quiseres saber o que está por trás da seta, continua a ler. + +::: angeberwissen +\`ActionListener\` é uma **interface**, uma espécie de contrato. Diz: quem quiser ser um ActionListener tem de ter um método \`actionPerformed(ActionEvent e)\`. A cada clique o botão chama exatamente esse método. +::: + +A linha com a seta já conheces do passo 3: + +\`\`\`java +botao.addActionListener(e -> botao.setText("Fui clicado")); +\`\`\` + +Sem a seta escreve-se o ouvinte como uma classe sem nome que cumpre o contrato (uma classe anónima): + +\`\`\`java +botao.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + botao.setText("Fui clicado"); + } +}); +\`\`\` + +Para isso precisas ainda de \`import java.awt.event.*;\` em cima. As duas formas fazem exatamente o mesmo. A seta \`e -> …\` é a forma curta (uma expressão lambda, desde o Java 8): \`e\` é o parâmetro de \`actionPerformed\`, e depois da seta vem o seu corpo. A forma curta funciona porque a interface tem um único método. Assim o Java sabe de que método se trata. + +## Jogo: Contrato cumprido? + +::: spiel vertrag +titel: Jogo: Contrato cumprido? +intro: O contrato \`ActionListener\` exige exatamente um método: \`public void actionPerformed(ActionEvent e)\`. O Ludwig mostra-te código. Cumpre o contrato, de forma a poder ser inscrito num botão? O Ludwig verificou cada resposta com o compilador de Java verdadeiro. +frage: Isto cumpre o contrato ActionListener? +antworten: cumprido | não cumprido + +runde: + class Saudacao implements ActionListener { + public void actionPerformed(ActionEvent e) { + System.out.println("Olá"); + } + } +richtig: cumprido +> Está tudo: \`implements ActionListener\` assina o contrato, e o método chama-se exatamente \`actionPerformed\`, é \`public\`, não devolve nada (\`void\`) e recebe um \`ActionEvent\`. + +runde: + class Saudacao implements ActionListener { + public void actionPerfomed(ActionEvent e) { + System.out.println("Olá"); + } + } +richtig: não cumprido +> Olha bem: \`actionPerfomed\` em vez de \`actionPerformed\`, falta um r. Para o Java é um método completamente diferente. O compilador avisa que falta \`actionPerformed\`. + +runde: + class Saudacao implements ActionListener { + public void actionPerformed() { + System.out.println("Olá"); + } + } +richtig: não cumprido +> Falta o parâmetro. O contrato exige \`actionPerformed(ActionEvent e)\`, porque com o clique o botão entrega o evento. + +runde: + class Saudacao implements ActionListener { + public void actionPerformed(ActionEvent evento) { + System.out.println("Olá"); + } + } +richtig: cumprido +> O nome do parâmetro escolhe-se livremente. Só conta o tipo \`ActionEvent\`. Em vez de \`e\` também se pode chamar \`evento\`. + +runde: + class Saudacao implements ActionListener { + void actionPerformed(ActionEvent e) { + System.out.println("Olá"); + } + } +richtig: não cumprido +> Falta o \`public\`. Todos os métodos de uma interface são públicos, porque o botão tem de os poder chamar de fora. Sem \`public\` o compilador indica um erro. + +runde: + class Saudacao implements ActionListener { + public int actionPerformed(ActionEvent e) { + return 0; + } + } +richtig: não cumprido +> O contrato diz \`void\`: o método não devolve nada. Com \`int\` como tipo de retorno já não serve. + +runde: + class Saudacao implements ActionListener { + public void actionPerformed(ActionEvent e) { + dizOla(); + } + void dizOla() { + System.out.println("Olá"); + } + } +richtig: cumprido +> Métodos a mais são permitidos. O contrato só exige que o \`actionPerformed\` exista, não que não haja mais nada. + +runde: + class Saudacao { + public void actionPerformed(ActionEvent e) { + System.out.println("Olá"); + } + } + botao.addActionListener(new Saudacao()); +richtig: não cumprido +> O método está certo, mas o contrato não foi assinado: falta \`implements ActionListener\`. Num botão, o Java só aceita objetos que cumprem oficialmente o contrato. + +runde: + botao.addActionListener(e -> System.out.println("Olá")); +richtig: cumprido +> A seta é a forma curta. Como o contrato só tem um método, o Java sabe: \`e\` é o parâmetro de \`actionPerformed\`, e depois da seta vem o seu corpo. + +runde: + botao.addActionListener((a, b) -> System.out.println("Olá")); +richtig: não cumprido +> Aqui a seta tem dois parâmetros. Mas o \`actionPerformed\` recebe exatamente um, o evento. Por isso esta forma curta não serve para o contrato. +::: + +## Tarefa: fui clicado + +Agora terminas a tarefa: constrói uma janela com um botão “Clica-me” de tamanho normal. Depois do clique, o botão diz “Fui clicado”. + +Extra: constrói dois botões “Vermelho” e “Azul”. Um clique num botão escreve o seu nome no título da janela, por exemplo “Escolheste Vermelho”. + +::: ludwig +Cada botão recebe o seu próprio ouvinte, com o seu próprio \`addActionListener\`. O título mudas com \`janela.setTitle(…)\`. +::: + +## 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. + +::: checkliste +- Consigo explicar o que é um evento. → Um clique é um evento +- Consigo usar addActionListener para decidir o que acontece com um clique. → A linha com a seta +- Consigo executar várias instruções com um clique. → Várias instruções com um clique +- Consigo construir um botão que muda o seu texto depois do clique. → Tarefa: fui clicado +::: + +## Teste de conhecimentos + +::: quiz +? O que é um ActionListener? +→ Um clique é um evento +- [ ] Um botão com texto +- [x] Um ouvinte que executa o teu código a cada clique +- [ ] Um layout para janelas +> Registas o ouvinte no botão com addActionListener. + +? Quando corre botao.setText("Fui clicado") dentro do ouvinte? +→ A linha com a seta +- [ ] Logo no início do programa +- [x] Sempre que alguém clica no botão +- [ ] Só no primeiro clique +> O código do ouvinte só corre quando o evento acontece. + +? Como termina um ouvinte com chavetas? +→ A linha com a seta +- [ ] };) +- [x] }); +- [ ] );} +> Primeiro fecha o bloco, depois o parêntese de addActionListener, depois o ponto e vírgula. + +? Associa cada parte à sua função. +→ A linha com a seta += JButton -> um botão += addActionListener -> registar um ouvinte += setText -> mudar o texto += setVisible(true) -> mostrar a janela +::: +`,yv=`--- +titel: Duplicar um número na janela +bereich: Janelas com Swing +kurz: Arrumar uma etiqueta, um campo de texto e um botão com um GridLayout e calcular com o texto do campo de texto. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- pôr um JLabel e um JTextField na janela +- explicar porque é que sem layout só se vê a última peça +- arrumar tudo umas por baixo das outras com GridLayout +- calcular com getText, Integer.parseInt e setText +- escrever um programa que não falha com “abc” +::: + +## O objetivo + +Vamos construir uma pequena calculadora com janela: em cima está uma etiqueta, por baixo um campo de texto e um botão **Calcular**. Se escreveres 2 e clicares, o campo de texto mostra 4. Clicas outra vez e passa a 8, depois 16 e assim por diante. + +Para isso precisas de duas peças novas: + +- **JLabel**: uma etiqueta, ou seja, texto simples na janela. +- **JTextField**: um campo de texto onde se pode escrever. + +Como nas últimas lições, marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## Três peças na janela + +Pomos as três peças na janela, tal como o botão na lição 29: + +\`\`\`java +import javax.swing.*; + +public class Duplicar { + public static void main(String[] args) { + JFrame janela = new JFrame("Duplicar número"); + janela.setSize(250, 150); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JLabel etiqueta = new JLabel("Escreve um número:"); + JTextField campo = new JTextField(); + JButton botao = new JButton("Calcular"); + janela.add(etiqueta); + janela.add(campo); + janela.add(botao); + + janela.setVisible(true); + } +} +\`\`\` + +Executa o programa. Ups: só se vê o botão gigante. Onde estão a etiqueta e o campo de texto? + +## Porque só se vê o botão + +::: ludwig +Lembras-te do botão gigante? Sem um layout próprio, um \`JFrame\` só tem **um** lugar: o meio. Cada \`add\` põe a peça nova exatamente aí, do tamanho da janela inteira. As três peças ficam por isso umas por cima das outras no mesmo lugar, e a janela só mostra a última que lá puseste: o botão. Assim não consegues usar o programa. +::: + +A solução é outra vez um layout. Desta vez usamos o **GridLayout**. Divide a janela em células do mesmo tamanho, como uma grelha: + +\`\`\`java +janela.setLayout(new GridLayout(0, 1)); +\`\`\` + +Os dois números são linhas e colunas. \`0\` linhas quer dizer “tantas quantas forem precisas”, \`1\` coluna quer dizer: tudo umas por baixo das outras. Para o \`GridLayout\` precisas ainda de \`import java.awt.*;\` lá em cima. + +| Layout | Como arruma | +|---|---| +| sem layout | tudo no meio, umas por cima das outras | +| \`FlowLayout\` | lado a lado como palavras, com mudança de linha quando é preciso | +| \`GridLayout(0, 1)\` | umas por baixo das outras, todas as linhas da mesma altura | + +## A janela com GridLayout + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Duplicar { + public static void main(String[] args) { + JFrame janela = new JFrame("Duplicar número"); + janela.setSize(250, 150); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new GridLayout(0, 1)); + + JLabel etiqueta = new JLabel("Escreve um número:"); + JTextField campo = new JTextField(); + JButton botao = new JButton("Calcular"); + janela.add(etiqueta); + janela.add(campo); + janela.add(botao); + + janela.setVisible(true); + } +} +\`\`\` + +Agora as três estão umas por baixo das outras. Podes escrever no campo de texto e carregar no botão. Mas o programa ainda não calcula nada. + +::: angeberwissen +Com \`new GridLayout(2, 3)\` obténs 2 linhas com 3 colunas cada, ou seja, 6 células do mesmo tamanho. É assim que se constroem, por exemplo, as teclas de uma calculadora. As peças preenchem as células pela ordem das linhas \`add\`, linha a linha da esquerda para a direita. +::: + +## Calcular com o texto do campo de texto + +Com um clique, o programa deve ir buscar o número ao campo de texto, duplicá-lo e voltar a escrevê-lo lá. Isso faz-se com três métodos: + +- \`campo.getText()\` dá-te o texto do campo de texto, por exemplo \`"2"\`. +- \`Integer.parseInt(…)\` transforma-o no número 2. Já conheces isto da lição 22. +- \`campo.setText(…)\` escreve um texto novo no campo de texto. + +Juntamente com o ActionListener da lição 30 fica assim: + +\`\`\`java +botao.addActionListener(e -> { + int numero = Integer.parseInt(campo.getText()); + campo.setText("" + numero * 2); +}); +\`\`\` + +\`setText\` precisa de um texto. \`"" + numero * 2\` junta o resultado a um texto vazio e assim transforma o número num texto. + +## Não é um número? Sem falhas! + +Escreve “abc” no campo de texto e clica em Calcular. A janela fica, mas não acontece nada, e na [consola](#zeige-konsole) aparece uma \`NumberFormatException\`. Da lição 22 já sabes o que fazer: + +\`\`\`java +botao.addActionListener(e -> { + try { + int numero = Integer.parseInt(campo.getText()); + campo.setText("" + numero * 2); + } catch (NumberFormatException erro) { + etiqueta.setText("Escreve um número inteiro!"); + } +}); +\`\`\` + +Em vez de um erro na consola, vês agora um aviso na janela. + +::: ludwig +A seta já tem um \`e\` para o evento. Por isso a exceção no \`catch\` precisa de outro nome, aqui \`erro\`. O Java não permite duas variáveis com o mesmo nome. +::: + +## Jogo: O que fica na janela? + +::: spiel frage +titel: Jogo: O que fica na janela? +intro: O Ludwig escreve algo no campo de texto e clica em Calcular. Lê o ouvinte e prevê o que a janela mostra depois. Seis rondas. + +runde: + botao.addActionListener(e -> { + int numero = Integer.parseInt(campo.getText()); + campo.setText("" + numero * 2); + }); +frage: No campo de texto está 21. O que fica lá depois do clique? +- 2121 +- [x] 42 +- 21 +> \`parseInt\` transforma o texto no número 21. O dobro é 42. + +runde: + botao.addActionListener(e -> { + int numero = Integer.parseInt(campo.getText()); + campo.setText("" + numero * 2); + }); +frage: No campo de texto está 21. Clicas duas vezes. O que fica lá depois? +- 42 +- [x] 84 +- 4242 +> Cada clique duplica o que está no campo nesse momento: 21, 42, 84. + +runde: + botao.addActionListener(e -> { + campo.setText(campo.getText() + campo.getText()); + }); +frage: No campo de texto está 21. O que fica lá depois do clique? +- 42 +- [x] 2121 +- 21 +> Sem \`parseInt\` continua a ser texto, e \`+\` junta textos. + +runde: + botao.addActionListener(e -> { + try { + int numero = Integer.parseInt(campo.getText()); + campo.setText("" + numero * 2); + } catch (NumberFormatException erro) { + etiqueta.setText("Escreve um número inteiro!"); + } + }); +frage: No campo de texto está abc. O que acontece com o clique? +- [x] A etiqueta mostra "Escreve um número inteiro!" +- No campo de texto fica abcabc. +- A janela vai abaixo. +> \`parseInt\` lança uma NumberFormatException, e o \`catch\` apanha-a. + +runde: + botao.addActionListener(e -> { + try { + int numero = Integer.parseInt(campo.getText()); + campo.setText("" + numero * 2); + } catch (NumberFormatException erro) { + etiqueta.setText("Escreve um número inteiro!"); + } + }); +frage: No campo de texto está 2.5. O que acontece com o clique? +- No campo de texto fica 5.0. +- No campo de texto fica 5. +- [x] A etiqueta mostra "Escreve um número inteiro!" +> \`Integer.parseInt\` só conhece números inteiros. Para ele, 2.5 não é um número. + +runde: + botao.addActionListener(e -> { + int numero = Integer.parseInt(campo.getText()); + campo.setText("" + numero + numero); + }); +frage: No campo de texto está 5. O que fica lá depois do clique? +- 10 +- [x] 55 +- 5 +> \`"" + numero\` já é um texto, e o segundo \`+\` junta outra vez o 5. Com \`"" + (numero + numero)\` o Java calcula primeiro. +::: + +## Tarefa: duplicar um número + +Junta o programa todo: + +- uma janela com o título “Duplicar número”, com 250 píxeis de largura e 150 píxeis de altura, +- umas por baixo das outras, uma etiqueta, um campo de texto e um botão “Calcular”, +- cada clique duplica o número no campo de texto: 2, 4, 8, 16, … +- com “abc” aparece um aviso na etiqueta em vez de uma falha. + +Extra: um segundo botão “Dividir por 2” divide o número por 2. O que acontece com 5? + +::: ludwig +O botão “Dividir por 2” entra no GridLayout como quarta linha e recebe o seu próprio ActionListener. Com \`int\`, o Java corta as casas decimais ao dividir. +::: + +## 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. + +::: checkliste +- Consigo pôr um JLabel e um JTextField na janela. → Três peças na janela +- Consigo explicar porque é que sem layout só se vê a última peça. → Porque só se vê o botão +- Consigo arrumar tudo umas por baixo das outras com GridLayout(0, 1). → A janela com GridLayout +- Consigo calcular com getText, Integer.parseInt e setText. → Calcular com o texto do campo de texto +- Consigo escrever um programa que não falha com “abc”. → Não é um número? Sem falhas! +::: + +## Teste de conhecimentos + +::: quiz +? Porque é que sem layout só se vê o botão? +→ Porque só se vê o botão +- [ ] Porque faltam a etiqueta e o campo de texto +- [x] Porque todas as peças estão no meio umas por cima das outras e a última tapa as outras +- [ ] Porque a janela é demasiado pequena + +? O que significa new GridLayout(0, 1)? +→ A janela com GridLayout +- [ ] Nenhuma linha e uma coluna, por isso a janela fica vazia +- [x] Tantas linhas quantas forem precisas numa coluna, ou seja, tudo umas por baixo das outras +- [ ] Uma linha, tudo lado a lado + +? O que te dá campo.getText()? +→ Calcular com o texto do campo de texto +- [ ] Sempre um número +- [x] O texto do campo de texto +- [ ] O título da janela +> Para um número precisas ainda de Integer.parseInt. + +? Associa cada peça à sua função. +→ Três peças na janela += JLabel -> etiqueta += JTextField -> campo de texto para escrever += JButton -> botão += GridLayout -> arrumação em grelha +::: +`,wv=`--- +titel: Contador de cliques com reset +bereich: Janelas com Swing +kurz: Dois botões alteram o mesmo número: criar uma variável para a classe toda. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- explicar porque é que um ouvinte não pode alterar uma variável do main +- criar uma variável static na classe +- fazer com que dois botões alterem o mesmo número +- construir um contador com −1 que nunca fica abaixo de 0 +::: + +## O objetivo + +Uma janela conta cliques: em cima está o número, por baixo dois botões. **+1** soma um, **Reset** volta a pôr o número a 0. + +A novidade desta vez: dois botões trabalham com o **mesmo** número. Para isso precisas de uma variável que os dois ouvintes conheçam. + +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## A primeira tentativa + +A ideia mais óbvia é criar o número no \`main\`, como de costume, e somá-lo no ouvinte: + +\`\`\`java +int contagem = 0; +botao.addActionListener(e -> { + contagem++; + numero.setText("" + contagem); +}); +\`\`\` + +Se executares isto com o Java verdadeiro, o compilador indica um erro: + +\`\`\` +local variables referenced from a lambda expression must be final or effectively final +\`\`\` + +::: ludwig +O ouvinte só corre mais tarde, a cada clique, muito depois de o \`main\` ter terminado. Por isso pode ler as variáveis do \`main\`, mas não alterá-las. O Java insiste: uma variável do \`main\` que aparece na seta tem de ficar igual. Para um número que muda a cada clique, precisamos de outro lugar. +::: + +## Uma variável para a classe toda + +A solução: a variável **não** vai para o \`main\`, mas diretamente para a classe, por cima do \`main\`. Assim pertence à classe toda, e qualquer ouvinte a pode alterar: + +\`\`\`java +public class Contador { + static int contagem = 0; + + public static void main(String[] args) { + // aqui a janela, como de costume + } +} +\`\`\` + +- \`static\` quer dizer: a variável pertence à própria classe. Como o \`main\` também é \`static\`, aqui é preciso. +- Uma variável destas chama-se **atributo** da classe. Vive tanto tempo como o programa, e não só enquanto o \`main\` corre. + +## O programa completo + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Contador { + static int contagem = 0; + + public static void main(String[] args) { + JFrame janela = new JFrame("Contador de cliques"); + janela.setSize(250, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new GridLayout(0, 1)); + + JLabel numero = new JLabel("0", SwingConstants.CENTER); + JButton mais = new JButton("+1"); + JButton reset = new JButton("Reset"); + + mais.addActionListener(e -> { + contagem++; + numero.setText("" + contagem); + }); + reset.addActionListener(e -> { + contagem = 0; + numero.setText("0"); + }); + + janela.add(numero); + janela.add(mais); + janela.add(reset); + janela.setVisible(true); + } +} +\`\`\` + +\`SwingConstants.CENTER\` põe o texto da etiqueta no meio. Clica algumas vezes em +1 e depois em Reset. + +::: angeberwissen +Com \`numero.setFont(new Font("SansSerif", Font.BOLD, 48));\` o número fica grande e a negrito. \`Font\` vem de \`java.awt\`, que já importaste. +::: + +## Jogo: Quem está a contar? + +::: spiel zuhoerer +titel: Jogo: Quem está a contar? +intro: Agora os ouvintes fazem contas com a variável da classe. O Ludwig mostra-te o código, a janela e os cliques. Que número aparece no fim? A seguir o Ludwig reproduz os cliques. +frage: O que diz a etiqueta depois dos cliques? + +runde: + static int contagem = 0; + JLabel numero = new JLabel("0"); + JButton mais = new JButton("+1"); + mais.addActionListener(e -> { + contagem++; + numero.setText("" + contagem); + }); +klicks: +1, +1, +1 +- 1 +- [x] 3 +- 0 +> A variável está na classe e guarda o valor entre os cliques. Cada clique soma um: 1, 2, 3. + +runde: + static int contagem = 0; + JLabel numero = new JLabel("0"); + JButton mais = new JButton("+1"); + JButton reset = new JButton("Reset"); + mais.addActionListener(e -> { + contagem++; + numero.setText("" + contagem); + }); + reset.addActionListener(e -> { + contagem = 0; + numero.setText("0"); + }); +klicks: +1, +1, Reset, +1 +- 3 +- 0 +- [x] 1 +> Depois de dois cliques aparece 2. O Reset põe a variável a 0, e o último clique volta a contar até 1. + +runde: + static int contagem = 0; + JLabel numero = new JLabel("0"); + JButton mais = new JButton("+1"); + mais.addActionListener(e -> contagem++); +klicks: +1, +1 +- 2 +- [x] 0 +- 1 +> A variável fica a 2, mas ninguém a escreve na etiqueta. Sem \`numero.setText(…)\` a janela continua a mostrar 0. Calcular e mostrar são duas coisas diferentes. + +runde: + static int contagem = 0; + JLabel numero = new JLabel("Cliques: 0"); + JButton mais = new JButton("+1"); + mais.addActionListener(e -> { + contagem++; + numero.setText("Cliques: " + contagem + 1); + }); +klicks: +1 +- Cliques: 2 +- Cliques: 1 +- [x] Cliques: 11 +> A armadilha dos parênteses: o Java calcula da esquerda para a direita. \`"Cliques: " + contagem\` dá o texto “Cliques: 1”, e \`+ 1\` junta mais um 1 no fim. + +runde: + static int contagem = 0; + JLabel numero = new JLabel("0"); + JButton um = new JButton("+1"); + JButton dez = new JButton("+10"); + um.addActionListener(e -> { + contagem++; + numero.setText("" + contagem); + }); + dez.addActionListener(e -> { + contagem += 10; + numero.setText("" + contagem); + }); +klicks: +10, +1, +10 +- 12 +- [x] 21 +- 111 +> Os dois ouvintes alteram a mesma variável: 10, depois 11, depois 21. \`contagem += 10\` é a forma curta de \`contagem = contagem + 10\`. +::: + +## Tarefa: contador de cliques + +Reconstrói o contador de cliques e acrescenta: + +- um botão **−1** que subtrai um, +- o número nunca deve ficar abaixo de 0. Se estiver em 0, o −1 não faz nada. + +::: ludwig +Para “nunca abaixo de 0”, o ouvinte do −1 precisa de um \`if\`: só se \`contagem > 0\` é que subtrai. +::: + +## 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. + +::: checkliste +- Consigo explicar porque é que um ouvinte não pode alterar uma variável do main. → A primeira tentativa +- Consigo criar uma variável static na classe. → Uma variável para a classe toda +- Consigo fazer com que dois botões alterem o mesmo número. → O programa completo +- Consigo construir um contador com −1 que nunca fica abaixo de 0. → Tarefa: contador de cliques +::: + +## Teste de conhecimentos + +::: quiz +? Porque é que o ouvinte não pode alterar a variável contagem do main? +→ A primeira tentativa +- [ ] Porque no Swing não são permitidos números +- [x] Porque o ouvinte só corre mais tarde e o Java não deixa a seta alterar variáveis do main +- [ ] Porque a contagem fica demasiado grande + +? Onde fica static int contagem = 0;? +→ Uma variável para a classe toda +- [ ] No main, bem em cima +- [x] Na classe, fora do main +- [ ] No ouvinte + +? O que faz SwingConstants.CENTER em new JLabel("0", SwingConstants.CENTER)? +→ O programa completo +- [x] Põe o texto no meio da etiqueta. +- [ ] Põe a janela no meio do ecrã. +- [ ] Aumenta a letra. +::: +`,zv=`--- +titel: Um semáforo com cores +bereich: Janelas com Swing +kurz: Definir cores de fundo e mudar um semáforo com uma variável de estado. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- pintar uma etiqueta com setOpaque e setBackground +- guardar um estado numa variável static +- usar o BorderLayout para pôr algo grande no meio e algo estreito em baixo +- explicar para que servem o FlowLayout, o GridLayout e o BorderLayout +- programar um semáforo com quatro fases +::: + +## O objetivo + +Vamos construir um semáforo: uma área grande acende a vermelho. A cada clique em **Seguinte** muda: vermelho, verde, amarelo e outra vez vermelho. + +As novidades desta vez são as **cores** e um **estado**: o programa tem de se lembrar de que cor está acesa. + +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## Cores no Swing + +As cores estão na classe \`Color\` de \`java.awt\`. Cores já prontas são, por exemplo, \`Color.RED\`, \`Color.GREEN\`, \`Color.YELLOW\`, \`Color.ORANGE\` e \`Color.WHITE\`. + +É assim que pintas uma etiqueta: + +\`\`\`java +JLabel luz = new JLabel("", SwingConstants.CENTER); +luz.setOpaque(true); +luz.setBackground(Color.RED); +\`\`\` + +- \`setBackground(…)\` define a cor de fundo. +- Um \`JLabel\` precisa ainda de \`setOpaque(true)\`. Sem esta linha o fundo é transparente e a cor fica invisível. + +::: ludwig +\`opaque\` é inglês para “opaco”, ou seja, não transparente. Normalmente uma etiqueta é transparente, como letras escritas num vidro. Só com \`setOpaque(true)\` ganha uma área própria que se pode pintar. +::: + +## Lembrar a cor + +Para o semáforo saber o que vem a seguir, guarda o seu estado num número: 0 é vermelho, 1 é verde, 2 é amarelo. Tal como no contador de cliques da lição 32, a variável fica na classe, para o ouvinte a poder alterar: + +\`\`\`java +static int fase = 0; +\`\`\` + +A cada clique a fase avança um. Depois do amarelo (2) vem outra vez o vermelho (0): + +\`\`\`java +seguinte.addActionListener(e -> { + fase++; + if (fase > 2) { + fase = 0; + } + if (fase == 0) { + luz.setBackground(Color.RED); + } else if (fase == 1) { + luz.setBackground(Color.GREEN); + } else { + luz.setBackground(Color.YELLOW); + } +}); +\`\`\` + +## O programa completo + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Semaforo { + static int fase = 0; + + public static void main(String[] args) { + JFrame janela = new JFrame("Semáforo"); + janela.setSize(200, 300); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new BorderLayout()); + + JLabel luz = new JLabel("", SwingConstants.CENTER); + luz.setOpaque(true); + luz.setBackground(Color.RED); + JButton seguinte = new JButton("Seguinte"); + + seguinte.addActionListener(e -> { + fase++; + if (fase > 2) { + fase = 0; + } + if (fase == 0) { + luz.setBackground(Color.RED); + } else if (fase == 1) { + luz.setBackground(Color.GREEN); + } else { + luz.setBackground(Color.YELLOW); + } + }); + + janela.add(luz, BorderLayout.CENTER); + janela.add(seguinte, BorderLayout.SOUTH); + janela.setVisible(true); + } +} +\`\`\` + +Aqui entra um layout novo, o **BorderLayout**. Tem cinco lugares: \`NORTH\` (em cima), \`SOUTH\` (em baixo), \`WEST\` (à esquerda), \`EAST\` (à direita) e \`CENTER\` (no meio). O meio fica com todo o espaço que sobra. Assim a luz fica grande e o botão fica estreito em baixo. + +::: angeberwissen +O BorderLayout é o layout que um \`JFrame\` usa quando não lhe dás nenhum. Um \`add\` sem indicação de lugar vai para o \`CENTER\`. É por isso que na lição 31 as peças ficaram todas umas por cima das outras. +::: + +::: angeberwissen +Os profissionais avançam a fase numa linha: \`fase = (fase + 1) % 3;\`. O operador de resto \`%\` dá o resto da divisão. 3 % 3 é 0, por isso depois do 2 recomeça no 0. +::: + +## Que layout para quê? + +Já conheces três layouts. Cada um arruma os blocos de outra maneira: + +| Layout | Como arruma | Bom para | +|---|---|---| +| \`FlowLayout\` (lição 29) | lado a lado, como palavras numa linha, cada bloco do tamanho necessário | alguns botões numa fila | +| \`GridLayout\` (lição 31) | uma grelha de células do mesmo tamanho, preenchida linha a linha | formulários, teclados como o da calculadora | +| \`BorderLayout\` (esta lição) | cinco lugares: em cima, em baixo, à esquerda, à direita e o meio, que fica com o resto | algo grande no meio, por exemplo uma imagem ou um mostrador, com botões na margem | + +Sem \`setLayout\`, uma janela usa o BorderLayout. É por isso que, nesse caso, tudo vai para o meio. + +::: ludwig +Ao planear, pergunta-te: todas as partes devem ter o mesmo tamanho? Então GridLayout. Uma parte deve ser grande e o resto estreito na margem? Então BorderLayout. As partes devem simplesmente manter o tamanho normal? Então FlowLayout. +::: + +## Jogo: Onde fica o botão? + +::: spiel layout +titel: Jogo: Onde fica o botão? +intro: Já conheces três layouts e a janela sem layout nenhum. O Ludwig mostra-te código com os botões A, B, C … Como fica a janela? Toca na imagem certa. +frage: Como fica a janela? + +runde: + janela.add(new JButton("A")); + janela.add(new JButton("B")); + janela.add(new JButton("C")); +- flow: A B C +- grid: A / B / C +- [x] border: C=C +> Sem layout próprio, cada \`add\` vai para o meio, do tamanho da janela. Os três ficam uns por cima dos outros e só se vê o último: C. + +runde: + janela.setLayout(new FlowLayout()); + janela.add(new JButton("A")); + janela.add(new JButton("B")); + janela.add(new JButton("C")); +- [x] flow: A B C +- grid: A B C +- border: C=C +> O FlowLayout põe os botões no tamanho normal lado a lado, como palavras numa linha, e centra-os. + +runde: + janela.setLayout(new GridLayout(0, 1)); + janela.add(new JButton("A")); + janela.add(new JButton("B")); + janela.add(new JButton("C")); +- flow: A B C +- [x] grid: A / B / C +- grid: A B C +> Uma coluna e tantas linhas quantas forem precisas: tudo uns por baixo dos outros, cada linha com a mesma altura e tão larga como a janela. + +runde: + janela.setLayout(new GridLayout(0, 2)); + janela.add(new JButton("A")); + janela.add(new JButton("B")); + janela.add(new JButton("C")); + janela.add(new JButton("D")); +- grid: A C / B D +- [x] grid: A B / C D +- grid: A / B / C / D +> Duas colunas. As células são preenchidas linha a linha, sempre primeiro à esquerda e depois à direita: A B, depois C D. + +runde: + janela.setLayout(new GridLayout(2, 3)); + janela.add(new JButton("A")); + janela.add(new JButton("B")); + janela.add(new JButton("C")); + janela.add(new JButton("D")); + janela.add(new JButton("E")); + janela.add(new JButton("F")); +- grid: A B / C D / E F +- [x] grid: A B C / D E F +- flow: A B C D E F +> Primeiro vêm as linhas, depois as colunas: 2 linhas com 3 colunas cada. + +runde: + janela.setLayout(new GridLayout(0, 2)); + janela.add(new JButton("A")); + janela.add(new JButton("B")); + janela.add(new JButton("C")); +- [x] grid: A B / C +- grid: A B C +- grid: A / B C +> Duas colunas, três botões: a primeira linha fica cheia, na segunda o C fica à esquerda e a célula da direita fica vazia. + +runde: + janela.setLayout(new BorderLayout()); + janela.add(new JButton("A"), BorderLayout.NORTH); + janela.add(new JButton("B"), BorderLayout.CENTER); + janela.add(new JButton("C"), BorderLayout.SOUTH); +- grid: A / B / C +- [x] border: N=A C=B S=C +- border: N=C C=B S=A +> NORTH é em cima, SOUTH em baixo. O meio fica com todo o espaço que sobra, por isso o B é grande. + +runde: + janela.setLayout(new BorderLayout()); + janela.add(new JButton("A"), BorderLayout.WEST); + janela.add(new JButton("B")); + janela.add(new JButton("C"), BorderLayout.EAST); +- flow: A B C +- border: N=A C=B S=C +- [x] border: W=A C=B E=C +> WEST é à esquerda, EAST à direita. O B não tem lugar indicado e por isso vai para o CENTER. +::: + +## Tarefa: semáforo + +Reconstrói o semáforo e torna-o mais realista. Em alguns países, como a Alemanha, depois do vermelho acendem durante pouco tempo o vermelho e o amarelo juntos. Acrescenta por isso uma quarta fase: + +- 0: vermelho +- 1: vermelho e amarelo (usa \`Color.ORANGE\`) +- 2: verde +- 3: amarelo + +Extra: em cada fase, escreve também com \`luz.setText(…)\` o que o semáforo quer dizer, por exemplo “Parar” ou “Avançar”. + +::: ludwig +Com quatro fases, depois do 3 vem o 0. Ajusta por isso o número em \`if (fase > 2)\`. +::: + +## 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. + +::: checkliste +- Consigo pintar uma etiqueta com setOpaque e setBackground. → Cores no Swing +- Consigo guardar um estado numa variável static. → Lembrar a cor +- Consigo usar o BorderLayout para pôr algo grande no meio e algo estreito em baixo. → O programa completo +- Consigo explicar para que servem o FlowLayout, o GridLayout e o BorderLayout. → Que layout para quê? +- Consigo programar um semáforo com quatro fases. → Tarefa: semáforo +::: + +## Teste de conhecimentos + +::: quiz +? Porque é que a cor fica invisível sem setOpaque(true)? +→ Cores no Swing +- [ ] Porque Color.RED não existe +- [x] Porque, sem isso, uma etiqueta é transparente +- [ ] Porque a janela é demasiado pequena + +? Que lugar do BorderLayout fica com o espaço que sobra? +→ O programa completo +- [ ] NORTH +- [ ] SOUTH +- [x] CENTER + +? fase é 2 e o ouvinte executa fase++ e depois if (fase > 2) { fase = 0; }. Que valor tem fase a seguir? +→ Lembrar a cor +- [x] 0 +- [ ] 2 +- [ ] 3 +> Depois de fase++ é 3, que é maior do que 2, por isso passa a 0. +::: +`,Iv=`--- +titel: Calculadora de notas na janela +bereich: Janelas com Swing +kurz: Escrever a percentagem, determinar o nível com else if e apanhar entradas erradas. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- transformar uma percentagem num nível com else if +- mostrar o nível na janela +- apanhar e avisar “abc” e valores fora de 0 a 100 +- testar um programa nos limites, por exemplo com 90 e 89 +::: + +## O objetivo + +Uma janela transforma a percentagem de um teste num nível: escreves a percentagem (0 a 100), clicas em **Calcular nível** e em baixo aparece o nível. + +Desta vez não há nenhuma peça nova do Swing. A novidade é que combinas tudo o que já sabes: campo de texto, botão, \`else if\` da lição 20 e try/catch da lição 22. + +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## A escala de níveis + +Usamos a escala de níveis do ensino básico: + +| Percentagem | Nível | +|---|---| +| 90 a 100 | 5 | +| 70 a 89 | 4 | +| 50 a 69 | 3 | +| 20 a 49 | 2 | +| 0 a 19 | 1 | + +Com \`else if\` verificas de cima para baixo. Ganha a primeira condição verdadeira: + +\`\`\`java +int nivel; +if (percentagem >= 90) { + nivel = 5; +} else if (percentagem >= 70) { + nivel = 4; +} else if (percentagem >= 50) { + nivel = 3; +} else if (percentagem >= 20) { + nivel = 2; +} else { + nivel = 1; +} +\`\`\` + +::: ludwig +Com 75 %, \`percentagem >= 90\` é falso, mas \`percentagem >= 70\` é verdadeiro. Portanto nível 4, e as restantes condições já nem são verificadas. É por isso que basta sempre o limite de baixo. +::: + +Podes experimentar esta parte sem janela na área [Código](#zeige-codelive). Escreve \`int percentagem = 75;\` antes e \`System.out.println("Nível: " + nivel);\` depois. O estrutograma mostra-te as decisões encaixadas. + +## A janela + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class CalculadoraNiveis { + public static void main(String[] args) { + JFrame janela = new JFrame("Calculadora de níveis"); + janela.setSize(260, 180); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new GridLayout(0, 1)); + + JLabel pergunta = new JLabel("Percentagem (0 a 100):"); + JTextField campo = new JTextField(); + JButton botao = new JButton("Calcular nível"); + JLabel resultado = new JLabel("Nível: ?"); + + botao.addActionListener(e -> { + int percentagem = Integer.parseInt(campo.getText()); + int nivel; + if (percentagem >= 90) { + nivel = 5; + } else if (percentagem >= 70) { + nivel = 4; + } else if (percentagem >= 50) { + nivel = 3; + } else if (percentagem >= 20) { + nivel = 2; + } else { + nivel = 1; + } + resultado.setText("Nível: " + nivel); + }); + + janela.add(pergunta); + janela.add(campo); + janela.add(botao); + janela.add(resultado); + janela.setVisible(true); + } +} +\`\`\` + +Experimenta 100, 75, 50 e 12. + +## Apanhar entradas erradas + +Ainda há duas coisas que podem correr mal: + +1. Alguém escreve “abc”. Então \`Integer.parseInt\` lança uma \`NumberFormatException\`. +2. Alguém escreve 150 ou −5. É um número, mas não é uma percentagem válida. + +O primeiro caso apanhas com try/catch, o segundo com um \`if\` antes de calcular o nível: + +\`\`\`java +botao.addActionListener(e -> { + try { + int percentagem = Integer.parseInt(campo.getText()); + if (percentagem < 0 || percentagem > 100) { + resultado.setText("Escreve um valor de 0 a 100."); + } else { + // aqui o cálculo do nível de cima + } + } catch (NumberFormatException erro) { + resultado.setText("Isso não é um número."); + } +}); +\`\`\` + +::: ludwig +\`||\` quer dizer “ou” (lição 9). A condição é verdadeira se a percentagem for demasiado pequena **ou** demasiado grande. +::: + +## Jogo: Que nível? + +::: spiel frage +titel: Jogo: Que nível? +intro: O Ludwig construiu calculadoras de níveis, mas nem todas estão certas. Calcula que nível sai. Seis rondas. + +runde: + if (percentagem >= 90) { + nivel = 5; + } else if (percentagem >= 70) { + nivel = 4; + } else if (percentagem >= 50) { + nivel = 3; + } else { + nivel = 2; + } +frage: percentagem é 70. Que nível sai? +- 5 +- [x] 4 +- 3 +> 70 >= 90 é falso, 70 >= 70 é verdadeiro. O limite ainda pertence ao 4. + +runde: + if (percentagem >= 90) { + nivel = 5; + } else if (percentagem >= 70) { + nivel = 4; + } else if (percentagem >= 50) { + nivel = 3; + } else if (percentagem >= 20) { + nivel = 2; + } else { + nivel = 1; + } +frage: percentagem é 49. Que nível sai? +- 3 +- [x] 2 +- 1 +> 49 >= 50 é falso por pouco, 49 >= 20 é verdadeiro. Portanto nível 2. + +runde: + if (percentagem >= 50) { + nivel = 3; + } else if (percentagem >= 90) { + nivel = 5; + } else { + nivel = 1; + } +frage: percentagem é 95. Que nível sai? +- 5 +- [x] 3 +- 1 +> Ganha a primeira condição verdadeira. 95 >= 50 já é verdadeiro, o 5 nunca é alcançado. Por isso verifica-se das percentagens altas para baixo. + +runde: + nivel = 1; + if (percentagem >= 20) { + nivel = 2; + } + if (percentagem >= 50) { + nivel = 3; + } +frage: percentagem é 80. Que valor tem nivel depois? +- 1 +- 2 +- [x] 3 +> Sem \`else\`, todos os \`if\` são verificados. Os dois são verdadeiros, e o último dá o nível 3. + +runde: + // nivel já está calculado + if (percentagem < 0 || percentagem > 100) { + resultado.setText("Escreve um valor de 0 a 100."); + } else { + resultado.setText("Nível: " + nivel); + } +frage: No campo de texto está 100. O que mostra a janela? +- [x] Nível: 5 +- Escreve um valor de 0 a 100. +- Isso não é um número. +> 100 > 100 é falso. Portanto 100 é válido e dá o nível 5. + +runde: + // nivel já está calculado + if (percentagem < 0 && percentagem > 100) { + resultado.setText("Escreve um valor de 0 a 100."); + } else { + resultado.setText("Nível: " + nivel); + } +frage: No campo de texto está 150. O que mostra a janela? +- Escreve um valor de 0 a 100. +- [x] um nível, embora 150 não seja válido +- Isso não é um número. +> Com \`&&\`, a percentagem teria de ser ao mesmo tempo menor que 0 e maior que 100. Isso nunca acontece, por isso o programa nunca avisa. O certo é \`||\`. +::: + +## Tarefa: calculadora de níveis + +Junta a calculadora de níveis, com as duas verificações do último passo. Testa com 90, 89, 0, 100, 101 e “dez”. + +Extra: escreve também a menção do nível, por exemplo “Nível: 4 (Bom)”. As menções são Muito bom, Bom, Suficiente, Insuficiente e Fraco. + +::: ludwig +Testa sempre os limites: 90 tem de dar 5, 89 tem de dar 4. É nos limites que se escondem a maioria dos erros, por exemplo \`>\` em vez de \`>=\`. +::: + +## 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. + +::: checkliste +- Consigo transformar uma percentagem num nível com else if. → A escala de níveis +- Consigo mostrar o nível na janela. → A janela +- Consigo apanhar e avisar “abc” e valores fora de 0 a 100. → Apanhar entradas erradas +- Consigo testar um programa nos limites, por exemplo com 90 e 89. → Tarefa: calculadora de níveis +::: + +## Teste de conhecimentos + +::: quiz +? Que nível dá a escala com 70 %? +→ A escala de níveis +- [ ] 3 +- [x] 4 +- [ ] 5 +> 70 é o limite de baixo do nível 4. + +? Porque é que em cada condição basta o limite de baixo? +→ A escala de níveis +- [x] Porque o else if já separou antes os casos mais altos +- [ ] Porque o Java não conhece limites de cima +- [ ] Porque a percentagem é sempre 100 + +? Que condição deteta percentagens inválidas? +→ Apanhar entradas erradas +- [ ] percentagem < 0 && percentagem > 100 +- [x] percentagem < 0 || percentagem > 100 +- [ ] percentagem >= 0 || percentagem <= 100 +> Um número não pode ser ao mesmo tempo menor do que 0 e maior do que 100, por isso é preciso o ou. +::: +`,kv=`--- +titel: Uma calculadora +bereich: Janelas com Swing +kurz: Duas colunas com GridLayout, quatro botões de cálculo e apanhar a divisão por 0. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- construir duas colunas com GridLayout +- explicar porque é que "" + (a + b) precisa de parênteses +- programar os quatro botões de cálculo +- construir uma calculadora que não falha com 0 nem com “abc” +::: + +## O objetivo + +Vamos construir uma pequena calculadora: dois campos de texto para os números, quatro botões **+**, **-**, **\\*** e **/** e uma linha para o resultado. + +As novidades desta vez são **duas colunas** no GridLayout e **vários botões** que calculam todos com os mesmos campos de texto. + +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## Duas colunas + +Até agora, com \`GridLayout(0, 1)\`, ficava tudo umas por baixo das outras. Com \`GridLayout(0, 2)\` há duas colunas. As peças preenchem as células pela ordem das linhas \`add\`, sempre primeiro à esquerda e depois à direita: + +| esquerda | direita | +|---|---| +| Primeiro número: | campo de texto | +| Segundo número: | campo de texto | +| + | - | +| \\* | / | +| Resultado: | ? | + +As etiquetas da esquerda não vais precisar delas mais tarde. Por isso podes construí-las logo dentro do \`add\`, sem variável: + +\`\`\`java +janela.add(new JLabel("Primeiro número:")); +janela.add(campo1); +\`\`\` + +## A janela com o primeiro botão + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Calculadora { + public static void main(String[] args) { + JFrame janela = new JFrame("Calculadora"); + janela.setSize(280, 220); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new GridLayout(0, 2)); + + JTextField campo1 = new JTextField(); + JTextField campo2 = new JTextField(); + JButton mais = new JButton("+"); + JButton menos = new JButton("-"); + JButton vezes = new JButton("*"); + JButton dividir = new JButton("/"); + JLabel resultado = new JLabel("?"); + + mais.addActionListener(e -> { + int a = Integer.parseInt(campo1.getText()); + int b = Integer.parseInt(campo2.getText()); + resultado.setText("" + (a + b)); + }); + + janela.add(new JLabel("Primeiro número:")); + janela.add(campo1); + janela.add(new JLabel("Segundo número:")); + janela.add(campo2); + janela.add(mais); + janela.add(menos); + janela.add(vezes); + janela.add(dividir); + janela.add(new JLabel("Resultado:")); + janela.add(resultado); + janela.setVisible(true); + } +} +\`\`\` + +Escreve 3 e 4 e clica em +. Em baixo aparece 7. + +::: ludwig +Atenção aos parênteses em \`"" + (a + b)\`. Sem eles, o Java calcula da esquerda para a direita: \`"" + a\` dá o texto “3”, e \`"3" + b\` junta o 4 no fim. Sai “34” em vez de 7. O parêntese garante que primeiro se faz a conta. +::: + +## Os outros três botões + +Os botões -, \\* e / funcionam da mesma maneira. Só muda o sinal na última linha: + +\`\`\`java +menos.addActionListener(e -> { + int a = Integer.parseInt(campo1.getText()); + int b = Integer.parseInt(campo2.getText()); + resultado.setText("" + (a - b)); +}); +\`\`\` + +O / tem duas particularidades: + +- Com \`int\`, o Java corta as casas decimais ao dividir. 7 / 2 dá 3. +- Se o segundo número for 0, o Java lança uma \`ArithmeticException\`, como na tarefa “Dividir em segurança” da lição 22. + +## Apanhar a divisão por 0 + +\`\`\`java +dividir.addActionListener(e -> { + int a = Integer.parseInt(campo1.getText()); + int b = Integer.parseInt(campo2.getText()); + try { + resultado.setText("" + (a / b)); + } catch (ArithmeticException erro) { + resultado.setText("Não se divide por 0!"); + } +}); +\`\`\` + +::: angeberwissen +Com \`double\` e \`Double.parseDouble(…)\` há casas decimais: 7 / 2 dá 3.5. Em contrapartida, com números decimais o Java não lança nenhuma exceção ao dividir por 0. O resultado é então \`Infinity\`, ou seja, “infinito”. +::: + +## Saber de profissional: um método próprio + +Isto não está no programa da disciplina, mas torna o código mais curto. + +::: angeberwissen +Cada ouvinte lê os mesmos dois campos. Podes passar esta repetição para um método próprio, um subprograma como na lição 18. Fica na classe, ao lado do \`main\`: + +\`static int numero(JTextField campo) { return Integer.parseInt(campo.getText()); }\` + +No ouvinte basta então escrever \`resultado.setText("" + (numero(campo1) + numero(campo2)));\`. +::: + +## Jogo: O que mostra a calculadora? + +::: spiel frage +titel: Jogo: O que mostra a calculadora? +intro: O Ludwig andou a mexer na calculadora. Lê o ouvinte e prevê o que aparece no resultado. Seis rondas. + +runde: + mais.addActionListener(e -> { + int a = Integer.parseInt(campo1.getText()); + int b = Integer.parseInt(campo2.getText()); + resultado.setText("" + a + b); + }); +frage: Escreves 3 e 4 e clicas em +. O que aparece no resultado? +- 7 +- [x] 34 +- 12 +> Sem parênteses, o Java trabalha da esquerda para a direita: \`"" + 3\` é o texto "3", e \`+ 4\` junta o 4 no fim. + +runde: + vezes.addActionListener(e -> { + int a = Integer.parseInt(campo1.getText()); + int b = Integer.parseInt(campo2.getText()); + resultado.setText("" + a * b); + }); +frage: Escreves 3 e 4 e clicas em *. O que aparece no resultado? +- 34 +- [x] 12 +- 7 +> A multiplicação vem antes da soma também aqui: o Java calcula primeiro 3 * 4 e depois junta o 12 ao texto. O mais não tem esta prioridade, por isso precisa dos parênteses. + +runde: + dividir.addActionListener(e -> { + int a = Integer.parseInt(campo1.getText()); + int b = Integer.parseInt(campo2.getText()); + resultado.setText("" + (a / b)); + }); +frage: Escreves 7 e 2 e clicas em /. O que aparece no resultado? +- 3.5 +- [x] 3 +- 4 +> Com \`int\`, o Java corta as casas decimais. Não arredonda. + +runde: + dividir.addActionListener(e -> { + int a = Integer.parseInt(campo1.getText()); + int b = Integer.parseInt(campo2.getText()); + try { + resultado.setText("" + (a / b)); + } catch (ArithmeticException erro) { + resultado.setText("Não se divide por 0!"); + } + }); +frage: Escreves 8 e 0 e clicas em /. O que aparece no resultado? +- 0 +- [x] Não se divide por 0! +- Infinity +> Com \`int\`, dividir por 0 lança uma ArithmeticException, e o \`catch\` escreve o aviso. + +runde: + dividir.addActionListener(e -> { + double a = Double.parseDouble(campo1.getText()); + double b = Double.parseDouble(campo2.getText()); + resultado.setText("" + (a / b)); + }); +frage: Escreves 7 e 2 e clicas em /. O que aparece no resultado? +- 3 +- [x] 3.5 +- 3.0 +> Com \`double\`, as casas decimais ficam. + +runde: + dividir.addActionListener(e -> { + double a = Double.parseDouble(campo1.getText()); + double b = Double.parseDouble(campo2.getText()); + try { + resultado.setText("" + (a / b)); + } catch (ArithmeticException erro) { + resultado.setText("Não se divide por 0!"); + } + }); +frage: Escreves 8 e 0 e clicas em /. O que aparece no resultado? +- Não se divide por 0! +- [x] Infinity +- 0.0 +> Com \`double\` não há exceção. O resultado é \`Infinity\`, ou seja "infinito", e o \`catch\` nunca chega a entrar. +::: + +## Tarefa: calculadora + +Acaba a calculadora: + +- os quatro botões calculam, +- o / avisa “Não se divide por 0!” em vez de falhar, +- se um campo tiver “abc” ou estiver vazio, aparece “Escreve dois números”. + +Extra: um quinto botão **C** esvazia os dois campos e volta a pôr o resultado em “?”. + +::: ludwig +Para o “abc” cada ouvinte precisa de um try/catch com \`NumberFormatException\`. Depois de um \`try\` também podem vir dois \`catch\`, um para \`NumberFormatException\` e outro para \`ArithmeticException\`. Já agora: um campo vazio dá o texto \`""\`, e isso também não é um número. +::: + +## 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. + +::: checkliste +- Consigo construir duas colunas com GridLayout(0, 2). → Duas colunas +- Consigo explicar porque é que "" + (a + b) precisa de parênteses. → A janela com o primeiro botão +- Consigo programar os quatro botões de cálculo. → Os outros três botões +- Consigo construir uma calculadora que não falha com 0 nem com “abc”. → Tarefa: calculadora +::: + +## Teste de conhecimentos + +::: quiz +? a é 3 e b é 4. Quanto dá "" + a + b? +→ A janela com o primeiro botão +- [ ] 7 +- [x] 34 +- [ ] Um erro +> O Java calcula da esquerda para a direita: primeiro surge o texto "3", depois junta-se o 4. + +? Quanto dá 7 / 2 com int? +→ Os outros três botões +- [ ] 3.5 +- [x] 3 +- [ ] 4 + +? Por que ordem preenche o GridLayout(0, 2) as células? +→ Duas colunas +- [x] Linha a linha, primeiro à esquerda e depois à direita +- [ ] Coluna a coluna, começando de cima para baixo na coluna da esquerda +- [ ] Ao acaso +::: +`,Sv=`--- +titel: Adivinha o número +bereich: Janelas com Swing +kurz: Um jogo com número aleatório, contagem de tentativas e um botão que se desliga no fim. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- criar com Math.random um número inteiro aleatório de 1 a 100 +- decidir que variáveis pertencem à classe +- desligar um botão com setEnabled +- construir um jogo de adivinhar com um botão “Novo jogo” +::: + +## O objetivo + +Agora um jogo: o computador pensa num número de 1 a 100. Tu adivinhas, e a janela diz-te “demasiado pequeno” ou “demasiado grande”. Quando o encontrares, diz-te quantas tentativas precisaste. + +As novidades desta vez são os **números aleatórios** e um botão que se **desliga** no fim. + +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## Um número aleatório + +\`Math.random()\` dá um número decimal aleatório de 0 até quase 1, por exemplo 0.4173. Em três passos transforma-se num número inteiro de 1 a 100: + +\`\`\`java +int secreto = (int) (Math.random() * 100) + 1; +\`\`\` + +| Passo | Exemplo | +|---|---| +| \`Math.random()\` | 0.4173 | +| \`* 100\` | 41.73 | +| \`(int)\` corta as casas decimais | 41 | +| \`+ 1\` | 42 | + +Sem o \`+ 1\` sairia de 0 a 99. + +Experimenta na área [Código](#zeige-codelive): \`int secreto = (int) (Math.random() * 100) + 1;\` e \`System.out.println(secreto);\`. Cada execução dá um número diferente. + +::: angeberwissen +Na verdade, os computadores não sabem lançar dados. O \`Math.random()\` calcula com uma fórmula uma longa sequência de números que só **parecem** aleatórios. Chamam-se números pseudoaleatórios. Para jogos chega perfeitamente. +::: + +## O que o jogo guarda + +O jogo tem de se lembrar de duas coisas ao longo de todos os cliques: o número secreto e o número de tentativas. Tal como no contador de cliques da lição 32, as duas ficam na classe: + +\`\`\`java +static int secreto = (int) (Math.random() * 100) + 1; +static int tentativas = 0; +\`\`\` + +## O programa completo + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class AdivinhaNumero { + static int secreto = (int) (Math.random() * 100) + 1; + static int tentativas = 0; + + public static void main(String[] args) { + JFrame janela = new JFrame("Adivinha o número"); + janela.setSize(320, 180); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new GridLayout(0, 1)); + + JLabel dica = new JLabel("Estou a pensar num número de 1 a 100."); + JTextField campo = new JTextField(); + JButton botao = new JButton("Adivinhar"); + + botao.addActionListener(e -> { + int palpite = Integer.parseInt(campo.getText()); + tentativas++; + if (palpite < secreto) { + dica.setText(palpite + " é demasiado pequeno."); + } else if (palpite > secreto) { + dica.setText(palpite + " é demasiado grande."); + } else { + dica.setText("Certo! Precisaste de " + tentativas + " tentativas."); + botao.setEnabled(false); + } + campo.setText(""); + }); + + janela.add(dica); + janela.add(campo); + janela.add(botao); + janela.setVisible(true); + } +} +\`\`\` + +- \`campo.setText("")\` esvazia o campo de texto depois de cada palpite, para escreveres logo o seguinte. +- \`botao.setEnabled(false)\` desliga o botão. Fica cinzento e já não se pode clicar. O jogo acabou. + +::: ludwig +Com \`setEnabled(true)\` voltas a ligar um botão. Assim podes, por exemplo, só ativar um botão depois de alguém ter escrito alguma coisa. +::: + +## Saber de profissional: ganhar com 7 tentativas + +::: angeberwissen +Quem adivinha com jeito nunca precisa de mais de 7 tentativas. Escolhe sempre o meio do intervalo que ainda resta: primeiro 50, depois 25 ou 75 e assim por diante. Cada palpite corta o intervalo a meio: 100, 50, 25, 13, 7, 4, 2, 1. É a **pesquisa binária** da lição 19. Como 2 elevado a 7 = 128 é maior do que 100, chegam 7 palpites. +::: + +## Tarefa: adivinha o número + +Reconstrói o jogo e melhora-o: + +- Uma entrada como “abc” não conta como tentativa e mostra a dica “Escreve um número”. +- Um segundo botão **Novo jogo** pensa num número novo, põe as tentativas a 0, volta a ligar o botão Adivinhar e repõe a dica. + +Extra: depois de 7 tentativas falhadas o jogo está perdido. A janela revela então o número secreto. + +::: ludwig +Para “não conta como tentativa”, o \`tentativas++\` tem de vir **depois** de \`Integer.parseInt\`, os dois dentro do bloco \`try\`. Se o \`parseInt\` lançar uma exceção, a linha com \`tentativas++\` é saltada. +::: + +## 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. + +::: checkliste +- Consigo criar com Math.random um número inteiro aleatório de 1 a 100. → Um número aleatório +- Consigo decidir que variáveis pertencem à classe. → O que o jogo guarda +- Consigo desligar um botão com setEnabled. → O programa completo +- Consigo construir um jogo de adivinhar com um botão “Novo jogo”. → Tarefa: adivinha o número +::: + +## Teste de conhecimentos + +::: quiz +? Que números dá (int) (Math.random() * 100) + 1? +→ Um número aleatório +- [ ] 0 a 100 +- [x] 1 a 100 +- [ ] 1 a 101 + +? O que faz botao.setEnabled(false)? +→ O programa completo +- [ ] Tira o botão da janela. +- [x] O botão fica cinzento e já não se pode clicar. +- [ ] Muda o texto do botão. + +? Com a pesquisa binária, quantas tentativas precisas no máximo para 1 a 100? +→ Tarefa: adivinha o número +- [ ] 50 +- [ ] 10 +- [x] 7 +> Cada palpite corta o intervalo a meio, e 2 elevado a 7 = 128 é maior do que 100. +::: +`,Tv=`--- +titel: Muitos botões, um ouvinte +bereich: Janelas com Swing +kurz: Um ouvinte para muitos botões e descobrir com getActionCommand e getSource qual foi o botão clicado. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- guardar um ouvinte numa variável do tipo ActionListener e registá-lo em vários botões +- explicar o que devolvem getActionCommand e getSource +- pôr botões num JPanel com um ciclo +- construir um cadeado que só abre com o código certo +::: + +## O objetivo + +Desde a história do bolo, o Ludwig quer trancar o seu estábulo. Ele constrói um **cadeado de código**: nove teclas com algarismos, um zero, **C** para apagar e **OK** para verificar. Só quem escrever 1234 recebe "Portão aberto!". + +São doze botões. Até agora, cada botão tinha o seu próprio ouvinte, como na calculadora da lição 35. Hoje aprendes como **um** ouvinte chega para todos os botões. + +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## Nove ouvintes quase iguais + +Com um ouvinte por tecla ficaria assim: + +\`\`\`java +um.addActionListener(e -> visor.setText(visor.getText() + "1")); +dois.addActionListener(e -> visor.setText(visor.getText() + "2")); +tres.addActionListener(e -> visor.setText(visor.getText() + "3")); +// ... e assim por diante até 9 +\`\`\` + +As linhas só se distinguem pelo algarismo. Quem quiser mudar um pormenor tem de o fazer nove vezes e de certeza que se esquece de uma linha. + +## Um ouvinte numa variável + +Um ouvinte também pode ficar numa **variável**. O seu tipo de dados é \`ActionListener\`, o contrato da lição 30. Depois registas o mesmo ouvinte em vários botões: + +\`\`\`java +ActionListener algarismo = e -> visor.setText(visor.getText() + e.getActionCommand()); + +um.addActionListener(algarismo); +dois.addActionListener(algarismo); +tres.addActionListener(algarismo); +\`\`\` + +\`ActionListener\` está no pacote \`java.awt.event\`. Por isso precisas de \`import java.awt.event.*;\` lá em cima. + +Agora o código só existe uma vez. Mas como sabe o ouvinte que algarismo deve acrescentar? + +## Quem clicou? + +O \`e\` antes da seta é o **evento**, um objeto do tipo \`ActionEvent\`. O botão entrega-o a cada clique, e lá dentro está o que aconteceu: + +| Chamada | Devolve | Exemplo | +|---|---|---| +| \`e.getActionCommand()\` | a legenda do botão clicado, como texto | \`"7"\` | +| \`e.getSource()\` | o próprio botão clicado | o botão \`ok\` | + +- \`getActionCommand()\` dá jeito quando a legenda já diz o que fazer, como nos algarismos. +- \`getSource()\` compara-se com um botão usando \`==\`: \`if (e.getSource() == ok)\`. Aqui \`==\` está certo, porque se trata exatamente deste objeto, não de um texto. + +::: ludwig +Textos comparas com \`equals\`, botões com \`==\`. Se quiseres decidir pela legenda, escreves \`e.getActionCommand().equals("OK")\`. Também funciona, mas deixa de funcionar assim que alguém mudar a legenda para "Abrir". \`e.getSource() == ok\` continua certo. +::: + +## Botões num ciclo + +Com um ouvinte partilhado, podes até criar as teclas dos algarismos num ciclo. Para ficarem bem arrumadas numa grelha, vão para um **JPanel**. Um JPanel é uma área na janela com o seu próprio layout: + +\`\`\`java +JPanel teclas = new JPanel(new GridLayout(0, 3)); +for (int i = 1; i <= 9; i++) { + JButton algarismo = new JButton("" + i); + algarismo.addActionListener(tecla); + teclas.add(algarismo); +} +\`\`\` + +- \`"" + i\` transforma o número \`i\` no texto da legenda. +- Em cada volta nasce um botão novo. Todos recebem o mesmo ouvinte \`tecla\`. +- \`janela.add(teclas, BorderLayout.CENTER)\` põe a área inteira, com todas as teclas, na janela. + +## O programa completo + +\`\`\`java +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class Cadeado { + public static void main(String[] args) { + JFrame janela = new JFrame("Cadeado de código"); + janela.setSize(240, 300); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new BorderLayout()); + + JLabel visor = new JLabel("", SwingConstants.CENTER); + JPanel teclas = new JPanel(new GridLayout(0, 3)); + JButton apagar = new JButton("C"); + JButton ok = new JButton("OK"); + + ActionListener tecla = e -> { + if (e.getSource() == apagar) { + visor.setText(""); + } else if (e.getSource() == ok) { + if (visor.getText().equals("1234")) { + visor.setText("Portão aberto!"); + } else { + visor.setText("Errado"); + } + } else { + visor.setText(visor.getText() + e.getActionCommand()); + } + }; + + for (int i = 1; i <= 9; i++) { + JButton algarismo = new JButton("" + i); + algarismo.addActionListener(tecla); + teclas.add(algarismo); + } + JButton zero = new JButton("0"); + zero.addActionListener(tecla); + apagar.addActionListener(tecla); + ok.addActionListener(tecla); + teclas.add(apagar); + teclas.add(zero); + teclas.add(ok); + + janela.add(visor, BorderLayout.NORTH); + janela.add(teclas, BorderLayout.CENTER); + janela.setVisible(true); + } +} +\`\`\` + +- \`apagar\` e \`ok\` são criados **antes** do ouvinte, porque o ouvinte compara com eles. +- O ouvinte verifica primeiro os dois botões especiais. Todos os outros são algarismos e acrescentam a sua legenda. + +::: angeberwissen +O teclado do telefone tem o 1 em cima à esquerda, o da calculadora e do teclado do computador tem o 7 em cima à esquerda. Porquê? Quando chegaram os telefones de teclas, fizeram-se testes com pessoas que tinham de marcar números com eles. Com o 1 em cima eram mais rápidas, e as máquinas de calcular já tinham a sua disposição há muito tempo. O cadeado do Ludwig faz como o telefone. +::: + +## Jogo: Quem clicou? + +::: spiel zuhoerer +titel: Jogo: Quem clicou? +intro: Em cada ronda, **um** ouvinte está registado em vários botões. O Ludwig mostra-te o código, a janela e os cliques. O que fica no visor no fim? Depois o Ludwig reproduz os cliques. +frage: O que fica no visor depois dos cliques? + +runde: + JFrame janela = new JFrame("Letras"); + JLabel visor = new JLabel(""); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + ActionListener z = e -> visor.setText(visor.getText() + e.getActionCommand()); + a.addActionListener(z); + b.addActionListener(z); +klicks: A, B, A +- A +- AB +- [x] ABA +> Um ouvinte, dois botões. \`e.getActionCommand()\` devolve de cada vez a legenda do botão clicado, e ela é acrescentada no fim. + +runde: + JFrame janela = new JFrame("Contador"); + static int numero = 0; + JLabel visor = new JLabel("0"); + JButton mais = new JButton("+"); + JButton menos = new JButton("-"); + ActionListener z = e -> { + if (e.getSource() == mais) { + numero++; + } else { + numero--; + } + visor.setText("" + numero); + }; + mais.addActionListener(z); + menos.addActionListener(z); +klicks: +, +, - +- 3 +- [x] 1 +- -1 +> \`e.getSource()\` diz qual foi o botão. Duas vezes mais, uma vez menos: 0 + 1 + 1 - 1 = 1. + +runde: + JFrame janela = new JFrame("Letras"); + JLabel visor = new JLabel(""); + JButton a = new JButton("A"); + JButton b = new JButton("B"); + JButton c = new JButton("C"); + ActionListener z = e -> visor.setText(visor.getText() + e.getActionCommand()); + a.addActionListener(z); + b.addActionListener(z); +klicks: A, C, B +- ACB +- [x] AB +- A +> O ouvinte só está registado em A e B. Quando se clica em C, ninguém está a ouvir. + +runde: + JFrame janela = new JFrame("Teclas"); + JLabel visor = new JLabel(""); + JButton um = new JButton("1"); + JButton dois = new JButton("2"); + JButton apagar = new JButton("C"); + ActionListener z = e -> { + if (e.getActionCommand().equals("C")) { + visor.setText(""); + } else { + visor.setText(visor.getText() + e.getActionCommand()); + } + }; + um.addActionListener(z); + dois.addActionListener(z); + apagar.addActionListener(z); +klicks: 1, 2, C, 1 +- 121 +- 12 +- [x] 1 +> Depois de 1 e 2 o visor mostra "12". C apaga tudo, e o último 1 fica sozinho. + +runde: + JFrame janela = new JFrame("Cadeado"); + JLabel visor = new JLabel(""); + JButton quatro = new JButton("4"); + JButton dois = new JButton("2"); + JButton ok = new JButton("OK"); + ActionListener z = e -> { + if (e.getSource() == ok) { + if (visor.getText().equals("42")) { + visor.setText("Portão aberto!"); + } else { + visor.setText("Errado"); + } + } else { + visor.setText(visor.getText() + e.getActionCommand()); + } + }; + quatro.addActionListener(z); + dois.addActionListener(z); + ok.addActionListener(z); +klicks: 2, 4, OK +- Portão aberto! +- [x] Errado +- 24OK +> Foi escrito "24", mas o segredo é "42". A ordem dos cliques conta. +::: + +## Tarefa: Cadeado de código + +Constrói o cadeado de código e experimenta-o. + +Depois melhora-o: + +- Depois de três tentativas erradas, o **OK** desliga-se, como o botão do Adivinha o número na lição 36. Conta as tentativas numa variável \`static int\` na classe. +- Extra: o visor mostra \`*\` em vez dos algarismos. Guarda a entrada verdadeira numa \`static String entrada = "";\` e acrescenta ao visor só uma estrela. + +::: ludwig +Também na calculadora da lição 35 chega um ouvinte para +, -, \\* e /. Verifica lá dentro com \`e.getActionCommand().equals("+")\` que sinal de operação foi clicado. +::: + +## 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. + +::: checkliste +- Consigo guardar um ouvinte numa variável do tipo ActionListener e registá-lo em vários botões. → Um ouvinte numa variável +- Consigo explicar o que devolvem getActionCommand e getSource. → Quem clicou? +- Consigo pôr botões num JPanel com um ciclo. → Botões num ciclo +- Consigo construir um cadeado que só abre com o código certo. → Tarefa: Cadeado de código +::: + +## Teste de conhecimentos + +::: quiz +? O que devolve e.getActionCommand() num clique no botão new JButton("7")? +→ Quem clicou? +- [ ] o número 7 +- [x] o texto "7" +- [ ] o próprio botão + +? Como verificas se foi clicado o botão ok? +→ Quem clicou? +- [x] e.getSource() == ok +- [ ] e.getSource().equals("ok") +- [ ] ok.getActionCommand() +> getSource devolve o próprio botão, e esse comparas com ==. + +? Porque é que um ouvinte fica numa variável? +→ Um ouvinte numa variável +- [ ] Para correr mais depressa. +- [x] Para o poder registar em vários botões e escrever o código só uma vez. +- [ ] Porque senão os lambdas não são permitidos. + +? Liga. +→ Quem clicou? += ActionListener -> tipo de dados de um ouvinte += ActionEvent -> o evento e com a informação sobre o clique += JPanel -> uma área com o seu próprio layout +::: +`,_v=`--- +titel: Classes internas +bereich: Janelas com Swing +kurz: Escrever um ouvinte como classe interna com nome, como classe anónima e como lambda, e saber quem vê o quê. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- escrever um ouvinte como classe interna com nome +- escrever um ouvinte como classe anónima +- explicar o que fica de fora no lambda +- explicar que maneira de escrever vê que variáveis +- construir um contador com três botões escritos de três maneiras +::: + +## O objetivo + +O contador de cliques da lição 32 já conheces. Hoje escreves o seu ouvinte de **três maneiras**, que fazem todas exatamente o mesmo: + +1. como **classe interna com nome**, como se fazia quase sempre antes do Java 8, +2. como **classe anónima**, que conheces do saber de profissional da lição 30, +3. como **lambda** com a seta, como até agora. + +Em código de outras pessoas, em livros e na internet vais encontrar as três. Depois desta lição vais reconhecê-las. + +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## Lembrete: o contrato + +Um ouvinte é tudo o que cumpre o contrato \`ActionListener\`. Nele está exatamente um método: + +\`\`\` +public void actionPerformed(ActionEvent e) +\`\`\` + +O botão chama-o a cada clique. As três maneiras de escrever são três caminhos para fornecer este único método. + +## 1. A classe interna com nome + +Uma **classe interna** fica dentro de outra classe. Tem um nome, aqui \`Mais\`, e cumpre o contrato com \`implements ActionListener\`: + +\`\`\`java +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class Contador { + static int contagem = 0; + static JLabel numero = new JLabel("0", SwingConstants.CENTER); + + static class Mais implements ActionListener { + public void actionPerformed(ActionEvent e) { + contagem++; + numero.setText("" + contagem); + } + } + + public static void main(String[] args) { + JFrame janela = new JFrame("Contador de cliques"); + janela.setSize(250, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new GridLayout(0, 1)); + + JButton mais = new JButton("+1"); + JButton outro = new JButton("Também +1"); + mais.addActionListener(new Mais()); + outro.addActionListener(new Mais()); + + janela.add(numero); + janela.add(mais); + janela.add(outro); + janela.setVisible(true); + } +} +\`\`\` + +- \`new Mais()\` cria um objeto da classe \`Mais\`. É esse o ouvinte que o botão recebe. +- Como a classe tem nome, podes usá-la em vários botões, aqui em \`mais\` e \`outro\`. +- A classe está **fora** de \`main\`. Por isso só vê o que está na classe \`Contador\`: \`contagem\` e \`numero\`. É por isso que \`numero\` desta vez é uma variável da classe e não de \`main\`. +- Precisas de \`static class\` porque \`main\` é static. Sem \`static\`, o javac indica "non-static variable this cannot be referenced from a static context". + +## 2. A classe anónima + +Se só precisas do ouvinte num sítio, podes escrever a classe mesmo onde o objeto é preciso. Assim ela não recebe nome: + +\`\`\`java +mais.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + contagem++; + numero.setText("" + contagem); + } +}); +\`\`\` + +- \`new ActionListener() { … }\` quer dizer: "um objeto novo que cumpre o contrato ActionListener, e é assim: …". +- No fim está \`});\`: a chaveta fecha a classe, o parêntese fecha a chamada de \`addActionListener\`. +- A classe anónima está **dentro** de \`main\`. Por isso também vê as variáveis de \`main\`, desde que já não mudem. + +## 3. O lambda + +O lambda é a forma curta da classe anónima, desde o Java 8: + +\`\`\`java +mais.addActionListener(e -> { + contagem++; + numero.setText("" + contagem); +}); +\`\`\` + +Fica de fora tudo o que o Java já sabe: \`new ActionListener()\`, o nome \`actionPerformed\`, \`public void\` e o tipo \`ActionEvent\`. Sobram o parâmetro \`e\`, a seta e o corpo. Isto só funciona porque o contrato tem exatamente **um** método. + +## As três comparadas + +| | classe interna com nome | classe anónima | lambda | +|---|---|---|---| +| tem nome | sim, p. ex. \`Mais\` | não | não | +| fica | na classe, fora de \`main\` | mesmo junto ao botão | mesmo junto ao botão | +| para vários botões | sim, \`new Mais()\` | não | sim, numa variável (lição 37) | +| vê variáveis de \`main\` | não | sim, se não mudarem | sim, se não mudarem | +| comprimento | a mais longa | média | a mais curta | + +::: ludwig +Se uma variável de \`main\` tiver de mudar no ouvinte, como \`contagem++\`, tem de ir para a classe, seja qual for a maneira de escrever. Esse era o problema da lição 32. +::: + +::: angeberwissen +Depois de compilar, espreita a pasta com os ficheiros \`.class\`. O javac cria um ficheiro para cada classe: \`Contador.class\`, \`Contador$Mais.class\` para a classe interna e \`Contador$1.class\` para a classe anónima. Como não tem nome, recebe um número. Um lambda não tem ficheiro próprio, o Java só o constrói quando o programa arranca. +::: + +## Jogo: Que maneira de escrever? + +::: spiel frage +titel: Jogo: Que maneira de escrever? +intro: O Ludwig mostra-te ouvintes de programas de outras pessoas. Que maneira de escrever é esta? Seis rondas. +frage: Que maneira de escrever é esta? +antworten: classe interna com nome | classe anónima | lambda + +runde: + botao.addActionListener(e -> texto.setText("Olá")); +richtig: lambda +> A seta \`->\` denuncia o lambda. + +runde: + botao.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + texto.setText("Olá"); + } + }); +richtig: classe anónima +> \`new ActionListener() {\` e a seguir um método inteiro: aqui está a ser escrita uma classe sem nome. + +runde: + static class Saudacao implements ActionListener { + public void actionPerformed(ActionEvent e) { + texto.setText("Olá"); + } + } +richtig: classe interna com nome +> A classe chama-se \`Saudacao\` e cumpre o contrato com \`implements ActionListener\`. + +runde: + botao.addActionListener(new Saudacao()); +richtig: classe interna com nome +> \`new Saudacao()\` cria um objeto da classe \`Saudacao\`. A própria classe está noutro sítio e tem nome. + +runde: + ActionListener tecla = e -> { + visor.setText(visor.getText() + e.getActionCommand()); + }; +richtig: lambda +> Um lambda numa variável, como no cadeado da lição 37. A seta denuncia-o. + +runde: + ActionListener tecla = new ActionListener() { + public void actionPerformed(ActionEvent e) { + visor.setText(visor.getText() + e.getActionCommand()); + } + }; +richtig: classe anónima +> Uma classe anónima também pode ficar numa variável. Assim pode ser registada em vários botões, tal como o lambda. +::: + +## Tarefa: Um contador, três maneiras + +Constrói o contador de cliques com três botões: + +- **+1** recebe a classe interna com nome \`Mais\`. +- **-1** recebe uma classe anónima. +- **Reset** recebe um lambda. + +Experimenta se os três botões contam como esperado. Depois tira o \`static\` da classe \`Mais\` e lê a mensagem de erro do javac. + +## 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. + +::: checkliste +- Consigo escrever um ouvinte como classe interna com nome. → 1. A classe interna com nome +- Consigo escrever um ouvinte como classe anónima. → 2. A classe anónima +- Consigo explicar o que fica de fora no lambda. → 3. O lambda +- Consigo explicar que maneira de escrever vê que variáveis. → As três comparadas +- Consigo construir um contador com três botões escritos de três maneiras. → Tarefa: Um contador, três maneiras +::: + +## Teste de conhecimentos + +::: quiz +? Porque é que a forma curta com a seta funciona com ActionListener? +→ 3. O lambda +- [ ] Porque ActionListener é uma classe. +- [x] Porque o contrato tem exatamente um método. +- [ ] Porque o botão o exige. + +? Que maneira de escrever podes usar com new Mais() em vários botões sem a guardar numa variável? +→ 1. A classe interna com nome +- [x] a classe interna com nome +- [ ] a classe anónima +- [ ] o lambda + +? Porque é que está static antes de class Mais? +→ 1. A classe interna com nome +- [ ] Para a classe ser mais rápida. +- [x] Porque main é static e senão não consegue criar um objeto de Mais. +- [ ] Porque todas as classes têm de ser static. + +? Liga. +→ As três comparadas += class Mais implements ActionListener -> classe interna com nome += new ActionListener() { … } -> classe anónima += a seta depois de e -> lambda +::: +`,Av=`--- +titel: Dois separadores +bereich: Janelas com Swing +kurz: Construir uma janela com dois separadores, levar dados de um separador para o outro e guardar a lista num ficheiro de texto. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- construir uma janela com dois separadores +- acrescentar linhas a uma JTextArea com append +- explicar porque é que um ouvinte pode usar peças dos dois separadores +- guardar um ficheiro dentro de um ouvinte com try e catch +- construir uma lista de compras que conta quantas coisas tem +::: + +## O objetivo + +A lista de compras do Ludwig da lição 23 ganha uma janela. Tem dois **separadores**, como os do browser: + +- No separador **Entrada** escreves o que precisas e clicas em **Adicionar**. +- No separador **Lista** está tudo o que escreveste. Um botão **Guardar** escreve a lista num ficheiro de texto. + +Novos são os separadores (\`JTabbedPane\`), uma área de texto com várias linhas (\`JTextArea\`) e guardar a partir de um ouvinte. + +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## Separadores com JTabbedPane + +Cada separador mostra a sua própria área. As áreas são JPanels, como o teclado do cadeado na lição 37: + +\`\`\`java +JTabbedPane separadores = new JTabbedPane(); +JPanel entrada = new JPanel(new GridLayout(0, 1)); +JPanel lista = new JPanel(new BorderLayout()); + +separadores.addTab("Entrada", entrada); +separadores.addTab("Lista", lista); +janela.add(separadores); +\`\`\` + +| Chamada | Significado | +|---|---| +| \`addTab("Entrada", entrada)\` | um separador novo com a legenda "Entrada", mostra o JPanel \`entrada\` | +| \`setSelectedIndex(1)\` | muda para o segundo separador, conta-se a partir de 0 | +| \`setTitleAt(1, "Lista (3)")\` | muda a legenda do segundo separador | + +No início está aberto o separador que foi adicionado primeiro. + +## Uma área de texto com várias linhas + +Um \`JTextField\` só tem uma linha. Para a lista precisas de uma \`JTextArea\`: + +\`\`\`java +JTextArea area = new JTextArea(); +area.setEditable(false); +area.append("Feno\\n"); +\`\`\` + +- \`append\` acrescenta texto no fim. O \`"\\n"\` começa depois uma nova linha, como ao dividir com \`split("\\n")\` na lição 24. +- \`setEditable(false)\` impede que se escreva diretamente na lista. +- \`getText()\` devolve o texto inteiro com todas as linhas. + +## De um separador para o outro + +O botão **Adicionar** está no separador Entrada, a área de texto no separador Lista. Mesmo assim, o ouvinte pode usar os dois. Todas as peças são variáveis em \`main\`, e o lambda vê-as todas, seja qual for o separador em que aparecem depois: + +\`\`\`java +adicionar.addActionListener(e -> { + area.append(campo.getText() + "\\n"); + info.setText(campo.getText() + " está na lista."); + campo.setText(""); +}); +\`\`\` + +::: ludwig +Uma peça só pode estar numa **única** área. Se juntares o mesmo botão primeiro a \`entrada\` e depois a \`lista\`, o Swing tira-o de \`entrada\`. Só aparece no separador Lista. +::: + +## Guardar dentro do ouvinte + +Para guardar usas o \`PrintWriter\` da lição 23. Dentro do ouvinte há um senão: a saída com \`throws Exception\` da lição 23 aqui não existe. O lambda é um método próprio, \`actionPerformed\`, e segundo o contrato não pode passar adiante uma \`FileNotFoundException\`. Por isso, guardar fica dentro de try e catch: + +\`\`\`java +guardar.addActionListener(e -> { + try { + PrintWriter saida = new PrintWriter("listacompras.txt"); + saida.print(area.getText()); + saida.close(); + info.setText("Guardado em listacompras.txt"); + separadores.setSelectedIndex(0); + } catch (FileNotFoundException ex) { + info.setText("Não foi possível guardar."); + } +}); +\`\`\` + +- A exceção chama-se aqui \`ex\`, porque o nome \`e\` já está ocupado pelo evento. +- Depois de guardar, a janela volta com \`setSelectedIndex(0)\` ao separador Entrada, onde está a mensagem. +- O VisuStruct mostra o ficheiro guardado por baixo da consola, assim que clicares em Guardar. + +## O programa completo + +\`\`\`java +import javax.swing.*; +import java.awt.*; +import java.io.*; + +public class ListaCompras { + public static void main(String[] args) { + JFrame janela = new JFrame("Lista de compras"); + janela.setSize(300, 250); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JTabbedPane separadores = new JTabbedPane(); + + JPanel entrada = new JPanel(new GridLayout(0, 1)); + JTextField campo = new JTextField(); + JButton adicionar = new JButton("Adicionar"); + JLabel info = new JLabel("Ainda não há nada na lista."); + entrada.add(new JLabel("Do que precisas?")); + entrada.add(campo); + entrada.add(adicionar); + entrada.add(info); + + JPanel lista = new JPanel(new BorderLayout()); + JTextArea area = new JTextArea(); + area.setEditable(false); + JButton guardar = new JButton("Guardar"); + lista.add(area, BorderLayout.CENTER); + lista.add(guardar, BorderLayout.SOUTH); + + separadores.addTab("Entrada", entrada); + separadores.addTab("Lista", lista); + + adicionar.addActionListener(e -> { + area.append(campo.getText() + "\\n"); + info.setText(campo.getText() + " está na lista."); + campo.setText(""); + }); + + guardar.addActionListener(e -> { + try { + PrintWriter saida = new PrintWriter("listacompras.txt"); + saida.print(area.getText()); + saida.close(); + info.setText("Guardado em listacompras.txt"); + separadores.setSelectedIndex(0); + } catch (FileNotFoundException ex) { + info.setText("Não foi possível guardar."); + } + }); + + janela.add(separadores); + janela.setVisible(true); + } +} +\`\`\` + +Escreve Feno, clica em Adicionar, depois Maçãs e outra vez Adicionar. Muda para o separador Lista e clica em Guardar. + +## Jogo: Onde vai parar? + +::: spiel frage +titel: Jogo: Onde vai parar? +intro: O Ludwig constrói janelas com separadores. Lê o código e prevê o que vês. Seis rondas. + +runde: + separadores.addTab("Entrada", entrada); + separadores.addTab("Lista", lista); +frage: Que separador está aberto no início? +- [x] Entrada +- Lista +- nenhum +> No início está aberto o separador que foi adicionado primeiro. + +runde: + separadores.addTab("Lista", lista); + separadores.addTab("Entrada", entrada); +frage: Que separador está aberto no início? +- Entrada +- [x] Lista +- os dois +> Desta vez a Lista vem primeiro. A ordem dos \`addTab\` decide a ordem dos separadores. + +runde: + separadores.addTab("Entrada", entrada); + separadores.addTab("Lista", lista); + separadores.addTab("Ajuda", ajuda); + separadores.setSelectedIndex(1); +frage: Que separador está aberto? +- Entrada +- [x] Lista +- Ajuda +> Conta-se a partir de 0: 0 é Entrada, 1 é Lista, 2 é Ajuda. + +runde: + adicionar.addActionListener(e -> { + area.append(campo.getText() + "\\n"); + campo.setText(""); + }); + // Escreves Feno, clicas em Adicionar, escreves Maçãs, clicas em Adicionar. +frage: O que está depois no separador Lista? +- Maçãs +- FenoMaçãs +- [x] Feno\\nMaçãs +> \`append\` acrescenta no fim, e cada \`"\\n"\` começa uma nova linha. + +runde: + JButton botao = new JButton("OK"); + entrada.add(botao); + lista.add(botao); +frage: Onde aparece o botão OK? +- nos dois separadores +- só no separador Entrada +- [x] só no separador Lista +> Uma peça só pode estar numa área. No segundo \`add\`, o Swing tira-a de \`entrada\`. + +runde: + guardar.addActionListener(e -> { + area.setText(""); + separadores.setTitleAt(1, "Lista (vazia)"); + separadores.setSelectedIndex(0); + }); + // O botão guardar está no separador Lista. +frage: O que vês depois do clique? +- o separador Lista vazio +- [x] o separador Entrada, e o segundo separador chama-se "Lista (vazia)" +- o separador Entrada, e o segundo separador continua a chamar-se "Lista" +> O ouvinte esvazia a área, muda o nome do separador e muda para o separador 0. Tudo acontece com um clique. +::: + +## Tarefa: Lista de compras com separadores + +Constrói o programa e experimenta-o. + +Depois melhora-o: + +- Entradas vazias não vão para a lista. Verifica antes \`campo.getText().isEmpty()\` (lição 17). +- O separador Lista mostra no título quantas coisas estão na lista: "Lista (3)". Conta numa variável \`static int\` e usa \`setTitleAt\`. +- Extra: um terceiro separador **Ajuda** com um JLabel que explica como funciona o programa. + +## 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. + +::: checkliste +- Consigo construir uma janela com dois separadores. → Separadores com JTabbedPane +- Consigo acrescentar linhas a uma JTextArea com append. → Uma área de texto com várias linhas +- Consigo explicar porque é que um ouvinte pode usar peças dos dois separadores. → De um separador para o outro +- Consigo guardar um ficheiro dentro de um ouvinte com try e catch. → Guardar dentro do ouvinte +- Consigo construir uma lista de compras que conta quantas coisas tem. → Tarefa: Lista de compras com separadores +::: + +## Teste de conhecimentos + +::: quiz +? Que separador está aberto depois de separadores.setSelectedIndex(0)? +→ Separadores com JTabbedPane +- [x] o primeiro +- [ ] o segundo +- [ ] nenhum + +? Porque é que guardar dentro do ouvinte fica em try e catch? +→ Guardar dentro do ouvinte +- [ ] Porque o PrintWriter só funciona dentro de try. +- [x] Porque actionPerformed não pode passar adiante uma FileNotFoundException. +- [ ] Porque o main não tem throws. + +? Qual é a diferença entre JTextField e JTextArea? +→ Uma área de texto com várias linhas +- [ ] Não há nenhuma. +- [x] A JTextArea pode mostrar várias linhas. +- [ ] Num JTextField não se pode escrever. + +? Liga. +→ Separadores com JTabbedPane += JTabbedPane -> uma área com separadores += JPanel -> a área de um separador += JTextArea -> uma área de texto com várias linhas +::: +`,Ov=`--- +titel: Model View Controller +bereich: Janelas com Swing +kurz: Dividir o contador de cliques em model, view e controller e perceber quem fala com quem. +--- + +## Competências que vou adquirir agora + +::: kompetenzen +- dizer o que fazem o model, a view e o controller +- escrever um model sem Swing e testá-lo sem janela +- explicar o que constrói new Contador() e porque é que ali não há static +- nomear as quatro mensagens depois de um clique +- acrescentar uma segunda view sem mudar o model +- construir um contador com −1, Reset e limites no model +::: + +## O objetivo + +Os programas grandes com janelas têm quase sempre a mesma estrutura. Chama-se **Model View Controller**, ou **MVC**, em português modelo, vista e controlador: + +- O **model** guarda os dados e conhece as suas regras. +- A **view** só mostra os dados. +- O **controller** reage aos cliques e dá o recado. + +Aprendes MVC com o contador de cliques da lição 32. Ele é dividido em três partes, passo a passo. No fim mostra a mesma contagem duas vezes: como número e como barra. + +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). + +## Tudo numa classe + +Até agora o contador de cliques era assim, tudo está em \`main\` e numa variável da classe: + +\`\`\`java +static int contagem = 0; + +public static void main(String[] args) { + // ... construir a janela ... + JLabel numero = new JLabel("0", SwingConstants.CENTER); + JButton mais = new JButton("+1"); + mais.addActionListener(e -> { + contagem++; + numero.setText("" + contagem); + }); +} +\`\`\` + +Funciona. Mas imagina que a contagem também deve aparecer como barra, mais tarde numa segunda janela e num ficheiro. Então cada ouvinte tem de se lembrar de todos os visores. Contar e mostrar ficam atados num nó, e com cada visor o nó fica maior. + +O MVC desata o nó: cada tarefa recebe a sua própria classe. + +## O model + +O model é o próprio contador, sem nada de Swing: + +\`\`\`java +class Contador { + int valor = 0; + + void aumentar() { + valor++; + } + + int getValor() { + return valor; + } +} +\`\`\` + +- Desta vez não há \`static\` antes de \`valor\` e dos métodos. Assim pertencem a um **objeto**: \`new Contador()\` constrói um contador com o seu próprio \`valor\`, tal como \`new JButton("+1")\` constrói um botão com a sua própria legenda. +- \`model.aumentar()\` chama o método deste contador, tal como \`botao.setText(…)\`. +- Quem quer saber o valor pergunta com \`getValor()\`. Mudá-lo só é possível através de \`aumentar()\`. + +Como o model não precisa de janela, podes experimentá-lo sem janela nenhuma: + +\`\`\`java +public class ContadorTeste { + public static void main(String[] args) { + Contador model = new Contador(); + model.aumentar(); + model.aumentar(); + System.out.println(model.getValor()); + } +} + +class Contador { + int valor = 0; + + void aumentar() { + valor++; + } + + int getValor() { + return valor; + } +} +\`\`\` + +A saída é 2. Num ficheiro podem estar várias classes. Só uma delas é \`public\`, e essa tem o \`main\`. + +## A view + +A view mostra o valor e mais nada. Não faz contas e não sabe de onde vem o número: + +\`\`\`java +class VistaNumero { + JLabel numero = new JLabel("0", SwingConstants.CENTER); + + void atualizar(int valor) { + numero.setText("" + valor); + } +} +\`\`\` + +- A view recebe o valor com \`atualizar(int valor)\` e escreve-o no seu JLabel. +- A janela e o botão constróis em \`main\`, como sempre. Com \`janela.add(view.numero)\` o JLabel da view entra na janela. + +## O controller + +O controller é o ouvinte do botão. Liga o model à view: + +\`\`\`java +Contador model = new Contador(); +VistaNumero view = new VistaNumero(); + +mais.addActionListener(e -> { + model.aumentar(); + view.atualizar(model.getValor()); +}); +\`\`\` + +- Primeiro muda o model, depois vai buscar o novo valor e entrega-o à view. +- O problema da lição 32 desapareceu: a variável \`model\` nunca muda, aponta sempre para o mesmo contador. Só o \`valor\` lá dentro muda. Por isso o lambda pode usar \`model\`, sem nenhum \`static\`. + +## Quem fala com quem? + +A cada clique correm quatro mensagens, sempre pela mesma ordem: + +::: grafik mvc-klick.svg +As setas acendem-se uma após a outra. O model conta na segunda seta, o visor só na quarta. +::: + +1. O botão comunica o clique ao controller (\`actionPerformed\`). +2. O controller diz ao model: \`aumentar()\`. +3. O controller pergunta ao model o novo valor: \`getValor()\`. +4. O controller entrega o valor à view: \`atualizar(valor)\`. + +O model não fala com ninguém. Espera até lhe perguntarem. + +::: ludwig +Lembra-te: o model não sabe nada de janelas. Em \`Contador\` não há nenhum \`JLabel\` nem nenhum \`import javax.swing\`. Se precisares de Swing ali, o código pertence à view. +::: + +## A vantagem: uma segunda view + +Agora a contagem também deve aparecer como barra. Para isso junta-se uma segunda view. Uma \`JProgressBar\` é uma barra que se enche, aqui de 0 a 10: + +\`\`\`java +class VistaBarra { + JProgressBar barra = new JProgressBar(0, 10); + + void atualizar(int valor) { + barra.setValue(valor); + } +} +\`\`\` + +O controller ganha mais uma linha. O model fica exatamente como estava: + +\`\`\`java +mais.addActionListener(e -> { + model.aumentar(); + view.atualizar(model.getValor()); + barra.atualizar(model.getValor()); +}); +\`\`\` + +É exatamente esta a vantagem do MVC: podes acrescentar ou trocar visores sem mexer no model. + +## O programa completo + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +class Contador { + int valor = 0; + + void aumentar() { + valor++; + } + + int getValor() { + return valor; + } +} + +class VistaNumero { + JLabel numero = new JLabel("0", SwingConstants.CENTER); + + void atualizar(int valor) { + numero.setText("" + valor); + } +} + +class VistaBarra { + JProgressBar barra = new JProgressBar(0, 10); + + void atualizar(int valor) { + barra.setValue(valor); + } +} + +public class ContadorCliques { + public static void main(String[] args) { + Contador model = new Contador(); + VistaNumero view = new VistaNumero(); + VistaBarra barra = new VistaBarra(); + + JFrame janela = new JFrame("Contador de cliques"); + janela.setSize(250, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new GridLayout(0, 1)); + + JButton mais = new JButton("+1"); + mais.addActionListener(e -> { + model.aumentar(); + view.atualizar(model.getValor()); + barra.atualizar(model.getValor()); + }); + + janela.add(view.numero); + janela.add(barra.barra); + janela.add(mais); + janela.setVisible(true); + } +} +\`\`\` + +Clica algumas vezes em +1 e vê o número e a barra a crescer juntos. + +::: angeberwissen +O MVC foi inventado em 1979 pelo norueguês Trygve Reenskaug, no centro de investigação Xerox PARC, na Califórnia. Já nessa altura havia lá computadores com janelas e rato. No mesmo ano, Steve Jobs visitou o laboratório e ficou tão entusiasmado que a Apple passou a construir computadores com janelas e rato. +::: + +## Jogo: Onde pertence o código? + +::: spiel frage +titel: Jogo: Onde pertence o código? +intro: O Ludwig atirou código de um programa MVC para um monte. Arruma cada peça. Oito rondas. +frage: Onde pertence este código? +antworten: Model | View | Controller + +runde: + int valor = 0; +richtig: Model +> A contagem são os dados. Os dados moram no model. + +runde: + numero.setText("" + valor); +richtig: View +> Mostrar algo no ecrã é a tarefa da view. + +runde: + mais.addActionListener(e -> model.aumentar()); +richtig: Controller +> Reagir a um clique e avisar o model: é isso que o controller faz. + +runde: + void aumentar() { + valor++; + } +richtig: Model +> O próprio model sabe como mudar os seus dados. + +runde: + barra.setValue(valor); +richtig: View +> Uma barra que se enche só mostra. Portanto: view. + +runde: + void aumentar() { + if (valor < 10) { + valor++; + } + } +richtig: Model +> "No máximo 10" é uma regra para os dados. As regras pertencem ao model, assim valem para todos os botões e todas as views. + +runde: + view.atualizar(model.getValor()); +richtig: Controller +> Ir buscar o valor ao model e entregá-lo à view: é o controller no meio. + +runde: + JLabel numero = new JLabel("0", SwingConstants.CENTER); +richtig: View +> Um JLabel é uma peça do ecrã. No model não há Swing. +::: + +## Jogo: Quem é o próximo? + +::: spiel reihenfolge +titel: Jogo: Quem é o próximo? +intro: Depois de um clique, o model, a view e o controller falam uns com os outros, mas só funciona por uma ordem. Põe os passos pela ordem certa. Cinco rondas. + +runde: +frage: Clicas em +1 no contador de cliques. O que acontece, um passo após o outro? +- Clicas em +1. +- O controller recebe \`actionPerformed\`. +- O controller chama \`model.aumentar()\`. +- O model aumenta o \`valor\`. +- O controller vai buscar \`model.getValor()\`. +- A view mostra o novo número. +> Clique, controller, mudar o model, ir buscar o valor, mostrar. São as quatro setas da imagem, com a contagem no meio. + +runde: + mais.addActionListener(e -> { + model.aumentar(); + view.atualizar(model.getValor()); + barra.atualizar(model.getValor()); + }); +frage: O que acontece depois de um clique em +1, um passo após o outro? +- O clique em +1 +- \`model.aumentar()\` +- O número mostra o novo valor. +- A barra cresce. +> O ouvinte trata as suas linhas de cima para baixo: primeiro o model, depois o número, depois a barra. + +runde: +frage: Põe o controller pela ordem certa, para que a view mostre o novo número. +- \`mais.addActionListener(e -> {\` +- \`model.aumentar();\` +- \`view.atualizar(model.getValor());\` +- \`});\` +> Primeiro mudar, depois mostrar. Ao contrário, a view ainda mostra o valor antigo. + +runde: + reset.addActionListener(e -> { + model.reiniciar(); + view.atualizar(model.getValor()); + }); +frage: O contador está em 5. Clicas em Reset. O que acontece, um passo após o outro? +- Clicas em Reset. +- O model põe o \`valor\` a 0. +- \`model.getValor()\` devolve 0. +- A view mostra 0. +> Também o Reset passa pelo controller até ao model. A view só sabe do novo valor no fim. + +runde: +frage: Um teste sem janela deve escrever 1. Por que ordem estão as linhas no main? +- \`Contador model = new Contador();\` +- \`model.aumentar();\` +- \`System.out.println(model.getValor());\` +> Primeiro construir o objeto, depois trabalhar com ele e no fim ver o resultado. O model pode ser testado sem janela nenhuma. +::: + +## Tarefa: Um contador com limites + +Constrói o programa completo e experimenta-o. + +Depois melhora-o: + +- Um botão **−1** conta para baixo. O model recebe para isso um método \`diminuir()\`, o controller um segundo ouvinte. +- Um botão **Reset** põe o contador a 0 com \`reiniciar()\`. +- O próprio model trata dos limites: nunca abaixo de 0 e nunca acima de 10, porque aí a barra está cheia. +- Extra: uma terceira view \`VistaConsola\`, cujo \`atualizar\` escreve "Novo valor: 3" com \`System.out.println\`. Uma view não tem de ser uma janela. + +## 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. + +::: checkliste +- Consigo dizer o que fazem o model, a view e o controller. → O objetivo +- Consigo escrever um model sem Swing e testá-lo sem janela. → O model +- Consigo explicar o que constrói new Contador() e porque é que ali não há static. → O model +- Consigo nomear as quatro mensagens depois de um clique. → Quem fala com quem? +- Consigo acrescentar uma segunda view sem mudar o model. → A vantagem: uma segunda view +- Consigo construir um contador com −1, Reset e limites no model. → Tarefa: Um contador com limites +::: + +## Teste de conhecimentos + +::: quiz +? Onde fica a regra "O contador nunca passa de 10"? +→ O model +- [x] no model +- [ ] na view +- [ ] no controller +> As regras sobre os dados pertencem ao model. Assim valem seja qual for o botão. + +? O que faz a view? +→ O objetivo +- [ ] Calcula o novo valor. +- [x] Mostra o valor que recebe. +- [ ] Ouve os cliques. + +? Porque é que o lambda pode usar model, se model é uma variável do main? +→ Quem fala com quem? +- [ ] Porque Contador é public. +- [x] Porque model aponta sempre para o mesmo contador; só o valor lá dentro muda. +- [ ] Porque os lambdas podem mudar qualquer variável. + +? O que tens de mudar no model quando se junta uma segunda view? +→ A vantagem: uma segunda view +- [x] nada +- [ ] um segundo método aumentar +- [ ] um segundo JLabel + +? Liga. +→ O objetivo += Contador com valor e aumentar() -> model += VistaNumero com atualizar(int valor) -> view += o ouvinte do botão -> controller +::: +`,Cv=`Termos técnicos da área de aprendizagem. Quando um termo aparece num passo, fica marcado uma vez e mostra a sua +explicação ao passar o rato ou ao tocar. Se estiver a negrito nesse passo, é explicado ali mesmo e não é marcado. +\`auch:\` indica outras formas que também são reconhecidas. Maiúsculas e minúsculas contam. + +### Algoritmo +auch: algoritmo, algoritmos, Algoritmos +Instruções exatas, passo a passo, para resolver uma tarefa. Cada passo é claro. + +### Estrutograma +auch: estrutograma, estrutogramas, Estrutogramas, diagrama de Nassi-Shneiderman, diagramas de Nassi-Shneiderman, diagrama estruturado +Um algoritmo desenhado como imagem feita de blocos. Lê-se de cima para baixo. Também se chama diagrama de Nassi-Shneiderman. + +### Fluxograma +auch: fluxograma, fluxogramas, Fluxogramas +Um algoritmo desenhado com símbolos ligados por setas (DIN 66001 / ISO 5807). Um losango é uma decisão. + +### Pseudocódigo +auch: pseudocódigo +Um algoritmo escrito como texto em linguagem corrente com palavras fixas como SE e ENQUANTO. A indentação mostra o que pertence ao quê. + +### Instrução +auch: instrução, instruções, Instruções +Um único passo no estrutograma, por exemplo um cálculo, uma entrada ou uma saída. + +### Sequência +auch: sequência, sequências, Sequências +Passos que são executados uns a seguir aos outros, de cima para baixo, cada um exatamente uma vez. + +### Decisão +auch: decisão, decisões, Decisões, instrução condicional, instruções condicionais, estrutura de decisão +Um bloco que usa uma condição para decidir qual de dois ramos é executado. Também se chama instrução condicional. + +### Ramo +auch: ramo, ramos +Um dos dois caminhos de uma decisão: à esquerda para verdadeiro (true), à direita para falso (false). + +### Ciclo +auch: ciclo, ciclos, Ciclos, repetição, estrutura de repetição +Um bloco que repete passos enquanto uma condição se verificar. + +### Corpo do ciclo +auch: corpo do ciclo +O interior de um ciclo, ou seja, os passos que são repetidos. + +### Iteração +auch: iteração, iterações +Executar uma vez o interior de um ciclo. + +### Condição +auch: condição, condições, Condições +Uma pergunta que só pode ter como resposta sim (true) ou não (false), por exemplo idade >= 18. + +### Marcador +auch: marcador, marcadores +Um bloco vazio com o sinal ø. Se arrastares um elemento para cima dele, o elemento substitui-o. + +### Inspetor de objetos +A área por baixo do diagrama. Aqui editas o texto e as definições do bloco em que acabaste de clicar. + +### Simulação +auch: simulação +Executa o teu estrutograma no editor, se quiseres passo a passo. Assim vês o que acontece. + +### Variável +auch: variável, variáveis, Variáveis +Uma caixa com etiqueta para um valor. Tem um nome, um tipo de dados e um valor. + +### camelCase +auch: CamelCase +Forma de escrever nomes com várias palavras: escritas juntas, cada palavra seguinte começa com maiúscula, p. ex. \`precoComIva\`. + +### Constante +auch: constante, constantes, Constantes +Uma variável cujo valor não muda depois de definido. Escreve-se \`const\` à frente, p. ex. \`const double IVA = 0.23\`. + +### Tipo de dados +auch: tipo de dados, tipos de dados, Tipos de dados +Diz que tipo de valor cabe numa variável: int (número inteiro), double (número decimal), String (texto), boolean (verdadeiro ou falso) ou char (um único caractere). + +### Atribuição +auch: atribuição, atribuições, Atribuições +O sinal =. Calcula o lado direito e guarda o resultado na variável à esquerda. + +### Variável auxiliar +auch: variável auxiliar, variáveis auxiliares +Uma variável extra que guarda um valor durante pouco tempo, por exemplo ao trocar valores. + +### Modelo EPS +auch: entrada-processamento-saída +Entrada, processamento, saída: primeiro pedir os valores, depois calcular, depois mostrar o resultado. + +### Análise do problema +auch: análise do problema +Lês uma tarefa com atenção e descobres o que é dado, o que procuras e como chegar de um ao outro. + +### Operador de comparação +auch: operador de comparação, operadores de comparação, Operadores de comparação +Um sinal que compara dois valores, por exemplo == ou <. O resultado é true ou false. + +### Seleção +auch: seleção, seleção múltipla, escolha múltipla +Um bloco que executa exatamente um de vários casos, consoante o valor de uma variável. Também se chama seleção múltipla. + +### Ciclo pré-teste +auch: ciclo pré-teste, ciclos pré-teste, controlado no início +O ciclo verifica a sua condição antes de cada iteração. Se a condição for falsa logo no início, o ciclo não é executado nem uma vez. + +### Ciclo pós-teste +auch: ciclo pós-teste, ciclos pós-teste, controlado no fim +O ciclo só verifica a sua condição depois de cada iteração. Por isso é sempre executado pelo menos uma vez. + +### Variável contadora +auch: variável contadora, variáveis contadoras, contador +Uma variável que vai contando num ciclo, normalmente i. + +### Ciclo infinito +auch: ciclo infinito, ciclos infinitos, ciclo sem fim +Um ciclo cuja condição nunca se torna falsa. Nunca para sozinho. + +### Array +auch: array, arrays, Arrays, vetor, vetores +Uma fila de posições com um nome comum e o mesmo tipo de dados. + +### Índice +auch: índice, índices +O número de uma posição num array. Começa-se a contar em 0. + +### char +O tipo de dados para um único caractere. Fica entre aspas simples, p. ex. 'C'. Já "C" com aspas duplas é uma String. + +### Código de caractere +auch: código de caractere, códigos de caractere, código ASCII, tabela ASCII +O número que está por trás de um caractere. Na tabela ASCII, o A tem o código 65, o B 66 e assim por diante. Em Java, (int) transforma um caractere no seu código e (char) transforma um código no caractere. + +### String +auch: strings, Strings, cadeia de caracteres, cadeias de caracteres +Um texto, ou seja, uma fila de caracteres. Em Java o tipo de dados chama-se String. Os caracteres contam-se a partir de 0. + +### Array 2D +auch: arrays 2D, array bidimensional, arrays bidimensionais, matriz, matrizes +Um array com linhas e colunas, como uma tabela. Uma posição precisa de dois índices, p. ex. \`lugares[1][2]\`. + +### Subprograma +auch: subprograma, subprogramas, Subprogramas, método, métodos, Métodos, procedimento, procedimentos, função, funções, Funções +Um estrutograma próprio para uma parte da tarefa. É executado quando é chamado. Em Java chama-se método; consoante o tipo, também procedimento ou função. + +### Parâmetro +auch: parâmetro, parâmetros, Parâmetros +Uma variável na linha de cabeçalho de um subprograma. Quando é chamado, recebe o valor que está entre parênteses. + +### Código esparguete +auch: código esparguete +Um programa que salta de um lado para o outro de forma tão confusa que mal se consegue seguir o que acontece. Os estrutogramas evitam isso. + +### Passagem por valor +auch: passagem por valor +Um subprograma recebe uma cópia do valor. Se alterar o seu parâmetro, a variável de quem chamou fica igual. + +### Passagem por referência +auch: passagem por referência +Um subprograma recebe uma referência para os mesmos dados, p. ex. para um array. Se alterar uma posição, quem chamou também vê a alteração. + +### Valor de retorno +auch: valor de retorno, valores de retorno, Valores de retorno +O resultado que um subprograma devolve à chamada com return. + +### Interrupção +Um bloco que sai imediatamente do ciclo em que está. Depois o programa continua por baixo do ciclo. + +### Teste de secretária +auch: teste de secretária, testes de secretária, Testes de secretária, teste de mesa +Executas um estrutograma no papel e anotas os valores das variáveis depois de cada passo. + +### Pesquisa linear +auch: pesquisa linear +Uma forma de pesquisar que compara todos os valores, um a seguir ao outro, com o valor procurado. Também funciona com valores desordenados. + +### Pesquisa binária +auch: pesquisa binária +Uma forma de pesquisar em valores ordenados. Olha para o meio e continua a pesquisar só na metade certa. + +### Bubble sort +auch: bubble sort, Bubblesort, ordenação por bolha +Uma forma simples de ordenar. Compara sempre dois vizinhos e troca-os se estiverem na ordem errada. + +### Evento +auch: evento, eventos, Eventos +Algo que uma pessoa faz num programa com janelas, por exemplo clicar num botão. O programa reage com um ouvinte (ActionListener). + +### Interface +auch: Interfaces +Uma espécie de contrato em Java: diz que métodos uma classe tem de ter. \`ActionListener\` é uma interface com o método \`actionPerformed\`. + +### Exceção +auch: exceção, exceções, Exceções, Exception, Exceptions +Um erro que só acontece durante a execução, por exemplo um índice fora do array. Se nenhum \`catch\` a apanhar, o programa termina. + +### Atributo +auch: atributo, atributos, Atributos +Uma variável que está diretamente na classe e não dentro de um método. Com \`static\` pertence à própria classe e vive tanto tempo como o programa, por exemplo um contador de cliques que vários ouvintes alteram. + +### Scanner +Um bloco pronto do Java que lê entradas do teclado, por exemplo um número com \`scanner.nextInt()\`. Precisa de \`import java.util.Scanner;\` mesmo no início. + +### Comentário +auch: Comentários, comentário, comentários +Uma nota no código para pessoas. O Java salta-a ao executar. \`//\` vale até ao fim da linha, \`/* … */\` pode ocupar várias linhas. + +### import +Uma linha mesmo no início do código Java que vai buscar um bloco pronto a um pacote, por exemplo \`import java.util.Scanner;\`. Sem ela, o Java não conhece o nome. +`,jv=`## Elementos básicos + +### Instrução + +Um único passo. Serve para criar variáveis ou para calcular. + +\`\`\` +int numero = 5 +double preco = 2.5 +String nome = "Ada" +numero = numero + 1 +\`\`\` + +### Tipos de dados + +O tipo de dados vem antes do nome da variável. + +| Tipo de dados | Significado | Exemplo | +|---|---|---| +| \`int\` | número inteiro | \`int quantidade = 3\` | +| \`double\` | número decimal (com ponto) | \`double preco = 2.5\` | +| \`String\` | texto entre aspas duplas | \`String nome = "Ada"\` | +| \`boolean\` | valor lógico | \`boolean pronto = false\` | +| \`char\` | um único caractere entre aspas simples | \`char nota = 'C'\` | + +\`'C'\` é um \`char\`, \`"C"\` é uma String. Um caractere de um texto obténs com \`charAt\`: \`char primeiro = nome.charAt(0)\`. Cada caractere tem um código de caractere: \`(int) 'A'\` é 65, \`(char) 66\` é \`'B'\`. + +### Entrada + +Pede um valor enquanto o estrutograma é executado e guarda-o numa variável. O texto entre aspas é a pergunta. + +\`\`\` +input: int idade "Quantos anos tens?" +input: double preco "Introduz um preço" +input: String nome "Como te chamas?" +\`\`\` + +### Saída + +Mostra um texto ou um valor. Os textos ficam entre aspas; juntas texto e variáveis com \`+\`. + +\`\`\` +output: "Olá" +output: soma +output: "Tens " + idade + " anos." +\`\`\` + +> Numa saída, \`+\` junta sempre as partes: com 3 e 4, \`output: a + b\` mostra 34. Por isso calcula primeiro numa variável, p. ex. \`int soma = a + b\`, e depois mostra \`soma\`. + +## Decisões + +### Decisão + +Verifica uma condição. Se for verdadeira, é executado o ramo da esquerda (true), senão o da direita (false). + +\`\`\` +idade >= 18 +numero % 2 == 0 +nota < 1 || nota > 5 +\`\`\` + +### Seleção + +Escolhe um de vários casos, consoante o valor de uma variável. Se nenhum caso servir, aplica-se \`default\`. Acrescentas casos à direita com **Adicionar caso**. + +## Ciclos + +### Ciclo while + +Repete o seu interior **enquanto** a condição for verdadeira. A condição é verificada antes de cada iteração. + +\`\`\` +numero != 1 +i < 10 +\`\`\` + +### Ciclo do-while + +Executa o seu interior **pelo menos uma vez** e só depois verifica a condição. + +### Ciclo for + +Conta uma variável desde um valor inicial até um limite. Os três campos são Início, Condição e Passo. + +\`\`\` +int i = 0 +i < 5 +i++ +\`\`\` + +### Ciclo infinito + +Repete o seu interior sem condição. Uma **Interrupção** lá dentro permite sair dele. + +### Interrupção + +Sai do ciclo que a rodeia (\`break\`). + +## Subprogramas + +### Chamada + +Representa um subprograma, p. ex. \`calcularSoma()\`. Com parâmetros e valor de retorno, o subprograma tem uma linha de cabeçalho como título: + +\`\`\` +int quadrado(int x) linha de cabeçalho do subprograma +return x * x devolve o resultado +int q = quadrado(5) chamada, q fica com 25 +mostrarSoma(3, 4) chamada de um subprograma void +\`\`\` + +## Cálculos e comparações + +### Operadores e comparações + +- \`+ - * /\` as quatro operações básicas +- \`%\` resto de uma divisão (\`7 % 2\` dá 1) +- \`==\` igual, \`!=\` diferente +- \`<\` \`<=\` \`>\` \`>=\` menor, menor ou igual, maior, maior ou igual +- \`&&\` e, \`||\` ou + +## Arrays + +### Arrays + +Vários valores com um só nome. Começa-se a contar em 0. + +\`\`\` +int[] numeros = {3, 7, 1} +output: numeros[0] +int[] vazio = new int[5] +\`\`\` + +Um **array 2D** é uma tabela com linhas e colunas: + +\`\`\` +boolean[][] lugares = new boolean[3][5] +lugares[1][4] = true +output: lugares.length + " filas, " + lugares[0].length + " lugares" +\`\`\` + +## Java + +### Comentários + +Notas no código. O Java salta-as, o estrutograma fica igual. + +\`\`\`java +/* + * Tarefa: somar os números de 1 a 10 + * (comentário de várias linhas) + */ +// Processamento (comentário de uma linha) +int soma = 0; +for (int i = 1; i <= 10; i++) { + soma = soma + i; // comentário depois do código +} // fim do for +\`\`\` + +Serve para: a tarefa, dividir o código em entrada, processamento e saída, uma explicação, o fim de um bloco depois de \`}\`, a saída esperada e notas para a próxima vez. +`,Pv=`--- +titel: Alter im Unterprogramm +nach: 18 +stufe: 2 +--- + +Die Altersprüfung aus „Volljährig?“ wird jetzt ein eigenes Unterprogramm. Das Hauptprogramm ruft es nur noch auf. + +::: übung aufgabe-alter-unterprogramm +titel: Alter im Unterprogramm +auftrag: Baue zwei Diagramme. Das Hauptprogramm gibt **Willkommen** aus, ruft dann \`pruefeAlter()\` auf und gibt zum Schluss **Auf Wiedersehen** aus. + Das Unterprogramm \`pruefeAlter\` steht in einem eigenen Reiter: Es fragt nach dem Alter und gibt **volljährig** oder **minderjährig** aus. +test: 20 -> Willkommen | volljährig | Auf Wiedersehen +test: 18 -> Willkommen | volljährig | Auf Wiedersehen +test: 12 -> Willkommen | minderjährig | Auf Wiedersehen +braucht: aufruf +tipp: Das Hauptprogramm hat drei Kästen. Die eigentliche Arbeit macht das Unterprogramm. +tipp: Öffne die Übung im Editor und baue dort das Hauptprogramm mit dem Aufruf \`pruefeAlter()\`. Lege dann mit **+** einen neuen Reiter an und gib ihm den Titel \`pruefeAlter\`. Darin baust du die Eingabe und die Verzweigung. Prüfen findet das Unterprogramm über den Titel des Reiters. +lösung: aufgabe-alter-haupt-loesung.visustruct +unterprogramm: aufgabe-alter-unterprogramm-loesung.visustruct +::: +`,Dv=`--- +titel: Ballwurf auswerten +nach: 25 +stufe: 2 +--- + +Beim Sportfest haben alle ihre Weite beim Ballwurf in eine Tabelle eingetragen: + +::: datei ballwurf.csv +Name;Weite +Ludwig;28 +Zora;42 +Fuchs;35 +Hase;21 +::: + +::: übung aufgabe-ballwurf +titel: Ballwurf auswerten +code: java +auftrag: Lies die Datei ein und überspringe die Kopfzeile. Gib aus, wie viele mitgemacht haben (**Teilnehmer: 4**) und wie weit im Schnitt geworfen wurde (**Schnitt: 31.5 m**). + Speichere den weitesten Wurf in der Datei **sieger.txt**, zum Beispiel **Sieger: Zora (42 m)**. +start: aufgabe-ballwurf-start.visustruct +test: - -> Teilnehmer: 4 | Schnitt: 31.5 m +datei: sieger.txt -> Sieger: Zora (42 m) +braucht: whileSchleife, verzweigung +tipp: Du brauchst vier Variablen vor der Schleife: die Anzahl, die Summe als \`double\`, die beste Weite und den besten Namen. +tipp: In der Schleife: \`String[] teile = zeile.split(";");\` und \`int weite = Integer.parseInt(teile[1]);\`. Ist \`weite > besteWeite\`, merkst du dir Weite und Namen. Zum Speichern: \`PrintWriter aus = new PrintWriter("sieger.txt");\`, \`aus.println(…)\` und \`aus.close();\`. +lösung: aufgabe-ballwurf-loesung.visustruct +::: +`,Bv=`--- +titel: Bestenliste +nach: 19 +stufe: 2 +--- + +Fünf Ziegen sind beim Hindernislauf gestartet. Jetzt soll die Bestenliste an die Stalltür: die meisten Punkte oben, die wenigsten unten. + +::: übung aufgabe-bestenliste +titel: Bestenliste +auftrag: Lies 5 Punktzahlen in ein Array ein. Sortiere das Array mit Bubblesort **absteigend**, also die größte Zahl zuerst. Gib danach die Liste mit Platz aus, zum Beispiel **1. 9**, in der nächsten Zeile **2. 9** und so weiter. +test: 3, 9, 2, 9, 1 -> 1. 9 | 2. 9 | 3. 3 | 4. 2 | 5. 1 +test: 10, 20, 30, 40, 50 -> 1. 50 | 2. 40 | 3. 30 | 4. 20 | 5. 10 +test: 5, 4, 3, 2, 1 -> 1. 5 | 2. 4 | 3. 3 | 4. 2 | 5. 1 +braucht: forSchleife, verzweigung +tipp: Bubblesort aus Lektion 19 sortiert aufsteigend. Für absteigend drehst du nur den Vergleich der Nachbarn um. +tipp: Getauscht wird, wenn \`punkte[i] < punkte[i + 1]\` ist, mit einer Hilfsvariablen. Für die Ausgabe rechnest du zuerst \`int platz = i + 1\` aus und gibst dann \`platz + ". " + punkte[i]\` aus. +lösung: aufgabe-bestenliste-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-bestenliste-java +titel: Bestenliste in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 3, 9, 2, 9, 1 -> 1. 9 | 2. 9 | 3. 3 | 4. 2 | 5. 1 +test: 10, 20, 30, 40, 50 -> 1. 50 | 2. 40 | 3. 30 | 4. 20 | 5. 10 +test: 5, 4, 3, 2, 1 -> 1. 5 | 2. 4 | 3. 3 | 4. 2 | 5. 1 +braucht: forSchleife, verzweigung +tipp: Lies jede Zahl erst in eine Variable ein und schreibe sie dann ins Array: \`int zahl = scanner.nextInt();\` und \`punkte[i] = zahl;\`. +tipp: Der Tausch braucht auch in Java eine Hilfsvariable: \`int hilf = punkte[i]; punkte[i] = punkte[i + 1]; punkte[i + 1] = hilf;\`. +lösung: aufgabe-bestenliste-loesung.visustruct +::: +`,Mv=`--- +titel: Binärzahl +nach: 11 +stufe: 3 +--- + +Computer rechnen mit nur zwei Ziffern: 0 und 1. So wandelst du eine Zahl ins **Binärsystem** um: + +1. Teile die Zahl durch 2 und merke dir den Rest (0 oder 1). +2. Rechne mit dem Ergebnis ohne Rest weiter. +3. Wiederhole das, bis die Zahl 0 ist. + +Die Reste von **unten nach oben** gelesen ergeben die Binärzahl. Bei 6 sind die Reste 0, 1, 1, also lautet die Binärzahl 110. + +::: übung aufgabe-binaer +titel: Binärzahl +auftrag: Frage nach einer ganzen Zahl größer als 0 und gib sie als Binärzahl aus. Bei 6 lautet die Ausgabe **110**, bei 13 **1101**. +test: 6 -> 110 +test: 13 -> 1101 +test: 1 -> 1 +test: 8 -> 1000 +braucht: whileSchleife +tipp: Teile die Zahl immer wieder durch 2 und merke dir jeden Rest. Die Reste rückwärts gelesen ergeben die Binärzahl. +tipp: Sammle die Ziffern in einem Text: \`String binaer = ""\`. In der Schleife berechnest du \`int rest = zahl % 2\` und hängst den Rest **vorne** an: \`binaer = rest + binaer\`. Danach \`zahl = zahl / 2\`. Weil zahl eine ganze Zahl ist, fällt der Rest dabei weg. +lösung: aufgabe-binaer-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-binaer-java +titel: Binärzahl in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 6 -> 110 +test: 13 -> 1101 +test: 1 -> 1 +test: 8 -> 1000 +braucht: whileSchleife +tipp: Fang mit \`String binaer = "";\` an. Die Schleife läuft mit \`while (zahl > 0)\`. +tipp: Im Rumpf: \`int rest = zahl % 2;\`, dann \`binaer = rest + binaer;\` und \`zahl = zahl / 2;\`. Weil \`binaer\` ein String ist, hängt \`+\` den Rest vorne an. +lösung: aufgabe-binaer-loesung.visustruct +::: +`,Zv=`--- +titel: Caesar-Verschlüsselung +nach: 17 +stufe: 3 +--- + +Schon vor über 2000 Jahren schickte der römische Feldherr Julius Caesar geheime Nachrichten an seine Truppen. Sein Trick war einfach: Er ersetzte jeden Buchstaben durch den Buchstaben, der **drei Stellen weiter** im Alphabet steht. Aus A wird D, aus B wird E und so weiter. Die lesbare Nachricht heißt **Klartext**, die verschlüsselte **Geheimtext**. Um wie viele Stellen verschoben wird, ist der **Schlüssel**, oft kurz \`k\` genannt. + +::: grafik caesar-verschiebung.svg +Verschlüsselung mit dem Schlüssel 3: Jeder Buchstabe oben wird zum Buchstaben darunter. Am Ende geht es von vorn weiter, aus X, Y und Z werden A, B und C. +::: + +Aus \`HALLO\` wird so \`KDOOR\`. Wer den Schlüssel kennt, schiebt einfach drei Stellen zurück und kann die Nachricht wieder lesen. + +### Die Chiffrierscheibe + +Damit man nicht jedes Mal abzählen muss, baute man sich eine **Chiffrierscheibe**: zwei Scheiben mit dem Alphabet, eine kleine auf einer großen, in der Mitte drehbar befestigt. Außen steht der Klartext, innen der Geheimtext. Dreht man die innere Scheibe um drei Buchstaben, steht unter jedem Buchstaben außen sein Geheimbuchstabe. Solche Scheiben gibt es seit dem 15. Jahrhundert. Im Amerikanischen Bürgerkrieg (1861–1865) trugen Soldaten kleine Scheiben aus Messing bei sich. + +::: grafik caesar-scheibe.svg +Eine Chiffrierscheibe nach dem Vorbild historischer Messingscheiben. Das blaue Fenster zeigt: Mit dem Schlüssel 3 steht unter A das D. +::: + +::: angeberwissen +Caesar selbst hatte noch gar keine Scheibe! Das wissen wir vom römischen Geschichtsschreiber Sueton: Caesar verschob in seinen Briefen jeden Buchstaben um drei Stellen und zählte das einfach im Kopf ab. Die Scheibe erfand erst Leon Battista Alberti um 1467, also rund 1500 Jahre später. Ich zähle übrigens auch im Kopf, ich habe ja keine Finger, nur Hufe. +::: + +Probiere es selbst aus. Drehe die innere Scheibe, tippe einen Text ein und schau zu, wie der Geheimtext entsteht. Mit **Entschlüsseln** geht es rückwärts. + +::: caesar 3 +LUDWIG +::: + +::: ludwig +Eine echte Scheibe kannst du ganz leicht selbst basteln: zwei Kreise aus Pappe, einer etwas kleiner, je 26 gleich große Felder mit dem Alphabet und in der Mitte eine Musterklammer. Fertig ist dein Geheimdienst-Werkzeug! +::: + +::: quiz +? Was wird mit dem Schlüssel 3 aus dem Buchstaben Y? +- [ ] A +- [x] B +- [ ] C +> Nach Y kommen Z, dann geht es von vorn los mit A und B. Drei Stellen weiter ist also B. + +? Ein Geheimtext wurde mit dem Schlüssel 5 verschlüsselt. Wie entschlüsselst du ihn? +- [ ] Noch einmal 5 Stellen weiter schieben +- [x] 5 Stellen zurück schieben +- [ ] Die Buchstaben rückwärts lesen +> Entschlüsseln ist das Gegenteil vom Verschlüsseln. Fünf Stellen zurück ist übrigens dasselbe wie 21 Stellen weiter, denn 5 + 21 = 26. +::: + +### Das Programm: Es gibt mehr als einen Weg + +Wie bringst du dem Computer bei, einen Buchstaben um \`k\` Stellen zu verschieben? Dafür gibt es nicht *die eine* richtige Lösung. Wir schauen uns zwei Wege an. Beide gehen den Text mit einer For-Schleife Zeichen für Zeichen durch, so wie in der Lektion Zeichenketten. Der Unterschied ist, wie sie einen einzelnen Buchstaben verschieben. + +In beiden Wegen hilft der Rest-Operator \`%\`. Er sorgt dafür, dass es nach Z wieder bei A weitergeht: Die Positionen 0 bis 25 bleiben, wie sie sind, aus 26 wird 0, aus 27 wird 1 und so weiter. + +### Weg 1: Das Alphabet in einem Array + +Du legst das Alphabet in ein Array \`char[] alphabet = {'A', 'B', …, 'Z'}\`. Für jeden Buchstaben des Wortes suchst du im Array seine Position \`pos\`, also seinen Index. Der Geheimbuchstabe steht dann im selben Array an der Stelle \`(pos + k) % 26\`. + +Ein Beispiel mit dem Schlüssel 3: X steht an der Position 23. Dann ist \`(23 + 3) % 26 = 0\`, und an der Position 0 steht A. + +::: übung aufgabe-caesar-array +titel: Caesar mit Array +auftrag: Das Startdiagramm enthält schon das Array \`alphabet\`. Frage nach einem Wort aus Großbuchstaben und nach dem Schlüssel \`k\`. Gib dann das verschlüsselte Wort aus. Bei HALLO und 3 also \`KDOOR\`. +start: aufgabe-caesar-array-start.visustruct +test: HALLO, 3 -> KDOOR +test: ZEBRA, 1 -> AFCSB +test: LUDWIG, 13 -> YHQJVT +braucht: forSchleife, verzweigung +tipp: Lege einen leeren Text \`String geheim = ""\` an. Gehe das Wort mit einer For-Schleife Zeichen für Zeichen durch. In jedem Durchlauf hängst du einen Geheimbuchstaben hinten an \`geheim\` an. +tipp: Um die Position eines Buchstabens zu finden, brauchst du eine zweite, innere Schleife über das Array: Ist \`alphabet[j] == zeichen\`, merkst du dir \`pos = j\`. +tipp: Nach der inneren Schleife hängst du \`alphabet[(pos + k) % 26]\` an: \`geheim = geheim + alphabet[(pos + k) % 26]\`. Nach der äußeren Schleife gibst du \`geheim\` aus. +lösung: aufgabe-caesar-array-loesung.visustruct +::: + +### Weg 2: Rechnen mit der ASCII-Tabelle + +Für den Computer ist jedes Zeichen eigentlich eine Zahl. Welche Zahl zu welchem Zeichen gehört, steht in der **ASCII-Tabelle**. Dort hat A den Code 65, B den Code 66 und so weiter bis Z mit 90. In Java wandelst du ein Zeichen mit \`(int)\` in seinen Code um und einen Code mit \`(char)\` zurück in ein Zeichen: + +\`\`\` +int code = (int) 'A' +char zeichen = (char) 68 +\`\`\` + +Danach ist \`code\` gleich 65 und \`zeichen\` gleich \`'D'\`. So eine Umwandlung von einem Datentyp in einen anderen heißt **Typumwandlung** (englisch *cast*). + +Jetzt kannst du mit dem Buchstaben rechnen. Damit der Sprung von Z zurück zu A klappt, ziehst du erst 65 ab. Dann hat A die Position 0 und Z die Position 25, genau wie in Weg 1. Du verschiebst mit \`% 26\` und zählst am Ende die 65 wieder dazu: + +::: grafik caesar-ascii.svg +Oben die Großbuchstaben mit ihren ASCII-Codes. Unten der Rechenweg für X mit dem Schlüssel 3: Heraus kommt A. +::: + +::: übung aufgabe-caesar-ascii +titel: Caesar mit ASCII +code: java +auftrag: Schreibe ein Java-Programm, das ein Wort aus Großbuchstaben und den Schlüssel \`k\` einliest und das verschlüsselte Wort ausgibt. Diesmal ohne Array: Rechne mit \`(int)\` und \`(char)\`. +test: HALLO, 3 -> KDOOR +test: ZEBRA, 1 -> AFCSB +test: LUDWIG, 13 -> YHQJVT +braucht: forSchleife +tipp: Gehe das Wort mit einer For-Schleife durch. Den Code des Zeichens an der Stelle \`i\` bekommst du mit \`int code = (int) wort.charAt(i);\`. +tipp: Rechne \`code = (code - 65 + k) % 26 + 65;\` und hänge das Zeichen an: \`geheim = geheim + (char) code;\`. Vor der Schleife steht \`String geheim = "";\`, nach der Schleife \`System.out.println(geheim);\`. +lösung: aufgabe-caesar-ascii-loesung.visustruct +::: + +### Welcher Weg ist besser? + +**Weg 1: Array.** Die Idee ist, die Position im Array zu suchen. +- Vorteil: leicht zu verstehen, und auch eigene Alphabete gehen, z. B. mit Ä, Ö und Ü. +- Nachteil: Für jeden Buchstaben muss gesucht werden. + +**Weg 2: ASCII.** Die Idee ist, mit dem Zeichencode zu rechnen. +- Vorteil: kurz und ohne Suche, darum schneller. +- Nachteil: Man muss die ASCII-Codes kennen. + +Beide Programme liefern dasselbe Ergebnis. Genau so ist es oft beim Programmieren: Es gibt mehrere richtige Lösungen, und du wählst die, die am besten zu deiner Aufgabe passt. + +::: übung aufgabe-caesar-entschluesseln +titel: Caesar entschlüsseln +code: java +auftrag: Jetzt drehst du den Spieß um. Lies einen Geheimtext aus Großbuchstaben und den Schlüssel \`k\` ein und gib den Klartext aus. Bei KDOOR und 3 also \`HALLO\`. Welchen Weg du nimmst, entscheidest du. +test: KDOOR, 3 -> HALLO +test: AFCSB, 1 -> ZEBRA +test: YHQJVT, 13 -> LUDWIG +braucht: forSchleife +tipp: Entschlüsseln heißt: \`k\` Stellen zurück statt vor. Aus dem \`+ k\` wird also ein \`- k\`. +tipp: Vorsicht bei A: \`0 - 3\` ergibt -3, und \`%\` macht daraus in Java keine positive Zahl. Zähle darum noch 26 dazu: \`code = (code - 65 - k + 26) % 26 + 65;\` +lösung: aufgabe-caesar-entschluesseln-loesung.visustruct +::: + +::: angeberwissen +Sicher ist Caesar leider nicht. Es gibt nur 25 Schlüssel, die kann man in ein paar Minuten alle ausprobieren. Noch schneller geht es mit einem Trick: Im Deutschen ist E der häufigste Buchstabe. Kommt im Geheimtext H am häufigsten vor, war der Schlüssel wohl 3. Im Internet gibt es übrigens ROT13, das ist Caesar mit dem Schlüssel 13. Zweimal ROT13 ergibt wieder den Klartext, weil 13 + 13 = 26. +::: +`,Lv=`--- +titel: Collatz-Folge +nach: 11 +stufe: 2 +--- + +Die Collatz-Folge ist ein berühmtes Rätsel der Mathematik. Du beginnst mit einer Zahl und wendest immer wieder dieselbe Regel an: + +- Ist die Zahl **gerade**, teilst du sie durch 2. +- Ist sie **ungerade**, rechnest du mal 3 plus 1. + +Bisher endet die Folge bei jeder ausprobierten Startzahl irgendwann bei 1. Ob das für alle Zahlen gilt, weiß bis heute niemand. + +::: übung aufgabe-collatz +titel: Collatz-Folge +auftrag: Frage nach einer Startzahl. Wende die Regel so lange an, bis die Zahl 1 ist, und gib nach jedem Schritt die neue Zahl aus. Zähle dabei die Schritte mit und gib am Ende **Schritte:** und die Anzahl aus. + Bei der Startzahl 6 lautet die Folge 3, 10, 5, 16, 8, 4, 2, 1. Das sind 8 Schritte. +test: 6 -> 3 | 10 | 5 | 16 | 8 | 4 | 2 | 1 | Schritte: 8 +test: 3 -> 10 | 5 | 16 | 8 | 4 | 2 | 1 | Schritte: 7 +test: 1 -> Schritte: 0 +braucht: whileSchleife, verzweigung +tipp: Du weißt nicht, wie viele Schritte es werden. Darum passt eine While-Schleife besser als eine For-Schleife. +tipp: Die While-Schleife läuft, solange \`zahl != 1\` gilt. Ob eine Zahl gerade ist, prüfst du mit \`zahl % 2 == 0\`. Die Ausgabe und \`schritte++\` kommen nach der Verzweigung, aber noch in die Schleife. +lösung: aufgabe-collatz-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-collatz-java +titel: Collatz-Folge in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 6 -> 3 | 10 | 5 | 16 | 8 | 4 | 2 | 1 | Schritte: 8 +test: 3 -> 10 | 5 | 16 | 8 | 4 | 2 | 1 | Schritte: 7 +test: 1 -> Schritte: 0 +braucht: whileSchleife, verzweigung +tipp: Eine \`while\`-Schleife läuft, solange \`zahl != 1\` ist. Darin entscheidet ein \`if\` mit \`zahl % 2 == 0\`. +tipp: Im Rumpf: halbieren oder \`zahl = zahl * 3 + 1;\`, dann \`System.out.println(zahl);\` und \`schritte++;\`. Nach der Schleife kommt \`"Schritte: " + schritte\`. +lösung: aufgabe-collatz-loesung.visustruct +::: + +::: angeberwissen +Mit dieser Aufgabe kann man reich werden! Der Mathematiker Paul Erdős setzte für einen Beweis 500 Dollar aus. 2021 legte die japanische Firma Bakuage noch einiges drauf: 120 Millionen Yen, damals umgerechnet rund eine Million Dollar, für einen Beweis oder ein Gegenbeispiel. Abgeholt hat das Geld bis heute niemand. Erfunden hat das Rätsel übrigens der deutsche Mathematiker Lothar Collatz im Jahr 1937. Ich rechne gleich mal los, für so viel Geld gibt es eine Menge Heu. +::: +`,Ev=`--- +titel: Einheitenrechner +nach: 35 +stufe: 2 +--- + +Baue ein Fenster, das Längen umrechnet. Oben tippst du eine Länge in Metern ein, darunter stehen drei Knöpfe: + +- **in cm** zeigt die Länge in Zentimetern, aus 1.5 wird „150.0 cm“, +- **in mm** zeigt sie in Millimetern, aus 1.5 wird „1500.0 mm“, +- **in km** zeigt sie in Kilometern, aus 1500 wird „1.5 km“. + +Das Ergebnis steht in einem JLabel unter den Knöpfen. Steht im Feld keine Zahl, erscheint dort „Bitte eine Zahl eingeben“, und das Programm stürzt nicht ab. + +So kannst du anfangen: + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Einheiten { + public static void main(String[] args) { + JFrame fenster = new JFrame("Einheitenrechner"); + fenster.setSize(300, 200); + fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + fenster.setLayout(new GridLayout(0, 1)); + + JTextField meter = new JTextField(); + JButton inCm = new JButton("in cm"); + JLabel ergebnis = new JLabel("?", SwingConstants.CENTER); + + inCm.addActionListener(e -> { + double m = Double.parseDouble(meter.getText()); + ergebnis.setText((m * 100) + " cm"); + }); + + fenster.add(meter); + fenster.add(inCm); + fenster.add(ergebnis); + fenster.setVisible(true); + } +} +\`\`\` + +Zusatz: Ein vierter Knopf **in Fuß** rechnet in die englische Einheit um. Ein Fuß sind 0.3048 m. + +::: ludwig +Tick im [Zahnrad](#zeige-einstellungen) **Echtes Java (mit Swing)** an. Für „abc“ im Feld brauchst du in jedem Zuhörer ein try/catch mit \`NumberFormatException\`, wie beim Taschenrechner. +::: +`,Wv=`--- +titel: Fibonacci-Zahlen +nach: 13 +stufe: 2 +--- + +Bei den Fibonacci-Zahlen ist jede Zahl die Summe der beiden Zahlen davor. Die Folge beginnt mit 1 und 1: + +1, 1, 2, 3, 5, 8, 13, 21, … + +Diese Zahlen findest du erstaunlich oft in der Natur, zum Beispiel bei der Anordnung von Sonnenblumenkernen. + +::: ludwig +Erinnerst du dich ans **Tauschen** aus Lektion 5? Dort brauchtest du eine Hilfsvariable, weil \`a = b\` den alten Wert von \`a\` überschreibt. Hier ist es genauso: Bevor \`zahl2\` die neue Zahl bekommt, muss ihr alter Wert in \`zahl1\` gerettet sein. Achte also auf die **Reihenfolge**: erst \`zahl1 = zahl2\`, dann \`zahl2 = zahl3\`. Dieses Weiterschieben und Tauschen brauchst du später wieder, zum Beispiel beim Sortieren in Lektion 19. +::: + +::: angeberwissen +Leonardo von Pisa, genannt Fibonacci, stellte 1202 in seinem Rechenbuch eine Aufgabe über Kaninchen: Jedes Kaninchenpaar bekommt ab dem zweiten Monat jeden Monat ein neues Paar. Wie viele Paare gibt es nach einem Jahr? Die Antwort ist diese Zahlenfolge. Ziegen kamen in dem Buch leider nicht vor. +::: + +::: übung aufgabe-fibonacci +titel: Fibonacci-Zahlen +auftrag: Frage, wie viele Fibonacci-Zahlen ausgegeben werden sollen. Gib dann genau so viele aus, jede in einer eigenen Zeile. Du kannst davon ausgehen, dass mindestens 2 eingegeben wird. +test: 5 -> 1 | 1 | 2 | 3 | 5 +test: 8 -> 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 +test: 2 -> 1 | 1 +braucht: forSchleife +tipp: Jede neue Zahl ist die Summe der beiden vorherigen. Du musst dir also immer die letzten zwei Zahlen merken. +tipp: Merke dir die beiden letzten Zahlen in \`zahl1\` und \`zahl2\` und gib beide vor der Schleife aus. Die Schleife beginnt bei \`int i = 2\`. Darin berechnest du \`int zahl3 = zahl1 + zahl2\`, gibst sie aus und schiebst dann weiter: \`zahl1 = zahl2\` und \`zahl2 = zahl3\`. +lösung: aufgabe-fibonacci-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-fibonacci-java +titel: Fibonacci-Zahlen in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 5 -> 1 | 1 | 2 | 3 | 5 +test: 8 -> 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 +test: 2 -> 1 | 1 +braucht: forSchleife +tipp: Die ersten beiden Zahlen gibst du vor der Schleife aus. Die \`for\`-Schleife beginnt dann bei \`int i = 2\`. +tipp: Im Rumpf: \`int zahl3 = zahl1 + zahl2;\`, ausgeben, dann \`zahl1 = zahl2;\` und \`zahl2 = zahl3;\`. +lösung: aufgabe-fibonacci-loesung.visustruct +::: + +::: quiz +? Warum muss in der Schleife \`zahl1 = zahl2\` vor \`zahl2 = zahl3\` stehen? +- [ ] Weil Java die Zuweisungen sonst nicht erlaubt +- [x] Weil sonst der alte Wert von zahl2 überschrieben ist, bevor zahl1 ihn bekommt +- [ ] Die Reihenfolge ist egal +> Andersherum hätten zahl1 und zahl2 danach denselben Wert. Wie beim Tauschen gilt: Erst retten, dann überschreiben. +::: +`,Nv=`--- +titel: Gerade oder ungerade +nach: 8 +stufe: 1 +--- + +Eine Zahl ist gerade, wenn beim Teilen durch 2 kein Rest bleibt. Den Rest berechnest du mit \`%\`: \`8 % 2\` ist 0, \`7 % 2\` ist 1. + +::: übung aufgabe-gerade +titel: Gerade oder ungerade +auftrag: Frage nach einer ganzen Zahl. Gib aus, ob sie gerade oder ungerade ist. Bei 4 lautet die Ausgabe **4 ist gerade**, bei 7 **7 ist ungerade**. +test: 4 -> 4 ist gerade +test: 7 -> 7 ist ungerade +test: 0 -> 0 ist gerade +test: 15 -> 15 ist ungerade +braucht: verzweigung +tipp: Eine Verzweigung entscheidet zwischen gerade und ungerade. Gerade heißt: durch 2 teilbar ohne Rest. +tipp: Die Bedingung lautet \`zahl % 2 == 0\`. In der Ausgabe verbindest du die Zahl und den Text mit \`+\`, z. B. \`zahl + " ist gerade"\`. +lösung: aufgabe-gerade-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-gerade-java +titel: Gerade oder ungerade in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 4 -> 4 ist gerade +test: 7 -> 7 ist ungerade +test: 0 -> 0 ist gerade +test: 15 -> 15 ist ungerade +braucht: verzweigung +tipp: Eine Zahl liest du mit \`int zahl = scanner.nextInt();\` ein. Vorher fragst du mit \`System.out.println(…)\`. +tipp: \`if (zahl % 2 == 0) { … } else { … }\`. Die Ausgabe ist \`System.out.println(zahl + " ist gerade");\`. +lösung: aufgabe-gerade-loesung.visustruct +::: +`,Fv=`--- +titel: Mehrwertsteuer +nach: 6 +stufe: 1 +--- + +Auf fast alles, was du kaufst, kommen 19 % **Mehrwertsteuer**. Der Laden rechnet mit dem Nettopreis (ohne Steuer) und schlägt die Steuer drauf. So entsteht der Bruttopreis, den du an der Kasse zahlst. + +Ein Beispiel: Du kaufst ein Falt-Handy, das aufgeklappt zum Tablet wird. Auf dem Preisschild des Händlers stehen 1000 € netto. Dazu kommen 19 %, also 190 €. An der Kasse zahlst du 1190 €. Die 190 € darf der Händler nicht behalten: Er führt sie an das Finanzamt ab. + +::: grafik aufgabe-mehrwertsteuer.svg +Nettopreis plus Mehrwertsteuer ergibt den Bruttopreis. Die Mehrwertsteuer geht an das Finanzamt. +::: + +::: angeberwissen +Mäh, der Händler hat das Handy ja selbst eingekauft: beim Hersteller für 800 € plus 152 € Mehrwertsteuer. Diese 152 € heißen **Vorsteuer**, und die darf er von den 190 € abziehen. Ans Finanzamt überweist er also nur 38 €. Die ganze Steuer zahlt am Ende nur einer: der Kunde an der Kasse. Also du. Ich zahle übrigens gar keine, ich fresse nur Gras. +::: + +Der Steuersatz ändert sich beim Rechnen nie. Darum legst du ihn als **Konstante** an: Das ist eine Variable, deren Wert nach dem Festlegen gleich bleibt. Du schreibst \`const\` davor, zum Beispiel \`const double MWST = 0.19\`. Namen von Konstanten schreibt man in Großbuchstaben, dann erkennt man sie sofort. Im Java-Code wird daraus \`final double MWST = 0.19;\`. + +Wenn sich der Steuersatz einmal ändert, musst du nur diese eine Zeile anpassen. + +::: übung aufgabe-mehrwertsteuer +titel: Mehrwertsteuer +auftrag: Lege die Konstante \`MWST\` mit dem Wert 0.19 an. Frage dann nach dem Nettopreis. Gib zuerst die Steuer und danach den Bruttopreis aus, jeweils nur die Zahl. + Bei einem Nettopreis von 100 lauten die Ausgaben **19** und **119**. +test: 100 -> 19 | 119 +test: 50 -> 9.5 | 59.5 +test: 0 -> 0 | 0 +tipp: Die Steuer ist 19 Prozent vom Nettopreis. Der Bruttopreis ist das, was man am Ende bezahlt. +tipp: Die Steuer ist \`nettopreis * MWST\`. Den Bruttopreis bekommst du, wenn du die Steuer zum Nettopreis addierst. Beide Werte sind Kommazahlen, also \`double\`. +lösung: aufgabe-mehrwertsteuer-loesung.visustruct +::: + +::: quiz +? Warum legst du den Steuersatz als Konstante an? +- [ ] Weil Konstanten schneller gerechnet werden +- [x] Weil sich sein Wert im Programm nicht ändern soll +- [ ] Weil man Kommazahlen nur als Konstante speichern kann +> Eine Konstante behält ihren Wert. Ändert sich der Steuersatz einmal, passt du nur die eine Zeile mit \`const\` an. +::: +`,Jv=`--- +titel: Notendurchschnitt +nach: 13 +stufe: 2 +--- + +Wie gut war die letzte Zeit? Der Durchschnitt ist die Summe aller Noten geteilt durch ihre Anzahl. + +::: übung aufgabe-durchschnitt +titel: Notendurchschnitt +auftrag: Frage zuerst, wie viele Noten eingegeben werden. Lies dann genau so viele Noten ein und gib den Durchschnitt aus, nur die Zahl. + Bei den Noten 1 und 2 ist der Durchschnitt **1.5**. +test: 2, 1, 2 -> 1.5 +test: 3, 1, 2, 3 -> 2 +test: 4, 2, 2, 3, 4 -> 2.75 +braucht: forSchleife +tipp: Du brauchst die Summe aller Noten und ihre Anzahl. Der Durchschnitt ist die Summe geteilt durch die Anzahl. +tipp: Die For-Schleife läuft von \`int i = 0\` bis \`i < anzahl\`. Darin liest du eine Note ein und zählst sie zur Summe. Den Durchschnitt speicherst du als Kommazahl: \`double schnitt = summe * 1.0 / anzahl\`. Das \`* 1.0\` sorgt dafür, dass auch in Java nicht ganzzahlig geteilt wird. +lösung: aufgabe-durchschnitt-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-durchschnitt-java +titel: Notendurchschnitt in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 2, 1, 2 -> 1.5 +test: 3, 1, 2, 3 -> 2 +test: 4, 2, 2, 3, 4 -> 2.75 +braucht: forSchleife +tipp: \`for (int i = 0; i < anzahl; i++)\` liest genau so viele Noten ein, wie vorher angegeben. +tipp: Teile mit \`double schnitt = summe * 1.0 / anzahl;\`. Ohne \`* 1.0\` teilt Java zwei \`int\` ganzzahlig, und aus 1.5 wird 1. +lösung: aufgabe-durchschnitt-loesung.visustruct +::: +`,Rv=`--- +titel: PIN prüfen +nach: 12 +stufe: 2 +--- + +Am Geldautomaten hast du drei Versuche für deine PIN. Gibst du dreimal eine falsche PIN ein, wird die Karte gesperrt. + +::: angeberwissen +John Shepherd-Barron, der 1967 den ersten Geldautomaten in London aufstellte, wollte eigentlich sechsstellige PINs. Seine Frau sagte aber, sie könne sich höchstens vier Ziffern merken. Deshalb hat deine PIN heute vier Stellen. +::: + +::: übung aufgabe-pin +titel: PIN prüfen +auftrag: Die richtige PIN ist 1234. Frage so lange nach der PIN, bis sie richtig ist oder drei Versuche verbraucht sind. Gib danach **PIN richtig** oder **Karte gesperrt** aus. +test: 1234 -> PIN richtig +test: 1111, 1234 -> PIN richtig +test: 1, 2, 1234 -> PIN richtig +test: 1, 2, 3 -> Karte gesperrt +braucht: doUntilSchleife, verzweigung +tipp: Die Schleife endet in zwei Fällen: wenn die PIN stimmt oder wenn drei Versuche verbraucht sind. Zähle die Versuche mit. +tipp: Die PIN wird mindestens einmal abgefragt, deshalb passt eine Do-while-Schleife. Lege vorher \`int pin = 0\` und \`int versuche = 0\` an. Die Schleife wiederholt sich, solange \`pin != 1234 && versuche < 3\` gilt. Nach der Schleife entscheidet eine Verzweigung, was ausgegeben wird. +lösung: aufgabe-pin-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-pin-java +titel: PIN prüfen in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 1234 -> PIN richtig +test: 1111, 1234 -> PIN richtig +test: 1, 2, 1234 -> PIN richtig +test: 1, 2, 3 -> Karte gesperrt +braucht: doUntilSchleife, verzweigung +tipp: \`do { … } while (…);\` fragt mindestens einmal. Hinter \`while (…)\` steht ein Semikolon. +tipp: Lege vorher \`int pin = 0;\` und \`int versuche = 0;\` an. In der Schleife: \`int eingabe = scanner.nextInt();\`, \`pin = eingabe;\` und \`versuche++;\`. Die Bedingung ist \`pin != 1234 && versuche < 3\`. +lösung: aufgabe-pin-java-loesung.visustruct +::: +`,Gv=`--- +titel: Schiffe versenken +nach: 16 +stufe: 2 +--- + +Beim Spiel Schiffe versenken ist das Meer ein Gitter. Die Spalten heißen A bis E, die Reihen 1 bis 5. Im Startdiagramm steht das Meer als 2D-Array \`meer\`: \`true\` heißt, auf diesem Feld liegt ein Teil eines Schiffs. + +::: grafik schiffe-versenken.svg +Grau heißt \`true\`: Hier liegt ein Schiff. Die kleinen grauen Zahlen sind die Indizes im Array, sie beginnen bei 0. Im Spiel heißen die Felder dagegen A bis E und 1 bis 5. +::: + +::: übung aufgabe-schiffe +titel: Schiffe versenken +auftrag: Gib alle Felder aus, auf denen ein Schiff liegt, jedes Feld in einer eigenen Zeile, z. B. **B1**. Gehe dafür mit zwei verschachtelten Schleifen Reihe für Reihe durch das Meer. + Für das Startdiagramm erscheinen **B1**, **C1**, **D1**, **E3**, **E4** und **A5**. +start: aufgabe-schiffe-start.visustruct +test: - -> B1 | C1 | D1 | E3 | E4 | A5 +braucht: forSchleife, verzweigung +tipp: Gehe das Meer wie den Kinosaal mit zwei verschachtelten Schleifen durch. Gib nur die Felder aus, auf denen \`true\` steht. +tipp: Die äußere Schleife zählt \`reihe\`, die innere \`spalte\`, beide ab 0. Liegt auf \`meer[reihe][spalte]\` ein Schiff, gibst du den Buchstaben aus \`spalten[spalte]\` und die Reihennummer aus: \`output: spalten[spalte] + (reihe + 1)\`. Das \`+ 1\` braucht es, weil das Spiel bei 1 zu zählen beginnt. +lösung: aufgabe-schiffe-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-schiffe-java +titel: Schiffe versenken in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +start: aufgabe-schiffe-start.visustruct +test: - -> B1 | C1 | D1 | E3 | E4 | A5 +braucht: forSchleife, verzweigung +tipp: Zwei \`for\`-Schleifen ineinander: außen die Reihe, innen die Spalte, beide bis \`.length\`. +tipp: \`if (meer[reihe][spalte]) { System.out.println(spalten[spalte] + (reihe + 1)); }\`. Die Klammer um \`reihe + 1\` sorgt dafür, dass Java erst rechnet. +lösung: aufgabe-schiffe-loesung.visustruct +::: +`,Hv=`--- +titel: Speisekarte +nach: 10 +stufe: 1 +--- + +In der Mensa bestellst du über eine Nummer. Das Programm sagt dir, welches Gericht zu der Nummer gehört. + +::: übung aufgabe-speisekarte +titel: Speisekarte +auftrag: Frage nach einer Nummer. Gib bei 1 **Griechischer Salat**, bei 2 **Reis-Bowl** und bei 3 **Falafel-Wrap** aus. Bei jeder anderen Nummer gib **Bitte eine gültige Nummer wählen** aus. +test: 1 -> Griechischer Salat +test: 2 -> Reis-Bowl +test: 3 -> Falafel-Wrap +test: 7 -> Bitte eine gültige Nummer wählen +braucht: fallauswahl +tipp: Für mehrere feste Nummern passt eine Fallauswahl. Was passiert mit allen anderen Nummern? +tipp: Lies die Nummer mit \`input: int nummer "Welches Gericht?"\` ein. Die Fallauswahl prüft \`nummer\`, die Fälle heißen \`1\`, \`2\` und \`3\`. Alle anderen Nummern landen im Fall \`default\`. +lösung: aufgabe-speisekarte-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-speisekarte-java +titel: Speisekarte in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 1 -> Griechischer Salat +test: 2 -> Reis-Bowl +test: 3 -> Falafel-Wrap +test: 7 -> Bitte eine gültige Nummer wählen +braucht: fallauswahl +tipp: In Java ist das eine Fallauswahl mit \`switch (nummer) { … }\`. +tipp: Jeder Fall sieht so aus: \`case 1 -> { System.out.println("…"); }\`. Für alle anderen Nummern gibt es \`default -> { … }\`. +lösung: aufgabe-speisekarte-loesung.visustruct +::: +`,Vv=`--- +titel: Summe bilden +nach: 2 +stufe: 1 +--- + +Lege zwei Zahlen fest, addiere sie und gib das Ergebnis aus. + +::: übung aufgabe-summe +titel: Summe bilden +auftrag: Lege \`zahl1\` mit dem Wert 4 und \`zahl2\` mit dem Wert 3 fest. Berechne die Summe in einer dritten Variablen und gib nur die Summe aus. +test: - -> 7 +tipp: Du brauchst drei Variablen: zwei für die Zahlen und eine für das Ergebnis. +tipp: Eine Variable legst du mit einer Anweisung wie \`int zahl1 = 4\` fest. Für die Ausgabe schreibst du den Namen der Variablen ohne Anführungszeichen. +lösung: aufgabe-summe-loesung.visustruct +::: +`,qv=`--- +titel: Tafeldienst auslosen +nach: 15 +stufe: 2 +--- + +Wer hat diese Woche Tafeldienst? Fünf Namen kommen in ein Array, dann wird eine Losnummer gezogen. + +::: übung aufgabe-tafeldienst +titel: Tafeldienst auslosen +auftrag: Lies fünf Namen in ein String-Array ein. Frage danach nach einer Losnummer von 1 bis 5 und gib **Tafeldienst:** und den passenden Namen aus. + Die Losnummer 1 gehört zum ersten Namen, die 5 zum letzten. +test: Ada, Ben, Cem, Dana, Emil, 3 -> Tafeldienst: Cem +test: Ada, Ben, Cem, Dana, Emil, 1 -> Tafeldienst: Ada +test: Lea, Max, Nia, Ole, Pia, 5 -> Tafeldienst: Pia +braucht: forSchleife +tipp: Erst liest eine Schleife die fünf Namen ein. Danach brauchst du keine Schleife mehr, nur noch einen Zugriff auf ein Fach. +tipp: Mit \`String[] namen = new String[5]\` legst du das Array an. Achtung: Die Losnummer beginnt bei 1, der Index bei 0. Der Name steht also in \`namen[nummer - 1]\`. +lösung: aufgabe-tafeldienst-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-tafeldienst-java +titel: Tafeldienst auslosen in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: Ada, Ben, Cem, Dana, Emil, 3 -> Tafeldienst: Cem +test: Ada, Ben, Cem, Dana, Emil, 1 -> Tafeldienst: Ada +test: Lea, Max, Nia, Ole, Pia, 5 -> Tafeldienst: Pia +braucht: forSchleife +tipp: Ein Array für fünf Namen legst du mit \`String[] namen = new String[5];\` an. +tipp: In der Schleife: \`namen[i] = scanner.next();\`. Die Losnummer 1 gehört zum Fach 0, darum gibst du \`namen[nummer - 1]\` aus. +lösung: aufgabe-tafeldienst-loesung.visustruct +::: + +> Mit \`int nummer = (int) (Math.random() * 5) + 1\` kannst du die Losnummer auch vom Zufall ziehen lassen. Für die automatische Prüfung brauchen wir aber eine feste Eingabe. +`,Qv=`--- +titel: Taschenrechner +nach: 10 +stufe: 2 +--- + +Ein kleiner Taschenrechner: zwei Zahlen und ein Rechenzeichen eingeben, das Ergebnis erscheint. + +::: übung aufgabe-rechner +titel: Taschenrechner +auftrag: Frage nach zwei ganzen Zahlen und danach nach einem Rechenzeichen als Text: \`+\`, \`-\` oder \`*\`. Gib das Ergebnis aus. Bei einem anderen Zeichen gib **Unbekanntes Rechenzeichen** aus. +test: 3, 4, + -> 7 +test: 10, 4, - -> 6 +test: 6, 7, * -> 42 +test: 1, 2, x -> Unbekanntes Rechenzeichen +braucht: fallauswahl +tipp: Lies alle drei Werte ein. Eine Fallauswahl über das Rechenzeichen entscheidet dann, was gerechnet wird. +tipp: Das Rechenzeichen liest du mit \`input: String zeichen "Rechenzeichen"\` ein. Die Fallauswahl prüft \`zeichen\`, die Fälle heißen \`"+"\`, \`"-"\` und \`"*"\`, der letzte Fall ist \`default\`. Rechne in jedem Fall erst in einer Variablen und gib sie dann aus, sonst hängt \`+\` die Zahlen nur aneinander. +lösung: aufgabe-rechner-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-rechner-java +titel: Taschenrechner in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 3, 4, + -> 7 +test: 10, 4, - -> 6 +test: 6, 7, * -> 42 +test: 1, 2, x -> Unbekanntes Rechenzeichen +braucht: fallauswahl +tipp: Das Rechenzeichen ist ein Text. Du liest es mit \`String zeichen = scanner.next();\` ein. +tipp: \`switch (zeichen) { case "+" -> { … } … default -> { … } }\`. Bei Texten stehen die Fälle in Anführungszeichen. +lösung: aufgabe-rechner-loesung.visustruct +::: +`,Uv=`--- +titel: Verleih-Menü +nach: 18 +stufe: 2 +--- + +Am Verleih-Automaten kannst du nacheinander mehrere Fahrzeuge buchen. Das Menü erscheint immer wieder, bis du **0** für Ende wählst. + +::: übung aufgabe-verleih +titel: Verleih-Menü +auftrag: Frage immer wieder nach einer Auswahl: 1 = E-Bike, 2 = E-Scooter, 0 = Ende. Gib bei 1 **E-Bike gebucht** und bei 2 **E-Scooter gebucht** aus, bei jeder anderen Zahl **Ungültige Auswahl**. + Bei 0 gibt das Programm **Tschüss** aus und verlässt die Schleife mit einem Aussprung. +test: 0 -> Tschüss +test: 1, 2, 0 -> E-Bike gebucht | E-Scooter gebucht | Tschüss +test: 2, 5, 1, 0 -> E-Scooter gebucht | Ungültige Auswahl | E-Bike gebucht | Tschüss +braucht: endlosschleife, aussprung +tipp: Das Menü läuft immer wieder, bis jemand 0 wählt. Dafür eignet sich eine Endlosschleife mit einem Aussprung. +tipp: Nimm eine Endlosschleife. Darin steht zuerst die Eingabe \`input: int wahl "1 = E-Bike, 2 = E-Scooter, 0 = Ende"\`, danach eine Fallauswahl über \`wahl\` mit den Fällen \`0\`, \`1\`, \`2\` und \`default\`. Im Fall \`0\` stehen die Ausgabe und darunter der Aussprung. +lösung: aufgabe-verleih-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-verleih-java +titel: Verleih-Menü in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 0 -> Tschüss +test: 1, 2, 0 -> E-Bike gebucht | E-Scooter gebucht | Tschüss +test: 2, 5, 1, 0 -> E-Scooter gebucht | Ungültige Auswahl | E-Bike gebucht | Tschüss +braucht: endlosschleife, aussprung +tipp: \`while (true) { … }\` läuft endlos, bis ein \`break;\` kommt. +tipp: Nimm in Java hier \`if\`/\`else if\` statt \`switch\`: Ein \`break;\` in einem \`switch\` verlässt nur den \`switch\`, nicht die Schleife. \`if (wahl == 0) { System.out.println("Tschüss"); break; } else if (wahl == 1) { … }\`. +lösung: aufgabe-verleih-java-loesung.visustruct +::: +`,$v=`--- +titel: Vokabeltrainer +nach: 27 +stufe: 3 +--- + +Ludwig lernt Englisch. Seine Vokabeln stehen in einer CSV-Datei, links Deutsch, rechts Englisch: + +::: datei vokabeln.csv +Deutsch;Englisch +Ziege;goat +Heu;hay +Wiese;meadow +::: + +Weil nur die Datei die Wörter kennt, kannst du später einfach neue Zeilen anhängen, ohne das Programm zu ändern. + +::: angeberwissen +Die Lernkartei mit mehreren Fächern hat Sebastian Leitner 1972 bekannt gemacht: Gewusste Karten wandern ein Fach weiter und kommen seltener dran, falsche wandern zurück ins erste Fach. Viele Vokabel-Apps arbeiten bis heute nach diesem Prinzip. +::: + +::: übung aufgabe-vokabeln +titel: Vokabeltrainer +code: java +auftrag: Frage jede Vokabel aus der Datei ab: Gib **Was heißt Ziege?** aus und lies die Antwort mit \`scanner.next()\` ein. Ist sie richtig, gib **Richtig!** aus, sonst zum Beispiel **Falsch, richtig ist goat.** + Am Ende steht da, wie viele richtig waren, zum Beispiel **2 von 3 richtig**. +start: aufgabe-vokabeln-start.visustruct +test: goat, hay, meadow -> Was heißt Ziege? | Richtig! | Was heißt Heu? | Richtig! | Was heißt Wiese? | Richtig! | 3 von 3 richtig +test: cow, hay, meadow -> Was heißt Ziege? | Falsch, richtig ist goat. | Was heißt Heu? | Richtig! | Was heißt Wiese? | Richtig! | 2 von 3 richtig +test: goat, heu, wiese -> Was heißt Ziege? | Richtig! | Was heißt Heu? | Falsch, richtig ist hay. | Was heißt Wiese? | Falsch, richtig ist meadow. | 1 von 3 richtig +braucht: whileSchleife, verzweigung +tipp: Überspringe die Kopfzeile. In der Schleife zerlegst du jede Zeile mit \`split(";")\`: \`teile[0]\` ist das deutsche Wort, \`teile[1]\` das englische. +tipp: Texte vergleichst du mit \`antwort.equals(teile[1])\`, nicht mit \`==\`. Zähle vor der Schleife mit \`int richtig = 0;\` und \`int anzahl = 0;\` mit. +lösung: aufgabe-vokabeln-loesung.visustruct +::: +`,Yv=`--- +titel: Volljährig? +nach: 8 +stufe: 1 +--- + +Im Kino, beim Führerschein oder bei der Wahl: Oft kommt es darauf an, ob jemand schon 18 ist. + +::: übung aufgabe-volljaehrig +titel: Volljährig? +auftrag: Frage nach dem Alter. Ist die Person 18 oder älter, gib **volljährig** aus, sonst **minderjährig**. +test: 18 -> volljährig +test: 35 -> volljährig +test: 17 -> minderjährig +test: 6 -> minderjährig +braucht: verzweigung +tipp: Es gibt zwei mögliche Ausgaben, also brauchst du eine Verzweigung. +tipp: Lies das Alter mit \`input: int alter "Wie alt bist du?"\` ein. Die Bedingung der Verzweigung lautet \`alter >= 18\`. Achte darauf, dass 18 schon volljährig ist. +lösung: aufgabe-volljaehrig-loesung.visustruct +::: + +Und jetzt dasselbe in Java: + +::: übung aufgabe-volljaehrig-java +titel: Volljährig? in Java +code: java +auftrag: Löse die Aufgabe von oben jetzt in Java. Die Ausgaben bleiben genau dieselben. +test: 18 -> volljährig +test: 35 -> volljährig +test: 17 -> minderjährig +test: 6 -> minderjährig +braucht: verzweigung +tipp: Lies das Alter mit \`int alter = scanner.nextInt();\` ein. +tipp: \`if (alter >= 18) { … } else { … }\`, in jedem Zweig ein \`System.out.println(…)\`. +lösung: aufgabe-volljaehrig-loesung.visustruct +::: +`,Xv=`--- +titel: Würfeln mit MVC +nach: 40 +stufe: 3 +--- + +Baue ein Würfelspiel nach Model View Controller. Ein Knopf **Würfeln** würfelt, und zwei Views zeigen das Ergebnis. + +Das Model ist schon fertig. Es würfelt und zählt mit, wie oft gewürfelt wurde und wie viele Sechsen dabei waren: + +\`\`\`java +class Wuerfel { + int augen = 1; + int wuerfe = 0; + int sechsen = 0; + + void wuerfeln() { + augen = (int) (Math.random() * 6) + 1; + wuerfe++; + if (augen == 6) { + sechsen++; + } + } +} +\`\`\` + +Deine Aufgabe: + +1. Teste das Model zuerst ohne Fenster: Würfle in \`main\` zehnmal und gib danach \`wuerfe\` und \`sechsen\` aus. +2. Schreibe die View \`AugenAnzeige\`. Sie zeigt in einem großen JLabel die gewürfelte Zahl, zum Beispiel „4“. +3. Schreibe die View \`StatistikAnzeige\`. Sie zeigt zum Beispiel „Sechsen: 2 von 10 Würfen“. +4. Der Controller ist der Zuhörer am Knopf: Er lässt das Model würfeln und gibt beiden Views die neuen Werte. + +Zusatz: Ein Knopf **Neues Spiel** setzt alles auf Anfang. Die Methode dafür gehört ins Model. + +::: ludwig +Denk an die Regel aus Lektion 40: Im Model steht kein einziges \`JLabel\`. Wenn du beim Würfeln die Schriftgröße änderst, gehört das in die View. +::: +`,Kv=`--- +titel: Zahl verdoppeln +nach: 2 +stufe: 1 +--- + +Eine Variable kann ihren Wert ändern. Hier wird eine Zahl verdoppelt. + +::: übung aufgabe-verdoppeln +titel: Zahl verdoppeln +auftrag: Lege die Variable \`zahl\` mit dem Wert 4 fest. Verdopple sie in einer zweiten Anweisung, ohne eine neue Variable anzulegen. Gib danach **Verdoppelte Zahl: 8** aus, wobei die 8 aus der Variablen kommt. +test: - -> Verdoppelte Zahl: 8 +tipp: Verdoppeln heißt: mal 2. Das Ergebnis speicherst du wieder in derselben Variablen. +tipp: \`zahl = zahl * 2\` rechnet mit dem alten Wert und speichert das Ergebnis wieder in \`zahl\`. Text und Variable verbindest du mit \`+\`. +lösung: aufgabe-verdoppeln-loesung.visustruct +::: +`,ey=`--- +titel: Age in a subprogram +nach: 18 +stufe: 2 +--- + +The age check from “Adult?” now becomes a subprogram of its own. The main program only calls it. + +::: übung aufgabe-alter-unterprogramm +titel: Age in a subprogram +auftrag: Build two diagrams. The main program outputs **Welcome**, then calls \`checkAge()\` and finally outputs **Goodbye**. + The subprogram \`checkAge\` is in a tab of its own: it asks for the age and outputs **adult** or **minor**. +test: 20 -> Welcome | adult | Goodbye +test: 18 -> Welcome | adult | Goodbye +test: 12 -> Welcome | minor | Goodbye +braucht: aufruf +tipp: The main program has three boxes. The subprogram does the real work. +tipp: Open the exercise in the editor and build the main program there with the call \`checkAge()\`. Then open a new tab with **+** and give it the title \`checkAge\`. Build the input and the branch in it. Check finds the subprogram by the title of the tab. +lösung: aufgabe-alter-haupt-loesung.visustruct +unterprogramm: aufgabe-alter-unterprogramm-loesung.visustruct +::: +`,ty=`--- +titel: Ball throw results +nach: 25 +stufe: 2 +--- + +At sports day everyone wrote their ball throw distance into a table: + +::: datei throw.csv +Name;Distance +Ludwig;28 +Zora;42 +Fox;35 +Hare;21 +::: + +::: übung aufgabe-ballwurf +titel: Ball throw results +code: java +auftrag: Read the file and skip the header line. Output how many took part (**Participants: 4**) and how far they threw on average (**Average: 31.5 m**). + Save the longest throw in the file **winner.txt**, for example **Winner: Zora (42 m)**. +start: aufgabe-ballwurf-start.visustruct +test: - -> Participants: 4 | Average: 31.5 m +datei: winner.txt -> Winner: Zora (42 m) +braucht: whileSchleife, verzweigung +tipp: You need four variables before the loop: the count, the sum as a \`double\`, the best distance and the best name. +tipp: In the loop: \`String[] parts = line.split(";");\` and \`int distance = Integer.parseInt(parts[1]);\`. If \`distance > bestDistance\`, remember the distance and the name. To save: \`PrintWriter out = new PrintWriter("winner.txt");\`, \`out.println(…)\` and \`out.close();\`. +lösung: aufgabe-ballwurf-loesung.visustruct +::: +`,ny=`--- +titel: Leaderboard +nach: 19 +stufe: 2 +--- + +Five goats have run the obstacle race. Now the leaderboard goes on the stable door: most points at the top, fewest at the bottom. + +::: übung aufgabe-bestenliste +titel: Leaderboard +auftrag: Read 5 scores into an array. Sort the array with bubble sort in **descending** order, so the biggest number comes first. Then output the list with places, for example **1. 9**, on the next line **2. 9** and so on. +test: 3, 9, 2, 9, 1 -> 1. 9 | 2. 9 | 3. 3 | 4. 2 | 5. 1 +test: 10, 20, 30, 40, 50 -> 1. 50 | 2. 40 | 3. 30 | 4. 20 | 5. 10 +test: 5, 4, 3, 2, 1 -> 1. 5 | 2. 4 | 3. 3 | 4. 2 | 5. 1 +braucht: forSchleife, verzweigung +tipp: Bubble sort from lesson 19 sorts in ascending order. For descending order you only turn round the comparison of the neighbours. +tipp: Swap when \`points[i] < points[i + 1]\`, using a temporary variable. For the output, first work out \`int place = i + 1\` and then output \`place + ". " + points[i]\`. +lösung: aufgabe-bestenliste-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-bestenliste-java +titel: Leaderboard in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 3, 9, 2, 9, 1 -> 1. 9 | 2. 9 | 3. 3 | 4. 2 | 5. 1 +test: 10, 20, 30, 40, 50 -> 1. 50 | 2. 40 | 3. 30 | 4. 20 | 5. 10 +test: 5, 4, 3, 2, 1 -> 1. 5 | 2. 4 | 3. 3 | 4. 2 | 5. 1 +braucht: forSchleife, verzweigung +tipp: Read each number into a variable first and then put it into the array: \`int number = scanner.nextInt();\` and \`points[i] = number;\`. +tipp: The swap needs a temporary variable in Java too: \`int temp = points[i]; points[i] = points[i + 1]; points[i + 1] = temp;\`. +lösung: aufgabe-bestenliste-loesung.visustruct +::: +`,iy=`--- +titel: Binary number +nach: 11 +stufe: 3 +--- + +Computers calculate with only two digits: 0 and 1. This is how you convert a number into the **binary system**: + +1. Divide the number by 2 and remember the remainder (0 or 1). +2. Carry on with the result without the remainder. +3. Repeat this until the number is 0. + +The remainders read **from bottom to top** give the binary number. For 6 the remainders are 0, 1, 1, so the binary number is 110. + +::: übung aufgabe-binaer +titel: Binary number +auftrag: Ask for a whole number greater than 0 and output it as a binary number. For 6 the output is **110**, for 13 **1101**. +test: 6 -> 110 +test: 13 -> 1101 +test: 1 -> 1 +test: 8 -> 1000 +braucht: whileSchleife +tipp: Keep dividing the number by 2 and remember every remainder. The remainders read backwards give the binary number. +tipp: Collect the digits in a text: \`String binary = ""\`. In the loop you calculate \`int remainder = number % 2\` and add the remainder at the **front**: \`binary = remainder + binary\`. After that, \`number = number / 2\`. Because number is a whole number, the remainder is dropped. +lösung: aufgabe-binaer-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-binaer-java +titel: Binary number in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 6 -> 110 +test: 13 -> 1101 +test: 1 -> 1 +test: 8 -> 1000 +braucht: whileSchleife +tipp: Start with \`String binary = "";\`. The loop runs with \`while (number > 0)\`. +tipp: In the body: \`int remainder = number % 2;\`, then \`binary = remainder + binary;\` and \`number = number / 2;\`. Because \`binary\` is a String, \`+\` puts the remainder at the front. +lösung: aufgabe-binaer-loesung.visustruct +::: +`,ay=`--- +titel: Caesar cipher +nach: 17 +stufe: 3 +--- + +More than 2000 years ago, the Roman general Julius Caesar sent secret messages to his troops. His trick was simple: he replaced every letter with the letter **three places further on** in the alphabet. A becomes D, B becomes E and so on. The readable message is called the **plain text**, the encrypted one the **secret text**. The number of places you shift by is the **key**, often just called \`k\`. + +::: grafik caesar-verschiebung.svg +Encryption with the key 3: each letter at the top becomes the letter below it. At the end you start again from the beginning, so X, Y and Z become A, B and C. +::: + +This turns \`HALLO\` into \`KDOOR\`. Anyone who knows the key simply shifts three places back and can read the message again. + +### The cipher wheel + +To avoid counting every time, people built a **cipher wheel**: two discs with the alphabet, a small one on top of a large one, fixed in the middle so it can turn. The outer ring shows the plain text, the inner ring the secret text. Turn the inner disc by three letters, and below every outer letter you find its secret letter. Wheels like this have existed since the 15th century. In the American Civil War (1861–1865), soldiers carried small brass wheels. + +::: grafik caesar-scheibe.svg +A cipher wheel modelled on historical brass wheels. The blue window shows: with the key 3, D is below A. +::: + +::: angeberwissen +Caesar himself didn’t even have a wheel! We know this from the Roman historian Suetonius: in his letters, Caesar shifted every letter by three places and simply counted it out in his head. The wheel was only invented by Leon Battista Alberti around 1467, about 1500 years later. By the way, I count in my head too. I don’t have fingers, only hooves. +::: + +Try it yourself. Turn the inner wheel, type a text and watch the secret text appear. **Decrypt** goes the other way. + +::: caesar 3 +LUDWIG +::: + +::: ludwig +You can easily make a real wheel yourself: two circles of cardboard, one a bit smaller, each with 26 equal fields for the alphabet, and a paper fastener in the middle. Your secret agent tool is ready! +::: + +::: quiz +? What does the letter Y become with the key 3? +- [ ] A +- [x] B +- [ ] C +> After Y comes Z, then you start again with A and B. Three places further on is therefore B. + +? A secret text was encrypted with the key 5. How do you decrypt it? +- [ ] Shift it 5 places further on again +- [x] Shift it 5 places back +- [ ] Read the letters backwards +> Decrypting is the opposite of encrypting. By the way, 5 places back is the same as 21 places forward, because 5 + 21 = 26. +::: + +### The program: there is more than one way + +How do you teach the computer to shift a letter by \`k\` places? There is no *single* right solution. We look at two ways. Both go through the text character by character with a for loop, just like in the lesson on strings. The difference is how they shift a single letter. + +In both ways the remainder operator \`%\` helps. It makes sure that after Z you continue with A: positions 0 to 25 stay as they are, 26 becomes 0, 27 becomes 1 and so on. + +### Way 1: the alphabet in an array + +You put the alphabet into an array \`char[] alphabet = {'A', 'B', …, 'Z'}\`. For every letter of the word you search the array for its position \`pos\`, that is its index. The secret letter is then in the same array at position \`(pos + k) % 26\`. + +An example with the key 3: X is at position 23. Then \`(23 + 3) % 26 = 0\`, and position 0 holds A. + +::: übung aufgabe-caesar-array +titel: Caesar with an array +auftrag: The start diagram already contains the array \`alphabet\`. Ask for a word in capital letters and for the key \`k\`. Then output the encrypted word. For HALLO and 3 that is \`KDOOR\`. +start: aufgabe-caesar-array-start.visustruct +test: HALLO, 3 -> KDOOR +test: ZEBRA, 1 -> AFCSB +test: LUDWIG, 13 -> YHQJVT +braucht: forSchleife, verzweigung +tipp: Create an empty text \`String secret = ""\`. Go through the word character by character with a for loop. In every pass you append one secret letter to \`secret\`. +tipp: To find the position of a letter you need a second, inner loop over the array: if \`alphabet[j] == letter\`, remember \`pos = j\`. +tipp: After the inner loop, append \`alphabet[(pos + k) % 26]\`: \`secret = secret + alphabet[(pos + k) % 26]\`. After the outer loop, output \`secret\`. +lösung: aufgabe-caesar-array-loesung.visustruct +::: + +### Way 2: calculating with the ASCII table + +For the computer, every character is really a number. Which number belongs to which character is listed in the **ASCII table**. There A has the code 65, B the code 66 and so on up to Z with 90. In Java you turn a character into its code with \`(int)\` and a code back into a character with \`(char)\`: + +\`\`\` +int code = (int) 'A' +char letter = (char) 68 +\`\`\` + +After that, \`code\` is 65 and \`letter\` is \`'D'\`. Changing a value from one data type into another like this is called a **type cast**. + +Now you can calculate with the letter. So that the jump from Z back to A works, first subtract 65. Then A has position 0 and Z position 25, exactly as in way 1. Shift with \`% 26\` and add the 65 back at the end: + +::: grafik caesar-ascii.svg +At the top the capital letters with their ASCII codes. Below, the calculation for X with the key 3: the result is A. +::: + +::: übung aufgabe-caesar-ascii +titel: Caesar with ASCII +code: java +auftrag: Write a Java program that reads a word in capital letters and the key \`k\` and outputs the encrypted word. This time without an array: calculate with \`(int)\` and \`(char)\`. +test: HALLO, 3 -> KDOOR +test: ZEBRA, 1 -> AFCSB +test: LUDWIG, 13 -> YHQJVT +braucht: forSchleife +tipp: Go through the word with a for loop. You get the code of the character at position \`i\` with \`int code = (int) word.charAt(i);\`. +tipp: Calculate \`code = (code - 65 + k) % 26 + 65;\` and append the character: \`secret = secret + (char) code;\`. Before the loop write \`String secret = "";\`, after the loop \`System.out.println(secret);\`. +lösung: aufgabe-caesar-ascii-loesung.visustruct +::: + +### Which way is better? + +**Way 1: array.** The idea is to search for the position in the array. +- Advantage: easy to understand, and your own alphabets work too, e.g. with Ä, Ö and Ü. +- Disadvantage: every letter has to be searched for. + +**Way 2: ASCII.** The idea is to calculate with the character code. +- Advantage: short and without searching, therefore faster. +- Disadvantage: you need to know the ASCII codes. + +Both programs give the same result. That is often how programming works: there are several correct solutions, and you choose the one that fits your task best. + +::: übung aufgabe-caesar-entschluesseln +titel: Decrypt Caesar +code: java +auftrag: Now turn the tables. Read a secret text in capital letters and the key \`k\` and output the plain text. For KDOOR and 3 that is \`HALLO\`. You decide which way to use. +test: KDOOR, 3 -> HALLO +test: AFCSB, 1 -> ZEBRA +test: YHQJVT, 13 -> LUDWIG +braucht: forSchleife +tipp: Decrypting means shifting \`k\` places back instead of forward. So \`+ k\` becomes \`- k\`. +tipp: Careful with A: \`0 - 3\` gives -3, and in Java \`%\` does not turn that into a positive number. So add another 26: \`code = (code - 65 - k + 26) % 26 + 65;\` +lösung: aufgabe-caesar-entschluesseln-loesung.visustruct +::: + +::: angeberwissen +Unfortunately, Caesar is not secure. There are only 25 keys, and you can try them all in a few minutes. It is even quicker with a trick: in English, E is the most common letter. If H is the most common letter in the secret text, the key was probably 3. On the internet there is also ROT13, which is Caesar with the key 13. Applying ROT13 twice gives you the plain text again, because 13 + 13 = 26. +::: +`,sy=`--- +titel: Collatz sequence +nach: 11 +stufe: 2 +--- + +The Collatz sequence is a famous puzzle in mathematics. You start with a number and apply the same rule again and again: + +- If the number is **even**, you divide it by 2. +- If it is **odd**, you multiply it by 3 and add 1. + +So far, for every start number anyone has tried, the sequence ends at 1 at some point. Whether this is true for all numbers, nobody knows to this day. + +::: übung aufgabe-collatz +titel: Collatz sequence +auftrag: Ask for a start number. Apply the rule until the number is 1, and output the new number after every step. Count the steps as you go and output **Steps:** and the count at the end. + With the start number 6 the sequence is 3, 10, 5, 16, 8, 4, 2, 1. That is 8 steps. +test: 6 -> 3 | 10 | 5 | 16 | 8 | 4 | 2 | 1 | Steps: 8 +test: 3 -> 10 | 5 | 16 | 8 | 4 | 2 | 1 | Steps: 7 +test: 1 -> Steps: 0 +braucht: whileSchleife, verzweigung +tipp: You do not know how many steps there will be. That is why a while loop fits better than a for loop. +tipp: The while loop runs as long as \`number != 1\`. You check whether a number is even with \`number % 2 == 0\`. The output and \`steps++\` come after the branch, but still inside the loop. +lösung: aufgabe-collatz-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-collatz-java +titel: Collatz sequence in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 6 -> 3 | 10 | 5 | 16 | 8 | 4 | 2 | 1 | Steps: 8 +test: 3 -> 10 | 5 | 16 | 8 | 4 | 2 | 1 | Steps: 7 +test: 1 -> Steps: 0 +braucht: whileSchleife, verzweigung +tipp: A \`while\` loop runs as long as \`number != 1\`. Inside it, an \`if\` with \`number % 2 == 0\` decides. +tipp: In the body: halve it or \`number = number * 3 + 1;\`, then \`System.out.println(number);\` and \`steps++;\`. After the loop comes \`"Steps: " + steps\`. +lösung: aufgabe-collatz-loesung.visustruct +::: + +::: angeberwissen +This task could make you rich! The mathematician Paul Erdős offered 500 dollars for a proof. In 2021 the Japanese company Bakuage added quite a bit more: 120 million yen, about a million dollars at the time, for a proof or a counterexample. Nobody has collected the money yet. By the way, the puzzle was invented by the German mathematician Lothar Collatz in 1937. I am going to start calculating right now; that much money buys a lot of hay. +::: +`,ry=`--- +titel: Unit converter +nach: 35 +stufe: 2 +--- + +Build a window that converts lengths. At the top you type a length in metres, below it there are three buttons: + +- **in cm** shows the length in centimetres, 1.5 becomes "150.0 cm", +- **in mm** shows it in millimetres, 1.5 becomes "1500.0 mm", +- **in km** shows it in kilometres, 1500 becomes "1.5 km". + +The result is shown in a JLabel below the buttons. If the field doesn't contain a number, it says "Please enter a number", and the program doesn't crash. + +You can start like this: + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Units { + public static void main(String[] args) { + JFrame window = new JFrame("Unit converter"); + window.setSize(300, 200); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + window.setLayout(new GridLayout(0, 1)); + + JTextField metres = new JTextField(); + JButton inCm = new JButton("in cm"); + JLabel result = new JLabel("?", SwingConstants.CENTER); + + inCm.addActionListener(e -> { + double m = Double.parseDouble(metres.getText()); + result.setText((m * 100) + " cm"); + }); + + window.add(metres); + window.add(inCm); + window.add(result); + window.setVisible(true); + } +} +\`\`\` + +Extra: a fourth button **in feet** converts to the imperial unit. One foot is 0.3048 m. + +::: ludwig +Tick **Real Java (with Swing)** in the [gear](#zeige-einstellungen). For "abc" in the field, every listener needs a try/catch with \`NumberFormatException\`, just like the calculator. +::: +`,oy=`--- +titel: Fibonacci numbers +nach: 13 +stufe: 2 +--- + +With the Fibonacci numbers, every number is the sum of the two numbers before it. The sequence starts with 1 and 1: + +1, 1, 2, 3, 5, 8, 13, 21, … + +You find these numbers surprisingly often in nature, for example in the way sunflower seeds are arranged. + +::: ludwig +Do you remember **swapping** from lesson 5? There you needed a helper variable, because \`a = b\` overwrites the old value of \`a\`. It is the same here: before \`number2\` gets the new number, its old value must be saved in \`number1\`. So watch the **order**: first \`number1 = number2\`, then \`number2 = number3\`. You will need this moving on and swapping again later, for example when sorting in lesson 19. +::: + +::: angeberwissen +In 1202 Leonardo of Pisa, known as Fibonacci, set a puzzle about rabbits in his arithmetic book: from its second month on, every pair of rabbits has a new pair every month. How many pairs are there after a year? The answer is this sequence. Sadly, there were no goats in the book. +::: + +::: übung aufgabe-fibonacci +titel: Fibonacci numbers +auftrag: Ask how many Fibonacci numbers should be output. Then output exactly that many, each on its own line. You can assume that at least 2 is typed in. +test: 5 -> 1 | 1 | 2 | 3 | 5 +test: 8 -> 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 +test: 2 -> 1 | 1 +braucht: forSchleife +tipp: Every new number is the sum of the two before it. So you always have to remember the last two numbers. +tipp: Keep the last two numbers in \`number1\` and \`number2\` and output both before the loop. The loop starts at \`int i = 2\`. Inside it you calculate \`int number3 = number1 + number2\`, output it and then move on: \`number1 = number2\` and \`number2 = number3\`. +lösung: aufgabe-fibonacci-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-fibonacci-java +titel: Fibonacci numbers in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 5 -> 1 | 1 | 2 | 3 | 5 +test: 8 -> 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 +test: 2 -> 1 | 1 +braucht: forSchleife +tipp: Output the first two numbers before the loop. The \`for\` loop then starts at \`int i = 2\`. +tipp: In the body: \`int number3 = number1 + number2;\`, output it, then \`number1 = number2;\` and \`number2 = number3;\`. +lösung: aufgabe-fibonacci-loesung.visustruct +::: + +::: quiz +? Why must \`number1 = number2\` come before \`number2 = number3\` in the loop? +- [ ] Because otherwise Java does not allow the assignments +- [x] Because otherwise the old value of number2 is overwritten before number1 gets it +- [ ] The order does not matter +> The other way round, number1 and number2 would have the same value afterwards. Just like swapping: first save, then overwrite. +::: +`,ly=`--- +titel: Even or odd +nach: 8 +stufe: 1 +--- + +A number is even if there is no remainder when you divide it by 2. You calculate the remainder with \`%\`: \`8 % 2\` is 0, \`7 % 2\` is 1. + +::: übung aufgabe-gerade +titel: Even or odd +auftrag: Ask for a whole number. Output whether it is even or odd. For 4 the output is **4 is even**, for 7 **7 is odd**. +test: 4 -> 4 is even +test: 7 -> 7 is odd +test: 0 -> 0 is even +test: 15 -> 15 is odd +braucht: verzweigung +tipp: A branch decides between even and odd. Even means: can be divided by 2 without a remainder. +tipp: The condition is \`number % 2 == 0\`. In the output you join the number and the text with \`+\`, e.g. \`number + " is even"\`. +lösung: aufgabe-gerade-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-gerade-java +titel: Even or odd in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 4 -> 4 is even +test: 7 -> 7 is odd +test: 0 -> 0 is even +test: 15 -> 15 is odd +braucht: verzweigung +tipp: Read a number with \`int number = scanner.nextInt();\`. Ask with \`System.out.println(…)\` before that. +tipp: \`if (number % 2 == 0) { … } else { … }\`. The output is \`System.out.println(number + " is even");\`. +lösung: aufgabe-gerade-loesung.visustruct +::: +`,uy=`--- +titel: Sales tax +nach: 6 +stufe: 1 +--- + +In Germany, 19 % **VAT** (value added tax, a kind of sales tax) is added to almost everything you buy. The shop calculates with the net price (without tax) and adds the tax on top. That gives the gross price you pay at the till. + +An example: you buy a folding phone that opens up into a tablet. The shop's price tag says 1000 euros net. On top of that come 19 %, so 190 euros. At the till you pay 1190 euros. The shop is not allowed to keep the 190 euros: it passes them on to the tax office. + +::: grafik aufgabe-mehrwertsteuer.svg +Net price plus VAT gives the gross price. The VAT goes to the tax office. +::: + +::: angeberwissen +Baah, the shop bought the phone itself, of course: from the manufacturer for 800 euros plus 152 euros VAT. These 152 euros are called **input tax**, and the shop may subtract them from the 190 euros. So it only transfers 38 euros to the tax office. In the end only one person pays the whole tax: the customer at the till. That is you. I pay no tax at all, by the way. I just eat grass. +::: + +The tax rate never changes while you calculate. That is why you create it as a **constant**: a variable whose value stays the same once it is set. You write \`const\` in front of it, for example \`const double VAT = 0.19\`. Names of constants are written in capital letters so you recognise them straight away. In Java code this becomes \`final double VAT = 0.19;\`. + +If the tax rate ever changes, you only have to change this one line. + +::: übung aufgabe-mehrwertsteuer +titel: Sales tax +auftrag: Create the constant \`VAT\` with the value 0.19. Then ask for the net price. First output the tax and then the gross price, only the number each time. + For a net price of 100 the outputs are **19** and **119**. +test: 100 -> 19 | 119 +test: 50 -> 9.5 | 59.5 +test: 0 -> 0 | 0 +tipp: The tax is 19 percent of the net price. The gross price is what you pay in the end. +tipp: The tax is \`netPrice * VAT\`. You get the gross price by adding the tax to the net price. Both values are decimal numbers, so \`double\`. +lösung: aufgabe-mehrwertsteuer-loesung.visustruct +::: + +::: quiz +? Why do you create the tax rate as a constant? +- [ ] Because constants are calculated faster +- [x] Because its value should not change in the program +- [ ] Because decimal numbers can only be stored as constants +> A constant keeps its value. If the tax rate ever changes, you only change the one line with \`const\`. +::: +`,cy=`--- +titel: Grade average +nach: 13 +stufe: 2 +--- + +How did you do lately? The average is the sum of all grades divided by how many there are. + +::: übung aufgabe-durchschnitt +titel: Grade average +auftrag: First ask how many grades will be typed in. Then read in exactly that many grades and output the average, only the number. + For the grades 1 and 2 the average is **1.5**. +test: 2, 1, 2 -> 1.5 +test: 3, 1, 2, 3 -> 2 +test: 4, 2, 2, 3, 4 -> 2.75 +braucht: forSchleife +tipp: You need the sum of all grades and how many there are. The average is the sum divided by the count. +tipp: The for loop runs from \`int i = 0\` while \`i < count\`. Inside it you read in a grade and add it to the sum. You store the average as a decimal number: \`double average = sum * 1.0 / count\`. The \`* 1.0\` makes sure that Java does not do whole-number division either. +lösung: aufgabe-durchschnitt-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-durchschnitt-java +titel: Grade average in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 2, 1, 2 -> 1.5 +test: 3, 1, 2, 3 -> 2 +test: 4, 2, 2, 3, 4 -> 2.75 +braucht: forSchleife +tipp: \`for (int i = 0; i < count; i++)\` reads exactly as many grades as were given before. +tipp: Divide with \`double average = sum * 1.0 / count;\`. Without \`* 1.0\`, Java divides two \`int\` values as whole numbers, and 1.5 becomes 1. +lösung: aufgabe-durchschnitt-loesung.visustruct +::: +`,my=`--- +titel: Check the PIN +nach: 12 +stufe: 2 +--- + +At a cash machine you have three tries for your PIN. If you type a wrong PIN three times, the card is blocked. + +::: angeberwissen +John Shepherd-Barron, who set up the first cash machine in London in 1967, actually wanted six-digit PINs. But his wife said she could remember four digits at most. That is why your PIN has four digits today. +::: + +::: übung aufgabe-pin +titel: Check the PIN +auftrag: The right PIN is 1234. Keep asking for the PIN until it is right or three tries have been used. Then output **PIN correct** or **Card blocked**. +test: 1234 -> PIN correct +test: 1111, 1234 -> PIN correct +test: 1, 2, 1234 -> PIN correct +test: 1, 2, 3 -> Card blocked +braucht: doUntilSchleife, verzweigung +tipp: The loop ends in two cases: when the PIN is right or when three tries have been used. Count the tries. +tipp: The PIN is asked for at least once, so a do-while loop fits. Create \`int pin = 0\` and \`int attempts = 0\` before it. The loop repeats as long as \`pin != 1234 && attempts < 3\`. After the loop, a branch decides what is output. +lösung: aufgabe-pin-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-pin-java +titel: Check the PIN in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 1234 -> PIN correct +test: 1111, 1234 -> PIN correct +test: 1, 2, 1234 -> PIN correct +test: 1, 2, 3 -> Card blocked +braucht: doUntilSchleife, verzweigung +tipp: \`do { … } while (…);\` asks at least once. There is a semicolon after \`while (…)\`. +tipp: Create \`int pin = 0;\` and \`int attempts = 0;\` first. In the loop: \`int entered = scanner.nextInt();\`, \`pin = entered;\` and \`attempts++;\`. The condition is \`pin != 1234 && attempts < 3\`. +lösung: aufgabe-pin-java-loesung.visustruct +::: +`,dy=`--- +titel: Battleship +nach: 16 +stufe: 2 +--- + +In the game Battleship the sea is a grid. The columns are called A to E, the rows 1 to 5. In the start diagram the sea is the 2D array \`sea\`: \`true\` means that part of a ship is on this square. + +::: grafik schiffe-versenken.svg +Grey means \`true\`: there is a ship here. The small grey numbers are the indices in the array; they start at 0. In the game, on the other hand, the squares are called A to E and 1 to 5. +::: + +::: übung aufgabe-schiffe +titel: Battleship +auftrag: Output all squares that have a ship on them, each square on its own line, e.g. **B1**. Go through the sea row by row with two nested loops. + For the start diagram, **B1**, **C1**, **D1**, **E3**, **E4** and **A5** appear. +start: aufgabe-schiffe-start.visustruct +test: - -> B1 | C1 | D1 | E3 | E4 | A5 +braucht: forSchleife, verzweigung +tipp: Go through the sea with two nested loops, just like the cinema. Only output the squares that hold \`true\`. +tipp: The outer loop counts \`row\`, the inner one \`column\`, both from 0. If there is a ship on \`sea[row][column]\`, you output the letter from \`columns[column]\` and the row number: \`output: columns[column] + (row + 1)\`. You need the \`+ 1\` because the game starts counting at 1. +lösung: aufgabe-schiffe-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-schiffe-java +titel: Battleship in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +start: aufgabe-schiffe-start.visustruct +test: - -> B1 | C1 | D1 | E3 | E4 | A5 +braucht: forSchleife, verzweigung +tipp: Two \`for\` loops inside each other: the row outside, the column inside, both up to \`.length\`. +tipp: \`if (sea[row][column]) { System.out.println(columns[column] + (row + 1)); }\`. The brackets around \`row + 1\` make Java calculate first. +lösung: aufgabe-schiffe-loesung.visustruct +::: +`,hy=`--- +titel: Menu +nach: 10 +stufe: 1 +--- + +In the school canteen you order by number. The program tells you which dish belongs to the number. + +::: übung aufgabe-speisekarte +titel: Menu +auftrag: Ask for a number. For 1 output **Greek salad**, for 2 **Rice bowl** and for 3 **Falafel wrap**. For any other number output **Please choose a valid number**. +test: 1 -> Greek salad +test: 2 -> Rice bowl +test: 3 -> Falafel wrap +test: 7 -> Please choose a valid number +braucht: fallauswahl +tipp: A switch fits several fixed numbers. What happens with all the other numbers? +tipp: Read in the number with \`input: int pick "Which dish?"\`. The switch checks \`pick\`, and the cases are called \`1\`, \`2\` and \`3\`. All other numbers end up in the case \`default\`. +lösung: aufgabe-speisekarte-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-speisekarte-java +titel: Menu in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 1 -> Greek salad +test: 2 -> Rice bowl +test: 3 -> Falafel wrap +test: 7 -> Please choose a valid number +braucht: fallauswahl +tipp: In Java this is a switch: \`switch (pick) { … }\`. +tipp: Every case looks like this: \`case 1 -> { System.out.println("…"); }\`. All other numbers go to \`default -> { … }\`. +lösung: aufgabe-speisekarte-loesung.visustruct +::: +`,gy=`--- +titel: Add up +nach: 2 +stufe: 1 +--- + +Set two numbers, add them and output the result. + +::: übung aufgabe-summe +titel: Add up +auftrag: Set \`number1\` to the value 4 and \`number2\` to the value 3. Calculate the sum in a third variable and output only the sum. +test: - -> 7 +tipp: You need three variables: two for the numbers and one for the result. +tipp: You set a variable with a statement such as \`int number1 = 4\`. For the output you write the name of the variable without quotation marks. +lösung: aufgabe-summe-loesung.visustruct +::: +`,py=`--- +titel: Draw for board duty +nach: 15 +stufe: 2 +--- + +Who is on board duty this week, cleaning the board? Five names go into an array, then a number is drawn. + +::: übung aufgabe-tafeldienst +titel: Draw for board duty +auftrag: Read five names into a String array. Then ask for a draw number from 1 to 5 and output **Board duty:** and the matching name. + Draw number 1 belongs to the first name, 5 to the last one. +test: Ada, Ben, Cem, Dana, Emil, 3 -> Board duty: Cem +test: Ada, Ben, Cem, Dana, Emil, 1 -> Board duty: Ada +test: Lea, Max, Nia, Ole, Pia, 5 -> Board duty: Pia +braucht: forSchleife +tipp: First a loop reads in the five names. After that you do not need a loop any more, just one look into a slot. +tipp: You create the array with \`String[] names = new String[5]\`. Careful: the draw number starts at 1, the index at 0. So the name is in \`names[pick - 1]\`. +lösung: aufgabe-tafeldienst-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-tafeldienst-java +titel: Draw for board duty in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: Ada, Ben, Cem, Dana, Emil, 3 -> Board duty: Cem +test: Ada, Ben, Cem, Dana, Emil, 1 -> Board duty: Ada +test: Lea, Max, Nia, Ole, Pia, 5 -> Board duty: Pia +braucht: forSchleife +tipp: Create an array for five names with \`String[] names = new String[5];\`. +tipp: In the loop: \`names[i] = scanner.next();\`. Ticket number 1 belongs to slot 0, so you output \`names[pick - 1]\`. +lösung: aufgabe-tafeldienst-loesung.visustruct +::: + +> With \`int pick = (int) (Math.random() * 5) + 1\` you can also let chance draw the number. But for the automatic check we need a fixed input. +`,fy=`--- +titel: Calculator +nach: 10 +stufe: 2 +--- + +A small calculator: type in two numbers and an operator, and the result appears. + +::: übung aufgabe-rechner +titel: Calculator +auftrag: Ask for two whole numbers and then for an operator as text: \`+\`, \`-\` or \`*\`. Output the result. For any other sign output **Unknown operator**. +test: 3, 4, + -> 7 +test: 10, 4, - -> 6 +test: 6, 7, * -> 42 +test: 1, 2, x -> Unknown operator +braucht: fallauswahl +tipp: Read in all three values. A switch on the operator then decides what is calculated. +tipp: You read in the operator with \`input: String operator "Operator"\`. The switch checks \`operator\`, the cases are called \`"+"\`, \`"-"\` and \`"*"\`, and the last case is \`default\`. In every case, first calculate in a variable and then output it, otherwise \`+\` only joins the numbers together. +lösung: aufgabe-rechner-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-rechner-java +titel: Calculator in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 3, 4, + -> 7 +test: 10, 4, - -> 6 +test: 6, 7, * -> 42 +test: 1, 2, x -> Unknown operator +braucht: fallauswahl +tipp: The operator is a text. Read it with \`String operator = scanner.next();\`. +tipp: \`switch (operator) { case "+" -> { … } … default -> { … } }\`. With texts, the cases are in quotation marks. +lösung: aufgabe-rechner-loesung.visustruct +::: +`,by=`--- +titel: Rental menu +nach: 18 +stufe: 2 +--- + +At the rental machine you can book several vehicles one after another. The menu keeps coming back until you choose **0** to quit. + +::: übung aufgabe-verleih +titel: Rental menu +auftrag: Keep asking for a choice: 1 = e-bike, 2 = e-scooter, 0 = quit. For 1 output **E-bike booked**, for 2 **E-scooter booked**, and for any other number **Invalid choice**. + For 0 the program outputs **Bye** and leaves the loop with a Break. +test: 0 -> Bye +test: 1, 2, 0 -> E-bike booked | E-scooter booked | Bye +test: 2, 5, 1, 0 -> E-scooter booked | Invalid choice | E-bike booked | Bye +braucht: endlosschleife, aussprung +tipp: The menu runs again and again until someone chooses 0. An endless loop with a Break is good for that. +tipp: Use an endless loop. Inside it, first comes the input \`input: int choice "1 = e-bike, 2 = e-scooter, 0 = quit"\`, then a switch on \`choice\` with the cases \`0\`, \`1\`, \`2\` and \`default\`. The case \`0\` holds the output and, below it, the Break. +lösung: aufgabe-verleih-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-verleih-java +titel: Rental menu in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 0 -> Bye +test: 1, 2, 0 -> E-bike booked | E-scooter booked | Bye +test: 2, 5, 1, 0 -> E-scooter booked | Invalid choice | E-bike booked | Bye +braucht: endlosschleife, aussprung +tipp: \`while (true) { … }\` runs forever until a \`break;\` comes. +tipp: In Java, use \`if\`/\`else if\` here instead of \`switch\`: a \`break;\` inside a \`switch\` only leaves the \`switch\`, not the loop. \`if (choice == 0) { System.out.println("Bye"); break; } else if (choice == 1) { … }\`. +lösung: aufgabe-verleih-java-loesung.visustruct +::: +`,xy=`--- +titel: Vocabulary trainer +nach: 27 +stufe: 3 +--- + +Ludwig is learning German. His words are in a CSV file, English on the left, German on the right: + +::: datei words.csv +English;German +goat;Ziege +hay;Heu +meadow;Wiese +::: + +Because only the file knows the words, you can simply add new lines later without changing the program. + +::: angeberwissen +Sebastian Leitner made the flashcard box with several compartments popular in 1972: cards you know move one compartment further and come up less often, wrong ones go back to the first compartment. Many vocabulary apps still work on this principle today. +::: + +::: übung aufgabe-vokabeln +titel: Vocabulary trainer +code: java +auftrag: Ask for every word in the file: output **What is goat in German?** and read the answer with \`scanner.next()\`. If it is right, output **Right!**, otherwise for example **Wrong, it is Ziege.** + At the end, show how many were right, for example **2 of 3 right**. +start: aufgabe-vokabeln-start.visustruct +test: Ziege, Heu, Wiese -> What is goat in German? | Right! | What is hay in German? | Right! | What is meadow in German? | Right! | 3 of 3 right +test: Kuh, Heu, Wiese -> What is goat in German? | Wrong, it is Ziege. | What is hay in German? | Right! | What is meadow in German? | Right! | 2 of 3 right +test: Ziege, hay, wiese -> What is goat in German? | Right! | What is hay in German? | Wrong, it is Heu. | What is meadow in German? | Wrong, it is Wiese. | 1 of 3 right +braucht: whileSchleife, verzweigung +tipp: Skip the header line. In the loop, split every line with \`split(";")\`: \`parts[0]\` is the English word, \`parts[1]\` the German one. +tipp: Compare texts with \`answer.equals(parts[1])\`, not with \`==\`. Count along with \`int right = 0;\` and \`int count = 0;\` before the loop. +lösung: aufgabe-vokabeln-loesung.visustruct +::: +`,vy=`--- +titel: Adult? +nach: 8 +stufe: 1 +--- + +At the cinema, for a driving licence or for voting: it often matters whether someone is already 18. + +::: übung aufgabe-volljaehrig +titel: Adult? +auftrag: Ask for the age. If the person is 18 or older, output **adult**, otherwise **minor**. +test: 18 -> adult +test: 35 -> adult +test: 17 -> minor +test: 6 -> minor +braucht: verzweigung +tipp: There are two possible outputs, so you need a branch. +tipp: Read in the age with \`input: int age "How old are you?"\`. The condition of the branch is \`age >= 18\`. Make sure that 18 already counts as adult. +lösung: aufgabe-volljaehrig-loesung.visustruct +::: + +And now the same in Java: + +::: übung aufgabe-volljaehrig-java +titel: Adult? in Java +code: java +auftrag: Now solve the task above in Java. The outputs stay exactly the same. +test: 18 -> adult +test: 35 -> adult +test: 17 -> minor +test: 6 -> minor +braucht: verzweigung +tipp: Read the age with \`int age = scanner.nextInt();\`. +tipp: \`if (age >= 18) { … } else { … }\`, with a \`System.out.println(…)\` in each branch. +lösung: aufgabe-volljaehrig-loesung.visustruct +::: +`,yy=`--- +titel: Rolling dice with MVC +nach: 40 +stufe: 3 +--- + +Build a dice game with Model View Controller. A button **Roll** rolls the dice, and two views show the result. + +The model is already finished. It rolls and counts how often it was rolled and how many sixes came up: + +\`\`\`java +class Dice { + int pips = 1; + int rolls = 0; + int sixes = 0; + + void roll() { + pips = (int) (Math.random() * 6) + 1; + rolls++; + if (pips == 6) { + sixes++; + } + } +} +\`\`\` + +Your task: + +1. Test the model without a window first: roll ten times in \`main\` and then output \`rolls\` and \`sixes\`. +2. Write the view \`PipsView\`. It shows the number rolled in a big JLabel, for example "4". +3. Write the view \`StatsView\`. It shows for example "Sixes: 2 of 10 rolls". +4. The controller is the listener at the button: it lets the model roll and hands the new values to both views. + +Extra: a button **New game** resets everything. The method for that belongs in the model. + +::: ludwig +Remember the rule from lesson 40: there isn't a single \`JLabel\` in the model. If you change the font size when rolling, that belongs in the view. +::: +`,wy=`--- +titel: Double a number +nach: 2 +stufe: 1 +--- + +A variable can change its value. Here a number is doubled. + +::: übung aufgabe-verdoppeln +titel: Double a number +auftrag: Set the variable \`number\` to the value 4. Double it in a second statement without creating a new variable. Then output **Doubled number: 8**, where the 8 comes from the variable. +test: - -> Doubled number: 8 +tipp: Doubling means: times 2. You store the result in the same variable again. +tipp: \`number = number * 2\` calculates with the old value and stores the result in \`number\` again. You join text and a variable with \`+\`. +lösung: aufgabe-verdoppeln-loesung.visustruct +::: +`,zy=`--- +titel: Idade num subprograma +nach: 18 +stufe: 2 +--- + +A verificação da idade de “Maior de idade?” passa agora a ser um subprograma próprio. O programa principal só o chama. + +::: übung aufgabe-alter-unterprogramm +titel: Idade num subprograma +auftrag: Constrói dois diagramas. O programa principal mostra **Bem-vindo**, depois chama \`verificarIdade()\` e no fim mostra **Adeus**. + O subprograma \`verificarIdade\` fica num separador próprio: pede a idade e mostra **maior de idade** ou **menor de idade**. +test: 20 -> Bem-vindo | maior de idade | Adeus +test: 18 -> Bem-vindo | maior de idade | Adeus +test: 12 -> Bem-vindo | menor de idade | Adeus +braucht: aufruf +tipp: O programa principal tem três blocos. O subprograma faz o trabalho a sério. +tipp: Abre o exercício no editor e constrói lá o programa principal com a chamada \`verificarIdade()\`. Depois abre um novo separador com **+** e dá-lhe o título \`verificarIdade\`. Constrói nele a entrada e a decisão. O Verificar encontra o subprograma pelo título do separador. +lösung: aufgabe-alter-haupt-loesung.visustruct +unterprogramm: aufgabe-alter-unterprogramm-loesung.visustruct +::: +`,Iy=`--- +titel: Avaliar o lançamento da bola +nach: 25 +stufe: 2 +--- + +No dia do desporto, todos escreveram numa tabela a distância a que lançaram a bola: + +::: datei lancamento.csv +Nome;Distancia +Ludwig;28 +Zora;42 +Raposa;35 +Lebre;21 +::: + +::: übung aufgabe-ballwurf +titel: Avaliar o lançamento da bola +code: java +auftrag: Lê o ficheiro e salta a linha de cabeçalho. Mostra quantos participaram (**Participantes: 4**) e a que distância lançaram em média (**Média: 31.5 m**). + Guarda o lançamento mais longo no ficheiro **vencedor.txt**, por exemplo **Vencedor: Zora (42 m)**. +start: aufgabe-ballwurf-start.visustruct +test: - -> Participantes: 4 | Média: 31.5 m +datei: vencedor.txt -> Vencedor: Zora (42 m) +braucht: whileSchleife, verzweigung +tipp: Precisas de quatro variáveis antes do ciclo: a contagem, a soma como \`double\`, a melhor distância e o melhor nome. +tipp: No ciclo: \`String[] partes = linha.split(";");\` e \`int distancia = Integer.parseInt(partes[1]);\`. Se \`distancia > melhorDistancia\`, guarda a distância e o nome. Para guardar: \`PrintWriter saida = new PrintWriter("vencedor.txt");\`, \`saida.println(…)\` e \`saida.close();\`. +lösung: aufgabe-ballwurf-loesung.visustruct +::: +`,ky=`--- +titel: Classificação +nach: 19 +stufe: 2 +--- + +Cinco cabras fizeram a corrida de obstáculos. Agora a classificação vai para a porta do estábulo: mais pontos em cima, menos pontos em baixo. + +::: übung aufgabe-bestenliste +titel: Classificação +auftrag: Lê 5 pontuações para um array. Ordena o array com o bubble sort por ordem **decrescente**, ou seja, o maior número primeiro. Depois mostra a lista com o lugar, por exemplo **1. 9**, na linha seguinte **2. 9** e assim por diante. +test: 3, 9, 2, 9, 1 -> 1. 9 | 2. 9 | 3. 3 | 4. 2 | 5. 1 +test: 10, 20, 30, 40, 50 -> 1. 50 | 2. 40 | 3. 30 | 4. 20 | 5. 10 +test: 5, 4, 3, 2, 1 -> 1. 5 | 2. 4 | 3. 3 | 4. 2 | 5. 1 +braucht: forSchleife, verzweigung +tipp: O bubble sort da lição 19 ordena por ordem crescente. Para decrescente basta inverter a comparação dos vizinhos. +tipp: Troca-se quando \`pontos[i] < pontos[i + 1]\`, com uma variável auxiliar. Para a saída, calcula primeiro \`int lugar = i + 1\` e depois mostra \`lugar + ". " + pontos[i]\`. +lösung: aufgabe-bestenliste-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-bestenliste-java +titel: Classificação em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 3, 9, 2, 9, 1 -> 1. 9 | 2. 9 | 3. 3 | 4. 2 | 5. 1 +test: 10, 20, 30, 40, 50 -> 1. 50 | 2. 40 | 3. 30 | 4. 20 | 5. 10 +test: 5, 4, 3, 2, 1 -> 1. 5 | 2. 4 | 3. 3 | 4. 2 | 5. 1 +braucht: forSchleife, verzweigung +tipp: Lê cada número primeiro para uma variável e depois põe-no no array: \`int numero = scanner.nextInt();\` e \`pontos[i] = numero;\`. +tipp: A troca também precisa de uma variável auxiliar em Java: \`int aux = pontos[i]; pontos[i] = pontos[i + 1]; pontos[i + 1] = aux;\`. +lösung: aufgabe-bestenliste-loesung.visustruct +::: +`,Sy=`--- +titel: Número binário +nach: 11 +stufe: 3 +--- + +Os computadores fazem contas só com dois algarismos: 0 e 1. É assim que se converte um número para o **sistema binário**: + +1. Divide o número por 2 e guarda o resto (0 ou 1). +2. Continua com o resultado sem o resto. +3. Repete isto até o número ser 0. + +Os restos lidos **de baixo para cima** dão o número binário. Para 6, os restos são 0, 1, 1, portanto o número binário é 110. + +::: übung aufgabe-binaer +titel: Número binário +auftrag: Pede um número inteiro maior do que 0 e mostra-o como número binário. Para 6 a saída é **110**, para 13 **1101**. +test: 6 -> 110 +test: 13 -> 1101 +test: 1 -> 1 +test: 8 -> 1000 +braucht: whileSchleife +tipp: Vai dividindo o número por 2 e guarda cada resto. Os restos lidos ao contrário dão o número binário. +tipp: Junta os algarismos num texto: \`String binario = ""\`. No ciclo calculas \`int resto = numero % 2\` e acrescentas o resto à **frente**: \`binario = resto + binario\`. Depois, \`numero = numero / 2\`. Como numero é um número inteiro, o resto desaparece. +lösung: aufgabe-binaer-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-binaer-java +titel: Número binário em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 6 -> 110 +test: 13 -> 1101 +test: 1 -> 1 +test: 8 -> 1000 +braucht: whileSchleife +tipp: Começa com \`String binario = "";\`. O ciclo corre com \`while (numero > 0)\`. +tipp: No corpo: \`int resto = numero % 2;\`, depois \`binario = resto + binario;\` e \`numero = numero / 2;\`. Como \`binario\` é uma String, o \`+\` põe o resto à frente. +lösung: aufgabe-binaer-loesung.visustruct +::: +`,Ty=`--- +titel: Cifra de César +nach: 17 +stufe: 3 +--- + +Há mais de 2000 anos, o general romano Júlio César enviava mensagens secretas às suas tropas. O truque era simples: substituía cada letra pela letra que está **três posições à frente** no alfabeto. O A passa a D, o B passa a E e assim por diante. A mensagem legível chama-se **texto simples**, a cifrada **texto cifrado**. O número de posições que se avança é a **chave**, muitas vezes chamada apenas \`k\`. + +::: grafik caesar-verschiebung.svg +Cifrar com a chave 3: cada letra de cima passa a ser a letra de baixo. No fim recomeça-se do início, por isso X, Y e Z passam a A, B e C. +::: + +Assim, \`HALLO\` passa a \`KDOOR\`. Quem conhece a chave recua simplesmente três posições e consegue voltar a ler a mensagem. + +### O disco de cifra + +Para não ter de contar sempre, construiu-se um **disco de cifra**: dois discos com o alfabeto, um pequeno sobre um grande, presos no meio para poderem rodar. Por fora está o texto simples, por dentro o texto cifrado. Rodando o disco interior três letras, por baixo de cada letra exterior aparece a sua letra cifrada. Discos assim existem desde o século XV. Na Guerra Civil Americana (1861–1865), os soldados levavam pequenos discos de latão. + +::: grafik caesar-scheibe.svg +Um disco de cifra inspirado nos discos históricos de latão. A janela azul mostra: com a chave 3, por baixo do A está o D. +::: + +::: angeberwissen +O próprio César nem sequer tinha um disco! Sabemo-lo pelo historiador romano Suetónio: nas suas cartas, César avançava cada letra três posições e contava isso simplesmente de cabeça. O disco só foi inventado por Leon Battista Alberti por volta de 1467, cerca de 1500 anos mais tarde. Aliás, eu também conto de cabeça. Não tenho dedos, só cascos. +::: + +Experimenta tu. Roda o disco interior, escreve um texto e vê como surge o texto cifrado. Com **Decifrar** faz-se o caminho inverso. + +::: caesar 3 +LUDWIG +::: + +::: ludwig +Um disco verdadeiro é muito fácil de fazer: dois círculos de cartão, um um pouco mais pequeno, cada um com 26 campos iguais para o alfabeto, e um colchete de latão no meio. Está pronta a tua ferramenta de agente secreto! +::: + +::: quiz +? Em que letra se transforma o Y com a chave 3? +- [ ] A +- [x] B +- [ ] C +> A seguir ao Y vem o Z, depois recomeça-se com A e B. Três posições à frente é, portanto, o B. + +? Um texto cifrado foi cifrado com a chave 5. Como o decifras? +- [ ] Avançar mais 5 posições +- [x] Recuar 5 posições +- [ ] Ler as letras de trás para a frente +> Decifrar é o contrário de cifrar. Recuar 5 posições é, aliás, o mesmo que avançar 21, porque 5 + 21 = 26. +::: + +### O programa: há mais do que um caminho + +Como ensinas o computador a avançar uma letra \`k\` posições? Não existe *a* única solução certa. Vamos ver dois caminhos. Ambos percorrem o texto carácter a carácter com um ciclo for, tal como na lição sobre cadeias de caracteres. A diferença está na forma como avançam uma única letra. + +Nos dois caminhos ajuda o operador de resto \`%\`. Ele garante que depois do Z se continua no A: as posições 0 a 25 ficam como estão, 26 passa a 0, 27 passa a 1 e assim por diante. + +### Caminho 1: o alfabeto num array + +Colocas o alfabeto num array \`char[] alfabeto = {'A', 'B', …, 'Z'}\`. Para cada letra da palavra procuras no array a sua posição \`pos\`, ou seja, o seu índice. A letra cifrada está então no mesmo array na posição \`(pos + k) % 26\`. + +Um exemplo com a chave 3: o X está na posição 23. Então \`(23 + 3) % 26 = 0\`, e na posição 0 está o A. + +::: übung aufgabe-caesar-array +titel: César com array +auftrag: O diagrama inicial já contém o array \`alfabeto\`. Pede uma palavra em maiúsculas e a chave \`k\`. Depois mostra a palavra cifrada. Para HALLO e 3, isso dá \`KDOOR\`. +start: aufgabe-caesar-array-start.visustruct +test: HALLO, 3 -> KDOOR +test: ZEBRA, 1 -> AFCSB +test: LUDWIG, 13 -> YHQJVT +braucht: forSchleife, verzweigung +tipp: Cria um texto vazio \`String segredo = ""\`. Percorre a palavra carácter a carácter com um ciclo for. Em cada passagem acrescentas uma letra cifrada ao fim de \`segredo\`. +tipp: Para encontrar a posição de uma letra precisas de um segundo ciclo, interior, sobre o array: se \`alfabeto[j] == letra\`, guardas \`pos = j\`. +tipp: Depois do ciclo interior acrescentas \`alfabeto[(pos + k) % 26]\`: \`segredo = segredo + alfabeto[(pos + k) % 26]\`. Depois do ciclo exterior mostras \`segredo\`. +lösung: aufgabe-caesar-array-loesung.visustruct +::: + +### Caminho 2: calcular com a tabela ASCII + +Para o computador, cada carácter é na verdade um número. Que número pertence a que carácter está na **tabela ASCII**. Aí o A tem o código 65, o B o código 66 e assim por diante até ao Z com 90. Em Java transformas um carácter no seu código com \`(int)\` e um código de volta num carácter com \`(char)\`: + +\`\`\` +int codigo = (int) 'A' +char letra = (char) 68 +\`\`\` + +Depois disso, \`codigo\` vale 65 e \`letra\` vale \`'D'\`. Uma conversão destas de um tipo de dados para outro chama-se **conversão de tipo** (em inglês *cast*). + +Agora já podes fazer contas com a letra. Para que o salto do Z de volta ao A funcione, subtrais primeiro 65. Assim o A fica na posição 0 e o Z na posição 25, tal como no caminho 1. Avanças com \`% 26\` e no fim voltas a somar os 65: + +::: grafik caesar-ascii.svg +Em cima, as letras maiúsculas com os seus códigos ASCII. Em baixo, o cálculo para o X com a chave 3: o resultado é A. +::: + +::: übung aufgabe-caesar-ascii +titel: César com ASCII +code: java +auftrag: Escreve um programa em Java que lê uma palavra em maiúsculas e a chave \`k\` e mostra a palavra cifrada. Desta vez sem array: calcula com \`(int)\` e \`(char)\`. +test: HALLO, 3 -> KDOOR +test: ZEBRA, 1 -> AFCSB +test: LUDWIG, 13 -> YHQJVT +braucht: forSchleife +tipp: Percorre a palavra com um ciclo for. O código do carácter na posição \`i\` obténs com \`int codigo = (int) palavra.charAt(i);\`. +tipp: Calcula \`codigo = (codigo - 65 + k) % 26 + 65;\` e acrescenta o carácter: \`segredo = segredo + (char) codigo;\`. Antes do ciclo escreves \`String segredo = "";\`, depois do ciclo \`System.out.println(segredo);\`. +lösung: aufgabe-caesar-ascii-loesung.visustruct +::: + +### Qual é o melhor caminho? + +**Caminho 1: array.** A ideia é procurar a posição no array. +- Vantagem: fácil de perceber, e também funciona com alfabetos próprios, p. ex. com Ç. +- Desvantagem: é preciso procurar cada letra. + +**Caminho 2: ASCII.** A ideia é calcular com o código do carácter. +- Vantagem: curto e sem procura, por isso mais rápido. +- Desvantagem: é preciso conhecer os códigos ASCII. + +Os dois programas dão o mesmo resultado. Na programação é muitas vezes assim: há várias soluções certas, e escolhes a que melhor se adapta à tua tarefa. + +::: übung aufgabe-caesar-entschluesseln +titel: Decifrar César +code: java +auftrag: Agora inverte o jogo. Lê um texto cifrado em maiúsculas e a chave \`k\` e mostra o texto simples. Para KDOOR e 3, isso dá \`HALLO\`. Escolhes tu o caminho. +test: KDOOR, 3 -> HALLO +test: AFCSB, 1 -> ZEBRA +test: YHQJVT, 13 -> LUDWIG +braucht: forSchleife +tipp: Decifrar significa recuar \`k\` posições em vez de avançar. Assim, o \`+ k\` passa a \`- k\`. +tipp: Cuidado com o A: \`0 - 3\` dá -3, e em Java o \`%\` não transforma isso num número positivo. Por isso soma ainda 26: \`codigo = (codigo - 65 - k + 26) % 26 + 65;\` +lösung: aufgabe-caesar-entschluesseln-loesung.visustruct +::: + +::: angeberwissen +Infelizmente, a cifra de César não é segura. Há apenas 25 chaves, e é possível experimentá-las todas em poucos minutos. Com um truque é ainda mais rápido: em português, as letras mais frequentes são o A e o E. Se no texto cifrado o H aparecer muitas vezes, a chave foi provavelmente 3. Na internet existe ainda o ROT13, que é a cifra de César com a chave 13. Aplicar ROT13 duas vezes devolve o texto simples, porque 13 + 13 = 26. +::: +`,_y=`--- +titel: Sequência de Collatz +nach: 11 +stufe: 2 +--- + +A sequência de Collatz é um enigma famoso da matemática. Começas com um número e aplicas sempre a mesma regra: + +- Se o número for **par**, divides por 2. +- Se for **ímpar**, multiplicas por 3 e somas 1. + +Até agora, para todos os números iniciais que alguém experimentou, a sequência acaba por chegar a 1. Se isto é verdade para todos os números, ninguém sabe até hoje. + +::: übung aufgabe-collatz +titel: Sequência de Collatz +auftrag: Pede um número inicial. Aplica a regra até o número ser 1 e mostra o novo número depois de cada passo. Vai contando os passos e mostra no fim **Passos:** e o número de passos. + Com o número inicial 6, a sequência é 3, 10, 5, 16, 8, 4, 2, 1. São 8 passos. +test: 6 -> 3 | 10 | 5 | 16 | 8 | 4 | 2 | 1 | Passos: 8 +test: 3 -> 10 | 5 | 16 | 8 | 4 | 2 | 1 | Passos: 7 +test: 1 -> Passos: 0 +braucht: whileSchleife, verzweigung +tipp: Não sabes quantos passos vão ser. Por isso um ciclo while serve melhor do que um ciclo for. +tipp: O ciclo while é executado enquanto \`numero != 1\`. Verificas se um número é par com \`numero % 2 == 0\`. A saída e \`passos++\` vêm depois da decisão, mas ainda dentro do ciclo. +lösung: aufgabe-collatz-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-collatz-java +titel: Sequência de Collatz em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 6 -> 3 | 10 | 5 | 16 | 8 | 4 | 2 | 1 | Passos: 8 +test: 3 -> 10 | 5 | 16 | 8 | 4 | 2 | 1 | Passos: 7 +test: 1 -> Passos: 0 +braucht: whileSchleife, verzweigung +tipp: Um ciclo \`while\` corre enquanto \`numero != 1\`. Lá dentro, um \`if\` com \`numero % 2 == 0\` decide. +tipp: No corpo: dividir por 2 ou \`numero = numero * 3 + 1;\`, depois \`System.out.println(numero);\` e \`passos++;\`. Depois do ciclo vem \`"Passos: " + passos\`. +lösung: aufgabe-collatz-loesung.visustruct +::: + +::: angeberwissen +Esta tarefa pode tornar-te rico! O matemático Paul Erdős ofereceu 500 dólares por uma demonstração. Em 2021, a empresa japonesa Bakuage juntou bastante mais: 120 milhões de ienes, na altura cerca de um milhão de dólares, por uma demonstração ou um contraexemplo. Ainda ninguém foi buscar o dinheiro. Já agora, o enigma foi inventado pelo matemático alemão Lothar Collatz em 1937. Vou já começar a fazer contas; com tanto dinheiro compra-se muito feno. +::: +`,Ay=`--- +titel: Conversor de unidades +nach: 35 +stufe: 2 +--- + +Constrói uma janela que converte comprimentos. Em cima escreves um comprimento em metros, por baixo há três botões: + +- **em cm** mostra o comprimento em centímetros, 1.5 passa a "150.0 cm", +- **em mm** mostra-o em milímetros, 1.5 passa a "1500.0 mm", +- **em km** mostra-o em quilómetros, 1500 passa a "1.5 km". + +O resultado aparece num JLabel por baixo dos botões. Se no campo não estiver um número, aparece "Escreve um número", e o programa não vai abaixo. + +Podes começar assim: + +\`\`\`java +import javax.swing.*; +import java.awt.*; + +public class Unidades { + public static void main(String[] args) { + JFrame janela = new JFrame("Conversor de unidades"); + janela.setSize(300, 200); + janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + janela.setLayout(new GridLayout(0, 1)); + + JTextField metros = new JTextField(); + JButton emCm = new JButton("em cm"); + JLabel resultado = new JLabel("?", SwingConstants.CENTER); + + emCm.addActionListener(e -> { + double m = Double.parseDouble(metros.getText()); + resultado.setText((m * 100) + " cm"); + }); + + janela.add(metros); + janela.add(emCm); + janela.add(resultado); + janela.setVisible(true); + } +} +\`\`\` + +Extra: um quarto botão **em pés** converte para a unidade inglesa. Um pé são 0.3048 m. + +::: ludwig +Marca **Java verdadeiro (com Swing)** na [roda dentada](#zeige-einstellungen). Para "abc" no campo, cada ouvinte precisa de um try/catch com \`NumberFormatException\`, tal como na calculadora. +::: +`,Oy=`--- +titel: Números de Fibonacci +nach: 13 +stufe: 2 +--- + +Nos números de Fibonacci, cada número é a soma dos dois anteriores. A sequência começa com 1 e 1: + +1, 1, 2, 3, 5, 8, 13, 21, … + +Encontras estes números surpreendentemente vezes na natureza, por exemplo na forma como as sementes do girassol estão dispostas. + +::: ludwig +Lembras-te da **troca** da lição 5? Aí precisavas de uma variável auxiliar, porque \`a = b\` substitui o valor antigo de \`a\`. Aqui é igual: antes de \`numero2\` receber o número novo, o seu valor antigo tem de estar guardado em \`numero1\`. Atenção à **ordem**: primeiro \`numero1 = numero2\`, depois \`numero2 = numero3\`. Vais precisar outra vez de avançar e trocar valores mais tarde, por exemplo ao ordenar na lição 19. +::: + +::: angeberwissen +Em 1202, Leonardo de Pisa, conhecido como Fibonacci, pôs no seu livro de cálculo um problema sobre coelhos: a partir do segundo mês, cada casal de coelhos tem um novo casal todos os meses. Quantos casais há ao fim de um ano? A resposta é esta sequência. Infelizmente, o livro não tinha cabras. +::: + +::: übung aufgabe-fibonacci +titel: Números de Fibonacci +auftrag: Pergunta quantos números de Fibonacci devem ser mostrados. Depois mostra exatamente esses, cada um na sua linha. Podes partir do princípio de que é introduzido pelo menos 2. +test: 5 -> 1 | 1 | 2 | 3 | 5 +test: 8 -> 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 +test: 2 -> 1 | 1 +braucht: forSchleife +tipp: Cada número novo é a soma dos dois anteriores. Por isso tens sempre de guardar os dois últimos números. +tipp: Guarda os dois últimos números em \`numero1\` e \`numero2\` e mostra os dois antes do ciclo. O ciclo começa em \`int i = 2\`. Lá dentro calculas \`int numero3 = numero1 + numero2\`, mostras e depois avanças: \`numero1 = numero2\` e \`numero2 = numero3\`. +lösung: aufgabe-fibonacci-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-fibonacci-java +titel: Números de Fibonacci em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 5 -> 1 | 1 | 2 | 3 | 5 +test: 8 -> 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 +test: 2 -> 1 | 1 +braucht: forSchleife +tipp: Os dois primeiros números mostras antes do ciclo. O ciclo \`for\` começa então em \`int i = 2\`. +tipp: No corpo: \`int numero3 = numero1 + numero2;\`, mostrar, depois \`numero1 = numero2;\` e \`numero2 = numero3;\`. +lösung: aufgabe-fibonacci-loesung.visustruct +::: + +::: quiz +? Porque é que no ciclo \`numero1 = numero2\` tem de vir antes de \`numero2 = numero3\`? +- [ ] Porque senão o Java não permite as atribuições +- [x] Porque senão o valor antigo de numero2 é substituído antes de numero1 o receber +- [ ] A ordem não importa +> Ao contrário, numero1 e numero2 ficariam depois com o mesmo valor. Tal como na troca: primeiro guardar, depois substituir. +::: +`,Cy=`--- +titel: Par ou ímpar +nach: 8 +stufe: 1 +--- + +Um número é par se não sobrar resto quando o divides por 2. O resto calcula-se com \`%\`: \`8 % 2\` dá 0, \`7 % 2\` dá 1. + +::: übung aufgabe-gerade +titel: Par ou ímpar +auftrag: Pede um número inteiro. Mostra se é par ou ímpar. Para 4 a saída é **4 é par**, para 7 **7 é ímpar**. +test: 4 -> 4 é par +test: 7 -> 7 é ímpar +test: 0 -> 0 é par +test: 15 -> 15 é ímpar +braucht: verzweigung +tipp: Uma decisão escolhe entre par e ímpar. Par quer dizer: divisível por 2 sem resto. +tipp: A condição é \`numero % 2 == 0\`. Na saída juntas o número e o texto com \`+\`, p. ex. \`numero + " é par"\`. +lösung: aufgabe-gerade-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-gerade-java +titel: Par ou ímpar em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 4 -> 4 é par +test: 7 -> 7 é ímpar +test: 0 -> 0 é par +test: 15 -> 15 é ímpar +braucht: verzweigung +tipp: Lês um número com \`int numero = scanner.nextInt();\`. Antes disso perguntas com \`System.out.println(…)\`. +tipp: \`if (numero % 2 == 0) { … } else { … }\`. A saída é \`System.out.println(numero + " é par");\`. +lösung: aufgabe-gerade-loesung.visustruct +::: +`,jy=`--- +titel: IVA +nach: 6 +stufe: 1 +--- + +Em Portugal continental, a quase tudo o que compras é somado 23 % de **IVA** (imposto sobre o valor acrescentado). A loja calcula com o preço sem IVA e soma o imposto por cima. Isso dá o preço com IVA que pagas na caixa. + +Um exemplo: compras um telemóvel dobrável que se abre e fica um tablet. Na etiqueta da loja estão 1000 euros sem IVA. Por cima vêm 23 %, ou seja, 230 euros. Na caixa pagas 1230 euros. A loja não pode ficar com os 230 euros: entrega-os às Finanças. + +::: grafik aufgabe-mehrwertsteuer.svg +Preço sem IVA mais IVA dá o preço com IVA. O IVA vai para as Finanças. +::: + +::: angeberwissen +Mééé, claro que a própria loja comprou o telemóvel: ao fabricante, por 800 euros mais 184 euros de IVA. Estes 184 euros chamam-se **IVA dedutível**, e a loja pode descontá-los dos 230 euros. Por isso só entrega 46 euros às Finanças. No fim, só uma pessoa paga o imposto todo: o cliente na caixa. Ou seja, tu. Eu, já agora, não pago imposto nenhum. Só como erva. +::: + +A taxa do imposto nunca muda enquanto fazes as contas. Por isso crias-a como **constante**: uma variável cujo valor não muda depois de definido. Escreves \`const\` à frente, por exemplo \`const double IVA = 0.23\`. Os nomes das constantes escrevem-se em maiúsculas para as reconheceres logo. No código Java isto passa a \`final double IVA = 0.23;\`. + +Se a taxa alguma vez mudar, só tens de alterar esta linha. + +::: übung aufgabe-mehrwertsteuer +titel: IVA +auftrag: Cria a constante \`IVA\` com o valor 0.23. Depois pede o preço sem IVA. Mostra primeiro o imposto e depois o preço com IVA, de cada vez só o número. + Para um preço sem IVA de 100, as saídas são **23** e **123**. +test: 100 -> 23 | 123 +test: 50 -> 11.5 | 61.5 +test: 0 -> 0 | 0 +tipp: O imposto é 23 por cento do preço sem IVA. O preço com IVA é o que pagas no fim. +tipp: O imposto é \`precoSemIva * IVA\`. O preço com IVA obténs somando o imposto ao preço sem IVA. Os dois valores são números decimais, portanto \`double\`. +lösung: aufgabe-mehrwertsteuer-loesung.visustruct +::: + +::: quiz +? Porque crias a taxa do imposto como constante? +- [ ] Porque as constantes são calculadas mais depressa +- [x] Porque o seu valor não deve mudar no programa +- [ ] Porque os números decimais só podem ser guardados como constantes +> Uma constante mantém o seu valor. Se a taxa alguma vez mudar, só alteras a linha com \`const\`. +::: +`,Py=`--- +titel: Média das notas +nach: 13 +stufe: 2 +--- + +Como te correu ultimamente? A média é a soma de todas as notas a dividir pelo número de notas. + +::: übung aufgabe-durchschnitt +titel: Média das notas +auftrag: Pergunta primeiro quantas notas vão ser introduzidas. Depois lê exatamente essas notas e mostra a média, só o número. + Para as notas 4 e 5, a média é **4.5**. +test: 2, 4, 5 -> 4.5 +test: 3, 3, 4, 5 -> 4 +test: 4, 3, 3, 4, 5 -> 3.75 +braucht: forSchleife +tipp: Precisas da soma de todas as notas e de quantas são. A média é a soma a dividir pela quantidade. +tipp: O ciclo for vai de \`int i = 0\` enquanto \`i < quantidade\`. Lá dentro lês uma nota e somas à soma. Guardas a média como número decimal: \`double media = soma * 1.0 / quantidade\`. O \`* 1.0\` garante que também o Java não faz uma divisão inteira. +lösung: aufgabe-durchschnitt-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-durchschnitt-java +titel: Média das notas em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 2, 4, 5 -> 4.5 +test: 3, 3, 4, 5 -> 4 +test: 4, 3, 3, 4, 5 -> 3.75 +braucht: forSchleife +tipp: \`for (int i = 0; i < quantidade; i++)\` lê exatamente as notas que foram indicadas antes. +tipp: Divide com \`double media = soma * 1.0 / quantidade;\`. Sem \`* 1.0\`, o Java divide dois \`int\` como inteiros, e 1.5 passa a 1. +lösung: aufgabe-durchschnitt-loesung.visustruct +::: +`,Dy=`--- +titel: Verificar o PIN +nach: 12 +stufe: 2 +--- + +Numa caixa multibanco tens três tentativas para o teu PIN. Se escreveres um PIN errado três vezes, o cartão fica bloqueado. + +::: angeberwissen +John Shepherd-Barron, que instalou o primeiro multibanco em Londres em 1967, queria PINs de seis algarismos. Mas a mulher dele disse que só conseguia decorar quatro. É por isso que o teu PIN tem hoje quatro algarismos. +::: + +::: übung aufgabe-pin +titel: Verificar o PIN +auftrag: O PIN certo é 1234. Pede o PIN até estar certo ou até se terem gastado três tentativas. Depois mostra **PIN correto** ou **Cartão bloqueado**. +test: 1234 -> PIN correto +test: 1111, 1234 -> PIN correto +test: 1, 2, 1234 -> PIN correto +test: 1, 2, 3 -> Cartão bloqueado +braucht: doUntilSchleife, verzweigung +tipp: O ciclo termina em dois casos: quando o PIN está certo ou quando se gastaram três tentativas. Conta as tentativas. +tipp: O PIN é pedido pelo menos uma vez, por isso serve um ciclo do-while. Antes dele, cria \`int pin = 0\` e \`int tentativas = 0\`. O ciclo repete-se enquanto \`pin != 1234 && tentativas < 3\`. Depois do ciclo, uma decisão decide o que é mostrado. +lösung: aufgabe-pin-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-pin-java +titel: Verificar o PIN em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 1234 -> PIN correto +test: 1111, 1234 -> PIN correto +test: 1, 2, 1234 -> PIN correto +test: 1, 2, 3 -> Cartão bloqueado +braucht: doUntilSchleife, verzweigung +tipp: \`do { … } while (…);\` pergunta pelo menos uma vez. Depois do \`while (…)\` há um ponto e vírgula. +tipp: Cria antes \`int pin = 0;\` e \`int tentativas = 0;\`. No ciclo: \`int entrada = scanner.nextInt();\`, \`pin = entrada;\` e \`tentativas++;\`. A condição é \`pin != 1234 && tentativas < 3\`. +lösung: aufgabe-pin-java-loesung.visustruct +::: +`,By=`--- +titel: Batalha naval +nach: 16 +stufe: 2 +--- + +No jogo da batalha naval, o mar é uma grelha. As colunas chamam-se A a E, as filas 1 a 5. No diagrama inicial, o mar é o array 2D \`mar\`: \`true\` quer dizer que há parte de um navio nesse quadrado. + +::: grafik schiffe-versenken.svg +Cinzento quer dizer \`true\`: aqui há um navio. Os pequenos números cinzentos são os índices no array; começam em 0. No jogo, pelo contrário, os quadrados chamam-se A a E e 1 a 5. +::: + +::: übung aufgabe-schiffe +titel: Batalha naval +auftrag: Mostra todos os quadrados que têm um navio, cada quadrado na sua linha, p. ex. **B1**. Percorre o mar fila a fila com dois ciclos encaixados. + Para o diagrama inicial aparecem **B1**, **C1**, **D1**, **E3**, **E4** e **A5**. +start: aufgabe-schiffe-start.visustruct +test: - -> B1 | C1 | D1 | E3 | E4 | A5 +braucht: forSchleife, verzweigung +tipp: Percorre o mar com dois ciclos encaixados, tal como no cinema. Só mostras os quadrados que têm \`true\`. +tipp: O ciclo exterior conta \`fila\`, o interior \`coluna\`, os dois a partir de 0. Se houver um navio em \`mar[fila][coluna]\`, mostras a letra de \`colunas[coluna]\` e o número da fila: \`output: colunas[coluna] + (fila + 1)\`. Precisas do \`+ 1\` porque o jogo começa a contar em 1. +lösung: aufgabe-schiffe-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-schiffe-java +titel: Batalha naval em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +start: aufgabe-schiffe-start.visustruct +test: - -> B1 | C1 | D1 | E3 | E4 | A5 +braucht: forSchleife, verzweigung +tipp: Dois ciclos \`for\` um dentro do outro: fora a fila, dentro a coluna, ambos até \`.length\`. +tipp: \`if (mar[fila][coluna]) { System.out.println(colunas[coluna] + (fila + 1)); }\`. Os parênteses à volta de \`fila + 1\` fazem o Java calcular primeiro. +lösung: aufgabe-schiffe-loesung.visustruct +::: +`,My=`--- +titel: Ementa +nach: 10 +stufe: 1 +--- + +Na cantina da escola pedes por número. O programa diz-te que prato corresponde ao número. + +::: übung aufgabe-speisekarte +titel: Ementa +auftrag: Pede um número. Para 1 mostra **Salada grega**, para 2 **Bacalhau à Brás** e para 3 **Wrap de falafel**. Para qualquer outro número mostra **Escolhe um número válido**. +test: 1 -> Salada grega +test: 2 -> Bacalhau à Brás +test: 3 -> Wrap de falafel +test: 7 -> Escolhe um número válido +braucht: fallauswahl +tipp: Para vários números fixos serve uma seleção. O que acontece com todos os outros números? +tipp: Lê o número com \`input: int prato "Que prato?"\`. A seleção verifica \`prato\`, e os casos chamam-se \`1\`, \`2\` e \`3\`. Todos os outros números vão parar ao caso \`default\`. +lösung: aufgabe-speisekarte-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-speisekarte-java +titel: Ementa em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 1 -> Salada grega +test: 2 -> Bacalhau à Brás +test: 3 -> Wrap de falafel +test: 7 -> Escolhe um número válido +braucht: fallauswahl +tipp: Em Java isto é uma seleção com \`switch (prato) { … }\`. +tipp: Cada caso é assim: \`case 1 -> { System.out.println("…"); }\`. Para todos os outros números há \`default -> { … }\`. +lösung: aufgabe-speisekarte-loesung.visustruct +::: +`,Zy=`--- +titel: Somar +nach: 2 +stufe: 1 +--- + +Define dois números, soma-os e mostra o resultado. + +::: übung aufgabe-summe +titel: Somar +auftrag: Dá a \`numero1\` o valor 4 e a \`numero2\` o valor 3. Calcula a soma numa terceira variável e mostra só a soma. +test: - -> 7 +tipp: Precisas de três variáveis: duas para os números e uma para o resultado. +tipp: Defines uma variável com uma instrução como \`int numero1 = 4\`. Na saída escreves o nome da variável sem aspas. +lösung: aufgabe-summe-loesung.visustruct +::: +`,Ly=`--- +titel: Sortear quem limpa o quadro +nach: 15 +stufe: 2 +--- + +Quem é que limpa o quadro esta semana? Cinco nomes vão para um array, depois é sorteado um número. + +::: übung aufgabe-tafeldienst +titel: Sortear quem limpa o quadro +auftrag: Lê cinco nomes para um array de Strings. Depois pede um número sorteado de 1 a 5 e mostra **Limpa o quadro:** e o nome correspondente. + O número 1 corresponde ao primeiro nome, o 5 ao último. +test: Ada, Rui, Inês, Duarte, Eva, 3 -> Limpa o quadro: Inês +test: Ada, Rui, Inês, Duarte, Eva, 1 -> Limpa o quadro: Ada +test: Lara, Mário, Nuno, Olga, Pedro, 5 -> Limpa o quadro: Pedro +braucht: forSchleife +tipp: Primeiro, um ciclo lê os cinco nomes. Depois já não precisas de ciclo, só de olhar para uma posição. +tipp: Crias o array com \`String[] nomes = new String[5]\`. Atenção: o número sorteado começa em 1, o índice em 0. Por isso o nome está em \`nomes[sorteado - 1]\`. +lösung: aufgabe-tafeldienst-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-tafeldienst-java +titel: Sortear quem limpa o quadro em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: Ada, Rui, Inês, Duarte, Eva, 3 -> Limpa o quadro: Inês +test: Ada, Rui, Inês, Duarte, Eva, 1 -> Limpa o quadro: Ada +test: Lara, Mário, Nuno, Olga, Pedro, 5 -> Limpa o quadro: Pedro +braucht: forSchleife +tipp: Um array para cinco nomes crias com \`String[] nomes = new String[5];\`. +tipp: No ciclo: \`nomes[i] = scanner.next();\`. O número 1 corresponde à posição 0, por isso mostras \`nomes[sorteado - 1]\`. +lösung: aufgabe-tafeldienst-loesung.visustruct +::: + +> Com \`int sorteado = (int) (Math.random() * 5) + 1\` também podes deixar o acaso sortear o número. Mas para a verificação automática precisamos de uma entrada fixa. +`,Ey=`--- +titel: Calculadora +nach: 10 +stufe: 2 +--- + +Uma pequena calculadora: escreves dois números e um operador, e aparece o resultado. + +::: übung aufgabe-rechner +titel: Calculadora +auftrag: Pede dois números inteiros e depois um operador como texto: \`+\`, \`-\` ou \`*\`. Mostra o resultado. Para qualquer outro sinal mostra **Operador desconhecido**. +test: 3, 4, + -> 7 +test: 10, 4, - -> 6 +test: 6, 7, * -> 42 +test: 1, 2, x -> Operador desconhecido +braucht: fallauswahl +tipp: Lê os três valores. Depois, uma seleção sobre o operador decide o que é calculado. +tipp: Lês o operador com \`input: String operador "Operador"\`. A seleção verifica \`operador\`, os casos chamam-se \`"+"\`, \`"-"\` e \`"*"\`, e o último caso é \`default\`. Em cada caso, calcula primeiro numa variável e depois mostra-a, senão o \`+\` só junta os números. +lösung: aufgabe-rechner-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-rechner-java +titel: Calculadora em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 3, 4, + -> 7 +test: 10, 4, - -> 6 +test: 6, 7, * -> 42 +test: 1, 2, x -> Operador desconhecido +braucht: fallauswahl +tipp: O operador é um texto. Lês com \`String operador = scanner.next();\`. +tipp: \`switch (operador) { case "+" -> { … } … default -> { … } }\`. Com textos, os casos ficam entre aspas. +lösung: aufgabe-rechner-loesung.visustruct +::: +`,Wy=`--- +titel: Menu de aluguer +nach: 18 +stufe: 2 +--- + +Na máquina de aluguer podes reservar vários veículos, um a seguir ao outro. O menu volta sempre até escolheres **0** para sair. + +::: übung aufgabe-verleih +titel: Menu de aluguer +auftrag: Pede sempre uma escolha: 1 = bicicleta elétrica, 2 = trotinete elétrica, 0 = sair. Para 1 mostra **Bicicleta reservada**, para 2 **Trotinete reservada** e para qualquer outro número **Escolha inválida**. + Para 0, o programa mostra **Adeus** e sai do ciclo com uma Interrupção. +test: 0 -> Adeus +test: 1, 2, 0 -> Bicicleta reservada | Trotinete reservada | Adeus +test: 2, 5, 1, 0 -> Trotinete reservada | Escolha inválida | Bicicleta reservada | Adeus +braucht: endlosschleife, aussprung +tipp: O menu é executado uma e outra vez até alguém escolher 0. Para isso serve bem um ciclo infinito com uma Interrupção. +tipp: Usa um ciclo infinito. Lá dentro vem primeiro a entrada \`input: int escolha "1 = bicicleta elétrica, 2 = trotinete elétrica, 0 = sair"\`, depois uma seleção sobre \`escolha\` com os casos \`0\`, \`1\`, \`2\` e \`default\`. O caso \`0\` tem a saída e, por baixo, a Interrupção. +lösung: aufgabe-verleih-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-verleih-java +titel: Menu de aluguer em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 0 -> Adeus +test: 1, 2, 0 -> Bicicleta reservada | Trotinete reservada | Adeus +test: 2, 5, 1, 0 -> Trotinete reservada | Escolha inválida | Bicicleta reservada | Adeus +braucht: endlosschleife, aussprung +tipp: \`while (true) { … }\` corre sem fim até aparecer um \`break;\`. +tipp: Em Java usa aqui \`if\`/\`else if\` em vez de \`switch\`: um \`break;\` dentro de um \`switch\` só sai do \`switch\`, não do ciclo. \`if (escolha == 0) { System.out.println("Adeus"); break; } else if (escolha == 1) { … }\`. +lösung: aufgabe-verleih-java-loesung.visustruct +::: +`,Ny=`--- +titel: Treino de vocabulário +nach: 27 +stufe: 3 +--- + +O Ludwig está a aprender inglês. As palavras dele estão num ficheiro CSV, à esquerda em português, à direita em inglês: + +::: datei vocabulario.csv +Português;Inglês +cabra;goat +feno;hay +prado;meadow +::: + +Como só o ficheiro conhece as palavras, mais tarde podes simplesmente acrescentar linhas novas sem alterar o programa. + +::: angeberwissen +Foi Sebastian Leitner quem, em 1972, tornou conhecida a caixa de fichas com várias divisões: as fichas que sabes passam para a divisão seguinte e aparecem menos vezes, as erradas voltam para a primeira. Muitas apps de vocabulário ainda funcionam assim. +::: + +::: übung aufgabe-vokabeln +titel: Treino de vocabulário +code: java +auftrag: Pergunta cada palavra do ficheiro: mostra **Como se diz cabra em inglês?** e lê a resposta com \`scanner.next()\`. Se estiver certa, mostra **Certo!**, senão por exemplo **Errado, é goat.** + No fim aparece quantas estavam certas, por exemplo **2 de 3 certas**. +start: aufgabe-vokabeln-start.visustruct +test: goat, hay, meadow -> Como se diz cabra em inglês? | Certo! | Como se diz feno em inglês? | Certo! | Como se diz prado em inglês? | Certo! | 3 de 3 certas +test: cow, hay, meadow -> Como se diz cabra em inglês? | Errado, é goat. | Como se diz feno em inglês? | Certo! | Como se diz prado em inglês? | Certo! | 2 de 3 certas +test: goat, feno, prado -> Como se diz cabra em inglês? | Certo! | Como se diz feno em inglês? | Errado, é hay. | Como se diz prado em inglês? | Errado, é meadow. | 1 de 3 certas +braucht: whileSchleife, verzweigung +tipp: Salta a linha de cabeçalho. No ciclo, divide cada linha com \`split(";")\`: \`partes[0]\` é a palavra em português, \`partes[1]\` a palavra em inglês. +tipp: Os textos comparam-se com \`resposta.equals(partes[1])\`, não com \`==\`. Conta com \`int certas = 0;\` e \`int contagem = 0;\` antes do ciclo. +lösung: aufgabe-vokabeln-loesung.visustruct +::: +`,Fy=`--- +titel: Maior de idade? +nach: 8 +stufe: 1 +--- + +No cinema, na carta de condução ou para votar: muitas vezes interessa saber se alguém já tem 18 anos. + +::: übung aufgabe-volljaehrig +titel: Maior de idade? +auftrag: Pede a idade. Se a pessoa tiver 18 anos ou mais, mostra **maior de idade**, senão **menor de idade**. +test: 18 -> maior de idade +test: 35 -> maior de idade +test: 17 -> menor de idade +test: 6 -> menor de idade +braucht: verzweigung +tipp: Há duas saídas possíveis, por isso precisas de uma decisão. +tipp: Lê a idade com \`input: int idade "Quantos anos tens?"\`. A condição da decisão é \`idade >= 18\`. Garante que 18 já conta como maior de idade. +lösung: aufgabe-volljaehrig-loesung.visustruct +::: + +E agora o mesmo em Java: + +::: übung aufgabe-volljaehrig-java +titel: Maior de idade? em Java +code: java +auftrag: Resolve agora em Java a tarefa de cima. As saídas ficam exatamente iguais. +test: 18 -> maior de idade +test: 35 -> maior de idade +test: 17 -> menor de idade +test: 6 -> menor de idade +braucht: verzweigung +tipp: Lê a idade com \`int idade = scanner.nextInt();\`. +tipp: \`if (idade >= 18) { … } else { … }\`, com um \`System.out.println(…)\` em cada ramo. +lösung: aufgabe-volljaehrig-loesung.visustruct +::: +`,Jy=`--- +titel: Lançar o dado com MVC +nach: 40 +stufe: 3 +--- + +Constrói um jogo de dados com Model View Controller. Um botão **Lançar** lança o dado, e duas views mostram o resultado. + +O model já está pronto. Lança o dado e conta quantas vezes foi lançado e quantos seis saíram: + +\`\`\`java +class Dado { + int pontos = 1; + int lancamentos = 0; + int seis = 0; + + void lancar() { + pontos = (int) (Math.random() * 6) + 1; + lancamentos++; + if (pontos == 6) { + seis++; + } + } +} +\`\`\` + +A tua tarefa: + +1. Testa primeiro o model sem janela: lança dez vezes no \`main\` e depois mostra \`lancamentos\` e \`seis\`. +2. Escreve a view \`VistaPontos\`. Mostra o número que saiu num JLabel grande, por exemplo "4". +3. Escreve a view \`VistaEstatistica\`. Mostra por exemplo "Seis: 2 em 10 lançamentos". +4. O controller é o ouvinte do botão: manda o model lançar e passa os valores novos às duas views. + +Extra: um botão **Novo jogo** põe tudo no início. O método para isso pertence ao model. + +::: ludwig +Lembra-te da regra da lição 40: no model não há um único \`JLabel\`. Se mudares o tamanho da letra ao lançar, isso pertence à view. +::: +`,Ry=`--- +titel: Duplicar um número +nach: 2 +stufe: 1 +--- + +Uma variável pode mudar de valor. Aqui um número é duplicado. + +::: übung aufgabe-verdoppeln +titel: Duplicar um número +auftrag: Dá à variável \`numero\` o valor 4. Duplica-a numa segunda instrução, sem criar uma variável nova. Depois mostra **Número duplicado: 8**, em que o 8 vem da variável. +test: - -> Número duplicado: 8 +tipp: Duplicar quer dizer: vezes 2. Guardas o resultado outra vez na mesma variável. +tipp: \`numero = numero * 2\` calcula com o valor antigo e volta a guardar o resultado em \`numero\`. Juntas texto e uma variável com \`+\`. +lösung: aufgabe-verdoppeln-loesung.visustruct +::: +`,Gy=`--- +titel: Der mBot2 +bereich: VisuBot +kurz: Lerne den Roboter kennen, den du gleich programmierst. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- die Teile des mBot2 benennen +- erklären, wie der mBot2 Abstände misst +- erklären, wie der mBot2 eine Linie erkennt +- erklären, was Sensoren und Aktoren sind +- den mBot2 mit Elementen aus der Gruppe mBot2-Befehle steuern +- den mBot2 im Simulator fahren lassen +- den echten mBot2 per USB-C verbinden und wieder trennen +- prüfen, ob alle Sensoren und Aktoren funktionieren +::: + +## Hallo mBot2 + +::: mbot2 +fokus: +drehen: ja +::: + +Der **mBot2** ist ein kleiner Roboter der Firma Makeblock. In dieser Lektion machst du eine Tour durch alle seine Teile: + +- den [CyberPi]{teil=cyberpi}, den kleinen Computer hinten oben +- das durchsichtige [Shield mit Akku]{teil=shield} in der Mitte +- zwei [Motoren]{teil=motors} mit [Rädern]{teil=wheels} +- den [Ultraschallsensor]{teil=ultrasonic} vorn, der wie zwei Augen aussieht +- den [Liniensensor]{teil=lineSensor} unten an der Nase +- das türkise [Chassis]{teil=chassis}, das alles zusammenhält + +In VisuBot programmierst du ihn mit Struktogrammen. Jedes Programm kannst du zuerst im Simulator ausprobieren, auch ganz ohne echten Roboter. + +> Fahr mit der Maus über ein gelb unterstrichenes Wort, dann leuchtet das Teil im Modell auf. Tippst du darauf, fährt die Kamera hin. Das Modell kannst du mit der Maus oder dem Finger drehen und mit dem Mausrad heranzoomen. + +## Der CyberPi + +::: mbot2 +fokus: cyberpi, screen, joystick, buttons, leds, lightSensor, microphone +ansicht: hinten +::: + +Der [CyberPi]{teil=cyberpi,screen,joystick,buttons,leds,lightSensor,microphone} ist das Gehirn des mBot2: ein **Mikrocontroller**, also ein kleiner Computer ohne Tastatur. Er führt dein Programm aus. Er liegt quer hinten oben auf dem Roboter und lässt sich auch abnehmen. + +Auf ihm ist schon eine Menge eingebaut: + +- ein farbiger [Bildschirm]{teil=screen}, auf dem Text und Bilder erscheinen +- ein [Joystick]{teil=joystick}, den du in vier Richtungen drücken kannst +- zwei [Tasten]{teil=buttons}, eine mit Dreieck und eine mit Quadrat, und an der Seite neben dem USB-Anschluss die Home-Taste +- fünf bunte [LEDs]{teil=leds} als Lichtleiste an der Rückseite +- ein [Lichtsensor]{teil=lightSensor} und ein [Mikrofon]{teil=microphone} + +Dazu kommen ein Lautsprecher und ein Lagesensor, die du von außen nicht siehst. Der Lagesensor merkt, ob der CyberPi gekippt oder gedreht wird. + +> Das Modell ist nach Fotos nachgebaut. Schau dir deinen eigenen mBot2 an und vergleiche. + +## Bildschirm, LEDs und Lautsprecher + +::: mbot2 +fokus: screen, leds +ansicht: hinten +::: + +Mit dem [Bildschirm]{teil=screen} und den fünf [LEDs]{teil=leds} zeigt dir der mBot2, was er gerade tut. Jede LED kann in fast jeder Farbe leuchten, weil sie Rot, Grün und Blau mischt. Darum heißen sie **RGB-LEDs**. + +Später lässt du die LEDs mit \`mbot.setLed(255, 0, 0)\` rot leuchten. Die drei Zahlen sind Rot, Grün und Blau, jeweils von 0 bis 255. + +Im [CyberPi]{teil=cyberpi} steckt außerdem ein kleiner **Lautsprecher**. Mit \`mbot.playTone(440, 300)\` spielt er einen Ton: 440 Schwingungen pro Sekunde (Hertz), 300 Millisekunden lang. + +## Licht und Geräusche messen + +::: mbot2 +fokus: lightSensor, microphone +ansicht: oben +::: + +Der [Lichtsensor]{teil=lightSensor} misst, wie hell es ist. Das [Mikrofon]{teil=microphone} misst, wie laut es ist. So kann der mBot2 zum Beispiel losfahren, wenn du in die Hände klatschst. + +## Tasten und Joystick + +::: mbot2 +fokus: joystick, buttons +ansicht: oben +::: + +Die [Tasten]{teil=buttons} A und B und der [Joystick]{teil=joystick} sind auch Sensoren: Sie merken, ob du sie drückst. Dein Programm kann zum Beispiel warten, bis du A drückst, und erst dann losfahren. Mit dem Joystick lenkst du den mBot2 wie mit einer Fernbedienung. + +## Der Lagesensor + +::: mbot2 +fokus: cyberpi +drehen: ja +::: + +Im [CyberPi]{teil=cyberpi} steckt ein Sensor, den du nicht siehst: der **Lagesensor** (ein Gyroskop mit Beschleunigungssensor). Er merkt, ob der mBot2 nach vorn, nach hinten oder zur Seite geneigt ist, wie weit er sich gedreht hat und ob ihn jemand schüttelt. Dein Handy hat so einen Sensor auch: Darum dreht sich das Bild, wenn du es quer hältst. + +## Strom: das Shield mit Akku + +::: mbot2 +fokus: shield, powerSwitch +ansicht: seite +::: + +Das große durchsichtige Gehäuse ist das [mBot2-Shield]{teil=shield}. Durch den Deckel siehst du den grauen **Akku**, der den Roboter mit Strom versorgt. Hinten am Shield stecken die Kabel der Motoren (M1 und M2) und des Ultraschallsensors. + +Links an der Seite ist der [Ein-Aus-Schalter]{teil=powerSwitch} mit der Aufschrift ON/OFF. Daneben liegen zwei Buchsen S1 und S2 für kleine Servomotoren. Schalte den mBot2 aus, wenn du ihn nicht brauchst, dann hält der Akku länger. Geladen wird er über das USB-Kabel am CyberPi. + +## Motoren und Räder + +::: mbot2 +fokus: motors, wheels +ansicht: seite +::: + +Zwei [Motoren]{teil=motors} treiben die beiden [Räder]{teil=wheels} an, jeder sein eigenes. Du siehst sie von unten: silberne Motoren in hellblauen Getrieben. + +- Drehen sich beide Räder gleich schnell vorwärts, fährt der mBot2 **geradeaus**. +- Dreht sich ein Rad vorwärts und das andere rückwärts, dreht er sich **auf der Stelle**. + +Die Motoren sind **Encoder-Motoren**: Sie zählen mit, wie weit sich das Rad gedreht hat. Darum weiß der mBot2, wann er genau 10 cm gefahren ist oder sich genau um 90° gedreht hat. + +## Der Ultraschallsensor + +::: mbot2 +fokus: ultrasonic +ansicht: vorn +::: + +Vorn sitzt der schwarze [Ultraschallsensor]{teil=ultrasonic}. Er sieht aus wie zwei Augen, ist aber eher ein Ohr: Der eine Kreis schickt einen sehr hohen Ton los, den wir nicht hören. Der andere wartet auf das Echo. Je länger das Echo braucht, desto weiter ist die Wand weg. + +So misst der mBot2 Abstände in Zentimetern. Die Ringe um die Kreise können außerdem blau leuchten. + +::: angeberwissen +Fledermäuse machen es genau wie der Ultraschallsensor: Sie rufen so hoch, dass wir es nicht hören, und lauschen auf das Echo. Schall ist etwa 343 Meter pro Sekunde schnell. Steht eine Wand einen Meter vor dem mBot2, ist das Echo schon nach knapp 6 Tausendstel Sekunden zurück. +::: + +## Unter dem Roboter + +::: mbot2 +fokus: lineSensor, caster +ansicht: unten +::: + +Jetzt schaust du von unten. Ganz vorn schaut die schwarze Platine des [Liniensensors]{teil=lineSensor} heraus. Er hat **vier** kleine Fühler nebeneinander. Jeder leuchtet den Boden an und misst, wie viel Licht zurückkommt. Auf einer schwarzen Linie kommt wenig zurück, auf hellem Boden viel. So erkennt der mBot2, ob er auf einer Linie fährt. + +Der Sensor heißt **Quad-RGB-Sensor**, weil er noch mehr kann: Er erkennt auch **Farben**, zum Beispiel ein rotes oder grünes Feld auf dem Boden. + +Die [Kugelrolle]{teil=caster} dahinter ist das dritte Bein. Sie hat keinen Motor und rollt einfach in jede Richtung mit. + +## Das Chassis + +::: mbot2 +fokus: chassis +::: + +Das [Chassis]{teil=chassis} ist der türkise Rahmen aus Aluminium. Er hält alle Teile zusammen. Vorn hat er zwei runde „Ohren“, hinten ein großes **M** für Makeblock. Die vielen Löcher sind kein Zufall: Dort kannst du weitere Teile anschrauben. + +## Sensoren und Aktoren + +Ein Roboter hat zwei Arten von Teilen: + +- **Sensoren** messen etwas: den Abstand, eine Linie, eine Farbe, die Helligkeit, die Lautstärke, die Neigung oder ob eine Taste gedrückt ist. +- **Aktoren** tun etwas: Die Motoren bewegen die Räder, die LEDs leuchten, der Bildschirm zeigt etwas an, der Lautsprecher piept. + +Das Wort kommt vom lateinischen *agere*, „handeln“: Aktoren handeln, Sensoren (von *sentire*, „fühlen“) fühlen. + +Dein Programm liest die Sensoren und steuert die Aktoren. Das kennst du schon als Eingabe, Verarbeitung und Ausgabe. + +::: quiz +? Ordne jedes Teil seiner Aufgabe zu. +→ Hallo mBot2 += Ultraschallsensor -> misst den Abstand += Motoren -> bewegen die Räder += CyberPi -> führt das Programm aus += Liniensensor -> erkennt eine dunkle Linie +? Welche Teile sind Aktoren? +→ Sensoren und Aktoren +- [x] Motoren +- [ ] Ultraschallsensor +- [x] LEDs +- [ ] Liniensensor +> Aktoren tun etwas, Sensoren messen etwas. +::: + +::: spiel frage +titel: Spiel: Sensor oder Aktor? +intro: Misst das Bauteil etwas, oder tut es etwas? Zehn Runden. +antworten: Sensor | Aktor + +runde: +frage: Der Ultraschallsensor misst, wie weit die Wand weg ist. +richtig: Sensor +> Er misst etwas: den Abstand. + +runde: +frage: Die Motoren drehen die Räder. +richtig: Aktor +> Sie tun etwas: Sie bewegen den mBot2. + +runde: +frage: Die LEDs leuchten rot. +richtig: Aktor +> Leuchten ist etwas tun, nicht messen. + +runde: +frage: Der Liniensensor erkennt das schwarze Klebeband. +richtig: Sensor +> Er misst, wie viel Licht vom Boden zurückkommt. + +runde: +frage: Der Lautsprecher piept. +richtig: Aktor +> Er gibt einen Ton aus. + +runde: +frage: Das Mikrofon hört dein Klatschen. +richtig: Sensor +> Es misst die Lautstärke. + +runde: +frage: Der Bildschirm zeigt „Hallo VisuBot!“. +richtig: Aktor +> Anzeigen ist eine Ausgabe. + +runde: +frage: Taste A merkt, dass du drückst. +richtig: Sensor +> Tasten sind Sensoren: Sie melden, ob sie gedrückt sind. + +runde: +frage: Der Lagesensor merkt, dass der mBot2 schief steht. +richtig: Sensor +> Er misst die Neigung. + +runde: +frage: Die Ringe am Ultraschallsensor leuchten blau. +richtig: Aktor +> Gemein! Das Bauteil ist ein Sensor, aber das Leuchten der Ringe ist eine Ausgabe. +::: + +## Finde die Bauteile + +Jetzt bist du dran: Klicke im Modell auf das gesuchte Teil. Liegst du richtig, kommt die nächste Frage. + +::: mbot2quiz +- ultrasonic: Womit misst der mBot2, wie weit die Wand weg ist? +- screen: Wo erscheint Text, den dein Programm ausgibt? +- wheels: Was bewegt den mBot2 vorwärts? +- lineSensor: Was erkennt eine schwarze Linie auf dem Boden? (Tipp: Dreh das Modell.) +- powerSwitch: Wo schaltest du den mBot2 ein und aus? +- leds: Was leuchtet bei \`mbot.setLed(255, 0, 0)\` rot? +fertig: Super, du kennst dich am mBot2 aus! +::: + +## Befehle für den mBot2 + +Unter den [Elementen](#zeige-elemente) gibt es in VisuBot eine eigene Gruppe **mBot2-Befehle**. Jeder Kasten darin ist eine Anweisung an den Roboter: + +| Element | Text im Kasten | Was passiert | +|---|---|---| +| fahre vor | \`mbot.forward()\` | 10 cm vorwärts | +| fahre zurück | \`mbot.backward()\` | 10 cm rückwärts | +| drehe rechts | \`mbot.turnRight()\` | 90° nach rechts drehen | +| drehe links | \`mbot.turnLeft()\` | 90° nach links drehen | +| LEDs an | \`mbot.setLed(255, 0, 0)\` | die LEDs leuchten rot | + +In die Klammern darfst du auch eine Zahl schreiben: \`mbot.forward(30)\` fährt 30 cm, \`mbot.turnRight(45)\` dreht nur 45°. + +> Die Anweisungen sind echtes Java. \`mbot\` ist der Roboter, hinter dem Punkt steht, was er tun soll. + +## Erste Fahrt + +Starte nach dem Bauen die [Simulation](#zeige-simulation). Rechts erscheint die VisuBot-Welt mit dem mBot2. Das Gitter auf dem Boden hat Kästchen von 10 cm, also genau ein **fahre vor**. + +::: übung vb-gerade +titel: Geradeaus +auftrag: Ziehe fünfmal **fahre vor** in das Struktogramm. Starte dann die Simulation und schau zu, wie der mBot2 50 cm geradeaus fährt. +fahrt: 5 x (forward) +tipp: Die Gruppe mBot2-Befehle findest du unter den normalen Elementen. +tipp: Fünf Kästen \`mbot.forward()\` untereinander. Jeder fährt 10 cm. +lösung: vb-gerade-loesung.visustruct +::: + +## Den echten mBot2 verbinden + +::: mbot2 +fokus: cyberpi, powerSwitch, joystick, buttons +ansicht: seite +::: + +Alles, was du im Simulator baust, kann auch der echte mBot2 fahren. So verbindest du ihn: + +1. Steck ein **USB-C-Kabel** in deinen Computer (zum Beispiel ein MacBook) und das andere Ende in den USB-C-Anschluss rechts am [CyberPi]{teil=cyberpi}, neben der Home-Taste. +2. Schieb den [Schiebeschalter ON/OFF]{teil=powerSwitch} links am Shield auf ON. Der Bildschirm des CyberPi leuchtet. +3. Auf dem Bildschirm erscheint ein Menü, in dem **neu starten** markiert ist. Drück den [Joystick]{teil=joystick} wie eine Taste nach unten, um das zu bestätigen. +4. Nach dem Neustart steht dort „Press B to start“. Drück **Taste B**, das ist die [Taste mit dem Dreieck]{teil=buttons}. +5. Öffne VisuStruct in **Chrome** oder **Edge**. Safari und das iPad können keine USB-Geräte ansprechen. +6. Sobald der CyberPi hochgefahren ist, klick oben auf **🔌 mBot2** (oder im Zahnrad auf „Mit mBot2 verbinden“). +7. Chrome zeigt eine Liste mit Anschlüssen. Wähle den Eintrag **USB Serial** (zum Beispiel „USB Serial (cu.usbserial-110)“). Er steht oft ganz unten, eventuell musst du nach unten scrollen. Dann klick auf **Verbinden**. +8. Der CyberPi startet kurz neu (⏳). Dann steht „Hallo VisuBot!“ auf seinem Bildschirm und der Knopf zeigt 🟢. + +Jetzt fährt der mBot2 bei jedem Schritt der Simulation mit. Stell ihn auf den Boden und lass ihm Platz! + +> Fertig? Klick noch einmal auf **🟢 mBot2**. Dann hält er an, zeigt „Bis bald!“ und gibt den Anschluss frei. Erst danach das Kabel ziehen. + +> Ganz ohne Kabel fahren? Das lernst du in Lektion 2 bei **Ohne Kabel fahren**. + +## Den mBot2 testen + +Ist der mBot2 verbunden, erscheint unter der Welt **🔧 mBot2 testen**. Klapp es auf: + +- Mit den Knöpfen probierst du jeden Aktor einmal aus: LEDs, Ton, Text auf dem Bildschirm und die Räder. Heb den mBot2 dafür hoch, damit er nicht vom Tisch fährt. +- Darunter stehen alle Sensoren mit ihren Werten, und die laufen live mit. Halte die Hand vor den Ultraschallsensor, drück Taste A, neige ihn, klatsch in die Hände oder stell ihn auf ein rotes Blatt. + +Ändert sich ein Wert nicht, obwohl du etwas tust, stimmt etwas nicht. Dann sag deiner Lehrkraft Bescheid, bevor du programmierst. + +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. + +::: checkliste +- Ich kann die Teile des mBot2 benennen. → Hallo mBot2 +- Ich kann erklären, wie der mBot2 Abstände misst. → Der Ultraschallsensor +- Ich kann erklären, wie der mBot2 eine Linie erkennt. → Unter dem Roboter +- Ich kann erklären, was Sensoren und Aktoren sind. → Sensoren und Aktoren +- Ich kann den mBot2 mit Elementen aus der Gruppe mBot2-Befehle steuern. → Befehle für den mBot2 +- Ich kann den mBot2 im Simulator fahren lassen. → Erste Fahrt +- Ich kann den echten mBot2 per USB-C verbinden und wieder trennen. → Den echten mBot2 verbinden +- Ich kann prüfen, ob alle Sensoren und Aktoren funktionieren. → Den mBot2 testen +::: +`,Hy=`--- +titel: Das Quadrat +bereich: VisuBot +kurz: Vom langen Struktogramm zur dreifach verschachtelten Schleife. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- einen Ablauf erst ohne Schleife bauen +- Wiederholungen erkennen und durch eine For-Schleife ersetzen +- zwei Schleifen ineinander schachteln +- drei Schleifen ineinander schachteln +- mein Programm auf den mBot2 übertragen und ohne Kabel mit Taste A starten +::: + +## Ein Quadrat fahren + +Der mBot2 soll ein Quadrat mit 50 cm Seitenlänge fahren. Eine Seite kennst du schon: fünfmal **fahre vor**. Danach dreht er sich nach rechts, und die nächste Seite beginnt. + +::: übung vb-quadrat +titel: Das Quadrat +auftrag: Baue ein Struktogramm, mit dem der mBot2 ein Quadrat fährt: fünfmal **fahre vor**, dann **drehe rechts**. Und das viermal. +fahrt: 4 x (5 x (forward), turnRight) +tipp: Eine Seite besteht aus fünfmal fahre vor und einmal drehe rechts. +tipp: Insgesamt sind es 24 Kästen: viermal fünf \`mbot.forward()\` und danach jeweils \`mbot.turnRight()\`. +lösung: vb-quadrat-loesung.visustruct +::: + +Ganz schön viele Kästen, oder? Wenn du dich beim Zählen vertust, fährt der mBot2 kein Quadrat mehr. + +## Immer das Gleiche + +Schau dein Struktogramm genau an: Fünfmal **fahre vor** steht viermal da. Wenn sich etwas wiederholt, nimmt man eine **Schleife**. Wir wissen genau, wie oft gefahren wird, nämlich fünfmal. Dafür passt die For-Schleife. + +Ziehe eine For-Schleife ins Struktogramm und gib ihr diese drei Teile: + +- Start: \`int i = 0\` +- Bedingung: \`i < 5\` +- Schritt: \`i++\` + +In den Inhalt der Schleife kommt ein einziges **fahre vor**. Die Schleife zählt \`i\` von 0 bis 4, das sind fünf Durchläufe. + +::: übung vb-quadrat-schleife +titel: Seiten mit Schleife +auftrag: Ersetze in deinem Quadrat jede Reihe aus fünf **fahre vor** durch eine For-Schleife, die fünfmal fährt. Der mBot2 fährt danach genau dasselbe Quadrat. +fahrt: 4 x (5 x (forward), turnRight) +braucht: forSchleife +tipp: Start \`int i = 0\`, Bedingung \`i < 5\`, Schritt \`i++\`. Im Inhalt steht nur \`mbot.forward()\`. +tipp: Viermal untereinander: die For-Schleife und danach \`mbot.turnRight()\`. +lösung: vb-quadrat-schleife-loesung.visustruct +::: + +## Schleife in der Schleife + +Jetzt steht viermal dasselbe Paar da: eine For-Schleife und **drehe rechts**. Auch das ist eine Wiederholung! Packe beides in eine zweite For-Schleife, die viermal läuft. Eine Schleife in einer Schleife heißt **verschachtelte Schleife**. + +Jede Schleife braucht ihre eigene Zählvariable, sonst kommen sich die beiden in die Quere. Üblich ist: Die äußere Schleife zählt mit \`i\`, die innere mit \`j\`. Benenne deine innere Schleife also in \`j\` um. + +::: übung vb-quadrat-verschachtelt +titel: Quadrat verschachtelt +auftrag: Baue das Quadrat mit zwei ineinander geschachtelten For-Schleifen. Die äußere läuft viermal, einmal für jede Seite. Die innere läuft fünfmal, einmal für jeden Schritt. +fahrt: 4 x (5 x (forward), turnRight) +schleifentiefe: 2 +tipp: Außen: Start \`int i = 0\`, Bedingung \`i < 4\`, Schritt \`i++\`. Innen: \`int j = 0\`, \`j < 5\`, \`j++\`. +tipp: In die äußere Schleife kommen die innere Schleife mit \`mbot.forward()\` und darunter \`mbot.turnRight()\`. +lösung: vb-quadrat-verschachtelt-loesung.visustruct +::: + +Aus 24 Kästen sind vier geworden. Gehe das Programm in der Simulation mit **Schritt** durch und beobachte die Variablen \`i\` und \`j\`. + +::: quiz +? Wie oft führt der mBot2 im verschachtelten Quadrat \`mbot.forward()\` aus? +- [ ] 9-mal +- [x] 20-mal +- [ ] 5-mal +> Die innere Schleife läuft fünfmal, und das in jedem der vier Durchläufe der äußeren Schleife: 4 · 5 = 20. +::: + +## Vier Quadrate + +Jetzt wird es richtig schön: Der mBot2 soll vier Quadrate fahren. Nach jedem Quadrat dreht er sich einmal nach rechts. So entsteht ein großes Fenster mit Fensterkreuz. + +Du könntest dein Quadrat viermal untereinander kopieren und nach jedem Quadrat ein **drehe rechts** einfügen. Probier es ruhig aus! Merkst du es? Schon wieder steht dasselbe viermal da. + +::: ludwig +Immer wenn du Kästen kopierst, frag dich: Wiederholt sich hier etwas? Dann passt eine Schleife. +::: + +::: übung vb-vier-quadrate +titel: Vier Quadrate +auftrag: Lass den mBot2 vier Quadrate fahren. Nach jedem Quadrat dreht er sich einmal nach rechts. Benutze drei ineinander geschachtelte Schleifen. +fahrt: 4 x (4 x (5 x (forward), turnRight), turnRight) +schleifentiefe: 3 +tipp: Lege um dein verschachteltes Quadrat noch eine dritte For-Schleife, die viermal läuft. +tipp: Ganz außen zählt jetzt \`i\` (\`int i = 0\`, \`i < 4\`, \`i++\`). Die Schleifen darin heißen dann \`j\` und \`k\`. In die äußere Schleife kommen dein Quadrat und danach \`mbot.turnRight()\`. +lösung: vb-vier-quadrate-loesung.visustruct +::: + +::: quiz +? Wie oft fährt der mBot2 bei den vier Quadraten 10 cm vor? +→ Vier Quadrate +- [ ] 20-mal +- [ ] 60-mal +- [x] 80-mal +> 4 Quadrate · 4 Seiten · 5 Schritte = 80. Ohne Schleifen wären das 80 Kästen. +::: + +## Ohne Kabel fahren + +::: mbot2 +fokus: cyberpi, buttons +ansicht: oben +::: + +Bisher hängt der mBot2 am Kabel, solange er fährt. Du kannst dein Programm aber auch **auf den mBot2 übertragen**. Dann merkt er es sich und fährt ganz allein, zum Beispiel durch ein Labyrinth auf dem Boden. + +1. Schließ den mBot2 mit dem USB-Kabel an und schalte ihn ein, wie in Lektion 1. Das geht nur in **Chrome** oder **Edge**. +2. Öffne dein Programm, zum Beispiel die vier Quadrate. +3. Klick oben auf **⬆ Übertragen** und dann auf **Jetzt übertragen**. Wähle wieder **USB Serial**. +4. Warte, bis „Fertig!“ dasteht. Der mBot2 startet neu und zeigt **A = Start**. +5. Zieh das Kabel ab und setz den mBot2 an den Start. +6. Drück **Taste A**, das ist die [Taste mit dem Quadrat]{teil=buttons}. Jetzt fährt dein Programm los. + +Das Programm bleibt gespeichert, auch wenn du den mBot2 aus- und wieder einschaltest. Erst das nächste Übertragen ersetzt es. + +> Fährt er los, bevor du bereit bist? Keine Sorge: Er wartet immer auf Taste A. Drückst du A noch einmal, während er fährt, passiert nichts. Ist er fertig, startet A das Programm von vorn. + +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. + +::: checkliste +- Ich kann einen Ablauf erst ohne Schleife bauen. → Ein Quadrat fahren +- Ich kann Wiederholungen erkennen und durch eine For-Schleife ersetzen. → Immer das Gleiche +- Ich kann zwei Schleifen ineinander schachteln. → Schleife in der Schleife +- Ich kann drei Schleifen ineinander schachteln. → Vier Quadrate +- Ich kann mein Programm auf den mBot2 übertragen und ohne Kabel mit Taste A starten. → Ohne Kabel fahren +::: +`,Vy='---\ntitel: Variablen und Ausgabe\nbereich: VisuBot\nkurz: Werte in Variablen speichern, den mBot2 damit fahren lassen und Ergebnisse ausgeben.\n---\n\n## Diese Kompetenzen erwerbe ich jetzt\n\n::: kompetenzen\n- eine Variable anlegen und benutzen\n- die Datentypen `int`, `double`, `String` und `boolean` unterscheiden\n- mit zwei Variablen ein Rechteck in Java fahren\n- mit `System.out.println` etwas ausgeben\n:::\n\n## Eine Variable für die Seite\n\nMit `mbot.forward(30)` fährt der mBot2 30 cm am Stück. Fährst du damit ein Quadrat ohne Schleife, steht die 30 aber viermal im Programm. Soll das Quadrat größer werden, musst du sie an vier Stellen ändern. Besser ist es, die Seitenlänge **einmal** zu speichern und dann überall zu benutzen.\n\nDafür gibt es **Variablen**. Eine Variable ist ein Kästchen mit einem Namen, in dem ein Wert liegt:\n\n```java\nint seite = 30;\nmbot.forward(seite);\n```\n\n- `int` ist der **Datentyp**: eine ganze Zahl.\n- `seite` ist der **Name**. Du darfst ihn selbst wählen.\n- `30` ist der **Wert**. Das `=` legt ihn in das Kästchen.\n\nWo danach `seite` steht, setzt der Computer den Wert ein. `mbot.forward(seite)` fährt also 30 cm.\n\n::: übung vb-variable-seite\ntitel: Quadrat mit Variable\nauftrag: Lege in einer Anweisung die Variable `int seite = 30` an. Danach fährt der mBot2 ein Quadrat: viermal `seite` Zentimeter vor und nach rechts drehen.\nfahrt: 4 x (forward 30, turnRight)\nbraucht: forSchleife\ntipp: Die erste Anweisung ist `int seite = 30`. Darunter kommt eine For-Schleife, die viermal läuft.\ntipp: In der Schleife stehen `mbot.forward(seite)` und `mbot.turnRight()`.\nlösung: vb-variable-seite-loesung.visustruct\n:::\n\n> Ändere jetzt nur die 30 in eine 60 und starte die Simulation. Das ganze Quadrat wird doppelt so groß.\n\n## Welche Datentypen gibt es?\n\nJede Variable hat einen Datentyp. Er legt fest, welche Werte hineinpassen:\n\n| Datentyp | Was passt hinein? | Beispiel |\n|---|---|---|\n| `int` | ganze Zahlen | `int seite = 30;` |\n| `double` | Kommazahlen, mit Punkt geschrieben | `double tempo = 1.5;` |\n| `String` | Text in Anführungszeichen | `String name = "Visu";` |\n| `boolean` | wahr oder falsch | `boolean fertig = false;` |\n\nMit Variablen kannst du auch rechnen: `int strecke = 4 * seite;` rechnet die ganze Strecke des Quadrats aus.\n\n## Jetzt in Java: Rechteck\n\nEin Rechteck hat zwei verschiedene Seiten. Also brauchst du zwei Variablen.\n\n::: übung vb-java-rechteck\ntitel: Rechteck mit Variablen\ncode: java\nauftrag: Schreibe in Java: Lege `int laenge = 60` und `int breite = 30` an. Der mBot2 fährt ein Rechteck: Länge, rechts drehen, Breite, rechts drehen, und das zweimal.\nfahrt: 2 x (forward 60, turnRight, forward 30, turnRight)\nbraucht: forSchleife\ntipp: Zwei Variablen oben: `int laenge = 60;` und `int breite = 30;`. Darunter eine For-Schleife, die zweimal läuft.\ntipp: In der Schleife: `mbot.forward(laenge);`, `mbot.turnRight();`, `mbot.forward(breite);`, `mbot.turnRight();`\nlösung: vb-java-rechteck-loesung.visustruct\n:::\n\n## Jetzt ohne Roboter: Ausgabe\n\nNicht jedes Ergebnis muss der Roboter fahren. Mit `System.out.println(…)` gibt ein Java-Programm Text in der [Konsole](#zeige-konsole) aus. Mit `+` hängst du Text und Werte aneinander:\n\n```java\nint seite = 30;\nint strecke = 4 * seite;\nSystem.out.println("Strecke: " + strecke + " cm");\n```\n\nDie Konsole zeigt dann **Strecke: 120 cm**.\n\n::: übung vb-ohne-strecke\ntitel: Wie weit fährt er?\ncode: java\nauftrag: Ein Rechteck ist 60 cm lang und 30 cm breit. Lege `laenge` und `breite` als Variablen an. Berechne in einer Variablen `strecke`, wie weit der mBot2 einmal ganz herum fährt, und gib **Strecke: 180 cm** aus. Ganz ohne `mbot`!\ntest: - -> Strecke: 180 cm\nbraucht: anweisung\ntipp: Einmal herum sind zweimal die Länge und zweimal die Breite.\ntipp: `int strecke = 2 * laenge + 2 * breite;` und dann `System.out.println("Strecke: " + strecke + " cm");`\nlösung: vb-ohne-strecke-loesung.visustruct\n:::\n\n::: quiz\n? Was fährt `mbot.forward(seite)`, wenn vorher `int seite = 40;` steht?\n→ Eine Variable für die Seite\n- [ ] 4 cm\n- [x] 40 cm\n- [ ] gar nichts, `seite` ist kein Befehl\n> Wo `seite` steht, setzt Java den Wert 40 ein.\n? Welcher Datentyp passt zu `"Visu"`?\n→ Welche Datentypen gibt es?\n- [ ] `int`\n- [ ] `double`\n- [x] `String`\n> Text in Anführungszeichen ist ein `String`.\n? Was gibt `System.out.println("Seite: " + 30);` aus?\n→ Jetzt ohne Roboter: Ausgabe\n- [x] Seite: 30\n- [ ] "Seite: " + 30\n- [ ] 30\n> Das `+` hängt den Text und die Zahl aneinander.\n:::\n\nSchä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.\n\n::: checkliste\n- Ich kann eine Variable anlegen und benutzen. → Eine Variable für die Seite\n- Ich kann die Datentypen `int`, `double`, `String` und `boolean` unterscheiden. → Welche Datentypen gibt es?\n- Ich kann mit zwei Variablen ein Rechteck in Java fahren. → Jetzt in Java: Rechteck\n- Ich kann mit `System.out.println` etwas ausgeben. → Jetzt ohne Roboter: Ausgabe\n:::\n',qy=`--- +titel: Sensoren abfragen +bereich: VisuBot +kurz: Der mBot2 misst etwas, und dein Programm entscheidet. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- den Unterschied zwischen Befehl und Sensor erklären +- einen Sensor in eine Bedingung einbauen +::: + +## Befehle und Sensoren + +Bisher hast du dem mBot2 nur **Befehle** gegeben: fahre vor, drehe rechts. Er hat sie ausgeführt, ohne auf seine Umgebung zu achten. + +Jetzt kommen die **Sensoren** dazu. Unter den [Elementen](#zeige-elemente) gibt es dafür die Gruppe **mBot2-Sensoren**: + +| Sensor | Text | Was du bekommst | +|---|---|---| +| Abstand | \`mbot.getDistance()\` | Abstand bis zur nächsten Wand in cm, z. B. \`38\` | +| Linie | \`mbot.getLine()\` | \`0\`, wenn unter dem Liniensensor alles hell ist, sonst eine Zahl größer als 0 | + +Der mBot2 hat noch mehr Sensoren: Farben, Tasten und Joystick, Licht, Lautstärke und Neigung. Jeden lernst du in den Lektionen 6 bis 13 einzeln kennen, die Motoren in Lektion 20 und Stoppuhr und Akku in Lektion 21. + +Ein Sensor ist **kein eigener Kasten**. Er liefert eine Zahl, und mit der baust du eine **Bedingung**: + +\`\`\`java +mbot.getDistance() < 20 +\`\`\` + +Das heißt: „Ist die Wand näher als 20 cm?“ Die Antwort ist wahr oder falsch. + +> So baust du es: Zieh zuerst eine **Verzweigung** ins Struktogramm. Dann ziehst du den Sensor **Abstand** auf die Verzweigung. In der Bedingung steht jetzt \`mbot.getDistance()\`. Den Vergleich \`< 20\` schreibst du selbst dazu. + +## Wand vorn? + +Der mBot2 soll selbst entscheiden: Ist vorn eine Wand, dreht er sich nach rechts. Ist frei, fährt er ein Stück vor. + +Diese Übung hat **zwei Welten**: In der einen steht die Wand direkt vor ihm, in der anderen ist viel Platz. Dein Programm muss in beiden das Richtige tun. + +::: übung vb-wand-vorn +titel: Wand vorn? +auftrag: Baue eine Verzweigung mit der Bedingung \`mbot.getDistance() < 20\`. Bei **wahr** dreht sich der mBot2 nach rechts, bei **falsch** fährt er vor. +welt: wand-nah -> turnRight +welt: wand-frei -> forward +braucht: verzweigung +tipp: Zieh eine Verzweigung ins Struktogramm und dann den Sensor **Abstand** auf die Verzweigung. Schreib dahinter \`< 20\`. +tipp: Im Ja-Zweig steht \`mbot.turnRight()\`, im Nein-Zweig \`mbot.forward()\`. +lösung: vb-wand-vorn-loesung.visustruct +::: + +## Was liefert der Sensor? + +::: quiz +? Die Wand ist 12 cm entfernt. Ist \`mbot.getDistance() < 20\` wahr oder falsch? +→ Wand vorn? +- [x] wahr +- [ ] falsch +> 12 ist kleiner als 20, also ist die Bedingung wahr. +? Der mBot2 steht auf hellem Boden. Was liefert \`mbot.getLine()\`? +→ Befehle und Sensoren +- [x] 0 +- [ ] 15 +- [ ] den Abstand in cm +> 0 heißt: Keiner der vier Fühler sieht etwas Dunkles. +? Warum ist der Sensor kein eigener Kasten im Struktogramm? +→ Wand vorn? +- [x] Er tut nichts, er liefert nur einen Wert. Den braucht man in einer Bedingung. +- [ ] Weil der mBot2 sonst zu langsam wird. +- [ ] Weil Sensoren nur in Java gehen. +> Befehle sind Anweisungen. Sensoren sind Werte, so wie eine Variable. +::: + +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. + +::: checkliste +- Ich kann den Unterschied zwischen Befehl und Sensor erklären. → Befehle und Sensoren +- Ich kann einen Sensor in eine Bedingung einbauen. → Wand vorn? +::: +`,Qy=`--- +titel: Bis zur Wand +bereich: VisuBot +kurz: Der mBot2 misst den Abstand und hält rechtzeitig an. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- mit \`mbot.getDistance()\` den Abstand abfragen +- entscheiden, wann ich eine While-Schleife statt einer For-Schleife nehme +- mit dem Liniensensor ein Ziel finden +::: + +## Wie weit ist die Wand? + +Bisher hast du genau gesagt, wie weit der mBot2 fahren soll. Jetzt soll er selbst merken, wann er anhalten muss. + +Dafür gibt es den Ultraschallsensor. \`mbot.getDistance()\` liefert den Abstand bis zur nächsten Wand in Zentimetern, zum Beispiel \`38\`. Du kannst ihn wie eine Zahl benutzen: + +\`\`\`java +mbot.getDistance() > 15 +\`\`\` + +Das ist eine **Bedingung**: Sie ist wahr, solange die Wand mehr als 15 cm entfernt ist. + +> Starte die [Simulation](#zeige-simulation): Unter der Welt steht immer der aktuelle Abstand. Fährt der mBot2 näher an die Wand, wird die Zahl kleiner. + +## Drei Welten, ein Programm + +Diese Übung hat **drei Welten**. In jeder steht die Wand woanders, und der mBot2 soll jedes Mal im Ziel mit der grünen Fahne anhalten, ohne anzustoßen. + +Mit einer festen Anzahl **fahre vor** klappt das nur in einer Welt. Du brauchst eine Schleife, die so lange fährt, wie die Bedingung wahr ist: die **While-Schleife**. + +::: übung vb-bis-wand +titel: Bis zur Wand +auftrag: Der mBot2 soll vorwärts fahren, bis die Wand höchstens 15 cm entfernt ist. Dein Programm muss in allen drei Welten funktionieren. Über der Simulation wählst du, welche Welt du siehst. +welt: wand-kurz, wand-mittel, wand-lang +braucht: whileSchleife +tipp: Zieh eine While-Schleife ins Struktogramm und den Sensor **Abstand** auf die Schleife. Dann fehlt nur noch der Vergleich. +tipp: Eine While-Schleife mit der Bedingung \`mbot.getDistance() > 15\`, darin ein \`mbot.forward()\`. +lösung: vb-bis-wand-loesung.visustruct +::: + +::: ludwig +Eine Schleife, die eine Bedingung prüft, bevor sie fährt, ist wie ich am Futtertrog: Ich frage zuerst, ob noch etwas drin ist, und erst dann fresse ich weiter. +::: + +## Bis zum Ziel + +Jetzt kommt der zweite Sensor dran. Das Ziel ist ein schwarzes Feld mit grüner Fahne. Fährt der mBot2 darauf, sieht es sein Liniensensor: \`mbot.getLine()\` ist dann nicht mehr \`0\`. + +::: übung vb-bis-ziel +titel: Fahre bis zum Ziel +auftrag: Der mBot2 soll so lange vorwärts fahren, bis er auf dem Ziel steht. Auch hier gibt es zwei Welten. +welt: ziel-kurz, ziel-lang +braucht: whileSchleife +tipp: Die Schleife soll laufen, solange der Liniensensor **nichts** sieht. Zieh den Sensor **Linie** auf die While-Schleife. +tipp: Die Bedingung heißt \`mbot.getLine() == 0\`. In der Schleife steht \`mbot.forward()\`. +lösung: vb-bis-ziel-loesung.visustruct +::: + +## Was prüft die Schleife? + +::: quiz +? Der mBot2 steht 40 cm vor der Wand. Wie oft fährt er mit \`while (mbot.getDistance() > 15) mbot.forward();\` vor, wenn jede Fahrt 10 cm ist? +→ Wie weit ist die Wand? +- [ ] gar nicht +- [ ] einmal +- [x] so oft, bis die Wand höchstens 15 cm weg ist +- [ ] immer genau fünfmal +> Die While-Schleife prüft vor jeder Fahrt die Bedingung. Ist die Wand nah genug, hört sie auf. +? Warum reicht hier keine For-Schleife mit fester Anzahl? +→ Drei Welten, ein Programm +- [x] Weil die Wand in jeder Welt anders weit weg ist. +- [ ] Weil eine For-Schleife keine Anweisungen enthalten darf. +- [ ] Weil der mBot2 For-Schleifen nicht versteht. +> Die For-Schleife weiß vorher, wie oft sie läuft. Die While-Schleife entscheidet unterwegs. +::: + +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. + +::: checkliste +- Ich kann mit \`mbot.getDistance()\` den Abstand abfragen. → Wie weit ist die Wand? +- Ich kann entscheiden, wann ich eine While-Schleife statt einer For-Schleife nehme. → Drei Welten, ein Programm +- Ich kann mit dem Liniensensor ein Ziel finden. → Bis zum Ziel +::: +`,Uy=`--- +titel: Der Ultraschallsensor +bereich: VisuBot +kurz: Abstand messen, Abstand halten und das Ganze in Java. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, was \`mbot.getDistance()\` misst +- zwei Verzweigungen ineinander bauen +- eine While-Schleife mit dem Abstand in Java schreiben +::: + +## Wie misst der mBot2 den Abstand? + +::: mbot2 +fokus: ultrasonic +ansicht: vorn +::: + +Der [Ultraschallsensor]{teil=ultrasonic} schickt einen sehr hohen Ton los und wartet auf das Echo. Je länger das Echo braucht, desto weiter ist die Wand weg. \`mbot.getDistance()\` liefert den Abstand in **Zentimetern**, von etwa 3 bis 300. + +| Sensor | Text | Wert | +|---|---|---| +| Abstand | \`mbot.getDistance()\` | ganze Zahl in cm, z. B. \`38\` | + +> In der [Simulation](#zeige-simulation) steht unter der Welt immer der aktuelle Abstand. Mit einem echten mBot2 kannst du die Hand vor den Sensor halten und zusehen, wie sich die Zahl ändert. + +## Abstand halten im Struktogramm + +Der mBot2 soll wie ein Hund an der Leine sein: Ist deine Hand zu nah (unter 10 cm), weicht er zurück. Ist sie zu weit weg (über 20 cm), kommt er näher. Dazwischen bleibt er stehen. + +Dafür brauchst du zwei Verzweigungen ineinander. Die äußere prüft „zu nah?“, die innere im Nein-Zweig prüft „zu weit?“. + +::: übung vb-abstand-halten +titel: Abstand halten +auftrag: Baue ein Struktogramm: Ist der Abstand kleiner als 10, fährt der mBot2 zurück. Sonst: Ist der Abstand größer als 20, fährt er vor. Sonst tut er nichts. +messwerte: getDistance=5 -> backward +messwerte: getDistance=35 -> forward +messwerte: getDistance=15 -> none +braucht: verzweigung +tipp: Zieh eine Verzweigung ins Struktogramm und den Sensor **Abstand** darauf. Schreib \`< 10\` dahinter. Im Ja-Zweig steht **fahre zurück**. +tipp: In den Nein-Zweig kommt eine zweite Verzweigung mit \`mbot.getDistance() > 20\` und **fahre vor** im Ja-Zweig. Ihr Nein-Zweig bleibt leer. +lösung: vb-abstand-halten-loesung.visustruct +::: + +> Beim Prüfen setzt VisuStruct den Abstand nacheinander auf 5, 35 und 15 cm und schaut, was dein mBot2 tut. + +## Jetzt in Java + +Im Bereich [Code](#zeige-codelive) siehst du dein Struktogramm schon als Java-Code. Eine Verzweigung heißt dort \`if\`, der Nein-Zweig \`else\`: + +\`\`\`java +if (mbot.getDistance() < 10) { + mbot.backward(); +} else { + ... +} +\`\`\` + +Den Sensor tippst du wie einen Befehl: \`mbot.\` und dann \`getDistance()\`. Nach dem Punkt schlägt dir der Editor alle Befehle und Sensoren vor. + +::: übung vb-java-wand-piep +titel: Bis zur Wand und piepen +code: java +auftrag: Schreibe in Java: Der mBot2 fährt vor, solange die Wand mehr als 15 cm entfernt ist. Danach spielt er einen Ton. Es gibt drei Welten. +welt: wand-kurz -> tone +welt: wand-mittel -> tone +welt: wand-lang -> tone +braucht: whileSchleife +tipp: Eine While-Schleife heißt in Java \`while (Bedingung) { … }\`. Die Bedingung ist \`mbot.getDistance() > 15\`. +tipp: In der Schleife steht \`mbot.forward();\`, nach der Schleife \`mbot.playTone(440, 300);\`. +lösung: vb-java-wand-piep-loesung.visustruct +::: + +::: quiz +? \`mbot.getDistance()\` liefert \`8\`. Was tut das Programm aus „Abstand halten“? +→ Abstand halten im Struktogramm +- [x] Es fährt zurück. +- [ ] Es fährt vor. +- [ ] Es bleibt stehen. +> 8 ist kleiner als 10, also ist schon die erste Bedingung wahr. +? Wie heißt der Nein-Zweig einer Verzweigung in Java? +→ Jetzt in Java +- [ ] \`then\` +- [x] \`else\` +- [ ] \`otherwise\` +> \`if\` ist der Anfang, \`else\` der Nein-Zweig. +::: + +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. + +::: checkliste +- Ich kann erklären, was \`mbot.getDistance()\` misst. → Wie misst der mBot2 den Abstand? +- Ich kann zwei Verzweigungen ineinander bauen. → Abstand halten im Struktogramm +- Ich kann eine While-Schleife mit dem Abstand in Java schreiben. → Jetzt in Java +::: +`,$y=`--- +titel: Der Liniensensor +bereich: VisuBot +kurz: Dunkle Linien auf dem Boden erkennen und nicht vom Tisch fallen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, was die Zahl von \`mbot.getLine()\` bedeutet +- bis zu einer Linie fahren +- in Java mit einer Variable Schritte zählen +::: + +## Vier Fühler unter der Nase + +::: mbot2 +fokus: lineSensor +ansicht: unten +::: + +Der [Liniensensor]{teil=lineSensor} hat vier Fühler nebeneinander. Jeder leuchtet den Boden an und misst, wie viel Licht zurückkommt. Schwarz schluckt das Licht, Weiß wirft es zurück. + +| Sensor | Text | Wert | +|---|---|---| +| Linie | \`mbot.getLine()\` | \`0\` = alles hell, größer als \`0\` = mindestens ein Fühler sieht Schwarz | + +Für den Anfang reicht dir: **\`mbot.getLine() == 0\` heißt „keine Linie“**, \`mbot.getLine() != 0\` heißt „Linie gefunden“. + +::: angeberwissen +\`mbot.getLine()\` ist eigentlich eine Binärzahl mit vier Stellen, eine für jeden Fühler: \`1111\` (also 15) heißt „alle vier sehen Schwarz“, \`0110\` (6) „nur die mittleren“. Damit kann ein mBot2 sogar einer Linie folgen. +::: + +## Am Rand umkehren im Struktogramm + +Stell dir einen Tisch mit schwarzem Klebeband am Rand vor. Der mBot2 soll vorfahren, bis er das Band sieht, und dann umkehren, damit er nicht herunterfällt. + +::: übung vb-rand +titel: Am Rand umkehren +auftrag: Der mBot2 fährt vor, solange \`mbot.getLine() == 0\` ist. Danach dreht er sich um 180°. Es gibt zwei Welten mit unterschiedlich weitem Weg. +welt: rand-1 -> forward 20, turnRight 180 +welt: rand-2 -> forward 50, turnRight 180 +braucht: whileSchleife +tipp: Zieh eine While-Schleife ins Struktogramm und den Sensor **Linie** darauf. Schreib \`== 0\` dahinter. In die Schleife kommt **fahre vor**. +tipp: Nach der Schleife (darunter, nicht darin) steht \`mbot.turnRight(180)\`. +lösung: vb-rand-loesung.visustruct +::: + +## Jetzt in Java: hin und zurück + +Jetzt soll der mBot2 nach dem Umkehren genau bis zum Start zurückfahren. Dafür zählt er mit einer **Variable**, wie oft er vorgefahren ist. + +\`\`\`java +int schritte = 0; +while (mbot.getLine() == 0) { + mbot.forward(); + schritte = schritte + 1; +} +\`\`\` + +::: übung vb-java-rand +titel: Bis zur Linie und zurück +code: java +auftrag: Schreibe in Java: Der mBot2 fährt bis zur Linie und zählt dabei seine Schritte. Dann dreht er sich um 180° und fährt mit einer For-Schleife genauso viele Schritte zurück. +welt: rand-1 -> forward 20, turnRight 180, forward 20 +welt: rand-2 -> forward 50, turnRight 180, forward 50 +braucht: whileSchleife, forSchleife +tipp: Nach der While-Schleife: \`mbot.turnRight(180);\` und dann \`for (int i = 0; i < schritte; i++) { … }\`. +tipp: In der For-Schleife steht nur \`mbot.forward();\`. +lösung: vb-java-rand-loesung.visustruct +::: + +::: quiz +? Der mBot2 steht auf weißem Papier. Was liefert \`mbot.getLine()\`? +→ Vier Fühler unter der Nase +- [x] 0 +- [ ] 15 +- [ ] 1 +> Kein Fühler sieht Schwarz, also 0. +? Welche Bedingung heißt „Linie gefunden“? +→ Am Rand umkehren im Struktogramm +- [ ] \`mbot.getLine() == 0\` +- [x] \`mbot.getLine() != 0\` +- [ ] \`mbot.getLine() < 0\` +> \`!=\` heißt „ungleich“. +::: + +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. + +::: checkliste +- Ich kann erklären, was die Zahl von \`mbot.getLine()\` bedeutet. → Vier Fühler unter der Nase +- Ich kann bis zu einer Linie fahren. → Am Rand umkehren im Struktogramm +- Ich kann in Java mit einer Variable Schritte zählen. → Jetzt in Java: hin und zurück +::: +`,Yy=`--- +titel: Farben erkennen +bereich: VisuBot +kurz: Der Quad-RGB-Sensor sagt, auf welcher Farbe der mBot2 steht. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- mit \`mbot.getColor().equals(…)\` eine Farbe abfragen +- mit \`!\` eine Bedingung umdrehen +- eine Verzweigung in eine Schleife schreiben +::: + +## Ein Sensor, der Farben sieht + +::: mbot2 +fokus: lineSensor +ansicht: unten +::: + +Der [Liniensensor]{teil=lineSensor} heißt eigentlich **Quad-RGB-Sensor**. „Quad“ heißt vier (vier Fühler), „RGB“ steht für Rot, Grün und Blau. Er leuchtet den Boden in diesen drei Farben an und misst, welche Farbe zurückkommt. So erkennt er farbige Felder. + +\`mbot.getColor()\` liefert den Namen der Farbe unter dem mBot2, und zwar als **Text**: + +| Boden | \`mbot.getColor()\` | +|---|---| +| rotes Feld | \`"rot"\` | +| grünes Feld | \`"grün"\` | +| blaues Feld | \`"blau"\` | +| gelbes Feld | \`"gelb"\` | +| schwarzes Feld oder Linie | \`"schwarz"\` | +| heller Boden | \`"weiß"\` | + +Ob es eine bestimmte Farbe ist, fragst du mit \`.equals(…)\`: \`mbot.getColor().equals("rot")\` ist **wahr**, wenn der mBot2 auf Rot steht, sonst **falsch**. Das ist also schon eine fertige Bedingung. + +> Texte vergleichst du in Java immer mit \`.equals(…)\`, **nicht** mit \`==\`. Das \`==\` sieht richtig aus, klappt bei Texten aber oft nicht. + +> Mit dem \`!\` davor drehst du eine Bedingung um: \`!mbot.getColor().equals("rot")\` heißt „**nicht** rot“. + +## Fahre bis Rot im Struktogramm + +::: übung vb-bis-rot +titel: Fahre bis Rot +auftrag: Der mBot2 fährt vor, solange er **nicht** auf einem roten Feld steht. In der zweiten Welt liegt vorher ein grünes Feld, das soll ihn nicht stören. +welt: farbe-1 -> forward 20 +welt: farbe-2 -> forward 50 +braucht: whileSchleife +tipp: Zieh eine While-Schleife ins Struktogramm und den Sensor **Farbe ist rot?** darauf. Schreib ein \`!\` vor \`mbot.getColor().equals("rot")\`. +tipp: Die Bedingung heißt \`!mbot.getColor().equals("rot")\`, in der Schleife steht **fahre vor**. +lösung: vb-bis-rot-loesung.visustruct +::: + +## Jetzt in Java: bei Grün piepen + +Jetzt kombinierst du eine Schleife mit einer Verzweigung: Der mBot2 fährt bis Blau. Kommt er unterwegs über ein grünes Feld, piept er. + +::: übung vb-java-blau-gruen +titel: Bis Blau, bei Grün piepen +code: java +auftrag: Schreibe in Java: Der mBot2 fährt vor, solange er nicht auf Blau steht. Nach jedem Schritt prüft er: Steht er auf Grün, spielt er einen Ton. In der zweiten Welt gibt es kein grünes Feld, da darf er nicht piepen. +welt: farbe-3 -> forward 30, tone +welt: farbe-4 -> forward 30, noTone +braucht: whileSchleife, verzweigung +tipp: Außen steht \`while (!mbot.getColor().equals("blau")) { … }\`. Darin zuerst \`mbot.forward();\`. +tipp: Danach, noch in der Schleife: \`if (mbot.getColor().equals("grün")) { mbot.playTone(880, 200); }\`. +lösung: vb-java-blau-gruen-loesung.visustruct +::: + +::: quiz +? Der mBot2 steht auf einem roten Feld. Was ist \`!mbot.getColor().equals("rot")\`? +→ Fahre bis Rot im Struktogramm +- [ ] wahr +- [x] falsch +> \`mbot.getColor().equals("rot")\` ist wahr, das \`!\` macht daraus falsch. Die Schleife hört also auf. +? Womit vergleichst du die Farbe mit \`"grün"\`? +→ Ein Sensor, der Farben sieht +- [x] \`mbot.getColor().equals("grün")\` +- [ ] \`mbot.getColor() == "grün"\` +- [ ] \`mbot.getColor() = "grün"\` +> \`mbot.getColor()\` liefert einen Text, und Texte vergleicht man mit \`.equals(…)\`. Ein einzelnes \`=\` ist eine Zuweisung, gar kein Vergleich. +::: + +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. + +::: checkliste +- Ich kann mit \`mbot.getColor().equals(…)\` eine Farbe abfragen. → Ein Sensor, der Farben sieht +- Ich kann mit \`!\` eine Bedingung umdrehen. → Fahre bis Rot im Struktogramm +- Ich kann eine Verzweigung in eine Schleife schreiben. → Jetzt in Java: bei Grün piepen +::: +`,Xy=`--- +titel: Fallauswahl mit Farben +bereich: VisuBot +kurz: Je nach Farbe oder Linie etwas anderes tun, mit einer Fallauswahl statt vieler Verzweigungen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- eine Fallauswahl mit Texten bauen +- eine Fallauswahl mit Zahlen in Java schreiben +- eine Zahl einlesen und je nach Wert etwas ausgeben +::: + +## Viele Farben, viele Fälle + +Der mBot2 soll auf jede Farbe anders reagieren: bei Rot rechts abbiegen, bei Grün ein Stück vorfahren, bei Blau piepen. Mit Verzweigungen bräuchtest du drei ineinander. Übersichtlicher ist die **Fallauswahl**, in Java \`switch\`: + +\`\`\`java +switch (mbot.getColor()) { + case "rot" -> { + mbot.turnRight(); + } + case "grün" -> { + mbot.forward(20); + } + default -> { + mbot.forward(10); + } +} +\`\`\` + +- Oben in den Klammern steht der Wert, der geprüft wird, hier die Farbe. +- Jeder \`case\` ist ein **Fall**. Passt der Wert, läuft genau dieser Fall. +- \`default\` ist der Fall für **alles andere**. + +Im Struktogramm ist die Fallauswahl ein Kasten mit mehreren Spalten, für jeden Fall eine. + +::: übung vb-farbweiche +titel: Farbweiche +auftrag: Baue eine Fallauswahl über \`mbot.getColor()\`. Bei \`"rot"\` dreht sich der mBot2 nach rechts. Bei \`"grün"\` fährt er 20 cm vor. Bei \`"blau"\` spielt er einen Ton mit 880 Hertz, 200 Millisekunden lang. In allen anderen Fällen fährt er 10 cm vor. +messwerte: getColor=rot -> turnRight +messwerte: getColor=grün -> forward 20 +messwerte: getColor=blau -> none, tone +messwerte: getColor=weiß -> forward 10 +braucht: fallauswahl +tipp: Zieh eine Fallauswahl ins Struktogramm. Oben steht \`mbot.getColor()\`, die Fälle heißen \`"rot"\`, \`"grün"\` und \`"blau"\`, dazu der Fall für alles andere. +tipp: Bei Rot \`mbot.turnRight()\`, bei Grün \`mbot.forward(20)\`, bei Blau \`mbot.playTone(880, 200)\`, sonst \`mbot.forward(10)\`. +lösung: vb-farbweiche-loesung.visustruct +::: + +## Jetzt in Java: Linienmuster + +Auch eine Zahl kann der Wert einer Fallauswahl sein. \`mbot.getLine()\` aus Lektion 7 liefert zum Beispiel: + +| Wert | Bedeutung | +|---|---| +| \`0\` | keine Linie | +| \`6\` | die beiden mittleren Fühler sehen die Linie: Er steht genau drauf | +| \`15\` | alle vier sehen Schwarz: eine Querlinie | + +Bei Zahlen schreibst du den Fall ohne Anführungszeichen: \`case 6 -> { … }\`. + +::: übung vb-linienmuster +titel: Linienmuster +code: java +auftrag: Schreibe in Java eine Fallauswahl über \`mbot.getLine()\`. Bei 6 fährt der mBot2 10 cm vor. Bei 0 dreht er sich nach rechts. Bei 15 zeigt er **Querlinie!** auf dem Bildschirm. In allen anderen Fällen fährt er 5 cm vor. +messwerte: getLine=6 -> forward 10 +messwerte: getLine=0 -> turnRight +messwerte: getLine=15 -> none, screen "Querlinie!" +messwerte: getLine=4 -> forward 5 +braucht: fallauswahl +tipp: \`switch (mbot.getLine()) { case 6 -> { … } case 0 -> { … } case 15 -> { … } default -> { … } }\` +tipp: Bei 6 \`mbot.forward(10);\`, bei 0 \`mbot.turnRight();\`, bei 15 \`mbot.showText("Querlinie!");\`, sonst \`mbot.forward(5);\`. +lösung: vb-linienmuster-loesung.visustruct +::: + +## Jetzt ohne Roboter: Noten in Worten + +Die Fallauswahl brauchst du nicht nur für Roboter. Dieses Programm liest eine Zahl ein, die der Benutzer in der [Konsole](#zeige-konsole) tippt: + +\`\`\`java +Scanner scanner = new Scanner(System.in); +int note = scanner.nextInt(); +\`\`\` + +::: übung vb-ohne-noten +titel: Noten in Worten +code: java +auftrag: Lies eine Note als Zahl ein. Gib bei 1 **sehr gut** aus, bei 2 **gut**, bei 3 **befriedigend** und bei allen anderen Zahlen **andere Note**. Ganz ohne \`mbot\`! +test: 1 -> sehr gut +test: 2 -> gut +test: 3 -> befriedigend +test: 5 -> andere Note +braucht: fallauswahl +tipp: Zuerst \`Scanner scanner = new Scanner(System.in);\` und \`int note = scanner.nextInt();\`. Danach kommt \`switch (note) { … }\`. +tipp: \`case 1 -> { System.out.println("sehr gut"); }\` und so weiter, zum Schluss \`default -> { System.out.println("andere Note"); }\`. +lösung: vb-ohne-noten-loesung.visustruct +::: + +::: quiz +? Der mBot2 steht auf Gelb. Welcher Fall der Farbweiche läuft? +→ Viele Farben, viele Fälle +- [ ] der Fall \`"rot"\` +- [ ] gar keiner +- [x] \`default\` +> Für Gelb gibt es keinen eigenen Fall. Dann läuft der Fall für alles andere. +? Wie schreibst du den Fall für die Zahl 6? +→ Jetzt in Java: Linienmuster +- [x] \`case 6 -> { … }\` +- [ ] \`case "6" -> { … }\` +- [ ] \`if 6 -> { … }\` +> Zahlen stehen ohne Anführungszeichen, Texte wie \`"rot"\` mit. +::: + +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. + +::: checkliste +- Ich kann eine Fallauswahl mit Texten bauen. → Viele Farben, viele Fälle +- Ich kann eine Fallauswahl mit Zahlen in Java schreiben. → Jetzt in Java: Linienmuster +- Ich kann eine Zahl einlesen und je nach Wert etwas ausgeben. → Jetzt ohne Roboter: Noten in Worten +::: +`,Ky=`--- +titel: Tasten und Joystick +bereich: VisuBot +kurz: Der mBot2 wartet auf dich und lässt sich fernsteuern. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- die Sensoren für Tasten und Joystick abfragen +- auf eine Taste warten +- den mBot2 mit dem Joystick steuern +::: + +## Drücken als Sensor + +::: mbot2 +fokus: joystick, buttons +ansicht: oben +::: + +Auf dem CyberPi sitzen zwei [Tasten]{teil=buttons} (A und B) und ein [Joystick]{teil=joystick}. Für dein Programm sind das Sensoren: Sie liefern **wahr**, solange du drückst. + +| Sensor | Text | +|---|---| +| Taste A / B gedrückt? | \`mbot.isButtonA()\`, \`mbot.isButtonB()\` | +| Joystick nach oben / unten | \`mbot.isJoystickUp()\`, \`mbot.isJoystickDown()\` | +| Joystick nach links / rechts | \`mbot.isJoystickLeft()\`, \`mbot.isJoystickRight()\` | + +> Ohne echten mBot2 klappst du in der [Simulation](#zeige-simulation) unter der Welt **🎛 Sensoren ausprobieren** auf. Dort gibt es die Knöpfe A, B und die Pfeile für den Joystick. Ein Klick hält sie eine Sekunde lang gedrückt. + +## Warten auf Taste A im Struktogramm + +Ein Roboter soll nicht sofort losfahren, wenn das Programm startet. Besser: Er wartet, bis du A drückst. + +Warten heißt: eine Schleife, die so lange läuft, wie A **nicht** gedrückt ist. Damit sie nicht ganz leer ist, wartet der mBot2 darin kurz mit **kurz warten** (\`mbot.pause(100)\`, also 100 Millisekunden). + +::: übung vb-start-a +titel: Start mit Taste A +auftrag: Der mBot2 wartet, bis Taste A gedrückt ist. Dann fährt er 30 cm vor. +messwerte: isButtonA=false/true -> forward 30 +messwerte: isButtonA=true -> forward 30 +braucht: whileSchleife +tipp: Eine While-Schleife mit der Bedingung \`!mbot.isButtonA()\`. Darin steht **kurz warten**. +tipp: Nach der Schleife steht \`mbot.forward(30)\`. +lösung: vb-start-a-loesung.visustruct +::: + +> Beim Prüfen ist Taste A erst eine Weile nicht gedrückt und dann gedrückt. Fährt dein mBot2 zu früh los, fällt das auf. + +## Jetzt in Java: Fernsteuerung + +Mit dem Joystick lenkst du den mBot2. Das Programm fragt fünfmal nacheinander den Joystick ab: nach oben heißt vorfahren, nach unten zurückfahren. + +::: übung vb-java-joystick +titel: Fernsteuerung +code: java +auftrag: Schreibe in Java eine For-Schleife, die fünfmal läuft. Darin: Ist der Joystick oben, fährt der mBot2 vor. Sonst: Ist er unten, fährt er zurück. +messwerte: isJoystickUp=true -> forward 50 +messwerte: isJoystickDown=true -> backward 50 +messwerte: isJoystickUp=false -> none +braucht: forSchleife, verzweigung +tipp: \`for (int i = 0; i < 5; i++) { … }\` und darin \`if (mbot.isJoystickUp()) { … } else { … }\`. +tipp: Im \`else\` steht noch eine Verzweigung: \`if (mbot.isJoystickDown()) { mbot.backward(); }\`. +lösung: vb-java-joystick-loesung.visustruct +::: + +::: quiz +? Was liefert \`mbot.isButtonB()\`, wenn niemand drückt? +→ Drücken als Sensor +- [ ] 0 +- [x] false +- [ ] B +> Tasten liefern wahr oder falsch. +? Warum steht in der Warteschleife **kurz warten**? +→ Warten auf Taste A im Struktogramm +- [x] Damit die Schleife nicht leer ist und der CyberPi nicht unnötig schnell im Kreis rennt. +- [ ] Damit die Taste länger leuchtet. +- [ ] Ohne Pause fährt der mBot2 rückwärts. +> Die Schleife fragt alle 100 Millisekunden nach, das reicht völlig. +::: + +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. + +::: checkliste +- Ich kann die Sensoren für Tasten und Joystick abfragen. → Drücken als Sensor +- Ich kann auf eine Taste warten. → Warten auf Taste A im Struktogramm +- Ich kann den mBot2 mit dem Joystick steuern. → Jetzt in Java: Fernsteuerung +::: +`,ew=`--- +titel: Der Lichtsensor +bereich: VisuBot +kurz: Hell oder dunkel? Der mBot2 wird zum Nachtlicht. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- die Helligkeit abfragen +- mit einer Verzweigung die LEDs schalten +- mehrere Befehle in einen Zweig schreiben +::: + +## Wie hell ist es? + +::: mbot2 +fokus: lightSensor +ansicht: oben +::: + +Der [Lichtsensor]{teil=lightSensor} sitzt auf dem CyberPi. \`mbot.getBrightness()\` liefert eine Zahl von **0** (stockdunkel) bis **100** (sehr hell). + +| Sensor | Text | Wert | +|---|---|---| +| Helligkeit | \`mbot.getBrightness()\` | 0 bis 100 | + +> In der Simulation stellst du die Helligkeit mit dem Regler unter **🎛 Sensoren ausprobieren** ein. Mit einem echten mBot2 hältst du einfach die Hand über den CyberPi. + +## Nachtlicht im Struktogramm + +::: übung vb-nachtlicht +titel: Nachtlicht +auftrag: Ist die Helligkeit kleiner als 30, leuchten die LEDs weiß (\`mbot.setLed(255, 255, 255)\`). Sonst gehen die LEDs aus (\`mbot.ledOff()\`). +messwerte: getBrightness=10 -> ledOn +messwerte: getBrightness=80 -> ledOff +braucht: verzweigung +tipp: Zieh eine Verzweigung ins Struktogramm und den Sensor **Helligkeit** darauf. Schreib \`< 30\` dahinter. +tipp: Im Ja-Zweig steht **LEDs an** mit \`mbot.setLed(255, 255, 255)\`, im Nein-Zweig **LEDs aus**. +lösung: vb-nachtlicht-loesung.visustruct +::: + +::: angeberwissen +Straßenlaternen machen es genauso: Ein Lichtsensor merkt, wann es dämmert, und schaltet sie ein. Darum gehen sie im Winter früher an als im Sommer, ohne dass jemand eine Uhr umstellt. +::: + +## Jetzt in Java: Nachtlicht mit Ton + +::: übung vb-java-nachtlicht-ton +titel: Nachtlicht mit Ton +code: java +auftrag: Schreibe das Nachtlicht in Java, aber mit zwei Änderungen: Im Dunkeln leuchten die LEDs gelb (\`mbot.setLed(255, 200, 0)\`) **und** der mBot2 spielt einen Ton. Im Hellen gehen die LEDs aus, ohne Ton. +messwerte: getBrightness=10 -> ledOn, tone +messwerte: getBrightness=80 -> ledOff, noTone +braucht: verzweigung +tipp: \`if (mbot.getBrightness() < 30) { … } else { … }\` +tipp: Im \`if\`-Teil stehen zwei Zeilen: \`mbot.setLed(255, 200, 0);\` und \`mbot.playTone(440, 300);\`. +lösung: vb-java-nachtlicht-ton-loesung.visustruct +::: + +::: quiz +? \`mbot.getBrightness()\` liefert 45. Was tut das Nachtlicht? +→ Nachtlicht im Struktogramm +- [ ] Die LEDs leuchten. +- [x] Die LEDs gehen aus. +> 45 ist nicht kleiner als 30. +? In welchem Bereich liegen die Werte des Lichtsensors? +→ Wie hell ist es? +- [ ] 0 bis 255 +- [x] 0 bis 100 +- [ ] -100 bis 100 +::: + +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. + +::: checkliste +- Ich kann die Helligkeit abfragen. → Wie hell ist es? +- Ich kann mit einer Verzweigung die LEDs schalten. → Nachtlicht im Struktogramm +- Ich kann mehrere Befehle in einen Zweig schreiben. → Jetzt in Java: Nachtlicht mit Ton +::: +`,tw=`--- +titel: Das Mikrofon +bereich: VisuBot +kurz: Klatschen zum Losfahren und eine Lärmampel für das Klassenzimmer. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- die Lautstärke abfragen +- warten, bis etwas passiert +- eine Lärmampel in Java schreiben +::: + +## Wie laut ist es? + +::: mbot2 +fokus: microphone +ansicht: oben +::: + +Das [Mikrofon]{teil=microphone} des CyberPi misst die Lautstärke. \`mbot.getLoudness()\` liefert **0** (still) bis **100** (sehr laut). Ein Klatschen in der Nähe ergibt ungefähr 60 bis 90. + +| Sensor | Text | Wert | +|---|---|---| +| Lautstärke | \`mbot.getLoudness()\` | 0 bis 100 | + +## Klatschen zum Losfahren im Struktogramm + +Wie beim Warten auf Taste A: Eine Schleife wartet, solange es leise ist. Erst dann fährt der mBot2 los. + +::: übung vb-klatschen +titel: Klatschen zum Losfahren +auftrag: Der mBot2 wartet, solange die Lautstärke kleiner als 50 ist. Danach fährt er 30 cm vor. +messwerte: getLoudness=0/80 -> forward 30 +messwerte: getLoudness=90 -> forward 30 +braucht: whileSchleife +tipp: Eine While-Schleife mit der Bedingung \`mbot.getLoudness() < 50\`, darin **kurz warten**. +tipp: Nach der Schleife: \`mbot.forward(30)\`. +lösung: vb-klatschen-loesung.visustruct +::: + +> In der Simulation schiebst du den Regler **Lautstärke** nach rechts, während das Programm wartet. + +## Jetzt in Java: Lärmampel + +::: übung vb-java-laermampel +titel: Lärmampel +code: java +auftrag: Schreibe in Java: Ist die Lautstärke größer als 60, leuchten die LEDs rot. Sonst sind sie aus. +messwerte: getLoudness=80 -> ledOn +messwerte: getLoudness=20 -> ledOff +braucht: verzweigung +tipp: \`if (mbot.getLoudness() > 60) { … } else { … }\` +tipp: Rot ist \`mbot.setLed(255, 0, 0);\`, aus ist \`mbot.ledOff();\`. +lösung: vb-java-laermampel-loesung.visustruct +::: + +::: angeberwissen +Lautstärke misst man eigentlich in **Dezibel** (dB). Flüstern hat etwa 30 dB, ein Klassenzimmer 60 bis 70 dB, ein Presslufthammer 100 dB. Der CyberPi rechnet das in eine einfache Zahl von 0 bis 100 um. +::: + +::: quiz +? Die Klatsch-Schleife lautet \`while (mbot.getLoudness() < 50)\`. Es ist 30 laut. Was passiert? +→ Klatschen zum Losfahren im Struktogramm +- [x] Der mBot2 wartet weiter. +- [ ] Der mBot2 fährt los. +> 30 ist kleiner als 50, die Bedingung ist wahr, die Schleife läuft weiter. +::: + +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. + +::: checkliste +- Ich kann die Lautstärke abfragen. → Wie laut ist es? +- Ich kann warten, bis etwas passiert. → Klatschen zum Losfahren im Struktogramm +- Ich kann eine Lärmampel in Java schreiben. → Jetzt in Java: Lärmampel +::: +`,nw=`--- +titel: Der Lagesensor +bereich: VisuBot +kurz: Neigung messen und Schütteln erkennen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, was der Lagesensor misst +- zwei Bedingungen mit „oder“ verbinden +- mehrere Bedingungen mit „und“ verbinden +::: + +## Schief oder gerade? + +::: mbot2 +fokus: cyberpi +drehen: ja +::: + +Im [CyberPi]{teil=cyberpi} steckt ein **Lagesensor** (Gyroskop). Er misst, wie schief der mBot2 steht, in Grad: + +| Sensor | Text | Wert | +|---|---|---| +| Neigung vorn/hinten | \`mbot.getPitch()\` | Nase nach unten: positiv, nach oben: negativ (−90 bis 90) | +| Neigung seitlich | \`mbot.getRoll()\` | zur einen Seite positiv, zur anderen negativ | +| Geschüttelt? | \`mbot.isShaken()\` | \`true\` oder \`false\` | + +Steht der mBot2 flach auf dem Tisch, sind beide Neigungen ungefähr **0**. + +> In der Simulation gibt es dafür zwei Regler unter **🎛 Sensoren ausprobieren** und den Knopf **schütteln**. Mit einem echten mBot2 kippst du ihn vorsichtig in der Hand. + +## Schräglage-Warnung im Struktogramm + +Fährt der mBot2 eine zu steile Rampe hoch oder runter, soll er warnen. Zu steil heißt: mehr als 20° nach vorn **oder** mehr als 20° nach hinten. + +::: übung vb-schraeglage +titel: Schräglage-Warnung +auftrag: Ist die Neigung vorn/hinten größer als 20 **oder** kleiner als −20, spielt der mBot2 einen Ton. Sonst tut er nichts. +messwerte: getPitch=30 -> tone +messwerte: getPitch=-30 -> tone +messwerte: getPitch=5 -> noTone +braucht: verzweigung +tipp: „oder“ heißt in einer Bedingung \`||\`. Zieh den Sensor **Neigung vorn/hinten** zweimal auf die Verzweigung. +tipp: Die Bedingung heißt \`mbot.getPitch() > 20 || mbot.getPitch() < -20\`, im Ja-Zweig steht **Ton spielen**. +lösung: vb-schraeglage-loesung.visustruct +::: + +## Jetzt in Java: Wasserwaage + +Eine Wasserwaage zeigt, ob etwas genau gerade ist. Der mBot2 leuchtet grün, wenn beide Neigungen zwischen −5 und 5 liegen. + +::: übung vb-java-wasserwaage +titel: Wasserwaage +code: java +auftrag: Schreibe in Java: Liegen \`mbot.getPitch()\` und \`mbot.getRoll()\` beide zwischen −5 und 5, leuchten die LEDs grün. Sonst sind sie aus. +messwerte: getPitch=0, getRoll=0 -> ledOn +messwerte: getPitch=0, getRoll=20 -> ledOff +messwerte: getPitch=-10, getRoll=0 -> ledOff +braucht: verzweigung +tipp: „und“ heißt \`&&\`. Du brauchst vier Vergleiche: \`mbot.getPitch() > -5 && mbot.getPitch() < 5 && …\` +tipp: Grün ist \`mbot.setLed(0, 255, 0);\`, im \`else\` steht \`mbot.ledOff();\`. +lösung: vb-java-wasserwaage-loesung.visustruct +::: + +::: quiz +? Der mBot2 steht flach auf dem Tisch. Was liefert \`mbot.getPitch()\` ungefähr? +→ Schief oder gerade? +- [x] 0 +- [ ] 90 +- [ ] 100 +? Was macht \`mbot.isShaken()\`? +→ Schief oder gerade? +- [ ] Es schüttelt den mBot2. +- [x] Es meldet, ob jemand den mBot2 schüttelt. +> Sensoren tun nichts, sie messen nur. +::: + +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. + +::: checkliste +- Ich kann erklären, was der Lagesensor misst. → Schief oder gerade? +- Ich kann zwei Bedingungen mit „oder“ verbinden. → Schräglage-Warnung im Struktogramm +- Ich kann mehrere Bedingungen mit „und“ verbinden. → Jetzt in Java: Wasserwaage +::: +`,iw=`--- +titel: Die LEDs +bereich: VisuBot +kurz: Farben mischen, eine Ampel bauen und blinken lassen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- eine Farbe aus Rot, Grün und Blau mischen +- Farben mit Pausen nacheinander zeigen +- die LEDs in Java blinken lassen +::: + +## Rot, Grün und Blau mischen + +::: mbot2 +fokus: leds +ansicht: hinten +::: + +Die fünf [LEDs]{teil=leds} sind ein **Aktor**: Sie tun etwas, sie leuchten. Jede LED mischt ihre Farbe aus Rot, Grün und Blau, jeweils von 0 (aus) bis 255 (ganz hell). + +| Befehl | Kasten | Was passiert | +|---|---|---| +| \`mbot.setLed(255, 0, 0)\` | **LEDs an** | alle LEDs rot | +| \`mbot.ledOff()\` | **LEDs aus** | alle LEDs aus | +| \`mbot.pause(1000)\` | **kurz warten** | 1000 Millisekunden (1 Sekunde) warten | + +| Farbe | Rot | Grün | Blau | +|---|---|---|---| +| Rot | 255 | 0 | 0 | +| Gelb | 255 | 200 | 0 | +| Grün | 0 | 255 | 0 | +| Blau | 0 | 0 | 255 | +| Weiß | 255 | 255 | 255 | +| Lila | 160 | 0 | 255 | + +> Ohne **kurz warten** schaltet der mBot2 die Farben so schnell um, dass du nur die letzte siehst. In der Simulation siehst du die Farbe an den LEDs des 3D-Modells. + +## Ampel im Struktogramm + +::: übung vb-ampel +titel: Ampel +auftrag: Die LEDs zeigen nacheinander Rot, Gelb und Grün wie eine Ampel. Zwischen den Farben wartet der mBot2 jeweils 1000 Millisekunden. Gelb ist \`255, 200, 0\`. +befehle: setLed 255 0 0, pause 1000, setLed 255 200 0, pause 1000, setLed 0 255 0 +tipp: Zieh dreimal **LEDs an** und zweimal **kurz warten** ins Struktogramm, abwechselnd. +tipp: Ändere die Zahlen: \`mbot.setLed(255, 0, 0)\`, \`mbot.pause(1000)\`, \`mbot.setLed(255, 200, 0)\`, \`mbot.pause(1000)\`, \`mbot.setLed(0, 255, 0)\`. +lösung: vb-ampel-loesung.visustruct +::: + +## Jetzt in Java: Blaulicht + +Blinken heißt: an, warten, aus, warten, und das immer wieder. Das „immer wieder“ ist eine Schleife. + +::: übung vb-java-blinken +titel: Blaulicht +code: java +auftrag: Schreibe in Java eine For-Schleife, die dreimal läuft. Darin gehen die LEDs blau an, der mBot2 wartet 500 Millisekunden, die LEDs gehen aus, und er wartet wieder 500 Millisekunden. +befehle: 3 x (setLed 0 0 255, pause 500, ledOff, pause 500) +braucht: forSchleife +tipp: \`for (int i = 0; i < 3; i++) { … }\` +tipp: In der Schleife: \`mbot.setLed(0, 0, 255);\`, \`mbot.pause(500);\`, \`mbot.ledOff();\`, \`mbot.pause(500);\`. +lösung: vb-java-blinken-loesung.visustruct +::: + +::: quiz +? Welche Farbe ergibt \`mbot.setLed(0, 255, 0)\`? +→ Rot, Grün und Blau mischen +- [ ] Rot +- [x] Grün +- [ ] Blau +> Die Zahlen sind Rot, Grün, Blau. Nur Grün ist an. +? Warum braucht das Blaulicht **kurz warten**? +→ Jetzt in Java: Blaulicht +- [x] Sonst wechselt es so schnell, dass man kein Blinken sieht. +- [ ] Sonst gehen die LEDs kaputt. +- [ ] Weil \`ledOff()\` sonst nicht geht. +::: + +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. + +::: checkliste +- Ich kann eine Farbe aus Rot, Grün und Blau mischen. → Rot, Grün und Blau mischen +- Ich kann Farben mit Pausen nacheinander zeigen. → Ampel im Struktogramm +- Ich kann die LEDs in Java blinken lassen. → Jetzt in Java: Blaulicht +::: +`,aw=`--- +titel: Einzelne LEDs +bereich: VisuBot +kurz: Jede der fünf LEDs bekommt ihre eigene Farbe, bis zum Lauflicht. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- die LEDs über ihre Nummern 0 bis 4 ansprechen +- einzelne LEDs in verschiedenen Farben leuchten lassen +- mit einer Schleife ein Lauflicht bauen +::: + +## Jede LED hat eine Nummer + +::: mbot2 +fokus: leds +ansicht: hinten +::: + +Bisher haben alle fünf [LEDs]{teil=leds} dieselbe Farbe gezeigt. Du kannst aber auch jede LED einzeln ansprechen. Dafür hat jede LED eine **Nummer**. Wie bei Arrays fängt das Zählen bei **0** an: Die fünf LEDs heißen 0, 1, 2, 3 und 4. + +| Befehl | Kasten | Was passiert | +|---|---|---| +| \`mbot.led(0).setColor("grün")\` | **LED-Farbe setzen** | LED 0 leuchtet grün | +| \`mbot.led(3).setColor("aus")\` | **LED-Farbe setzen** | LED 3 geht aus | + +Die Farbe schreibst du als Namen in Anführungszeichen: + +| Farbname | Farbname | Farbname | +|---|---|---| +| \`"rot"\` | \`"orange"\` | \`"gelb"\` | +| \`"grün"\` | \`"türkis"\` | \`"blau"\` | +| \`"lila"\` | \`"pink"\` | \`"weiß"\` | + +Mit \`"aus"\` schaltest du eine LED aus. + +> Die Nummer darf auch eine Variable sein: \`mbot.led(i).setColor("rot")\`. So kann eine Schleife eine LED nach der anderen einschalten. + +## Drei Lichter im Struktogramm + +::: übung vb-drei-lichter +titel: Drei Lichter +auftrag: Schalte LED 0 rot, LED 2 gelb und LED 4 grün. Die LEDs 1 und 3 bleiben aus. +befehle: ledColor 0 "rot", ledColor 2 "gelb", ledColor 4 "grün" +tipp: Zieh dreimal **LED-Farbe setzen** ins Struktogramm. +tipp: Ändere Nummer und Farbe: \`mbot.led(0).setColor("rot")\`, \`mbot.led(2).setColor("gelb")\`, \`mbot.led(4).setColor("grün")\`. +lösung: vb-drei-lichter-loesung.visustruct +::: + +## Jetzt in Java: Lauflicht + +Bei einem Lauflicht wandert ein Licht von einer LED zur nächsten. Die Schleifenvariable \`i\` ist dabei die Nummer der LED. + +::: übung vb-java-lauflicht +titel: Lauflicht +code: java +auftrag: Schreibe in Java eine For-Schleife, in der \`i\` von 0 bis 4 läuft. Darin geht LED \`i\` blau an, der mBot2 wartet 200 Millisekunden, und LED \`i\` geht wieder aus. +befehle: ledColor 0 "blau", pause 200, ledColor 0 "aus", ledColor 1 "blau", pause 200, ledColor 1 "aus", ledColor 2 "blau", pause 200, ledColor 2 "aus", ledColor 3 "blau", pause 200, ledColor 3 "aus", ledColor 4 "blau", pause 200, ledColor 4 "aus" +braucht: forSchleife +tipp: \`for (int i = 0; i < 5; i++) { … }\` +tipp: In der Schleife: \`mbot.led(i).setColor("blau");\`, \`mbot.pause(200);\`, \`mbot.led(i).setColor("aus");\`. +lösung: vb-java-lauflicht-loesung.visustruct +::: + +::: quiz +? Welche Nummer hat die erste LED? +→ Jede LED hat eine Nummer +- [x] 0 +- [ ] 1 +- [ ] 5 +> Wie bei Arrays zählt man ab 0. Die fünf LEDs haben die Nummern 0 bis 4. +? Was macht \`mbot.led(4).setColor("aus")\`? +→ Drei Lichter im Struktogramm +- [ ] Alle LEDs gehen aus. +- [x] Nur LED 4 geht aus. +- [ ] Vier LEDs gehen aus. +::: + +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. + +::: checkliste +- Ich kann die LEDs über ihre Nummern 0 bis 4 ansprechen. → Jede LED hat eine Nummer +- Ich kann einzelne LEDs in verschiedenen Farben leuchten lassen. → Drei Lichter im Struktogramm +- Ich kann mit einer Schleife ein Lauflicht bauen. → Jetzt in Java: Lauflicht +::: +`,sw=`--- +titel: Der Lautsprecher +bereich: VisuBot +kurz: Töne, eine Tonleiter und eine Sirene. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- erklären, was die beiden Zahlen bei \`playTone\` bedeuten +- eine Tonfolge bauen +- in Java mit der Zählvariable rechnen +- den mBot2 ein Gefühl zeigen lassen +::: + +## Wie hoch, wie lang? + +::: mbot2 +fokus: cyberpi +ansicht: oben +::: + +Im [CyberPi]{teil=cyberpi} steckt ein kleiner Lautsprecher. \`mbot.playTone(440, 300)\` spielt einen Ton: + +- Die erste Zahl ist die **Tonhöhe** in Hertz (Schwingungen pro Sekunde). Je größer, desto höher. +- Die zweite Zahl ist die **Länge** in Millisekunden. + +| Ton | c | d | e | f | g | a | h | c' | +|---|---|---|---|---|---|---|---|---| +| Hertz | 262 | 294 | 330 | 349 | 392 | 440 | 494 | 523 | + +> In der Simulation hörst du die Töne über die Lautsprecher deines Computers. Dreh ruhig etwas leiser. + +## Tonleiter im Struktogramm + +::: übung vb-tonleiter +titel: Tonleiter +auftrag: Der mBot2 spielt die Töne c, d, e, f, g nacheinander, jeden 300 Millisekunden lang. Die Hertz-Zahlen stehen in der Tabelle. +befehle: playTone 262 300, playTone 294 300, playTone 330 300, playTone 349 300, playTone 392 300 +tipp: Zieh fünfmal **Ton spielen** ins Struktogramm. +tipp: Die Kästen heißen \`mbot.playTone(262, 300)\`, \`mbot.playTone(294, 300)\` und so weiter. +lösung: vb-tonleiter-loesung.visustruct +::: + +::: angeberwissen +Der Ton a mit 440 Hertz heißt **Kammerton**. Nach ihm stimmen Orchester ihre Instrumente. Eine Oktave höher hat genau doppelt so viele Schwingungen: 880 Hertz. +::: + +## Jetzt in Java: immer höher + +In einer For-Schleife kannst du mit der Zählvariable rechnen. So wird jeder Ton höher als der letzte: + +\`\`\`java +mbot.playTone(i * 200, 200); +\`\`\` + +::: übung vb-java-hoeher +titel: Immer höher +code: java +auftrag: Schreibe in Java eine For-Schleife, in der \`i\` von 1 bis 5 zählt. In jedem Durchgang spielt der mBot2 einen Ton mit \`i * 200\` Hertz, 200 Millisekunden lang. +befehle: playTone 200 200, playTone 400 200, playTone 600 200, playTone 800 200, playTone 1000 200 +braucht: forSchleife +tipp: \`for (int i = 1; i <= 5; i++) { … }\` +tipp: In der Schleife steht nur \`mbot.playTone(i * 200, 200);\`. +lösung: vb-java-hoeher-loesung.visustruct +::: + +## Gefühle zeigen + +Der mBot2 kann auch fröhlich, traurig oder müde sein. Mit **Gefühl zeigen** (\`mbot.emotion("smile")\`) spielt er eine kleine Vorführung: Die LEDs leuchten, er macht ein Geräusch und wackelt ein bisschen. + +| Text | Gefühl | +|---|---| +| \`mbot.emotion("smile")\` | lacht | +| \`mbot.emotion("hello")\` | grüßt | +| \`mbot.emotion("sad")\` | ist traurig | +| \`mbot.emotion("angry")\` | ist wütend | +| \`mbot.emotion("dizzy")\` | ist schwindelig | +| \`mbot.emotion("zzz")\` | schläft | + +> Probier es mit dem echten mBot2 aus. Im Simulator siehst du davon nichts, er zeigt nur den Befehl an. Weitere Gefühle stehen unter **Nachschlagen**. + +::: quiz +? Welcher Ton ist höher? +→ Wie hoch, wie lang? +- [x] \`mbot.playTone(880, 300)\` +- [ ] \`mbot.playTone(440, 300)\` +> Mehr Hertz heißt höher. +? Wie lange klingt \`mbot.playTone(440, 1000)\`? +→ Wie hoch, wie lang? +- [ ] 440 Sekunden +- [x] 1 Sekunde +- [ ] 1000 Sekunden +> 1000 Millisekunden sind eine Sekunde. +::: + +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. + +::: checkliste +- Ich kann erklären, was die beiden Zahlen bei \`playTone\` bedeuten. → Wie hoch, wie lang? +- Ich kann eine Tonfolge bauen. → Tonleiter im Struktogramm +- Ich kann in Java mit der Zählvariable rechnen. → Jetzt in Java: immer höher +- Ich kann den mBot2 ein Gefühl zeigen lassen. → Gefühle zeigen +::: +`,rw=`--- +titel: Arrays und Melodien +bereich: VisuBot +kurz: Viele Werte in einem Array speichern und mit einer Schleife abarbeiten. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- ein Array anlegen und mit einer Schleife abspielen +- ein Array mit Texten in Java benutzen +- alle Werte eines Arrays zusammenzählen +::: + +## Eine Melodie als Array + +Eine Melodie ist eine Reihe von Tönen. Statt fünf Variablen \`ton1\`, \`ton2\`, … nimmst du ein **Array**. Ein Array ist eine Reihe von Fächern unter **einem** Namen: + +\`\`\`java +int[] toene = {262, 294, 330, 349, 392}; +\`\`\` + +- \`int[]\` heißt: ein Array aus ganzen Zahlen. +- Die Fächer sind von **0** an nummeriert. \`toene[0]\` ist 262, \`toene[4]\` ist 392. +- \`toene.length\` sagt, wie viele Fächer es gibt, hier 5. + +Eine For-Schleife mit \`i\` von 0 bis \`toene.length - 1\` kommt so an jedes Fach. + +::: übung vb-melodie +titel: Melodie +auftrag: Lege ein Array \`toene\` mit den Tonhöhen 262, 294, 330, 349 und 392 an. Eine For-Schleife spielt sie nacheinander, jeden 300 Millisekunden lang. +befehle: playTone 262 300, playTone 294 300, playTone 330 300, playTone 349 300, playTone 392 300 +braucht: forSchleife +tipp: \`int[] toene = {262, 294, 330, 349, 392}\` legt das Array an. +tipp: Die Schleife läuft von \`i = 0\` bis \`i < toene.length\`. Darin steht \`mbot.playTone(toene[i], 300)\`. +lösung: vb-melodie-loesung.visustruct +::: + +> Willst du eine andere Melodie, änderst du nur das Array. Die Schleife bleibt gleich. + +## Jetzt in Java: Regenbogen + +Die fünf LEDs haben die Nummern 0 bis 4, genau wie die Fächer eines Arrays mit fünf Werten. Ein Array kann auch Texte enthalten: \`String[] farben = {"rot", "gelb"};\`. LED \`i\` bekommt dann die Farbe aus Fach \`i\`: \`mbot.led(i).setColor(farben[i])\`. + +::: übung vb-farben +titel: Regenbogen +code: java +auftrag: Schreibe in Java: Lege ein Array \`farben\` mit den Texten \`"rot"\`, \`"gelb"\`, \`"grün"\`, \`"blau"\` und \`"lila"\` an. Eine For-Schleife gibt jeder LED \`i\` die Farbe aus \`farben[i]\`. +befehle: ledColor 0 "rot", ledColor 1 "gelb", ledColor 2 "grün", ledColor 3 "blau", ledColor 4 "lila" +braucht: forSchleife +tipp: \`String[] farben = {"rot", "gelb", "grün", "blau", "lila"};\` legt das Array an. +tipp: \`for (int i = 0; i < farben.length; i++) { mbot.led(i).setColor(farben[i]); }\` +lösung: vb-farben-loesung.visustruct +::: + +## Jetzt ohne Roboter: Summe der Noten + +Mit einer Schleife kannst du auch alle Werte eines Arrays zusammenzählen. Dafür brauchst du eine Variable, die mit 0 anfängt und in jedem Durchgang wächst: + +\`\`\`java +int summe = 0; +for (int i = 0; i < noten.length; i++) { + summe = summe + noten[i]; +} +\`\`\` + +::: übung vb-ohne-summe +titel: Summe der Noten +code: java +auftrag: Lege \`int[] noten = {2, 1, 3, 2}\` an. Zähle in einer Schleife alle Noten zusammen und gib danach **Summe: 8** und in einer zweiten Zeile **Anzahl: 4** aus. Die Anzahl liefert \`noten.length\`. Ganz ohne \`mbot\`! +test: - -> Summe: 8 | Anzahl: 4 +braucht: forSchleife +tipp: Vor der Schleife \`int summe = 0;\`, in der Schleife \`summe = summe + noten[i];\`. +tipp: Nach der Schleife \`System.out.println("Summe: " + summe);\` und \`System.out.println("Anzahl: " + noten.length);\`. +lösung: vb-ohne-summe-loesung.visustruct +::: + +::: quiz +? Was ist \`toene[1]\`, wenn \`int[] toene = {262, 294, 330};\`? +→ Eine Melodie als Array +- [ ] 262 +- [x] 294 +- [ ] 1 +> Die Fächer zählen ab 0. Fach 1 ist also das zweite. +? Wie viele Fächer hat \`{262, 294, 330}\`, also was ist \`toene.length\`? +→ Eine Melodie als Array +- [ ] 2 +- [x] 3 +- [ ] 330 +> \`length\` zählt die Fächer, hier drei. Das letzte Fach hat deshalb die Nummer 2. +::: + +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. + +::: checkliste +- Ich kann ein Array anlegen und mit einer Schleife abspielen. → Eine Melodie als Array +- Ich kann ein Array mit Texten in Java benutzen. → Jetzt in Java: Regenbogen +- Ich kann alle Werte eines Arrays zusammenzählen. → Jetzt ohne Roboter: Summe der Noten +::: +`,ow=`--- +titel: Der Bildschirm +bereich: VisuBot +kurz: Text, Zahlen und Messwerte auf dem CyberPi anzeigen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- Text auf dem Bildschirm anzeigen +- mehrere Texte nacheinander zeigen +- Zahlen und Messwerte anzeigen +- einen Countdown in Java schreiben +::: + +## Text anzeigen + +::: mbot2 +fokus: screen +ansicht: hinten +::: + +Der farbige [Bildschirm]{teil=screen} des CyberPi ist auch ein Aktor. Mit **Text anzeigen** schreibst du etwas darauf: + +\`\`\`java +mbot.showText("Hallo!") +\`\`\` + +Der Text steht in Anführungszeichen, wie bei \`System.out.println\`. Ein neuer Text ersetzt den alten. + +> In der Simulation erscheint der Text auf dem Bildschirm des 3D-Modells und unter der Welt hinter 📺. + +## Begrüßung im Struktogramm + +::: übung vb-begruessung +titel: Begrüßung +auftrag: Der mBot2 zeigt zuerst „Hallo!“, wartet 1000 Millisekunden und zeigt dann „Ich bin VisuBot“. +befehle: showText "Hallo!", pause 1000, showText "Ich bin VisuBot" +tipp: Zieh zweimal **Text anzeigen** und einmal **kurz warten** ins Struktogramm. +tipp: \`mbot.showText("Hallo!")\`, \`mbot.pause(1000)\`, \`mbot.showText("Ich bin VisuBot")\`. +lösung: vb-begruessung-loesung.visustruct +::: + +## Zahlen und Messwerte + +Statt Text kannst du auch Zahlen und Variablen anzeigen, und mit \`+\` setzt du alles zusammen: + +\`\`\`java +mbot.showText(i) +mbot.showText("Abstand: " + mbot.getDistance()) +\`\`\` + +So zeigt der mBot2 dir, was seine Sensoren gerade messen. + +## Jetzt in Java: Countdown + +::: übung vb-java-countdown +titel: Countdown +code: java +auftrag: Schreibe in Java einen Countdown: Eine For-Schleife zählt \`i\` von 3 rückwärts bis 1. In jedem Durchgang zeigt der mBot2 \`i\` an und wartet 1000 Millisekunden. Danach zeigt er „Los!“. +befehle: showText "3", pause 1000, showText "2", pause 1000, showText "1", pause 1000, showText "Los!" +braucht: forSchleife +tipp: Rückwärts zählen: \`for (int i = 3; i >= 1; i--) { … }\` +tipp: In der Schleife: \`mbot.showText(i);\` und \`mbot.pause(1000);\`. Nach der Schleife \`mbot.showText("Los!");\`. +lösung: vb-java-countdown-loesung.visustruct +::: + +::: quiz +? Was zeigt \`mbot.showText("Abstand: " + 25)\`? +→ Zahlen und Messwerte +- [x] Abstand: 25 +- [ ] "Abstand: " + 25 +- [ ] 25 +> Das \`+\` hängt die Zahl an den Text. +? Was passiert mit dem alten Text, wenn du einen neuen anzeigst? +→ Text anzeigen +- [x] Er wird ersetzt. +- [ ] Der neue kommt darunter. +::: + +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. + +::: checkliste +- Ich kann Text auf dem Bildschirm anzeigen. → Text anzeigen +- Ich kann mehrere Texte nacheinander zeigen. → Begrüßung im Struktogramm +- Ich kann Zahlen und Messwerte anzeigen. → Zahlen und Messwerte +- Ich kann einen Countdown in Java schreiben. → Jetzt in Java: Countdown +::: +`,lw=`--- +titel: Zeichenketten +bereich: VisuBot +kurz: Mit Texten rechnen, Buchstaben herausholen und auf dem Bildschirm zeigen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- mit \`length()\` und \`substring(…)\` arbeiten +- Texte und Zahlen mit \`+\` verbinden +- mit \`charAt(…)\` einzelne Zeichen holen +::: + +## Buchstabe für Buchstabe + +Ein Text heißt in Java **Zeichenkette** oder \`String\`. Er besteht aus einzelnen Zeichen, die wie bei einem Array ab **0** nummeriert sind: + +| Zeichen | V | i | s | u | B | o | t | +|---|---|---|---|---|---|---|---| +| Nummer | 0 | 1 | 2 | 3 | 4 | 5 | 6 | + +- \`wort.length()\` liefert die Anzahl der Zeichen, hier 7. +- \`wort.substring(0, 3)\` liefert die ersten 3 Zeichen: \`"Vis"\`. + +Der mBot2 soll seinen Namen auf dem [Bildschirm]{teil=screen} aufbauen: erst **V**, dann **Vi**, dann **Vis** und so weiter bis **VisuBot**. + +::: übung vb-buchstaben +titel: Name aufbauen +auftrag: Lege \`String wort = "VisuBot"\` an. Eine For-Schleife zählt \`i\` von 1 bis \`wort.length()\`. Darin zeigt der mBot2 \`wort.substring(0, i)\` und wartet 300 Millisekunden. +befehle: showText "V", pause 300, showText "Vi", pause 300, showText "Vis", pause 300, showText "Visu", pause 300, showText "VisuB", pause 300, showText "VisuBo", pause 300, showText "VisuBot", pause 300 +braucht: forSchleife +tipp: Die Schleife beginnt bei \`int i = 1\` und läuft, solange \`i <= wort.length()\`. +tipp: In der Schleife: \`mbot.showText(wort.substring(0, i))\` und \`mbot.pause(300)\`. +lösung: vb-buchstaben-loesung.visustruct +::: + +## Jetzt in Java: Text und Länge + +Mit \`+\` hängst du Texte und Zahlen aneinander. So zeigt der mBot2 einen Text und dahinter seine Länge. + +::: übung vb-java-textlaenge +titel: Wie lang ist der Text? +code: java +auftrag: Schreibe in Java: Lege \`String text = "Hallo Klasse"\` an. Der mBot2 zeigt den Text und in Klammern seine Länge, also **Hallo Klasse (12)**. +befehle: showText "Hallo Klasse (12)" +tipp: Die Länge liefert \`text.length()\`. Auch das Leerzeichen zählt mit. +tipp: \`mbot.showText(text + " (" + text.length() + ")");\` +lösung: vb-java-textlaenge-loesung.visustruct +::: + +## Jetzt ohne Roboter: rückwärts lesen + +\`wort.charAt(i)\` liefert das Zeichen mit der Nummer \`i\`. Hängst du jedes Zeichen **vorne** an einen neuen Text, steht das Wort am Ende rückwärts da: + +| Durchgang | Zeichen | neuer Text | +|---|---|---| +| 1 | L | L | +| 2 | u | uL | +| 3 | d | duL | + +::: übung vb-ohne-rueckwaerts +titel: Ludwig rückwärts +code: java +auftrag: Lege \`String wort = "Ludwig"\` und \`String rueckwaerts = ""\` an. Eine Schleife hängt jedes Zeichen von \`wort\` vorne an \`rueckwaerts\`. Zum Schluss gibst du **giwduL** aus. Ganz ohne \`mbot\`! +test: - -> giwduL +braucht: forSchleife +tipp: Die Schleife läuft von \`i = 0\` bis \`i < wort.length()\`. +tipp: In der Schleife: \`rueckwaerts = wort.charAt(i) + rueckwaerts;\`. Nach der Schleife: \`System.out.println(rueckwaerts);\`. +lösung: vb-ohne-rueckwaerts-loesung.visustruct +::: + +::: quiz +? Was liefert \`"VisuBot".substring(0, 4)\`? +→ Buchstabe für Buchstabe +- [ ] \`"VisuB"\` +- [x] \`"Visu"\` +- [ ] \`"uBot"\` +> \`substring(0, 4)\` nimmt die Zeichen 0, 1, 2 und 3, also vier Stück. +? Was liefert \`"Ludwig".charAt(0)\`? +→ Jetzt ohne Roboter: rückwärts lesen +- [x] \`L\` +- [ ] \`u\` +- [ ] \`g\` +> Die Zeichen werden ab 0 gezählt. Zeichen 0 ist das erste. +::: + +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. + +::: checkliste +- Ich kann mit \`length()\` und \`substring(…)\` arbeiten. → Buchstabe für Buchstabe +- Ich kann Texte und Zahlen mit \`+\` verbinden. → Jetzt in Java: Text und Länge +- Ich kann mit \`charAt(…)\` einzelne Zeichen holen. → Jetzt ohne Roboter: rückwärts lesen +::: +`,uw=`--- +titel: Motoren und Geschwindigkeit +bereich: VisuBot +kurz: Gas geben, lenken und einer Linie folgen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- mit Räder einzeln Gas geben und anhalten +- fahren, bis ein Sensor etwas meldet +- einen Linienfolger in Java schreiben +::: + +## Zwei Motoren, zwei Räder + +::: mbot2 +fokus: motors, wheels +ansicht: unten +::: + +Der mBot2 hat zwei [Motoren]{teil=motors}, jeder treibt ein [Rad]{teil=wheels} an. Bisher hast du **fahre vor** und **drehe rechts** benutzt. Diese Befehle fahren eine feste Strecke und warten, bis der mBot2 angekommen ist. + +Mit **Räder einzeln** (\`mbot.drive(links, rechts)\`) gibst du stattdessen Gas: Du sagst, wie stark sich jedes Rad dreht, in Prozent von −100 bis 100. Der mBot2 fährt dann **weiter**, bis du ihm etwas anderes sagst. Mit **anhalten** (\`mbot.stop()\`) bleibt er stehen. + +| Befehl | Was passiert? | +|---|---| +| \`mbot.drive(40, 40)\` | beide Räder gleich schnell: geradeaus | +| \`mbot.drive(-40, -40)\` | rückwärts | +| \`mbot.drive(10, 40)\` | rechts schneller: Kurve nach links | +| \`mbot.drive(40, -40)\` | Räder gegeneinander: dreht auf der Stelle nach rechts | +| \`mbot.stop()\` | anhalten | + +> Im Simulator fährt \`mbot.drive(100, 100)\` 20 cm pro Sekunde. Probier es in der [Simulation](#zeige-simulation) aus. + +## Gas geben bis zur Wand im Struktogramm + +In Lektion 5 ist der mBot2 in 10-cm-Schritten bis zur Wand gefahren. Mit **Räder einzeln** geht das ohne Ruckeln: einmal Gas geben, dann warten, bis die Wand nah ist, dann anhalten. + +::: übung vb-gas-bis-wand +titel: Gas geben bis zur Wand +auftrag: Der mBot2 gibt mit 50 % Gas. Solange die Wand mehr als 15 cm entfernt ist, wartet er kurz. Danach hält er an. Es gibt drei Welten. +welt: wand-kurz, wand-mittel, wand-lang +braucht: whileSchleife +tipp: Ganz oben steht \`mbot.drive(50, 50)\`. Darunter eine While-Schleife mit der Bedingung \`mbot.getDistance() > 15\`. +tipp: In der Schleife steht nur **kurz warten**. Der mBot2 fährt dabei weiter! Nach der Schleife steht **anhalten**. +lösung: vb-gas-bis-wand-loesung.visustruct +::: + +## Der Linienfolger + +::: mbot2 +fokus: lineSensor +ansicht: unten +::: + +Ein Klassiker: Der mBot2 folgt einer schwarzen Linie auf dem Boden. Dafür schaut er auf die beiden mittleren Fühler des [Liniensensors]{teil=lineSensor}: + +| Sensor | Text | +|---|---| +| linker mittlerer Fühler sieht Schwarz | \`mbot.isLineLeft()\` | +| rechter mittlerer Fühler sieht Schwarz | \`mbot.isLineRight()\` | + +Die Idee: Sehen **beide** die Linie, fährt er geradeaus. Sieht nur der **linke** sie, ist die Linie nach links gewandert: Er lenkt nach links, also dreht sich das rechte Rad schneller. Sieht nur der **rechte** sie, lenkt er nach rechts. + +## Jetzt in Java: Linienfolger + +::: übung vb-java-linienfolger +titel: Linienfolger +code: java +auftrag: Schreibe in Java einen Linienfolger. Solange die Wand mehr als 15 cm entfernt ist, prüft der mBot2 seine beiden Fühler und lenkt. Danach hält er an. In der ersten Welt biegt die Linie nach rechts ab, in der zweiten nach links. +welt: linie-1, linie-2 +braucht: whileSchleife, verzweigung +tipp: \`while (mbot.getDistance() > 15) { … }\` und danach \`mbot.stop();\`. +tipp: In der Schleife: \`if (mbot.isLineLeft() && mbot.isLineRight()) { mbot.drive(40, 40); } else if (mbot.isLineLeft()) { mbot.drive(10, 40); } else if (mbot.isLineRight()) { mbot.drive(40, 10); }\` +lösung: vb-java-linienfolger-loesung.visustruct +::: + +> Am echten mBot2 klebst du die Linie mit schwarzem Isolierband auf einen hellen Boden. Fahr anfangs langsam, sonst schießt er in der Kurve über die Linie hinaus. + +::: quiz +? Was macht \`mbot.drive(30, 30)\`? +→ Zwei Motoren, zwei Räder +- [ ] Er fährt 30 cm und hält an. +- [x] Er fährt geradeaus und hört nicht auf, bis ein anderer Fahrbefehl kommt. +- [ ] Er dreht sich um 30°. +> **Räder einzeln** gibt nur Gas. Anhalten musst du selbst. +? Der mBot2 soll nach rechts lenken. Welcher Befehl passt? +→ Zwei Motoren, zwei Räder +- [ ] \`mbot.drive(10, 40)\` +- [x] \`mbot.drive(40, 10)\` +- [ ] \`mbot.drive(-40, -40)\` +> Dreht sich das linke Rad schneller, fährt er eine Rechtskurve. +::: + +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. + +::: checkliste +- Ich kann mit Räder einzeln Gas geben und anhalten. → Zwei Motoren, zwei Räder +- Ich kann fahren, bis ein Sensor etwas meldet. → Gas geben bis zur Wand im Struktogramm +- Ich kann einen Linienfolger in Java schreiben. → Jetzt in Java: Linienfolger +::: +`,cw=`--- +titel: Stoppuhr und Akku +bereich: VisuBot +kurz: Zeit messen und den Akku im Blick behalten. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- die Stoppuhr auf 0 setzen und ablesen +- eine bestimmte Zeit lang fahren +- den Akkustand anzeigen +::: + +## Die Stoppuhr + +::: mbot2 +fokus: cyberpi +ansicht: oben +::: + +Im [CyberPi]{teil=cyberpi} läuft eine Stoppuhr. Sie zählt die Sekunden, seit das Programm läuft. Mit **Stoppuhr auf 0** (\`mbot.resetTimer()\`) fängt sie wieder bei 0 an. + +| Sensor oder Befehl | Text | Wert | +|---|---|---| +| Stoppuhr auf 0 | \`mbot.resetTimer()\` | | +| Stoppuhr | \`mbot.getTimer()\` | Sekunden mit Nachkommastelle, z. B. \`1.5\` | + +So fährst du eine bestimmte Zeit lang: Stoppuhr auf 0, Gas geben, warten, solange die Stoppuhr noch nicht weit genug ist, anhalten. + +## Zwei Sekunden fahren im Struktogramm + +::: übung vb-zwei-sekunden +titel: Zwei Sekunden +auftrag: Der mBot2 setzt die Stoppuhr auf 0 und gibt mit 50 % Gas. Solange die Stoppuhr unter 2 Sekunden ist, wartet er kurz. Danach hält er an. Mit 50 % schafft er 10 cm pro Sekunde, er muss also 20 cm weiter stehen bleiben. +welt: zeit-1 +braucht: whileSchleife +tipp: Oben stehen **Stoppuhr auf 0** und \`mbot.drive(50, 50)\`. Darunter eine While-Schleife mit \`mbot.getTimer() < 2\`. +tipp: In der Schleife steht **kurz warten**, nach der Schleife **anhalten**. +lösung: vb-zwei-sekunden-loesung.visustruct +::: + +## Der Akku + +::: mbot2 +fokus: shield +ansicht: oben +::: + +Unter dem durchsichtigen [Shield]{teil=shield} siehst du den Akku. Wie voll er ist, liefert \`mbot.getBattery()\` in Prozent: \`100\` ist ganz voll. Ist er fast leer, fahren die Motoren schwächer. Dann wird es Zeit zum Laden. + +::: angeberwissen +Auch dein Handy misst seinen Akku nicht direkt in Prozent. Es misst die Spannung: Ein voller Lithium-Akku hat etwas über 4 Volt, ein leerer gut 3. Daraus rechnet es die Prozente aus, genau wie der CyberPi. +::: + +## Jetzt in Java: Akku-Anzeige + +::: übung vb-java-akku +titel: Akku-Anzeige +code: java +auftrag: Schreibe in Java: Der mBot2 zeigt auf dem Bildschirm zum Beispiel **Akku: 80 %**. Ist der Akku unter 20 %, leuchten zusätzlich die LEDs rot. +messwerte: getBattery=80 -> none, ledOff, screen "Akku: 80 %" +messwerte: getBattery=15 -> none, ledOn, screen "Akku: 15 %" +braucht: verzweigung +tipp: \`mbot.showText("Akku: " + mbot.getBattery() + " %");\` setzt den Text aus drei Teilen zusammen. +tipp: Danach: \`if (mbot.getBattery() < 20) { mbot.setLed(255, 0, 0); }\` +lösung: vb-java-akku-loesung.visustruct +::: + +::: quiz +? Was liefert \`mbot.getTimer()\` direkt nach \`mbot.resetTimer()\`? +→ Die Stoppuhr +- [x] 0 +- [ ] 100 +- [ ] Die Uhrzeit +> Die Stoppuhr fängt wieder bei 0 an. +? Warum wartet der mBot2 in der Schleife nur **kurz** und hält nicht an? +→ Zwei Sekunden fahren im Struktogramm +- [ ] Weil die Schleife sonst nicht startet. +- [x] Weil er weiterfahren soll, bis die Zeit um ist. +- [ ] Weil die Stoppuhr sonst stehen bleibt. +> Gas geben gilt weiter, auch während er wartet. +::: + +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. + +::: checkliste +- Ich kann die Stoppuhr auf 0 setzen und ablesen. → Die Stoppuhr +- Ich kann eine bestimmte Zeit lang fahren. → Zwei Sekunden fahren im Struktogramm +- Ich kann den Akkustand anzeigen. → Jetzt in Java: Akku-Anzeige +::: +`,mw=`--- +titel: Eigene Methoden +bereich: VisuBot +kurz: Eigene Befehle mit Parametern und Rückgabewert schreiben und aufrufen. +--- + +## Diese Kompetenzen erwerbe ich jetzt + +::: kompetenzen +- ein Unterprogramm mit Parameter bauen und aufrufen +- Methoden in Java erkennen +- eine Methode mit Rückgabewert schreiben +::: + +## Ein Unterprogramm für das Quadrat + +Ein Quadrat fahren kann der mBot2 schon. Jetzt soll er zwei verschieden große Quadrate fahren. Statt die Schleife zweimal zu bauen, schreibst du ein **Unterprogramm**. In Java heißt es **Methode**. Es ist ein eigener Befehl, den du so oft aufrufen kannst, wie du willst. + +Die Kopfzeile \`void quadrat(int seite)\` sagt: + +- \`void\`: Die Methode liefert kein Ergebnis zurück, sie **tut** nur etwas. +- \`quadrat\`: So heißt dein neuer Befehl. +- \`int seite\`: Beim Aufruf gibst du eine Zahl mit, den **Parameter**. + +::: übung vb-quadrat-methode +titel: Zwei Quadrate +auftrag: Baue ein Unterprogramm \`void quadrat(int seite)\`, das ein Quadrat mit der Seitenlänge \`seite\` fährt. Das Hauptprogramm ruft es zweimal auf: erst mit 30, dann mit 50. +fahrt: 4 x (forward 30, turnRight), 4 x (forward 50, turnRight) +braucht: aufruf +tipp: Lege mit **+** einen neuen Reiter an und gib ihm den Titel \`void quadrat(int seite)\`. Darin steht eine For-Schleife, die viermal \`mbot.forward(seite)\` und \`mbot.turnRight()\` ausführt. +tipp: Im Hauptprogramm stehen zwei Aufruf-Kästen: \`quadrat(30)\` und \`quadrat(50)\`. +lösung: vb-quadrat-methode-loesung.visustruct +unterprogramm: vb-quadrat-unterprogramm-loesung.visustruct +::: + +## Methoden in Java + +In Java steht jede Methode in einer Klasse. Das Programm beginnt immer in der Methode \`main\`. Von dort wird \`quadrat\` aufgerufen: + +\`\`\`java +public class Quadrate { + public static void main(String[] args) { + quadrat(30); + quadrat(50); + } + + static void quadrat(int seite) { + for (int i = 0; i < 4; i++) { + mbot.forward(seite); + mbot.turnRight(); + } + } +} +\`\`\` + +Im Bereich [Code](#zeige-codelive) siehst du jede Methode in ihrem eigenen Reiter, so wie im Struktogramm. + +::: quiz +? Was bedeutet \`void\` in \`void quadrat(int seite)\`? +→ Methoden in Java +- [ ] Die Methode hat keinen Parameter. +- [x] Die Methode liefert kein Ergebnis zurück. +- [ ] Die Methode darf nur einmal aufgerufen werden. +> \`void\` heißt „leer“: Es kommt kein Wert zurück. Der Parameter steht in den Klammern. +? Mit welchem Wert für \`seite\` läuft \`quadrat(50)\`? +→ Ein Unterprogramm für das Quadrat +- [ ] 30 +- [x] 50 +- [ ] mit keinem +> Der Wert in den Klammern des Aufrufs wird zum Parameter \`seite\`. +::: + +## Jetzt ohne Roboter: Methode mit Rückgabe + +Eine Methode kann auch etwas **ausrechnen** und das Ergebnis zurückgeben. Statt \`void\` steht dann der Datentyp des Ergebnisses in der Kopfzeile, und \`return\` gibt den Wert zurück: + +\`\`\`java +static int doppelt(int x) { + return 2 * x; +} +\`\`\` + +Der Aufruf \`int d = doppelt(4);\` legt dann 8 in \`d\`. + +::: übung vb-ohne-quadratzahl +titel: Quadratzahlen +auftrag: Baue ein Unterprogramm \`int quadratzahl(int x)\`, das \`x * x\` zurückgibt. Das Hauptprogramm ruft es mit 3 und mit 5 auf und gibt beide Ergebnisse aus: erst **9**, dann **25**. Ganz ohne \`mbot\`! +test: - -> 9 | 25 +braucht: aufruf +tipp: Neuer Reiter mit dem Titel \`int quadratzahl(int x)\`. Darin reicht eine Anweisung: \`return x * x\`. +tipp: Im Hauptprogramm: Aufruf \`int a = quadratzahl(3)\`, Aufruf \`int b = quadratzahl(5)\`, danach die Ausgaben \`a\` und \`b\`. +lösung: vb-ohne-quadratzahl-loesung.visustruct +unterprogramm: vb-ohne-quadratzahl-unterprogramm-loesung.visustruct +::: + +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. + +::: checkliste +- Ich kann ein Unterprogramm mit Parameter bauen und aufrufen. → Ein Unterprogramm für das Quadrat +- Ich kann Methoden in Java erkennen. → Methoden in Java +- Ich kann eine Methode mit Rückgabewert schreiben. → Jetzt ohne Roboter: Methode mit Rückgabe +::: +`,dw=`## 🤖 mBot2-Befehle + +Ein Befehl sagt dem mBot2, was er **tun** soll. Jeder Befehl beginnt mit \`mbot.\` und endet mit Klammern. In die Klammern schreibst du oft eine Zahl. + +### Fahren und Drehen + +Der mBot2 fährt geradeaus oder dreht sich auf der Stelle. + +\`\`\` +mbot.forward() fährt 10 cm nach vorn +mbot.forward(30) fährt 30 cm nach vorn +mbot.backward(20) fährt 20 cm zurück +mbot.turnRight() dreht sich nach rechts (90°) +mbot.turnLeft() dreht sich nach links (90°) +mbot.turnLeft(45) dreht sich nur ein bisschen nach links (45°) +mbot.turnRight(180) dreht sich ganz um +\`\`\` + +> Ohne Zahl fährt er 10 cm oder dreht sich 90°. 90° ist ein rechter Winkel, wie die Ecke von einem Blatt Papier. + +> Für ein Vieleck dreht er sich insgesamt einmal ganz herum: Dreieck 3 × 120°, Quadrat 4 × 90°, Sechseck 6 × 60°. + +### Räder einzeln + +Hier gibst du jedem Rad selbst Gas. Die Zahlen sind Prozent: 100 ist volles Gas, 0 ist Stillstand, eine Zahl mit Minus fährt rückwärts. Der mBot2 fährt so lange weiter, bis ein anderer Fahrbefehl kommt. + +\`\`\` +mbot.drive(40, 40) beide Räder gleich: geradeaus +mbot.drive(10, 40) links langsamer: Kurve nach links +mbot.drive(40, -40) ein Rad vor, eins zurück: dreht sich +mbot.stop() hält an +\`\`\` + +### Licht, Ton und Bildschirm + +Der mBot2 kann leuchten, piepen und Text zeigen. + +\`\`\` +mbot.setLed(255, 0, 0) alle LEDs leuchten rot +mbot.ledOff() alle LEDs aus +mbot.led(0).setColor("grün") nur LED 0 leuchtet grün +mbot.led(0).setColor("aus") nur LED 0 aus +mbot.playTone(440, 300) spielt einen Ton +mbot.showText("Hallo") zeigt Hallo auf dem Bildschirm +\`\`\` + +- **LEDs:** Es gibt fünf LEDs mit den Nummern 0 bis 4. Bei \`setLed\` mischst du Rot, Grün und Blau, jedes von 0 (aus) bis 255 (ganz hell). +- **Ton:** Die erste Zahl ist die Tonhöhe. Je größer, desto höher. Die zweite Zahl ist die Länge in Millisekunden (1000 Millisekunden sind 1 Sekunde). +- **Bildschirm:** Mit \`+\` hängst du Text und Zahlen aneinander: \`mbot.showText("Abstand: " + mbot.getDistance())\`. + +### Gefühle + +Der mBot2 zeigt ein Gefühl mit Licht, Ton und Wackeln. Das siehst du nur am echten mBot2. + +\`\`\` +mbot.emotion("smile") lacht +mbot.emotion("sad") ist traurig +mbot.emotion("wow") staunt +\`\`\` + +Weitere Gefühle: hello, yeah, proud, yummy, naughty, uh_oh, hurt, angry, startle, shiver, dizzy, sleepy, zzz, wake_up, blink, yes, no, look_up, look_down, look_left, look_right, look_around + +### Warten und Stoppuhr + +\`\`\` +mbot.pause(1000) wartet 1 Sekunde +mbot.resetTimer() stellt die Stoppuhr auf 0 +\`\`\` + +Die Zeit der Stoppuhr liest du mit dem Sensor \`mbot.getTimer()\` (unten bei **Stoppuhr und Akku**). + +## 📡 mBot2-Sensoren + +Ein Sensor **misst** etwas und gibt dir einen Wert zurück. Den Wert benutzt du in einer Bedingung, zum Beispiel in einer Schleife oder Verzweigung. Manche Sensoren liefern eine **Zahl**, manche **wahr oder falsch**, einer einen **Text**. + +### Abstand + +Der Ultraschallsensor vorn misst, wie weit die nächste Wand weg ist, in Zentimetern. + +\`\`\` +mbot.getDistance() Abstand in cm, z. B. 25 +mbot.getDistance() > 15 ist vorn mehr als 15 cm frei? +int abstand = mbot.getDistance() Abstand in einer Variablen merken +\`\`\` + +### Linie + +Unter dem mBot2 sitzen vier Fühler. Sie sehen, ob der Boden schwarz ist. + +\`\`\` +mbot.getLine() Zahl: 0 heißt, kein Fühler sieht Schwarz +mbot.getLine() == 0 kein Schwarz, weiterfahren +mbot.getLine() != 0 ein Fühler sieht Schwarz +mbot.isLineLeft() sieht der linke mittlere Fühler Schwarz? +mbot.isLineRight() sieht der rechte mittlere Fühler Schwarz? +\`\`\` + +### Farben + +Derselbe Sensor unten erkennt auch Farben. \`mbot.getColor()\` gibt dir den Namen der Farbe als Text: \`"rot"\`, \`"grün"\`, \`"blau"\`, \`"gelb"\`, \`"weiß"\` oder \`"schwarz"\`. + +\`\`\` +mbot.getColor().equals("rot") steht er auf Rot? +!mbot.getColor().equals("rot") steht er nicht auf Rot? +\`\`\` + +> Texte vergleichst du mit \`.equals(…)\`, nicht mit \`==\`. Das \`!\` davor heißt **nicht**. + +### Tasten und Joystick + +Auf dem CyberPi gibt es die Tasten A und B und einen kleinen Joystick. Jeder Sensor sagt **wahr**, solange gedrückt wird. + +\`\`\` +mbot.isButtonA() wird Taste A gedrückt? +mbot.isButtonB() wird Taste B gedrückt? +mbot.isJoystickUp() Joystick nach oben gedrückt? +mbot.isJoystickDown() Joystick nach unten gedrückt? +mbot.isJoystickLeft() Joystick nach links gedrückt? +mbot.isJoystickRight() Joystick nach rechts gedrückt? +\`\`\` + +### Licht und Lautstärke + +\`\`\` +mbot.getBrightness() wie hell? 0 ist dunkel, 100 ist hell +mbot.getLoudness() wie laut? 0 ist still, 100 ist laut +\`\`\` + +### Neigung und Schütteln + +\`\`\` +mbot.getPitch() nach vorn oder hinten gekippt? (in Grad) +mbot.getRoll() zur Seite gekippt? (in Grad) +mbot.isShaken() wird er geschüttelt? +\`\`\` + +> Liegt der mBot2 flach, sind beide Neigungen 0. In der Simulation stellst du diese Werte unter **🎛 Sensoren ausprobieren** ein. + +### Stoppuhr und Akku + +\`\`\` +mbot.getTimer() Sekunden seit dem Start oder seit resetTimer() +mbot.getBattery() wie voll ist der Akku? (in Prozent) +\`\`\` + +### Echter mBot2 + +Mit **🔌 mBot2** neben „Simulation starten“ verbindest du den echten Roboter mit dem USB-Kabel. Das geht nur in Chrome oder Edge. Dann fährt er jeden Schritt der Simulation mit, und die Sensoren messen echte Werte. Ein zweiter Klick trennt ihn wieder. + +### Ohne Kabel fahren + +Mit **⬆ Übertragen** speicherst du dein Programm fest auf dem mBot2. Danach Kabel ab, mBot2 an den Start und **Taste A** drücken: Er fährt dein Programm allein. Es bleibt gespeichert, bis du ein neues überträgst. Eingaben mit der Tastatur gehen am mBot2 nicht. +`,hw=`--- +titel: The mBot2 +bereich: VisuBot +kurz: Get to know the robot you are about to program. +--- + +## Skills I will gain now + +::: kompetenzen +- name the parts of the mBot2 +- explain how the mBot2 measures distances +- explain how the mBot2 detects a line +- explain what sensors and actuators are +- control the mBot2 with elements from the group mBot2 commands +- let the mBot2 drive in the simulator +- connect the real mBot2 with USB-C and disconnect it again +- check that all sensors and actuators work +::: + +## Hello mBot2 + +::: mbot2 +focus: +spin: yes +::: + +The **mBot2** is a small robot made by Makeblock. In this lesson you take a tour through all its parts: + +- the [CyberPi]{part=cyberpi}, the small computer at the back on top +- the see-through [shield with battery]{part=shield} in the middle +- two [motors]{part=motors} with [wheels]{part=wheels} +- the [ultrasonic sensor]{part=ultrasonic} at the front, which looks like two eyes +- the [line sensor]{part=lineSensor} under the nose +- the turquoise [chassis]{part=chassis} that holds everything together + +In VisuBot you program it with structure charts. You can try every program in the simulator first, even without a real robot. + +> Move the mouse over a word underlined in yellow and the part lights up in the model. Tap the word and the camera flies there. You can rotate the model with the mouse or your finger and zoom with the mouse wheel. + +## The CyberPi + +::: mbot2 +focus: cyberpi, screen, joystick, buttons, leds, lightSensor, microphone +view: back +::: + +The [CyberPi]{part=cyberpi,screen,joystick,buttons,leds,lightSensor,microphone} is the brain of the mBot2: a **microcontroller**, a small computer without a keyboard. It runs your program. It lies crosswise at the back on top of the robot and can be taken off. + +A lot is already built in: + +- a colour [screen]{part=screen} that shows text and pictures +- a [joystick]{part=joystick} you can push in four directions +- two [buttons]{part=buttons}, one with a triangle and one with a square, and the Home button on the side next to the USB port +- five colourful [LEDs]{part=leds} as a light bar along the back +- a [light sensor]{part=lightSensor} and a [microphone]{part=microphone} + +There is also a speaker and a motion sensor that you cannot see from outside. The motion sensor notices when the CyberPi is tilted or turned. + +> The model was built from photos. Look at your own mBot2 and compare. + +## Screen, LEDs and speaker + +::: mbot2 +focus: screen, leds +view: back +::: + +With the [screen]{part=screen} and the five [LEDs]{part=leds} the mBot2 shows you what it is doing. Each LED can glow in almost any colour because it mixes red, green and blue. That is why they are called **RGB LEDs**. + +Later you make the LEDs glow red with \`mbot.setLed(255, 0, 0)\`. The three numbers are red, green and blue, each from 0 to 255. + +The [CyberPi]{part=cyberpi} also has a small **speaker**. With \`mbot.playTone(440, 300)\` it plays a tone: 440 vibrations per second (hertz), 300 milliseconds long. + +## Measuring light and sound + +::: mbot2 +focus: lightSensor, microphone +view: top +::: + +The [light sensor]{part=lightSensor} measures how bright it is. The [microphone]{part=microphone} measures how loud it is. For example, the mBot2 can start driving when you clap your hands. + +## Buttons and joystick + +::: mbot2 +focus: joystick, buttons +view: top +::: + +The [buttons]{part=buttons} A and B and the [joystick]{part=joystick} are sensors too: they notice when you press them. Your program can, for example, wait until you press A and only then start driving. With the joystick you steer the mBot2 like with a remote control. + +## The motion sensor + +::: mbot2 +focus: cyberpi +spin: yes +::: + +Inside the [CyberPi]{part=cyberpi} there is a sensor you cannot see: the **motion sensor** (a gyroscope with an accelerometer). It notices whether the mBot2 is tilted forward, backward or to the side, how far it has turned and whether someone shakes it. Your phone has such a sensor too: that is why the picture turns when you hold it sideways. + +## Power: the shield with battery + +::: mbot2 +focus: shield, powerSwitch +view: side +::: + +The big see-through case is the [mBot2 shield]{part=shield}. Through the lid you see the grey **battery** that powers the robot. At the back of the shield the cables of the motors (M1 and M2) and of the ultrasonic sensor are plugged in. + +On the left side is the [power switch]{part=powerSwitch} labelled ON/OFF. Next to it are two sockets S1 and S2 for small servo motors. Switch the mBot2 off when you do not need it, so the battery lasts longer. You charge it with the USB cable on the CyberPi. + +## Motors and wheels + +::: mbot2 +focus: motors, wheels +view: side +::: + +Two [motors]{part=motors} drive the two [wheels]{part=wheels}, each its own. You see them from below: silver motors in light blue gearboxes. + +- If both wheels turn forward at the same speed, the mBot2 drives **straight**. +- If one wheel turns forward and the other backward, it turns **on the spot**. + +The motors are **encoder motors**: they count how far the wheel has turned. That is how the mBot2 knows when it has driven exactly 10 cm or turned exactly 90°. + +## The ultrasonic sensor + +::: mbot2 +focus: ultrasonic +view: front +::: + +At the front sits the black [ultrasonic sensor]{part=ultrasonic}. It looks like two eyes but is more like an ear: one circle sends out a very high sound we cannot hear. The other waits for the echo. The longer the echo takes, the farther away the wall is. + +That is how the mBot2 measures distances in centimetres. The rings around the circles can also glow blue. + +::: angeberwissen +Bats do exactly what the ultrasonic sensor does: they call so high that we cannot hear it and listen for the echo. Sound travels about 343 metres per second. If a wall is one metre in front of the mBot2, the echo is back after just under 6 thousandths of a second. +::: + +## Under the robot + +::: mbot2 +focus: lineSensor, caster +view: bottom +::: + +Now you look from below. Right at the front the black board of the [line sensor]{part=lineSensor} sticks out. It has **four** small probes side by side. Each one shines light on the floor and measures how much comes back. A black line reflects little, a bright floor a lot. That is how the mBot2 knows whether it is on a line. + +The sensor is called a **quad RGB sensor** because it can do even more: it also recognises **colours**, for example a red or green field on the floor. + +The [ball caster]{part=caster} behind it is the third leg. It has no motor and simply rolls along in any direction. + +## The chassis + +::: mbot2 +focus: chassis +::: + +The [chassis]{part=chassis} is the turquoise aluminium frame. It holds all the parts together. At the front it has two round "ears", at the back a big **M** for Makeblock. The many holes are there on purpose: you can screw more parts onto them. + +## Sensors and actuators + +A robot has two kinds of parts: + +- **Sensors** measure something: the distance, a line, a colour, the brightness, the loudness, the tilt or whether a button is pressed. +- **Actuators** do something: the motors turn the wheels, the LEDs light up, the screen shows something, the speaker beeps. + +The word comes from the Latin *agere*, “to act”: actuators act, sensors (from *sentire*, “to feel”) feel. + +Your program reads the sensors and controls the actuators. You already know this as input, processing and output. + +::: quiz +? Match each part to its job. +→ Hello mBot2 += Ultrasonic sensor -> measures the distance += Motors -> move the wheels += CyberPi -> runs the program += Line sensor -> detects a dark line +? Which parts are actuators? +→ Sensors and actuators +- [x] Motors +- [ ] Ultrasonic sensor +- [x] LEDs +- [ ] Line sensor +> Actuators do something, sensors measure something. +::: + +::: spiel frage +titel: Game: sensor or actuator? +intro: Does the part measure something, or does it do something? Ten rounds. +antworten: Sensor | Actuator + +runde: +frage: The ultrasonic sensor measures how far away the wall is. +richtig: Sensor +> It measures something: the distance. + +runde: +frage: The motors turn the wheels. +richtig: Actuator +> They do something: they move the mBot2. + +runde: +frage: The LEDs glow red. +richtig: Actuator +> Glowing is doing something, not measuring. + +runde: +frage: The line sensor recognises the black tape. +richtig: Sensor +> It measures how much light comes back from the floor. + +runde: +frage: The speaker beeps. +richtig: Actuator +> It outputs a sound. + +runde: +frage: The microphone hears you clap. +richtig: Sensor +> It measures the loudness. + +runde: +frage: The screen shows “Hello VisuBot!”. +richtig: Actuator +> Showing something is an output. + +runde: +frage: Button A notices that you press it. +richtig: Sensor +> Buttons are sensors: they report whether they are pressed. + +runde: +frage: The motion sensor notices that the mBot2 is tilted. +richtig: Sensor +> It measures the tilt. + +runde: +frage: The rings on the ultrasonic sensor glow blue. +richtig: Actuator +> Tricky! The part is a sensor, but the glowing rings are an output. +::: + +## Find the parts + +Your turn: click the part you are looking for in the model. If you are right, the next question appears. + +::: mbot2quiz +- ultrasonic: What does the mBot2 use to measure how far away the wall is? +- screen: Where does text from your program appear? +- wheels: What moves the mBot2 forward? +- lineSensor: What detects a black line on the floor? (Hint: rotate the model.) +- powerSwitch: Where do you switch the mBot2 on and off? +- leds: What glows red with \`mbot.setLed(255, 0, 0)\`? +done: Great, you know your way around the mBot2! +::: + +## Commands for the mBot2 + +In VisuBot the [Elements](#zeige-elemente) have their own group **mBot2 commands**. Each box in it is a command for the robot: + +| Element | Text in the box | What happens | +|---|---|---| +| move forward | \`mbot.forward()\` | 10 cm forward | +| move back | \`mbot.backward()\` | 10 cm back | +| turn right | \`mbot.turnRight()\` | turn 90° to the right | +| turn left | \`mbot.turnLeft()\` | turn 90° to the left | +| LEDs on | \`mbot.setLed(255, 0, 0)\` | the LEDs light up red | + +You may also put a number in the brackets: \`mbot.forward(30)\` drives 30 cm, \`mbot.turnRight(45)\` turns only 45°. + +> The commands are real Java. \`mbot\` is the robot, and after the dot comes what it should do. + +## First drive + +After building, start the [simulation](#zeige-simulation). The VisuBot world with the mBot2 appears on the right. The grid on the floor has squares of 10 cm, exactly one **move forward**. + +::: übung vb-gerade +titel: Straight ahead +auftrag: Drag **move forward** into the structure chart five times. Then start the simulation and watch the mBot2 drive 50 cm straight ahead. +fahrt: 5 x (forward) +tipp: You find the group mBot2 commands below the normal elements. +tipp: Five boxes \`mbot.forward()\` one below the other. Each drives 10 cm. +lösung: vb-gerade-loesung.visustruct +::: + +## Connecting the real mBot2 + +::: mbot2 +focus: cyberpi, powerSwitch, joystick, buttons +view: side +::: + +Everything you build in the simulator can also be driven by the real mBot2. This is how you connect it: + +1. Plug a **USB-C cable** into your computer (for example a MacBook) and the other end into the USB-C port on the right of the [CyberPi]{part=cyberpi}, next to the Home button. +2. Push the [ON/OFF slide switch]{part=powerSwitch} on the left of the shield to ON. The CyberPi's screen lights up. +3. A menu appears on the screen with **restart** highlighted (on a German CyberPi: „neu starten“). Press the [joystick]{part=joystick} down like a button to confirm it. +4. After the restart it says “Press B to start”. Press **button B**, that is the [button with the triangle]{part=buttons}. +5. Open VisuStruct in **Chrome** or **Edge**. Safari and the iPad cannot talk to USB devices. +6. As soon as the CyberPi has started up, click **🔌 mBot2** at the top (or “Connect mBot2” in the gear menu). +7. Chrome shows a list of ports. Choose the entry **USB Serial** (for example “USB Serial (cu.usbserial-110)”). It is often at the very bottom, so you may have to scroll down. Then click **Connect**. +8. The CyberPi restarts briefly (⏳). Then “Hallo VisuBot!” appears on its screen and the button shows 🟢. + +Now the mBot2 drives along with every step of the simulation. Put it on the floor and give it room! + +> Finished? Click **🟢 mBot2** once more. It stops, shows “Bis bald!” and releases the port. Only then pull out the cable. + +> Want to drive with no cable at all? You learn that in lesson 2 under **Driving without a cable**. + +## Testing the mBot2 + +When the mBot2 is connected, **🔧 Test the mBot2** appears below the world. Open it: + +- With the buttons you try each actuator once: LEDs, tone, text on the screen and the wheels. Lift the mBot2 up for this so it does not drive off the table. +- Below are all sensors with their values, and they update live. Hold your hand in front of the ultrasonic sensor, press button A, tilt it, clap your hands or put it on a red sheet of paper. + +If a value does not change although you do something, something is wrong. Then tell your teacher before you start programming. + +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. + +::: checkliste +- I can name the parts of the mBot2. → Hello mBot2 +- I can explain how the mBot2 measures distances. → The ultrasonic sensor +- I can explain how the mBot2 detects a line. → Under the robot +- I can explain what sensors and actuators are. → Sensors and actuators +- I can control the mBot2 with elements from the group mBot2 commands. → Commands for the mBot2 +- I can let the mBot2 drive in the simulator. → First drive +- I can connect the real mBot2 with USB-C and disconnect it again. → Connecting the real mBot2 +- I can check that all sensors and actuators work. → Testing the mBot2 +::: +`,gw=`--- +titel: The square +bereich: VisuBot +kurz: From a long structure chart to a triple nested loop. +--- + +## Skills I will gain now + +::: kompetenzen +- build a sequence without a loop first +- spot repetitions and replace them with a for loop +- nest two loops +- nest three loops +- upload my program to the mBot2 and start it with button A without a cable +::: + +## Driving a square + +The mBot2 should drive a square with sides of 50 cm. You already know one side: **move forward** five times. Then it turns right, and the next side begins. + +::: übung vb-quadrat +titel: The square +auftrag: Build a structure chart that makes the mBot2 drive a square: **move forward** five times, then **turn right**. And all of that four times. +fahrt: 4 x (5 x (forward), turnRight) +tipp: One side is five times move forward and once turn right. +tipp: That makes 24 boxes: four times five \`mbot.forward()\`, each followed by \`mbot.turnRight()\`. +lösung: vb-quadrat-loesung.visustruct +::: + +Quite a lot of boxes, right? If you miscount, the mBot2 no longer drives a square. + +## Always the same + +Look closely at your structure chart: five times **move forward** appears four times. When something repeats, you use a **loop**. We know exactly how often to drive, five times. The for loop fits that. + +Drag a for loop into the structure chart and give it these three parts: + +- Start: \`int i = 0\` +- Condition: \`i < 5\` +- Step: \`i++\` + +The body of the loop gets a single **move forward**. The loop counts \`i\` from 0 to 4, that is five runs. + +::: übung vb-quadrat-schleife +titel: Sides with a loop +auftrag: In your square, replace each row of five **move forward** with a for loop that drives five times. The mBot2 then drives exactly the same square. +fahrt: 4 x (5 x (forward), turnRight) +braucht: forSchleife +tipp: Start \`int i = 0\`, condition \`i < 5\`, step \`i++\`. The body only contains \`mbot.forward()\`. +tipp: Four times one below the other: the for loop and then \`mbot.turnRight()\`. +lösung: vb-quadrat-schleife-loesung.visustruct +::: + +## A loop in a loop + +Now the same pair appears four times: a for loop and **turn right**. That is a repetition too! Put both into a second for loop that runs four times. A loop inside a loop is called a **nested loop**. + +Each loop needs its own counter variable, otherwise the two get in each other's way. The usual way: the outer loop counts with \`i\`, the inner one with \`j\`. So rename your inner loop to \`j\`. + +::: übung vb-quadrat-verschachtelt +titel: Nested square +auftrag: Build the square with two nested for loops. The outer one runs four times, once for each side. The inner one runs five times, once for each step. +fahrt: 4 x (5 x (forward), turnRight) +schleifentiefe: 2 +tipp: Outside: start \`int i = 0\`, condition \`i < 4\`, step \`i++\`. Inside: \`int j = 0\`, \`j < 5\`, \`j++\`. +tipp: The outer loop contains the inner loop with \`mbot.forward()\` and below it \`mbot.turnRight()\`. +lösung: vb-quadrat-verschachtelt-loesung.visustruct +::: + +24 boxes have become four. Step through the program in the simulation with **Step** and watch the variables. + +::: quiz +? How often does the mBot2 run \`mbot.forward()\` in the nested square? +- [ ] 9 times +- [x] 20 times +- [ ] 5 times +> The inner loop runs five times, in each of the four runs of the outer loop: 4 · 5 = 20. +::: + +## Four squares + +Now it gets really nice: the mBot2 should drive four squares. After each square it turns right once. That makes a big window with a cross. + +You could copy your square four times and add a **turn right** after each square. Go ahead and try it! Notice something? Again the same thing appears four times. + +::: ludwig +Whenever you copy boxes, ask yourself: does something repeat here? Then a loop fits. +::: + +::: übung vb-vier-quadrate +titel: Four squares +auftrag: Let the mBot2 drive four squares. After each square it turns right once. Use three nested loops. +fahrt: 4 x (4 x (5 x (forward), turnRight), turnRight) +schleifentiefe: 3 +tipp: Put a third for loop that runs four times around your nested square. +tipp: Now \`i\` counts on the very outside (\`int i = 0\`, \`i < 4\`, \`i++\`). The loops inside are then called \`j\` and \`k\`. Inside the outer loop goes your square and then \`mbot.turnRight()\`. +lösung: vb-vier-quadrate-loesung.visustruct +::: + +::: quiz +? How often does the mBot2 drive 10 cm forward for the four squares? +→ Four squares +- [ ] 20 times +- [ ] 60 times +- [x] 80 times +> 4 squares · 4 sides · 5 steps = 80. Without loops that would be 80 boxes. +::: + +## Driving without a cable + +::: mbot2 +fokus: cyberpi, buttons +ansicht: oben +::: + +So far the mBot2 hangs on the cable while it drives. But you can also **upload your program to the mBot2**. Then it remembers it and drives all by itself, for example through a maze on the floor. + +1. Connect the mBot2 with the USB cable and switch it on, as in lesson 1. This only works in **Chrome** or **Edge**. +2. Open your program, for example the four squares. +3. Click **⬆ Upload** at the top and then **Upload now**. Choose **USB Serial** again. +4. Wait until it says “Done!”. The mBot2 restarts and shows **A = Start**. +5. Unplug the cable and put the mBot2 at the start. +6. Press **button A**, that is the [button with the square]{teil=buttons}. Now your program starts. + +The program stays saved, even when you switch the mBot2 off and on again. Only the next upload replaces it. + +> Afraid it drives off before you are ready? Don't worry: it always waits for button A. If you press A again while it drives, nothing happens. When it has finished, A starts the program again from the beginning. + +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. + +::: checkliste +- I can build a sequence without a loop first. → Driving a square +- I can spot repetitions and replace them with a for loop. → Always the same +- I can nest two loops. → A loop in a loop +- I can nest three loops. → Four squares +- I can upload my program to the mBot2 and start it with button A without a cable. → Driving without a cable +::: +`,pw='---\ntitel: Variables and output\nbereich: VisuBot\nkurz: Store values in variables, drive the mBot2 with them and print results.\n---\n\n## Skills I will gain now\n\n::: kompetenzen\n- create and use a variable\n- tell the data types `int`, `double`, `String` and `boolean` apart\n- drive a rectangle in Java with two variables\n- print something with `System.out.println`\n:::\n\n## A variable for the side\n\nWith `mbot.forward(30)` the mBot2 drives 30 cm in one go. If you drive a square with it and no loop, the 30 appears four times in your program. To make the square bigger, you have to change it in four places. It is better to store the side length **once** and then use it everywhere.\n\nThat is what **variables** are for. A variable is a box with a name that holds a value:\n\n```java\nint side = 30;\nmbot.forward(side);\n```\n\n- `int` is the **data type**: a whole number.\n- `side` is the **name**. You may choose it yourself.\n- `30` is the **value**. The `=` puts it into the box.\n\nWherever `side` appears afterwards, the computer uses its value. So `mbot.forward(side)` drives 30 cm.\n\n::: übung vb-variable-seite\ntitel: Square with a variable\nauftrag: In one statement, create the variable `int side = 30`. After that the mBot2 drives a square: four times `side` centimetres forward and turn right.\nfahrt: 4 x (forward 30, turnRight)\nbraucht: forSchleife\ntipp: The first statement is `int side = 30`. Below it comes a for loop that runs four times.\ntipp: Inside the loop are `mbot.forward(side)` and `mbot.turnRight()`.\nlösung: vb-variable-seite-loesung.visustruct\n:::\n\n> Now change only the 30 to 60 and start the simulation. The whole square becomes twice as big.\n\n## Which data types are there?\n\nEvery variable has a data type. It decides which values fit inside:\n\n| Data type | What fits inside? | Example |\n|---|---|---|\n| `int` | whole numbers | `int side = 30;` |\n| `double` | decimal numbers, written with a point | `double speed = 1.5;` |\n| `String` | text in quotation marks | `String name = "Visu";` |\n| `boolean` | true or false | `boolean done = false;` |\n\nYou can also calculate with variables: `int distance = 4 * side;` works out the whole distance around the square.\n\n## Now in Java: rectangle\n\nA rectangle has two different sides. So you need two variables.\n\n::: übung vb-java-rechteck\ntitel: Rectangle with variables\ncode: java\nauftrag: Write in Java: create `int length = 60` and `int width = 30`. The mBot2 drives a rectangle: length, turn right, width, turn right, and all that twice.\nfahrt: 2 x (forward 60, turnRight, forward 30, turnRight)\nbraucht: forSchleife\ntipp: Two variables at the top: `int length = 60;` and `int width = 30;`. Below them a for loop that runs twice.\ntipp: Inside the loop: `mbot.forward(length);`, `mbot.turnRight();`, `mbot.forward(width);`, `mbot.turnRight();`\nlösung: vb-java-rechteck-loesung.visustruct\n:::\n\n## Now without the robot: output\n\nNot every result has to be driven by the robot. With `System.out.println(…)` a Java program prints text in the [console](#zeige-konsole). With `+` you join text and values:\n\n```java\nint side = 30;\nint distance = 4 * side;\nSystem.out.println("Distance: " + distance + " cm");\n```\n\nThe console then shows **Distance: 120 cm**.\n\n::: übung vb-ohne-strecke\ntitel: How far does it drive?\ncode: java\nauftrag: A rectangle is 60 cm long and 30 cm wide. Create `length` and `width` as variables. Calculate in a variable `distance` how far the mBot2 drives once all the way round, and print **Distance: 180 cm**. No `mbot` at all!\ntest: - -> Distance: 180 cm\nbraucht: anweisung\ntipp: Once round is twice the length plus twice the width.\ntipp: `int distance = 2 * length + 2 * width;` and then `System.out.println("Distance: " + distance + " cm");`\nlösung: vb-ohne-strecke-loesung.visustruct\n:::\n\n::: quiz\n? What does `mbot.forward(side)` drive if `int side = 40;` comes first?\n→ A variable for the side\n- [ ] 4 cm\n- [x] 40 cm\n- [ ] nothing, `side` is not a command\n> Wherever `side` appears, Java uses the value 40.\n? Which data type fits `"Visu"`?\n→ Which data types are there?\n- [ ] `int`\n- [ ] `double`\n- [x] `String`\n> Text in quotation marks is a `String`.\n? What does `System.out.println("Side: " + 30);` print?\n→ Now without the robot: output\n- [x] Side: 30\n- [ ] "Side: " + 30\n- [ ] 30\n> The `+` joins the text and the number.\n:::\n\nRate 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.\n\n::: checkliste\n- I can create and use a variable. → A variable for the side\n- I can tell the data types `int`, `double`, `String` and `boolean` apart. → Which data types are there?\n- I can drive a rectangle in Java with two variables. → Now in Java: rectangle\n- I can print something with `System.out.println`. → Now without the robot: output\n:::\n',fw=`--- +titel: Reading sensors +bereich: VisuBot +kurz: The mBot2 measures something, and your program decides. +--- + +## Skills I will gain now + +::: kompetenzen +- explain the difference between a command and a sensor +- build a sensor into a condition +::: + +## Commands and sensors + +So far you have only given the mBot2 **commands**: move forward, turn right. It carried them out without paying attention to its surroundings. + +Now the **sensors** join in. Among the [elements](#zeige-elemente) there is a group **mBot2 sensors** for them: + +| Sensor | Text | What you get | +|---|---|---| +| Distance | \`mbot.getDistance()\` | distance to the next wall in cm, e.g. \`38\` | +| Line | \`mbot.getLine()\` | \`0\` if everything under the line sensor is bright, otherwise a number greater than 0 | + +The mBot2 has even more sensors: colours, buttons and joystick, light, loudness and tilt. You get to know each of them in lessons 6 to 13, the motors in lesson 20 and the stopwatch and battery in lesson 21. + +A sensor is **not a box of its own**. It gives you a number, and with that number you build a **condition**: + +\`\`\`java +mbot.getDistance() < 20 +\`\`\` + +This means: "Is the wall closer than 20 cm?" The answer is true or false. + +> How to build it: first drag a **branch** into the structure chart. Then drag the sensor **Distance** onto the branch. The condition now says \`mbot.getDistance()\`. You add the comparison \`< 20\` yourself. + +## Wall ahead? + +The mBot2 should decide by itself: if there is a wall ahead, it turns right. If the way is free, it drives forward a bit. + +This exercise has **two worlds**: in one the wall is right in front of it, in the other there is plenty of space. Your program must do the right thing in both. + +::: übung vb-wand-vorn +titel: Wall ahead? +auftrag: Build a branch with the condition \`mbot.getDistance() < 20\`. If **true**, the mBot2 turns right; if **false**, it moves forward. +welt: wand-nah -> turnRight +welt: wand-frei -> forward +braucht: verzweigung +tipp: Drag a branch into the structure chart and then the sensor **Distance** onto the branch. Write \`< 20\` after it. +tipp: The yes branch contains \`mbot.turnRight()\`, the no branch \`mbot.forward()\`. +lösung: vb-wand-vorn-loesung.visustruct +::: + +## What does the sensor give you? + +::: quiz +? The wall is 12 cm away. Is \`mbot.getDistance() < 20\` true or false? +→ Wall ahead? +- [x] true +- [ ] false +> 12 is less than 20, so the condition is true. +? The mBot2 is standing on a bright floor. What does \`mbot.getLine()\` give you? +→ Commands and sensors +- [x] 0 +- [ ] 15 +- [ ] the distance in cm +> 0 means: none of the four probes sees anything dark. +? Why is the sensor not a box of its own in the structure chart? +→ Wall ahead? +- [x] It does nothing, it only gives a value. You need that value in a condition. +- [ ] Because the mBot2 would get too slow otherwise. +- [ ] Because sensors only work in Java. +> Commands are statements. Sensors are values, just like a variable. +::: + +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. + +::: checkliste +- I can explain the difference between a command and a sensor. → Commands and sensors +- I can build a sensor into a condition. → Wall ahead? +::: +`,bw=`--- +titel: Up to the wall +bereich: VisuBot +kurz: The mBot2 measures the distance and stops in time. +--- + +## Skills I will gain now + +::: kompetenzen +- ask for the distance with \`mbot.getDistance()\` +- decide when to use a while loop instead of a for loop +- find a goal with the line sensor +::: + +## How far away is the wall? + +So far you told the mBot2 exactly how far to drive. Now it should notice by itself when to stop. + +That is what the ultrasonic sensor is for. \`mbot.getDistance()\` gives the distance to the next wall in centimetres, for example \`38\`. You can use it like a number: + +\`\`\`java +mbot.getDistance() > 15 +\`\`\` + +This is a **condition**: it is true as long as the wall is more than 15 cm away. + +> Start the [simulation](#zeige-simulation): below the world you always see the current distance. When the mBot2 gets closer to the wall, the number gets smaller. + +## Three worlds, one program + +This exercise has **three worlds**. In each one the wall is somewhere else, and the mBot2 should stop at the goal with the green flag every time, without bumping into it. + +A fixed number of **move forward** only works in one world. You need a loop that keeps driving as long as the condition is true: the **while loop**. + +::: übung vb-bis-wand +titel: Up to the wall +auftrag: The mBot2 should drive forward until the wall is at most 15 cm away. Your program must work in all three worlds. Above the simulation you choose which world you see. +welt: wand-kurz, wand-mittel, wand-lang +braucht: whileSchleife +tipp: Drag a while loop into the structure chart and the sensor **Distance** onto the loop. Then only the comparison is missing. +tipp: A while loop with the condition \`mbot.getDistance() > 15\`, with \`mbot.forward()\` inside. +lösung: vb-bis-wand-loesung.visustruct +::: + +::: ludwig +A loop that checks a condition before it drives is like me at the feeding trough: first I check whether there is anything left, and only then do I keep eating. +::: + +## To the goal + +Now it is the second sensor's turn. The goal is a black square with a green flag. When the mBot2 drives onto it, its line sensor sees it: \`mbot.getLine()\` is then no longer \`0\`. + +::: übung vb-bis-ziel +titel: Drive to the goal +auftrag: The mBot2 should keep driving forward until it is on the goal. Again there are two worlds. +welt: ziel-kurz, ziel-lang +braucht: whileSchleife +tipp: The loop should run as long as the line sensor sees **nothing**. Drag the sensor **Line** onto the while loop. +tipp: The condition is \`mbot.getLine() == 0\`. Inside the loop is \`mbot.forward()\`. +lösung: vb-bis-ziel-loesung.visustruct +::: + +## What does the loop check? + +::: quiz +? The mBot2 is 40 cm in front of the wall. How often does it drive forward with \`while (mbot.getDistance() > 15) mbot.forward();\` if each move is 10 cm? +→ How far away is the wall? +- [ ] not at all +- [ ] once +- [x] until the wall is at most 15 cm away +- [ ] always exactly five times +> The while loop checks the condition before every move. When the wall is close enough, it stops. +? Why is a for loop with a fixed count not enough here? +→ Three worlds, one program +- [x] Because the wall is at a different distance in every world. +- [ ] Because a for loop must not contain statements. +- [ ] Because the mBot2 does not understand for loops. +> The for loop knows beforehand how often it runs. The while loop decides on the way. +::: + +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. + +::: checkliste +- I can ask for the distance with \`mbot.getDistance()\`. → How far away is the wall? +- I can decide when to use a while loop instead of a for loop. → Three worlds, one program +- I can find a goal with the line sensor. → To the goal +::: +`,xw=`--- +titel: The ultrasonic sensor +bereich: VisuBot +kurz: Measure the distance, keep your distance, and do it all in Java. +--- + +## Skills I will gain now + +::: kompetenzen +- explain what \`mbot.getDistance()\` measures +- put one branch inside another +- write a while loop with the distance in Java +::: + +## How does the mBot2 measure distance? + +::: mbot2 +focus: ultrasonic +view: front +::: + +The [ultrasonic sensor]{part=ultrasonic} sends out a very high sound and waits for the echo. The longer the echo takes, the further away the wall is. \`mbot.getDistance()\` gives you the distance in **centimetres**, from about 3 to 300. + +| Sensor | Text | Value | +|---|---|---| +| Distance | \`mbot.getDistance()\` | whole number in cm, e.g. \`38\` | + +> In the [simulation](#zeige-simulation) the current distance is always shown below the world. With a real mBot2 you can hold your hand in front of the sensor and watch the number change. + +## Keep your distance in the structure chart + +The mBot2 should behave like a dog on a lead: if your hand is too close (under 10 cm), it backs away. If it is too far away (over 20 cm), it comes closer. In between, it stays where it is. + +For this you need two branches, one inside the other. The outer one checks “too close?”, the inner one in the No branch checks “too far?”. + +::: übung vb-abstand-halten +titel: Keep your distance +auftrag: Build a structure chart: if the distance is less than 10, the mBot2 drives back. Otherwise: if the distance is greater than 20, it drives forward. Otherwise it does nothing. +messwerte: getDistance=5 -> backward +messwerte: getDistance=35 -> forward +messwerte: getDistance=15 -> none +braucht: verzweigung +tipp: Drag a branch into the structure chart and the sensor **Distance** onto it. Write \`< 10\` after it. The Yes branch gets **move back**. +tipp: The No branch gets a second branch with \`mbot.getDistance() > 20\` and **move forward** in its Yes branch. Its No branch stays empty. +lösung: vb-abstand-halten-loesung.visustruct +::: + +> When checking, VisuStruct sets the distance to 5, 35 and 15 cm one after the other and looks at what your mBot2 does. + +## Now in Java + +In the [Code](#zeige-codelive) area you already see your structure chart as Java code. A branch is called \`if\` there, the No branch is \`else\`: + +\`\`\`java +if (mbot.getDistance() < 10) { + mbot.backward(); +} else { + ... +} +\`\`\` + +You type a sensor like a command: \`mbot.\` and then \`getDistance()\`. After the dot the editor suggests all commands and sensors. + +::: übung vb-java-wand-piep +titel: To the wall and beep +code: java +auftrag: Write in Java: the mBot2 drives forward as long as the wall is more than 15 cm away. Then it plays a tone. There are three worlds. +welt: wand-kurz -> tone +welt: wand-mittel -> tone +welt: wand-lang -> tone +braucht: whileSchleife +tipp: A while loop in Java is \`while (condition) { … }\`. The condition is \`mbot.getDistance() > 15\`. +tipp: Inside the loop is \`mbot.forward();\`, after the loop \`mbot.playTone(440, 300);\`. +lösung: vb-java-wand-piep-loesung.visustruct +::: + +::: quiz +? \`mbot.getDistance()\` gives \`8\`. What does the program from “Keep your distance” do? +→ Keep your distance in the structure chart +- [x] It drives back. +- [ ] It drives forward. +- [ ] It stays where it is. +> 8 is less than 10, so the first condition is already true. +? What is the No branch of a branch called in Java? +→ Now in Java +- [ ] \`then\` +- [x] \`else\` +- [ ] \`otherwise\` +> \`if\` is the start, \`else\` the No branch. +::: + +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. + +::: checkliste +- I can explain what \`mbot.getDistance()\` measures. → How does the mBot2 measure distance? +- I can put one branch inside another. → Keep your distance in the structure chart +- I can write a while loop with the distance in Java. → Now in Java +::: +`,vw=`--- +titel: The line sensor +bereich: VisuBot +kurz: Detect dark lines on the floor and don't fall off the table. +--- + +## Skills I will gain now + +::: kompetenzen +- explain what the number from \`mbot.getLine()\` means +- drive up to a line +- count steps with a variable in Java +::: + +## Four probes under the nose + +::: mbot2 +focus: lineSensor +view: bottom +::: + +The [line sensor]{part=lineSensor} has four probes side by side. Each one shines light on the floor and measures how much comes back. Black swallows the light, white reflects it. + +| Sensor | Text | Value | +|---|---|---| +| Line | \`mbot.getLine()\` | \`0\` = all bright, greater than \`0\` = at least one probe sees black | + +To start with, this is all you need: **\`mbot.getLine() == 0\` means “no line”**, \`mbot.getLine() != 0\` means “line found”. + +::: angeberwissen +\`mbot.getLine()\` is really a binary number with four digits, one for each probe: \`1111\` (that is 15) means “all four see black”, \`0110\` (6) “only the middle two”. With that an mBot2 can even follow a line. +::: + +## Turn round at the edge in the structure chart + +Imagine a table with black tape along the edge. The mBot2 should drive forward until it sees the tape and then turn round so it doesn't fall off. + +::: übung vb-rand +titel: Turn round at the edge +auftrag: The mBot2 drives forward as long as \`mbot.getLine() == 0\`. Then it turns 180°. There are two worlds with different distances. +welt: rand-1 -> forward 20, turnRight 180 +welt: rand-2 -> forward 50, turnRight 180 +braucht: whileSchleife +tipp: Drag a while loop into the structure chart and the sensor **Line** onto it. Write \`== 0\` after it. **move forward** goes inside the loop. +tipp: After the loop (below it, not inside) is \`mbot.turnRight(180)\`. +lösung: vb-rand-loesung.visustruct +::: + +## Now in Java: there and back + +Now the mBot2 should drive exactly back to the start after turning round. To do that it counts with a **variable** how often it drove forward. + +\`\`\`java +int steps = 0; +while (mbot.getLine() == 0) { + mbot.forward(); + steps = steps + 1; +} +\`\`\` + +::: übung vb-java-rand +titel: To the line and back +code: java +auftrag: Write in Java: the mBot2 drives to the line and counts its steps. Then it turns 180° and uses a for loop to drive the same number of steps back. +welt: rand-1 -> forward 20, turnRight 180, forward 20 +welt: rand-2 -> forward 50, turnRight 180, forward 50 +braucht: whileSchleife, forSchleife +tipp: After the while loop: \`mbot.turnRight(180);\` and then \`for (int i = 0; i < steps; i++) { … }\`. +tipp: The for loop only contains \`mbot.forward();\`. +lösung: vb-java-rand-loesung.visustruct +::: + +::: quiz +? The mBot2 is on white paper. What does \`mbot.getLine()\` give? +→ Four probes under the nose +- [x] 0 +- [ ] 15 +- [ ] 1 +> No probe sees black, so 0. +? Which condition means “line found”? +→ Turn round at the edge in the structure chart +- [ ] \`mbot.getLine() == 0\` +- [x] \`mbot.getLine() != 0\` +- [ ] \`mbot.getLine() < 0\` +> \`!=\` means “not equal”. +::: + +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. + +::: checkliste +- I can explain what the number from \`mbot.getLine()\` means. → Four probes under the nose +- I can drive up to a line. → Turn round at the edge in the structure chart +- I can count steps with a variable in Java. → Now in Java: there and back +::: +`,yw=`--- +titel: Recognising colours +bereich: VisuBot +kurz: The quad RGB sensor tells you which colour the mBot2 is standing on. +--- + +## Skills I will gain now + +::: kompetenzen +- ask for a colour with \`mbot.getColor().equals(…)\` +- turn a condition round with \`!\` +- put a branch inside a loop +::: + +## A sensor that sees colours + +::: mbot2 +focus: lineSensor +view: bottom +::: + +The [line sensor]{part=lineSensor} is really called a **quad RGB sensor**. “Quad” means four (four probes), “RGB” stands for red, green and blue. It shines these three colours on the floor and measures which colour comes back. That is how it recognises coloured fields. + +\`mbot.getColor()\` gives the name of the colour under the mBot2, as **text**: + +| Floor | \`mbot.getColor()\` | +|---|---| +| red field | \`"red"\` | +| green field | \`"green"\` | +| blue field | \`"blue"\` | +| yellow field | \`"yellow"\` | +| black field or line | \`"black"\` | +| light floor | \`"white"\` | + +You ask whether it is a certain colour with \`.equals(…)\`: \`mbot.getColor().equals("red")\` is **true** when the mBot2 stands on red, otherwise **false**. So it is already a complete condition. + +> In Java you always compare texts with \`.equals(…)\`, **not** with \`==\`. The \`==\` looks right but often doesn't work with texts. + +> With a \`!\` in front you turn a condition round: \`!mbot.getColor().equals("red")\` means “**not** red”. + +## Drive to red in the structure chart + +::: übung vb-bis-rot +titel: Drive to red +auftrag: The mBot2 drives forward as long as it is **not** on a red field. In the second world there is a green field first, which should not bother it. +welt: farbe-1 -> forward 20 +welt: farbe-2 -> forward 50 +braucht: whileSchleife +tipp: Drag a while loop into the structure chart and the sensor **Colour is red?** onto it. Write a \`!\` in front of \`mbot.getColor().equals("red")\`. +tipp: The condition is \`!mbot.getColor().equals("red")\`, inside the loop is **move forward**. +lösung: vb-bis-rot-loesung.visustruct +::: + +## Now in Java: beep on green + +Now you combine a loop with a branch: the mBot2 drives to blue. If it passes over a green field on the way, it beeps. + +::: übung vb-java-blau-gruen +titel: To blue, beep on green +code: java +auftrag: Write in Java: the mBot2 drives forward as long as it is not on blue. After each step it checks: if it is on green, it plays a tone. In the second world there is no green field, so it must not beep there. +welt: farbe-3 -> forward 30, tone +welt: farbe-4 -> forward 30, noTone +braucht: whileSchleife, verzweigung +tipp: Outside is \`while (!mbot.getColor().equals("blue")) { … }\`. Inside, first \`mbot.forward();\`. +tipp: After that, still inside the loop: \`if (mbot.getColor().equals("green")) { mbot.playTone(880, 200); }\`. +lösung: vb-java-blau-gruen-loesung.visustruct +::: + +::: quiz +? The mBot2 is on a red field. What is \`!mbot.getColor().equals("red")\`? +→ Drive to red in the structure chart +- [ ] true +- [x] false +> \`mbot.getColor().equals("red")\` is true, the \`!\` turns it into false. So the loop stops. +? How do you compare the colour with \`"green"\`? +→ A sensor that sees colours +- [x] \`mbot.getColor().equals("green")\` +- [ ] \`mbot.getColor() == "green"\` +- [ ] \`mbot.getColor() = "green"\` +> \`mbot.getColor()\` gives a text, and texts are compared with \`.equals(…)\`. A single \`=\` is an assignment, not a comparison at all. +::: + +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. + +::: checkliste +- I can ask for a colour with \`mbot.getColor().equals(…)\`. → A sensor that sees colours +- I can turn a condition round with \`!\`. → Drive to red in the structure chart +- I can put a branch inside a loop. → Now in Java: beep on green +::: +`,ww=`--- +titel: Case selection with colours +bereich: VisuBot +kurz: Do something different for each colour or line, with one case selection instead of many branches. +--- + +## Skills I will gain now + +::: kompetenzen +- build a case selection with texts +- write a case selection with numbers in Java +- read a number and print something depending on its value +::: + +## Many colours, many cases + +The mBot2 should react differently to each colour: turn right on red, drive forward a bit on green, beep on blue. With branches you would need three inside each other. A **case selection** is clearer, in Java \`switch\`: + +\`\`\`java +switch (mbot.getColor()) { + case "red" -> { + mbot.turnRight(); + } + case "green" -> { + mbot.forward(20); + } + default -> { + mbot.forward(10); + } +} +\`\`\` + +- The value being checked goes in the brackets at the top, here the colour. +- Each \`case\` is one **case**. If the value matches, exactly this case runs. +- \`default\` is the case for **everything else**. + +In the structogram the case selection is a box with several columns, one for each case. + +::: übung vb-farbweiche +titel: Colour switch +auftrag: Build a case selection on \`mbot.getColor()\`. For \`"red"\` the mBot2 turns right. For \`"green"\` it drives forward 20 cm. For \`"blue"\` it plays a tone of 880 hertz for 200 milliseconds. In all other cases it drives forward 10 cm. +messwerte: getColor=red -> turnRight +messwerte: getColor=green -> forward 20 +messwerte: getColor=blue -> none, tone +messwerte: getColor=white -> forward 10 +braucht: fallauswahl +tipp: Drag a case selection into the structogram. At the top goes \`mbot.getColor()\`, the cases are \`"red"\`, \`"green"\` and \`"blue"\`, plus the case for everything else. +tipp: For red \`mbot.turnRight()\`, for green \`mbot.forward(20)\`, for blue \`mbot.playTone(880, 200)\`, otherwise \`mbot.forward(10)\`. +lösung: vb-farbweiche-loesung.visustruct +::: + +## Now in Java: line patterns + +A number can also be the value of a case selection. \`mbot.getLine()\` from lesson 7 gives for example: + +| Value | Meaning | +|---|---| +| \`0\` | no line | +| \`6\` | the two middle sensors see the line: it is right on it | +| \`15\` | all four see black: a cross line | + +For numbers you write the case without quotation marks: \`case 6 -> { … }\`. + +::: übung vb-linienmuster +titel: Line patterns +code: java +auftrag: Write a case selection on \`mbot.getLine()\` in Java. For 6 the mBot2 drives forward 10 cm. For 0 it turns right. For 15 it shows **Cross line!** on its screen. In all other cases it drives forward 5 cm. +messwerte: getLine=6 -> forward 10 +messwerte: getLine=0 -> turnRight +messwerte: getLine=15 -> none, screen "Cross line!" +messwerte: getLine=4 -> forward 5 +braucht: fallauswahl +tipp: \`switch (mbot.getLine()) { case 6 -> { … } case 0 -> { … } case 15 -> { … } default -> { … } }\` +tipp: For 6 \`mbot.forward(10);\`, for 0 \`mbot.turnRight();\`, for 15 \`mbot.showText("Cross line!");\`, otherwise \`mbot.forward(5);\`. +lösung: vb-linienmuster-loesung.visustruct +::: + +## Now without the robot: grades in words + +You don't only need the case selection for robots. This program reads a number that the user types in the [console](#zeige-konsole): + +\`\`\`java +Scanner scanner = new Scanner(System.in); +int grade = scanner.nextInt(); +\`\`\` + +::: übung vb-ohne-noten +titel: Grades in words +code: java +auftrag: Read a grade as a number. For 1 print **very good**, for 2 **good**, for 3 **satisfactory** and for all other numbers **other grade**. No \`mbot\` at all! +test: 1 -> very good +test: 2 -> good +test: 3 -> satisfactory +test: 5 -> other grade +braucht: fallauswahl +tipp: First \`Scanner scanner = new Scanner(System.in);\` and \`int grade = scanner.nextInt();\`. Then comes \`switch (grade) { … }\`. +tipp: \`case 1 -> { System.out.println("very good"); }\` and so on, finally \`default -> { System.out.println("other grade"); }\`. +lösung: vb-ohne-noten-loesung.visustruct +::: + +::: quiz +? The mBot2 is on yellow. Which case of the colour switch runs? +→ Many colours, many cases +- [ ] the case \`"red"\` +- [ ] none at all +- [x] \`default\` +> There is no case of its own for yellow. So the case for everything else runs. +? How do you write the case for the number 6? +→ Now in Java: line patterns +- [x] \`case 6 -> { … }\` +- [ ] \`case "6" -> { … }\` +- [ ] \`if 6 -> { … }\` +> Numbers have no quotation marks, texts like \`"red"\` do. +::: + +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. + +::: checkliste +- I can build a case selection with texts. → Many colours, many cases +- I can write a case selection with numbers in Java. → Now in Java: line patterns +- I can read a number and print something depending on its value. → Now without the robot: grades in words +::: +`,zw=`--- +titel: Buttons and joystick +bereich: VisuBot +kurz: The mBot2 waits for you and can be remote controlled. +--- + +## Skills I will gain now + +::: kompetenzen +- ask the sensors for buttons and joystick +- wait for a button +- steer the mBot2 with the joystick +::: + +## Pressing as a sensor + +::: mbot2 +focus: joystick, buttons +view: top +::: + +On the CyberPi there are two [buttons]{part=buttons} (A and B) and a [joystick]{part=joystick}. For your program these are sensors: they give **true** as long as you press them. + +| Sensor | Text | +|---|---| +| Button A / B pressed? | \`mbot.isButtonA()\`, \`mbot.isButtonB()\` | +| Joystick up / down | \`mbot.isJoystickUp()\`, \`mbot.isJoystickDown()\` | +| Joystick left / right | \`mbot.isJoystickLeft()\`, \`mbot.isJoystickRight()\` | + +> Without a real mBot2, open **🎛 Try the sensors** below the world in the [simulation](#zeige-simulation). There you find the buttons A, B and the arrows for the joystick. A click keeps them pressed for one second. + +## Waiting for button A in the structure chart + +A robot should not drive off as soon as the program starts. Better: it waits until you press A. + +Waiting means: a loop that runs as long as A is **not** pressed. So that it is not completely empty, the mBot2 waits briefly inside with **wait a moment** (\`mbot.pause(100)\`, that is 100 milliseconds). + +::: übung vb-start-a +titel: Start with button A +auftrag: The mBot2 waits until button A is pressed. Then it drives forward 30 cm. +messwerte: isButtonA=false/true -> forward 30 +messwerte: isButtonA=true -> forward 30 +braucht: whileSchleife +tipp: A while loop with the condition \`!mbot.isButtonA()\`. Inside is **wait a moment**. +tipp: After the loop is \`mbot.forward(30)\`. +lösung: vb-start-a-loesung.visustruct +::: + +> When checking, button A is not pressed for a while and then pressed. If your mBot2 drives off too early, it shows. + +## Now in Java: remote control + +With the joystick you steer the mBot2. The program asks the joystick five times in a row: up means drive forward, down means drive back. + +::: übung vb-java-joystick +titel: Remote control +code: java +auftrag: Write a for loop in Java that runs five times. Inside: if the joystick is up, the mBot2 drives forward. Otherwise: if it is down, it drives back. +messwerte: isJoystickUp=true -> forward 50 +messwerte: isJoystickDown=true -> backward 50 +messwerte: isJoystickUp=false -> none +braucht: forSchleife, verzweigung +tipp: \`for (int i = 0; i < 5; i++) { … }\` and inside \`if (mbot.isJoystickUp()) { … } else { … }\`. +tipp: The \`else\` contains another branch: \`if (mbot.isJoystickDown()) { mbot.backward(); }\`. +lösung: vb-java-joystick-loesung.visustruct +::: + +::: quiz +? What does \`mbot.isButtonB()\` give when nobody presses it? +→ Pressing as a sensor +- [ ] 0 +- [x] false +- [ ] B +> Buttons give true or false. +? Why is there **wait a moment** in the waiting loop? +→ Waiting for button A in the structure chart +- [x] So the loop is not empty and the CyberPi doesn't race round in circles for nothing. +- [ ] So the button glows longer. +- [ ] Without a pause the mBot2 drives backwards. +> The loop checks every 100 milliseconds, that is plenty. +::: + +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. + +::: checkliste +- I can ask the sensors for buttons and joystick. → Pressing as a sensor +- I can wait for a button. → Waiting for button A in the structure chart +- I can steer the mBot2 with the joystick. → Now in Java: remote control +::: +`,Iw=`--- +titel: The light sensor +bereich: VisuBot +kurz: Bright or dark? The mBot2 becomes a night light. +--- + +## Skills I will gain now + +::: kompetenzen +- ask for the brightness +- switch the LEDs with a branch +- write several commands in one branch +::: + +## How bright is it? + +::: mbot2 +focus: lightSensor +view: top +::: + +The [light sensor]{part=lightSensor} is on the CyberPi. \`mbot.getBrightness()\` gives a number from **0** (pitch dark) to **100** (very bright). + +| Sensor | Text | Value | +|---|---|---| +| Brightness | \`mbot.getBrightness()\` | 0 to 100 | + +> In the simulation you set the brightness with the slider under **🎛 Try the sensors**. With a real mBot2 you simply hold your hand over the CyberPi. + +## Night light in the structure chart + +::: übung vb-nachtlicht +titel: Night light +auftrag: If the brightness is less than 30, the LEDs glow white (\`mbot.setLed(255, 255, 255)\`). Otherwise the LEDs go off (\`mbot.ledOff()\`). +messwerte: getBrightness=10 -> ledOn +messwerte: getBrightness=80 -> ledOff +braucht: verzweigung +tipp: Drag a branch into the structure chart and the sensor **Brightness** onto it. Write \`< 30\` after it. +tipp: The Yes branch gets **LEDs on** with \`mbot.setLed(255, 255, 255)\`, the No branch **LEDs off**. +lösung: vb-nachtlicht-loesung.visustruct +::: + +::: angeberwissen +Street lights do the same: a light sensor notices when it gets dark and switches them on. That is why they come on earlier in winter than in summer, without anyone changing a clock. +::: + +## Now in Java: night light with sound + +::: übung vb-java-nachtlicht-ton +titel: Night light with sound +code: java +auftrag: Write the night light in Java, but with two changes: in the dark the LEDs glow yellow (\`mbot.setLed(255, 200, 0)\`) **and** the mBot2 plays a tone. In the light the LEDs go off, without a tone. +messwerte: getBrightness=10 -> ledOn, tone +messwerte: getBrightness=80 -> ledOff, noTone +braucht: verzweigung +tipp: \`if (mbot.getBrightness() < 30) { … } else { … }\` +tipp: The \`if\` part has two lines: \`mbot.setLed(255, 200, 0);\` and \`mbot.playTone(440, 300);\`. +lösung: vb-java-nachtlicht-ton-loesung.visustruct +::: + +::: quiz +? \`mbot.getBrightness()\` gives 45. What does the night light do? +→ Night light in the structure chart +- [ ] The LEDs glow. +- [x] The LEDs go off. +> 45 is not less than 30. +? What range do the light sensor's values have? +→ How bright is it? +- [ ] 0 to 255 +- [x] 0 to 100 +- [ ] -100 to 100 +::: + +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. + +::: checkliste +- I can ask for the brightness. → How bright is it? +- I can switch the LEDs with a branch. → Night light in the structure chart +- I can write several commands in one branch. → Now in Java: night light with sound +::: +`,kw=`--- +titel: The microphone +bereich: VisuBot +kurz: Clap to start, and a noise light for the classroom. +--- + +## Skills I will gain now + +::: kompetenzen +- ask for the loudness +- wait until something happens +- write a noise light in Java +::: + +## How loud is it? + +::: mbot2 +focus: microphone +view: top +::: + +The CyberPi's [microphone]{part=microphone} measures the loudness. \`mbot.getLoudness()\` gives **0** (silent) to **100** (very loud). A clap nearby gives about 60 to 90. + +| Sensor | Text | Value | +|---|---|---| +| Loudness | \`mbot.getLoudness()\` | 0 to 100 | + +## Clap to start in the structure chart + +Just like waiting for button A: a loop waits as long as it is quiet. Only then does the mBot2 drive off. + +::: übung vb-klatschen +titel: Clap to start +auftrag: The mBot2 waits as long as the loudness is less than 50. Then it drives forward 30 cm. +messwerte: getLoudness=0/80 -> forward 30 +messwerte: getLoudness=90 -> forward 30 +braucht: whileSchleife +tipp: A while loop with the condition \`mbot.getLoudness() < 50\`, with **wait a moment** inside. +tipp: After the loop: \`mbot.forward(30)\`. +lösung: vb-klatschen-loesung.visustruct +::: + +> In the simulation you push the **Loudness** slider to the right while the program is waiting. + +## Now in Java: noise light + +::: übung vb-java-laermampel +titel: Noise light +code: java +auftrag: Write in Java: if the loudness is greater than 60, the LEDs glow red. Otherwise they are off. +messwerte: getLoudness=80 -> ledOn +messwerte: getLoudness=20 -> ledOff +braucht: verzweigung +tipp: \`if (mbot.getLoudness() > 60) { … } else { … }\` +tipp: Red is \`mbot.setLed(255, 0, 0);\`, off is \`mbot.ledOff();\`. +lösung: vb-java-laermampel-loesung.visustruct +::: + +::: angeberwissen +Loudness is really measured in **decibels** (dB). Whispering is about 30 dB, a classroom 60 to 70 dB, a pneumatic drill 100 dB. The CyberPi turns that into a simple number from 0 to 100. +::: + +::: quiz +? The clap loop is \`while (mbot.getLoudness() < 50)\`. The loudness is 30. What happens? +→ Clap to start in the structure chart +- [x] The mBot2 keeps waiting. +- [ ] The mBot2 drives off. +> 30 is less than 50, the condition is true, the loop keeps running. +::: + +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. + +::: checkliste +- I can ask for the loudness. → How loud is it? +- I can wait until something happens. → Clap to start in the structure chart +- I can write a noise light in Java. → Now in Java: noise light +::: +`,Sw=`--- +titel: The motion sensor +bereich: VisuBot +kurz: Measure tilt and detect shaking. +--- + +## Skills I will gain now + +::: kompetenzen +- explain what the motion sensor measures +- join two conditions with “or” +- join several conditions with “and” +::: + +## Tilted or level? + +::: mbot2 +focus: cyberpi +spin: yes +::: + +Inside the [CyberPi]{part=cyberpi} there is a **motion sensor** (gyroscope). It measures how tilted the mBot2 is, in degrees: + +| Sensor | Text | Value | +|---|---|---| +| Tilt forward/back | \`mbot.getPitch()\` | nose down: positive, nose up: negative (−90 to 90) | +| Tilt sideways | \`mbot.getRoll()\` | positive to one side, negative to the other | +| Shaken? | \`mbot.isShaken()\` | \`true\` or \`false\` | + +When the mBot2 is lying flat on the table, both tilts are about **0**. + +> In the simulation there are two sliders for this under **🎛 Try the sensors** and the button **shake**. With a real mBot2 you tilt it carefully in your hand. + +## Tilt warning in the structure chart + +If the mBot2 drives up or down a ramp that is too steep, it should warn you. Too steep means: more than 20° forward **or** more than 20° back. + +::: übung vb-schraeglage +titel: Tilt warning +auftrag: If the forward/back tilt is greater than 20 **or** less than −20, the mBot2 plays a tone. Otherwise it does nothing. +messwerte: getPitch=30 -> tone +messwerte: getPitch=-30 -> tone +messwerte: getPitch=5 -> noTone +braucht: verzweigung +tipp: “or” in a condition is \`||\`. Drag the sensor **Tilt forward/back** onto the branch twice. +tipp: The condition is \`mbot.getPitch() > 20 || mbot.getPitch() < -20\`, the Yes branch gets **play a tone**. +lösung: vb-schraeglage-loesung.visustruct +::: + +## Now in Java: spirit level + +A spirit level shows whether something is exactly level. The mBot2 glows green when both tilts are between −5 and 5. + +::: übung vb-java-wasserwaage +titel: Spirit level +code: java +auftrag: Write in Java: if \`mbot.getPitch()\` and \`mbot.getRoll()\` are both between −5 and 5, the LEDs glow green. Otherwise they are off. +messwerte: getPitch=0, getRoll=0 -> ledOn +messwerte: getPitch=0, getRoll=20 -> ledOff +messwerte: getPitch=-10, getRoll=0 -> ledOff +braucht: verzweigung +tipp: “and” is \`&&\`. You need four comparisons: \`mbot.getPitch() > -5 && mbot.getPitch() < 5 && …\` +tipp: Green is \`mbot.setLed(0, 255, 0);\`, the \`else\` has \`mbot.ledOff();\`. +lösung: vb-java-wasserwaage-loesung.visustruct +::: + +::: quiz +? The mBot2 is lying flat on the table. What does \`mbot.getPitch()\` give, roughly? +→ Tilted or level? +- [x] 0 +- [ ] 90 +- [ ] 100 +? What does \`mbot.isShaken()\` do? +→ Tilted or level? +- [ ] It shakes the mBot2. +- [x] It reports whether someone is shaking the mBot2. +> Sensors don't do anything, they only measure. +::: + +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. + +::: checkliste +- I can explain what the motion sensor measures. → Tilted or level? +- I can join two conditions with “or”. → Tilt warning in the structure chart +- I can join several conditions with “and”. → Now in Java: spirit level +::: +`,Tw=`--- +titel: The LEDs +bereich: VisuBot +kurz: Mix colours, build a traffic light and make it blink. +--- + +## Skills I will gain now + +::: kompetenzen +- mix a colour from red, green and blue +- show colours one after the other with pauses +- make the LEDs blink in Java +::: + +## Mixing red, green and blue + +::: mbot2 +focus: leds +view: back +::: + +The five [LEDs]{part=leds} are an **actuator**: they do something, they light up. Each LED mixes its colour from red, green and blue, each from 0 (off) to 255 (fully bright). + +| Command | Box | What happens | +|---|---|---| +| \`mbot.setLed(255, 0, 0)\` | **LEDs on** | all LEDs red | +| \`mbot.ledOff()\` | **LEDs off** | all LEDs off | +| \`mbot.pause(1000)\` | **wait a moment** | wait 1000 milliseconds (1 second) | + +| Colour | Red | Green | Blue | +|---|---|---|---| +| Red | 255 | 0 | 0 | +| Yellow | 255 | 200 | 0 | +| Green | 0 | 255 | 0 | +| Blue | 0 | 0 | 255 | +| White | 255 | 255 | 255 | +| Purple | 160 | 0 | 255 | + +> Without **wait a moment** the mBot2 switches the colours so fast that you only see the last one. In the simulation you see the colour on the LEDs of the 3D model. + +## Traffic light in the structure chart + +::: übung vb-ampel +titel: Traffic light +auftrag: The LEDs show red, yellow and green one after the other like a traffic light. Between the colours the mBot2 waits 1000 milliseconds each time. Yellow is \`255, 200, 0\`. +befehle: setLed 255 0 0, pause 1000, setLed 255 200 0, pause 1000, setLed 0 255 0 +tipp: Drag **LEDs on** three times and **wait a moment** twice into the structure chart, taking turns. +tipp: Change the numbers: \`mbot.setLed(255, 0, 0)\`, \`mbot.pause(1000)\`, \`mbot.setLed(255, 200, 0)\`, \`mbot.pause(1000)\`, \`mbot.setLed(0, 255, 0)\`. +lösung: vb-ampel-loesung.visustruct +::: + +## Now in Java: blue light + +Blinking means: on, wait, off, wait, again and again. “Again and again” is a loop. + +::: übung vb-java-blinken +titel: Blue light +code: java +auftrag: Write a for loop in Java that runs three times. Inside, the LEDs go blue, the mBot2 waits 500 milliseconds, the LEDs go off, and it waits 500 milliseconds again. +befehle: 3 x (setLed 0 0 255, pause 500, ledOff, pause 500) +braucht: forSchleife +tipp: \`for (int i = 0; i < 3; i++) { … }\` +tipp: Inside the loop: \`mbot.setLed(0, 0, 255);\`, \`mbot.pause(500);\`, \`mbot.ledOff();\`, \`mbot.pause(500);\`. +lösung: vb-java-blinken-loesung.visustruct +::: + +::: quiz +? Which colour does \`mbot.setLed(0, 255, 0)\` give? +→ Mixing red, green and blue +- [ ] Red +- [x] Green +- [ ] Blue +> The numbers are red, green, blue. Only green is on. +? Why does the blue light need **wait a moment**? +→ Now in Java: blue light +- [x] Otherwise it changes so fast that you can't see any blinking. +- [ ] Otherwise the LEDs break. +- [ ] Because \`ledOff()\` doesn't work otherwise. +::: + +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. + +::: checkliste +- I can mix a colour from red, green and blue. → Mixing red, green and blue +- I can show colours one after the other with pauses. → Traffic light in the structure chart +- I can make the LEDs blink in Java. → Now in Java: blue light +::: +`,_w=`--- +titel: Single LEDs +bereich: VisuBot +kurz: Each of the five LEDs gets its own colour, all the way to a running light. +--- + +## Skills I will gain now + +::: kompetenzen +- address the LEDs by their numbers 0 to 4 +- make single LEDs light up in different colours +- build a running light with a loop +::: + +## Every LED has a number + +::: mbot2 +focus: leds +view: back +::: + +So far all five [LEDs]{part=leds} showed the same colour. But you can also address each LED on its own. For that, every LED has a **number**. As with arrays, counting starts at **0**: the five LEDs are called 0, 1, 2, 3 and 4. + +| Command | Box | What happens | +|---|---|---| +| \`mbot.led(0).setColor("green")\` | **set LED colour** | LED 0 lights up green | +| \`mbot.led(3).setColor("off")\` | **set LED colour** | LED 3 goes off | + +You write the colour as a name in quotes: + +| Colour name | Colour name | Colour name | +|---|---|---| +| \`"red"\` | \`"orange"\` | \`"yellow"\` | +| \`"green"\` | \`"cyan"\` | \`"blue"\` | +| \`"purple"\` | \`"pink"\` | \`"white"\` | + +With \`"off"\` you switch an LED off. + +> The number can also be a variable: \`mbot.led(i).setColor("red")\`. That way a loop can switch on one LED after the other. + +## Three lights in the structogram + +::: übung vb-drei-lichter +titel: Three lights +auftrag: Switch LED 0 red, LED 2 yellow and LED 4 green. LEDs 1 and 3 stay off. +befehle: ledColor 0 "red", ledColor 2 "yellow", ledColor 4 "green" +tipp: Drag **set LED colour** into the structogram three times. +tipp: Change number and colour: \`mbot.led(0).setColor("red")\`, \`mbot.led(2).setColor("yellow")\`, \`mbot.led(4).setColor("green")\`. +lösung: vb-drei-lichter-loesung.visustruct +::: + +## Now in Java: running light + +In a running light, a light moves from one LED to the next. The loop variable \`i\` is the number of the LED. + +::: übung vb-java-lauflicht +titel: Running light +code: java +auftrag: Write a for loop in Java in which \`i\` runs from 0 to 4. Inside, LED \`i\` turns blue, the mBot2 waits 200 milliseconds, and LED \`i\` goes off again. +befehle: ledColor 0 "blue", pause 200, ledColor 0 "off", ledColor 1 "blue", pause 200, ledColor 1 "off", ledColor 2 "blue", pause 200, ledColor 2 "off", ledColor 3 "blue", pause 200, ledColor 3 "off", ledColor 4 "blue", pause 200, ledColor 4 "off" +braucht: forSchleife +tipp: \`for (int i = 0; i < 5; i++) { … }\` +tipp: Inside the loop: \`mbot.led(i).setColor("blue");\`, \`mbot.pause(200);\`, \`mbot.led(i).setColor("off");\`. +lösung: vb-java-lauflicht-loesung.visustruct +::: + +::: quiz +? Which number does the first LED have? +→ Every LED has a number +- [x] 0 +- [ ] 1 +- [ ] 5 +> As with arrays, you count from 0. The five LEDs have the numbers 0 to 4. +? What does \`mbot.led(4).setColor("off")\` do? +→ Three lights in the structogram +- [ ] All LEDs go off. +- [x] Only LED 4 goes off. +- [ ] Four LEDs go off. +::: + +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. + +::: checkliste +- I can address the LEDs by their numbers 0 to 4. → Every LED has a number +- I can make single LEDs light up in different colours. → Three lights in the structogram +- I can build a running light with a loop. → Now in Java: running light +::: +`,Aw=`--- +titel: The speaker +bereich: VisuBot +kurz: Tones, a scale and a siren. +--- + +## Skills I will gain now + +::: kompetenzen +- explain what the two numbers in \`playTone\` mean +- build a sequence of tones +- calculate with the counting variable in Java +- make the mBot2 show a feeling +::: + +## How high, how long? + +::: mbot2 +focus: cyberpi +view: top +::: + +The [CyberPi]{part=cyberpi} has a small speaker. \`mbot.playTone(440, 300)\` plays a tone: + +- The first number is the **pitch** in hertz (vibrations per second). The bigger, the higher. +- The second number is the **length** in milliseconds. + +| Note | C | D | E | F | G | A | B | C' | +|---|---|---|---|---|---|---|---|---| +| Hertz | 262 | 294 | 330 | 349 | 392 | 440 | 494 | 523 | + +> In the simulation you hear the tones through your computer's speakers. Feel free to turn it down a bit. + +## Scale in the structure chart + +::: übung vb-tonleiter +titel: Scale +auftrag: The mBot2 plays the notes C, D, E, F, G one after the other, each 300 milliseconds long. The hertz numbers are in the table. +befehle: playTone 262 300, playTone 294 300, playTone 330 300, playTone 349 300, playTone 392 300 +tipp: Drag **play a tone** into the structure chart five times. +tipp: The boxes are \`mbot.playTone(262, 300)\`, \`mbot.playTone(294, 300)\` and so on. +lösung: vb-tonleiter-loesung.visustruct +::: + +::: angeberwissen +The note A at 440 hertz is called **concert pitch**. Orchestras tune their instruments to it. One octave higher has exactly twice as many vibrations: 880 hertz. +::: + +## Now in Java: higher and higher + +In a for loop you can calculate with the counting variable. That way each tone is higher than the last: + +\`\`\`java +mbot.playTone(i * 200, 200); +\`\`\` + +::: übung vb-java-hoeher +titel: Higher and higher +code: java +auftrag: Write a for loop in Java in which \`i\` counts from 1 to 5. In each round the mBot2 plays a tone with \`i * 200\` hertz, 200 milliseconds long. +befehle: playTone 200 200, playTone 400 200, playTone 600 200, playTone 800 200, playTone 1000 200 +braucht: forSchleife +tipp: \`for (int i = 1; i <= 5; i++) { … }\` +tipp: The loop only contains \`mbot.playTone(i * 200, 200);\`. +lösung: vb-java-hoeher-loesung.visustruct +::: + +## Showing feelings + +The mBot2 can also be happy, sad or sleepy. With **show a feeling** (\`mbot.emotion("smile")\`) it plays a little show: the LEDs light up, it makes a sound and wiggles a bit. + +| Text | Feeling | +|---|---| +| \`mbot.emotion("smile")\` | laughs | +| \`mbot.emotion("hello")\` | says hello | +| \`mbot.emotion("sad")\` | is sad | +| \`mbot.emotion("angry")\` | is angry | +| \`mbot.emotion("dizzy")\` | is dizzy | +| \`mbot.emotion("zzz")\` | sleeps | + +> Try it with the real mBot2. The simulator only shows the command. More feelings are listed under **Reference**. + +::: quiz +? Which tone is higher? +→ How high, how long? +- [x] \`mbot.playTone(880, 300)\` +- [ ] \`mbot.playTone(440, 300)\` +> More hertz means higher. +? How long does \`mbot.playTone(440, 1000)\` sound? +→ How high, how long? +- [ ] 440 seconds +- [x] 1 second +- [ ] 1000 seconds +> 1000 milliseconds are one second. +::: + +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. + +::: checkliste +- I can explain what the two numbers in \`playTone\` mean. → How high, how long? +- I can build a sequence of tones. → Scale in the structure chart +- I can calculate with the counting variable in Java. → Now in Java: higher and higher +- I can make the mBot2 show a feeling. → Showing feelings +::: +`,Ow=`--- +titel: Arrays and melodies +bereich: VisuBot +kurz: Store many values in one array and work through them with a loop. +--- + +## Skills I will gain now + +::: kompetenzen +- create an array and play it with a loop +- use an array of texts in Java +- add up all values of an array +::: + +## A melody as an array + +A melody is a row of tones. Instead of five variables \`tone1\`, \`tone2\`, … you use an **array**. An array is a row of slots under **one** name: + +\`\`\`java +int[] tones = {262, 294, 330, 349, 392}; +\`\`\` + +- \`int[]\` means: an array of whole numbers. +- The slots are numbered from **0**. \`tones[0]\` is 262, \`tones[4]\` is 392. +- \`tones.length\` tells you how many slots there are, here 5. + +A for loop with \`i\` from 0 to \`tones.length - 1\` reaches every slot. + +::: übung vb-melodie +titel: Melody +auftrag: Create an array \`tones\` with the pitches 262, 294, 330, 349 and 392. A for loop plays them one after the other, each for 300 milliseconds. +befehle: playTone 262 300, playTone 294 300, playTone 330 300, playTone 349 300, playTone 392 300 +braucht: forSchleife +tipp: \`int[] tones = {262, 294, 330, 349, 392}\` creates the array. +tipp: The loop runs from \`i = 0\` while \`i < tones.length\`. Inside is \`mbot.playTone(tones[i], 300)\`. +lösung: vb-melodie-loesung.visustruct +::: + +> If you want a different melody, you only change the array. The loop stays the same. + +## Now in Java: rainbow + +The five LEDs have the numbers 0 to 4, just like the slots of an array with five values. An array can hold texts too: \`String[] colours = {"red", "yellow"};\`. LED \`i\` then gets the colour from slot \`i\`: \`mbot.led(i).setColor(colours[i])\`. + +::: übung vb-farben +titel: Rainbow +code: java +auftrag: Write in Java: create an array \`colours\` with the texts \`"red"\`, \`"yellow"\`, \`"green"\`, \`"blue"\` and \`"purple"\`. A for loop gives every LED \`i\` the colour from \`colours[i]\`. +befehle: ledColor 0 "red", ledColor 1 "yellow", ledColor 2 "green", ledColor 3 "blue", ledColor 4 "purple" +braucht: forSchleife +tipp: \`String[] colours = {"red", "yellow", "green", "blue", "purple"};\` creates the array. +tipp: \`for (int i = 0; i < colours.length; i++) { mbot.led(i).setColor(colours[i]); }\` +lösung: vb-farben-loesung.visustruct +::: + +## Now without the robot: sum of the grades + +With a loop you can also add up all the values of an array. You need a variable that starts at 0 and grows in every round: + +\`\`\`java +int sum = 0; +for (int i = 0; i < grades.length; i++) { + sum = sum + grades[i]; +} +\`\`\` + +::: übung vb-ohne-summe +titel: Sum of the grades +code: java +auftrag: Create \`int[] grades = {2, 1, 3, 2}\`. Add up all grades in a loop and then print **Sum: 8** and on a second line **Count: 4**. The count comes from \`grades.length\`. No \`mbot\` at all! +test: - -> Sum: 8 | Count: 4 +braucht: forSchleife +tipp: Before the loop \`int sum = 0;\`, inside the loop \`sum = sum + grades[i];\`. +tipp: After the loop \`System.out.println("Sum: " + sum);\` and \`System.out.println("Count: " + grades.length);\`. +lösung: vb-ohne-summe-loesung.visustruct +::: + +::: quiz +? What is \`tones[1]\` if \`int[] tones = {262, 294, 330};\`? +→ A melody as an array +- [ ] 262 +- [x] 294 +- [ ] 1 +> The slots count from 0. So slot 1 is the second one. +? How many slots does \`{262, 294, 330}\` have, so what is \`tones.length\`? +→ A melody as an array +- [ ] 2 +- [x] 3 +- [ ] 330 +> \`length\` counts the slots, here three. That is why the last slot has the number 2. +::: + +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. + +::: checkliste +- I can create an array and play it with a loop. → A melody as an array +- I can use an array of texts in Java. → Now in Java: rainbow +- I can add up all values of an array. → Now without the robot: sum of the grades +::: +`,Cw=`--- +titel: The screen +bereich: VisuBot +kurz: Show text, numbers and sensor values on the CyberPi. +--- + +## Skills I will gain now + +::: kompetenzen +- show text on the screen +- show several texts one after the other +- show numbers and sensor values +- write a countdown in Java +::: + +## Showing text + +::: mbot2 +focus: screen +view: back +::: + +The CyberPi's colour [screen]{part=screen} is an actuator too. With **show text** you write something on it: + +\`\`\`java +mbot.showText("Hello!") +\`\`\` + +The text is in quotation marks, as with \`System.out.println\`. A new text replaces the old one. + +> In the simulation the text appears on the screen of the 3D model and below the world after 📺. + +## Greeting in the structure chart + +::: übung vb-begruessung +titel: Greeting +auftrag: The mBot2 first shows “Hello!”, waits 1000 milliseconds and then shows “I am VisuBot”. +befehle: showText "Hello!", pause 1000, showText "I am VisuBot" +tipp: Drag **show text** twice and **wait a moment** once into the structure chart. +tipp: \`mbot.showText("Hello!")\`, \`mbot.pause(1000)\`, \`mbot.showText("I am VisuBot")\`. +lösung: vb-begruessung-loesung.visustruct +::: + +## Numbers and sensor values + +Instead of text you can also show numbers and variables, and with \`+\` you join everything together: + +\`\`\`java +mbot.showText(i) +mbot.showText("Distance: " + mbot.getDistance()) +\`\`\` + +That way the mBot2 shows you what its sensors are measuring right now. + +## Now in Java: countdown + +::: übung vb-java-countdown +titel: Countdown +code: java +auftrag: Write a countdown in Java: a for loop counts \`i\` backwards from 3 to 1. In each round the mBot2 shows \`i\` and waits 1000 milliseconds. After that it shows “Go!”. +befehle: showText "3", pause 1000, showText "2", pause 1000, showText "1", pause 1000, showText "Go!" +braucht: forSchleife +tipp: Counting backwards: \`for (int i = 3; i >= 1; i--) { … }\` +tipp: Inside the loop: \`mbot.showText(i);\` and \`mbot.pause(1000);\`. After the loop \`mbot.showText("Go!");\`. +lösung: vb-java-countdown-loesung.visustruct +::: + +::: quiz +? What does \`mbot.showText("Distance: " + 25)\` show? +→ Numbers and sensor values +- [x] Distance: 25 +- [ ] "Distance: " + 25 +- [ ] 25 +> The \`+\` adds the number to the text. +? What happens to the old text when you show a new one? +→ Showing text +- [x] It is replaced. +- [ ] The new one appears below it. +::: + +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. + +::: checkliste +- I can show text on the screen. → Showing text +- I can show several texts one after the other. → Greeting in the structure chart +- I can show numbers and sensor values. → Numbers and sensor values +- I can write a countdown in Java. → Now in Java: countdown +::: +`,jw=`--- +titel: Strings +bereich: VisuBot +kurz: Work with texts, pick out letters and show them on the screen. +--- + +## Skills I will gain now + +::: kompetenzen +- work with \`length()\` and \`substring(…)\` +- join texts and numbers with \`+\` +- get single characters with \`charAt(…)\` +::: + +## Letter by letter + +In Java a text is called a **string** or \`String\`. It consists of single characters, numbered from **0** just like an array: + +| Character | V | i | s | u | B | o | t | +|---|---|---|---|---|---|---|---| +| Number | 0 | 1 | 2 | 3 | 4 | 5 | 6 | + +- \`word.length()\` gives the number of characters, here 7. +- \`word.substring(0, 3)\` gives the first 3 characters: \`"Vis"\`. + +The mBot2 should build its name on the [screen]{part=screen}: first **V**, then **Vi**, then **Vis** and so on up to **VisuBot**. + +::: übung vb-buchstaben +titel: Build the name +auftrag: Create \`String word = "VisuBot"\`. A for loop counts \`i\` from 1 to \`word.length()\`. Inside, the mBot2 shows \`word.substring(0, i)\` and waits 300 milliseconds. +befehle: showText "V", pause 300, showText "Vi", pause 300, showText "Vis", pause 300, showText "Visu", pause 300, showText "VisuB", pause 300, showText "VisuBo", pause 300, showText "VisuBot", pause 300 +braucht: forSchleife +tipp: The loop starts at \`int i = 1\` and runs as long as \`i <= word.length()\`. +tipp: Inside the loop: \`mbot.showText(word.substring(0, i))\` and \`mbot.pause(300)\`. +lösung: vb-buchstaben-loesung.visustruct +::: + +## Now in Java: text and length + +With \`+\` you join texts and numbers. This way the mBot2 shows a text followed by its length. + +::: übung vb-java-textlaenge +titel: How long is the text? +code: java +auftrag: Write in Java: create \`String text = "Hello class"\`. The mBot2 shows the text and its length in brackets, so **Hello class (11)**. +befehle: showText "Hello class (11)" +tipp: \`text.length()\` gives the length. The space counts too. +tipp: \`mbot.showText(text + " (" + text.length() + ")");\` +lösung: vb-java-textlaenge-loesung.visustruct +::: + +## Now without the robot: read it backwards + +\`word.charAt(i)\` gives the character with the number \`i\`. If you put every character at the **front** of a new text, the word ends up backwards: + +| Round | Character | new text | +|---|---|---| +| 1 | L | L | +| 2 | u | uL | +| 3 | d | duL | + +::: übung vb-ohne-rueckwaerts +titel: Ludwig backwards +code: java +auftrag: Create \`String word = "Ludwig"\` and \`String backwards = ""\`. A loop puts every character of \`word\` at the front of \`backwards\`. Finally you print **giwduL**. No \`mbot\` at all! +test: - -> giwduL +braucht: forSchleife +tipp: The loop runs from \`i = 0\` while \`i < word.length()\`. +tipp: Inside the loop: \`backwards = word.charAt(i) + backwards;\`. After the loop: \`System.out.println(backwards);\`. +lösung: vb-ohne-rueckwaerts-loesung.visustruct +::: + +::: quiz +? What does \`"VisuBot".substring(0, 4)\` give? +→ Letter by letter +- [ ] \`"VisuB"\` +- [x] \`"Visu"\` +- [ ] \`"uBot"\` +> \`substring(0, 4)\` takes the characters 0, 1, 2 and 3, so four of them. +? What does \`"Ludwig".charAt(0)\` give? +→ Now without the robot: read it backwards +- [x] \`L\` +- [ ] \`u\` +- [ ] \`g\` +> Characters are counted from 0. Character 0 is the first one. +::: + +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. + +::: checkliste +- I can work with \`length()\` and \`substring(…)\`. → Letter by letter +- I can join texts and numbers with \`+\`. → Now in Java: text and length +- I can get single characters with \`charAt(…)\`. → Now without the robot: read it backwards +::: +`,Pw=`--- +titel: Motors and speed +bereich: VisuBot +kurz: Step on the gas, steer and follow a line. +--- + +## Skills I will gain now + +::: kompetenzen +- step on the gas with wheels separately and stop +- drive until a sensor reports something +- write a line follower in Java +::: + +## Two motors, two wheels + +::: mbot2 +focus: motors, wheels +view: bottom +::: + +The mBot2 has two [motors]{part=motors}, each drives one [wheel]{part=wheels}. So far you have used **move forward** and **turn right**. These commands drive a fixed distance and wait until the mBot2 has arrived. + +With **wheels separately** (\`mbot.drive(left, right)\`) you step on the gas instead: you say how strongly each wheel turns, in percent from −100 to 100. The mBot2 then **keeps going** until you tell it something else. With **stop** (\`mbot.stop()\`) it stops. + +| Command | What happens? | +|---|---| +| \`mbot.drive(40, 40)\` | both wheels equally fast: straight ahead | +| \`mbot.drive(-40, -40)\` | backwards | +| \`mbot.drive(10, 40)\` | right faster: curve to the left | +| \`mbot.drive(40, -40)\` | wheels against each other: turns right on the spot | +| \`mbot.stop()\` | stop | + +> In the simulator \`mbot.drive(100, 100)\` drives 20 cm per second. Try it in the [simulation](#zeige-simulation). + +## Full speed to the wall in the structure chart + +In lesson 5 the mBot2 drove to the wall in steps of 10 cm. With **wheels separately** it works without jerking: step on the gas once, wait until the wall is close, then stop. + +::: übung vb-gas-bis-wand +titel: Full speed to the wall +auftrag: The mBot2 steps on the gas with 50 %. As long as the wall is more than 15 cm away, it waits a moment. Then it stops. There are three worlds. +welt: wand-kurz, wand-mittel, wand-lang +braucht: whileSchleife +tipp: At the top is \`mbot.drive(50, 50)\`. Below it a while loop with the condition \`mbot.getDistance() > 15\`. +tipp: Inside the loop is only **wait a moment**. The mBot2 keeps driving meanwhile! After the loop is **stop**. +lösung: vb-gas-bis-wand-loesung.visustruct +::: + +## The line follower + +::: mbot2 +focus: lineSensor +view: bottom +::: + +A classic: the mBot2 follows a black line on the floor. For this it looks at the two middle probes of the [line sensor]{part=lineSensor}: + +| Sensor | Text | +|---|---| +| left middle probe sees black | \`mbot.isLineLeft()\` | +| right middle probe sees black | \`mbot.isLineRight()\` | + +The idea: if **both** see the line, it drives straight ahead. If only the **left** one sees it, the line has moved to the left: it steers left, so the right wheel turns faster. If only the **right** one sees it, it steers right. + +## Now in Java: line follower + +::: übung vb-java-linienfolger +titel: Line follower +code: java +auftrag: Write a line follower in Java. As long as the wall is more than 15 cm away, the mBot2 checks its two probes and steers. Then it stops. In the first world the line bends to the right, in the second to the left. +welt: linie-1, linie-2 +braucht: whileSchleife, verzweigung +tipp: \`while (mbot.getDistance() > 15) { … }\` and after it \`mbot.stop();\`. +tipp: Inside the loop: \`if (mbot.isLineLeft() && mbot.isLineRight()) { mbot.drive(40, 40); } else if (mbot.isLineLeft()) { mbot.drive(10, 40); } else if (mbot.isLineRight()) { mbot.drive(40, 10); }\` +lösung: vb-java-linienfolger-loesung.visustruct +::: + +> For the real mBot2, stick the line with black insulating tape on a light floor. Drive slowly at first, otherwise it shoots past the line in the curve. + +::: quiz +? What does \`mbot.drive(30, 30)\` do? +→ Two motors, two wheels +- [ ] It drives 30 cm and stops. +- [x] It drives straight ahead and does not stop until another driving command comes. +- [ ] It turns by 30°. +> **wheels separately** only steps on the gas. You have to stop it yourself. +? The mBot2 should steer to the right. Which command fits? +→ Two motors, two wheels +- [ ] \`mbot.drive(10, 40)\` +- [x] \`mbot.drive(40, 10)\` +- [ ] \`mbot.drive(-40, -40)\` +> If the left wheel turns faster, it drives a right curve. +::: + +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. + +::: checkliste +- I can step on the gas with wheels separately and stop. → Two motors, two wheels +- I can drive until a sensor reports something. → Full speed to the wall in the structure chart +- I can write a line follower in Java. → Now in Java: line follower +::: +`,Dw=`--- +titel: Stopwatch and battery +bereich: VisuBot +kurz: Measure time and keep an eye on the battery. +--- + +## Skills I will gain now + +::: kompetenzen +- reset the stopwatch and read it +- drive for a certain time +- show the battery level +::: + +## The stopwatch + +::: mbot2 +focus: cyberpi +view: top +::: + +A stopwatch runs inside the [CyberPi]{part=cyberpi}. It counts the seconds since the program started. With **reset stopwatch** (\`mbot.resetTimer()\`) it starts again at 0. + +| Sensor or command | Text | Value | +|---|---|---| +| reset stopwatch | \`mbot.resetTimer()\` | | +| stopwatch | \`mbot.getTimer()\` | seconds with a decimal place, e.g. \`1.5\` | + +This is how you drive for a certain time: reset the stopwatch, step on the gas, wait as long as the stopwatch is not far enough yet, stop. + +## Driving two seconds in the structure chart + +::: übung vb-zwei-sekunden +titel: Two seconds +auftrag: The mBot2 resets the stopwatch and steps on the gas with 50 %. As long as the stopwatch is below 2 seconds, it waits a moment. Then it stops. With 50 % it manages 10 cm per second, so it must stop 20 cm further on. +welt: zeit-1 +braucht: whileSchleife +tipp: At the top are **reset stopwatch** and \`mbot.drive(50, 50)\`. Below it a while loop with \`mbot.getTimer() < 2\`. +tipp: Inside the loop is **wait a moment**, after the loop **stop**. +lösung: vb-zwei-sekunden-loesung.visustruct +::: + +## The battery + +::: mbot2 +focus: shield +view: top +::: + +Under the transparent [shield]{part=shield} you see the battery. How full it is comes from \`mbot.getBattery()\` in percent: \`100\` is completely full. When it is almost empty, the motors get weaker. Then it is time to charge. + +::: angeberwissen +Your phone does not measure its battery directly in percent either. It measures the voltage: a full lithium battery has a little over 4 volts, an empty one just over 3. From that it calculates the percentage, just like the CyberPi. +::: + +## Now in Java: battery display + +::: übung vb-java-akku +titel: Battery display +code: java +auftrag: Write in Java: the mBot2 shows for example **Battery: 80 %** on the screen. If the battery is below 20 %, the LEDs also light up red. +messwerte: getBattery=80 -> none, ledOff, screen "Battery: 80 %" +messwerte: getBattery=15 -> none, ledOn, screen "Battery: 15 %" +braucht: verzweigung +tipp: \`mbot.showText("Battery: " + mbot.getBattery() + " %");\` puts the text together from three parts. +tipp: After it: \`if (mbot.getBattery() < 20) { mbot.setLed(255, 0, 0); }\` +lösung: vb-java-akku-loesung.visustruct +::: + +::: quiz +? What does \`mbot.getTimer()\` give right after \`mbot.resetTimer()\`? +→ The stopwatch +- [x] 0 +- [ ] 100 +- [ ] The time of day +> The stopwatch starts again at 0. +? Why does the mBot2 only wait **a moment** in the loop instead of stopping? +→ Driving two seconds in the structure chart +- [ ] Because otherwise the loop does not start. +- [x] Because it should keep driving until the time is up. +- [ ] Because otherwise the stopwatch stops. +> Stepping on the gas still applies while it waits. +::: + +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. + +::: checkliste +- I can reset the stopwatch and read it. → The stopwatch +- I can drive for a certain time. → Driving two seconds in the structure chart +- I can show the battery level. → Now in Java: battery display +::: +`,Bw=`--- +titel: Your own methods +bereich: VisuBot +kurz: Write and call your own commands with parameters and return values. +--- + +## Skills I will gain now + +::: kompetenzen +- build and call a subprogram with a parameter +- recognise methods in Java +- write a method with a return value +::: + +## A subprogram for the square + +The mBot2 can already drive a square. Now it should drive two squares of different sizes. Instead of building the loop twice, you write a **subprogram**. In Java it is called a **method**. It is a command of your own that you can call as often as you like. + +The header \`void square(int side)\` says: + +- \`void\`: the method gives no result back, it only **does** something. +- \`square\`: that is the name of your new command. +- \`int side\`: when you call it, you pass a number, the **parameter**. + +::: übung vb-quadrat-methode +titel: Two squares +auftrag: Build a subprogram \`void square(int side)\` that drives a square with side length \`side\`. The main program calls it twice: first with 30, then with 50. +fahrt: 4 x (forward 30, turnRight), 4 x (forward 50, turnRight) +braucht: aufruf +tipp: Create a new tab with **+** and give it the title \`void square(int side)\`. Inside is a for loop that runs \`mbot.forward(side)\` and \`mbot.turnRight()\` four times. +tipp: The main program contains two call boxes: \`square(30)\` and \`square(50)\`. +lösung: vb-quadrat-methode-loesung.visustruct +unterprogramm: vb-quadrat-unterprogramm-loesung.visustruct +::: + +## Methods in Java + +In Java every method lives in a class. The program always starts in the method \`main\`. From there \`square\` is called: + +\`\`\`java +public class Squares { + public static void main(String[] args) { + square(30); + square(50); + } + + static void square(int side) { + for (int i = 0; i < 4; i++) { + mbot.forward(side); + mbot.turnRight(); + } + } +} +\`\`\` + +In [Code](#zeige-codelive) you see each method in its own tab, just like in the structogram. + +::: quiz +? What does \`void\` mean in \`void square(int side)\`? +→ Methods in Java +- [ ] The method has no parameter. +- [x] The method gives no result back. +- [ ] The method may only be called once. +> \`void\` means "empty": no value comes back. The parameter is in the brackets. +? With which value for \`side\` does \`square(50)\` run? +→ A subprogram for the square +- [ ] 30 +- [x] 50 +- [ ] with none +> The value in the brackets of the call becomes the parameter \`side\`. +::: + +## Now without the robot: a method with a return value + +A method can also **calculate** something and give the result back. Instead of \`void\`, the header then names the data type of the result, and \`return\` gives the value back: + +\`\`\`java +static int twice(int x) { + return 2 * x; +} +\`\`\` + +The call \`int d = twice(4);\` then puts 8 into \`d\`. + +::: übung vb-ohne-quadratzahl +titel: Square numbers +auftrag: Build a subprogram \`int squareNumber(int x)\` that returns \`x * x\`. The main program calls it with 3 and with 5 and prints both results: first **9**, then **25**. No \`mbot\` at all! +test: - -> 9 | 25 +braucht: aufruf +tipp: New tab with the title \`int squareNumber(int x)\`. One statement is enough inside: \`return x * x\`. +tipp: In the main program: call \`int a = squareNumber(3)\`, call \`int b = squareNumber(5)\`, then the outputs \`a\` and \`b\`. +lösung: vb-ohne-quadratzahl-loesung.visustruct +unterprogramm: vb-ohne-quadratzahl-unterprogramm-loesung.visustruct +::: + +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. + +::: checkliste +- I can build and call a subprogram with a parameter. → A subprogram for the square +- I can recognise methods in Java. → Methods in Java +- I can write a method with a return value. → Now without the robot: a method with a return value +::: +`,Mw=`## 🤖 mBot2 commands + +A command tells the mBot2 what to **do**. Every command starts with \`mbot.\` and ends with brackets. Often you write a number in the brackets. + +### Driving and turning + +The mBot2 drives straight or turns on the spot. + +\`\`\` +mbot.forward() drives 10 cm forward +mbot.forward(30) drives 30 cm forward +mbot.backward(20) drives 20 cm back +mbot.turnRight() turns to the right (90°) +mbot.turnLeft() turns to the left (90°) +mbot.turnLeft(45) turns just a little to the left (45°) +mbot.turnRight(180) turns all the way round +\`\`\` + +> Without a number it drives 10 cm or turns 90°. 90° is a right angle, like the corner of a sheet of paper. + +> For a polygon it turns all the way round once in total: triangle 3 × 120°, square 4 × 90°, hexagon 6 × 60°. + +### Wheels separately + +Here you give each wheel gas yourself. The numbers are percent: 100 is full gas, 0 is standing still, a number with a minus drives backwards. The mBot2 keeps going until another driving command comes. + +\`\`\` +mbot.drive(40, 40) both wheels the same: straight ahead +mbot.drive(10, 40) left slower: curve to the left +mbot.drive(40, -40) one wheel forward, one back: it turns +mbot.stop() stops +\`\`\` + +### Light, sound and screen + +The mBot2 can light up, beep and show text. + +\`\`\` +mbot.setLed(255, 0, 0) all LEDs light up red +mbot.ledOff() all LEDs off +mbot.led(0).setColor("green") only LED 0 lights up green +mbot.led(0).setColor("off") only LED 0 off +mbot.playTone(440, 300) plays a tone +mbot.showText("Hello") shows Hello on the screen +\`\`\` + +- **LEDs:** There are five LEDs with the numbers 0 to 4. With \`setLed\` you mix red, green and blue, each from 0 (off) to 255 (very bright). +- **Tone:** The first number is the pitch. The bigger, the higher. The second number is the length in milliseconds (1000 milliseconds are 1 second). +- **Screen:** With \`+\` you join text and numbers: \`mbot.showText("Distance: " + mbot.getDistance())\`. + +### Emotions + +The mBot2 shows a feeling with light, sound and wiggling. You only see it on the real mBot2. + +\`\`\` +mbot.emotion("smile") laughs +mbot.emotion("sad") is sad +mbot.emotion("wow") is amazed +\`\`\` + +More feelings: hello, yeah, proud, yummy, naughty, uh_oh, hurt, angry, startle, shiver, dizzy, sleepy, zzz, wake_up, blink, yes, no, look_up, look_down, look_left, look_right, look_around + +### Waiting and stopwatch + +\`\`\` +mbot.pause(1000) waits 1 second +mbot.resetTimer() sets the stopwatch to 0 +\`\`\` + +You read the stopwatch time with the sensor \`mbot.getTimer()\` (below under **Stopwatch and battery**). + +## 📡 mBot2 sensors + +A sensor **measures** something and gives you a value back. You use the value in a condition, for example in a loop or a branch. Some sensors give a **number**, some **true or false**, one gives a **text**. + +### Distance + +The ultrasonic sensor at the front measures how far away the next wall is, in centimetres. + +\`\`\` +mbot.getDistance() distance in cm, e.g. 25 +mbot.getDistance() > 15 is there more than 15 cm free ahead? +int distance = mbot.getDistance() remember the distance in a variable +\`\`\` + +### Line + +Under the mBot2 there are four probes. They see whether the floor is black. + +\`\`\` +mbot.getLine() number: 0 means no probe sees black +mbot.getLine() == 0 no black, keep driving +mbot.getLine() != 0 a probe sees black +mbot.isLineLeft() does the left middle probe see black? +mbot.isLineRight() does the right middle probe see black? +\`\`\` + +### Colours + +The same sensor underneath also recognises colours. \`mbot.getColor()\` gives you the name of the colour as text: \`"red"\`, \`"green"\`, \`"blue"\`, \`"yellow"\`, \`"white"\` or \`"black"\`. + +\`\`\` +mbot.getColor().equals("red") is it standing on red? +!mbot.getColor().equals("red") is it not standing on red? +\`\`\` + +> You compare texts with \`.equals(…)\`, not with \`==\`. The \`!\` in front means **not**. + +### Buttons and joystick + +On the CyberPi there are the buttons A and B and a small joystick. Each sensor says **true** while it is being pressed. + +\`\`\` +mbot.isButtonA() is button A pressed? +mbot.isButtonB() is button B pressed? +mbot.isJoystickUp() joystick pushed up? +mbot.isJoystickDown() joystick pushed down? +mbot.isJoystickLeft() joystick pushed left? +mbot.isJoystickRight() joystick pushed right? +\`\`\` + +### Light and loudness + +\`\`\` +mbot.getBrightness() how bright? 0 is dark, 100 is bright +mbot.getLoudness() how loud? 0 is silent, 100 is loud +\`\`\` + +### Tilt and shaking + +\`\`\` +mbot.getPitch() tipped forward or back? (in degrees) +mbot.getRoll() tipped to the side? (in degrees) +mbot.isShaken() is it being shaken? +\`\`\` + +> When the mBot2 lies flat, both tilts are 0. In the simulation you set these values under **🎛 Try the sensors**. + +### Stopwatch and battery + +\`\`\` +mbot.getTimer() seconds since the start or since resetTimer() +mbot.getBattery() how full is the battery? (in percent) +\`\`\` + +### Real mBot2 + +With **🔌 mBot2** next to "Start simulation" you connect the real robot with the USB cable. This only works in Chrome or Edge. Then it drives every step of the simulation along, and the sensors measure real values. A second click disconnects it again. + +### Driving without a cable + +With **⬆ Upload** you save your program on the mBot2. Then unplug the cable, put the mBot2 at the start and press **button A**: it drives your program on its own. It stays saved until you upload a new one. Keyboard inputs do not work on the mBot2. +`,Zw=`--- +titel: Die Alarmanlage +nach: 16 +stufe: 2 +--- + +Der mBot2 bewacht dein Zimmer. Kommt jemand näher als 20 cm **oder** wird es laut (Lautstärke über 60), schlägt er Alarm: Die LEDs leuchten rot und er piept. Sonst sind die LEDs aus. Mit Taste B schaltest du die Alarmanlage ab. + +::: übung vb-alarmanlage +titel: Die Alarmanlage +auftrag: Solange Taste B nicht gedrückt ist, prüft der mBot2 immer wieder: Ist der Abstand unter 20 cm oder die Lautstärke über 60, leuchten die LEDs rot und er spielt einen Ton. Sonst gehen die LEDs aus. Danach wartet er kurz. +messwerte: getDistance=10, isButtonB=false/true -> none, tone +messwerte: getLoudness=80, isButtonB=false/true -> none, tone +messwerte: getDistance=100, getLoudness=0, isButtonB=false/true -> none, noTone, ledOff +braucht: whileSchleife, verzweigung +tipp: Außen steht eine While-Schleife mit \`!mbot.isButtonB()\`. Darin eine Verzweigung und danach **kurz warten**. +tipp: Die Bedingung der Verzweigung: \`mbot.getDistance() < 20 || mbot.getLoudness() > 60\`. Im Ja-Zweig \`mbot.setLed(255, 0, 0)\` und \`mbot.playTone(880, 200)\`, im Nein-Zweig \`mbot.ledOff()\`. +lösung: vb-alarmanlage-loesung.visustruct +::: +`,Lw=`--- +titel: Labyrinth mit Ausgängen +nach: 5 +stufe: 3 +--- + +Der mBot2 steht unten links und schaut nach rechts. Über ihm liegen Wandreihen. Jede hat genau eine Lücke, und jede Lücke liegt weiter rechts als die darunter. Ganz oben ist das Ziel. + +Der mBot2 fährt nach rechts und schaut in jedem Feld nach oben. Ist dort eine Lücke, fährt er hindurch in den nächsten Gang. + +::: übung vb-ausgang +titel: Labyrinth mit Ausgängen +auftrag: Programmiere den mBot2 so, dass er in beiden Welten durch alle Lücken bis zum Ziel fährt, ohne anzustoßen. Ein Feld ist 30 cm groß. +welt: ausgang-1, ausgang-2 +braucht: whileSchleife, verzweigung +tipp: In jedem Durchlauf dreht sich der mBot2 zuerst nach links und misst. Ist oben frei, sind es mehr als 20 cm. +tipp: Durch die Lücke sind es zwei Felder bis in den nächsten Gang. Danach soll er wieder nach rechts schauen. Ist oben eine Wand, dreht er sich zurück und fährt ein Feld weiter. +lösung: vb-ausgang-loesung.visustruct +::: +`,Ew=`--- +titel: Binär zählen +nach: 15 +stufe: 3 +--- + +Computer rechnen mit nur zwei Ziffern: 0 und 1. Das heißt **binär**. Mit drei LEDs kannst du die Zahlen 0 bis 7 binär zeigen: LED 0 zählt 1, LED 1 zählt 2 und LED 2 zählt 4. Die Zahl 5 ist 4 + 1, also leuchten LED 2 und LED 0. + +| Zahl | LED 2 (4) | LED 1 (2) | LED 0 (1) | +|---|---|---|---| +| 0 | aus | aus | aus | +| 1 | aus | aus | an | +| 2 | aus | an | aus | +| 3 | aus | an | an | +| 5 | an | aus | an | + +::: übung vb-binaer-zaehlen +titel: Binär zählen +auftrag: Eine For-Schleife zählt \`zahl\` von 0 bis 7. Für jede Zahl leuchtet jede der LEDs 0, 1 und 2 grün oder ist aus, genau wie in der Tabelle. Danach wartet der mBot2 1000 Millisekunden. Schalte die LEDs immer in der Reihenfolge 0, 1, 2. +befehle: ledColor 0 "aus", ledColor 1 "aus", ledColor 2 "aus", pause 1000, ledColor 0 "grün", ledColor 1 "aus", ledColor 2 "aus", pause 1000, ledColor 0 "aus", ledColor 1 "grün", ledColor 2 "aus", pause 1000, ledColor 0 "grün", ledColor 1 "grün", ledColor 2 "aus", pause 1000, ledColor 0 "aus", ledColor 1 "aus", ledColor 2 "grün", pause 1000, ledColor 0 "grün", ledColor 1 "aus", ledColor 2 "grün", pause 1000, ledColor 0 "aus", ledColor 1 "grün", ledColor 2 "grün", pause 1000, ledColor 0 "grün", ledColor 1 "grün", ledColor 2 "grün", pause 1000 +braucht: forSchleife, verzweigung +tipp: Ob LED 0 an ist, verrät der Rest beim Teilen durch 2: \`zahl % 2 == 1\`. Für LED 1 teilst du erst durch 2: \`zahl / 2 % 2 == 1\`. Für LED 2 durch 4: \`zahl / 4 % 2 == 1\`. +tipp: In der Schleife stehen drei Verzweigungen und danach **kurz warten**. Im Ja-Zweig zum Beispiel \`mbot.led(0).setColor("grün")\`, im Nein-Zweig \`mbot.led(0).setColor("aus")\`. +lösung: vb-binaer-zaehlen-loesung.visustruct +::: +`,Ww=`--- +titel: Das Dreieck +nach: 2 +stufe: 1 +--- + +Beim Quadrat dreht sich der mBot2 viermal um 90°. Zusammen sind das 360°, eine ganze Runde. Bei einem Dreieck dreht er sich auch einmal ganz herum, aber nur in drei Ecken. + +In die Klammer von **drehe rechts** kannst du schreiben, wie weit er sich drehen soll: \`mbot.turnRight(45)\` dreht nur 45°. + +::: übung vb-dreieck +titel: Das Dreieck +auftrag: Lass den mBot2 ein Dreieck mit drei gleich langen Seiten fahren. Jede Seite ist 30 cm lang. Benutze eine Schleife. +fahrt: 3 x (forward 30, turnRight 120) +braucht: forSchleife +tipp: Wie viel Grad muss eine Ecke sein, damit drei Ecken zusammen eine ganze Runde (360°) ergeben? +tipp: In der Schleife fährt der mBot2 eine Seite und dreht sich dann um 120°. +lösung: vb-dreieck-loesung.visustruct +::: + +::: angeberwissen +Die Idee, mit einem fahrenden Roboter Figuren zu zeichnen, ist über 50 Jahre alt: Ende der 1960er-Jahre entstand die Sprache **Logo**. Kinder steuerten damit eine „Schildkröte“, die mit einem Stift über das Papier fuhr. +::: +`,Nw=`--- +titel: Rückwärts einparken +nach: 16 +stufe: 2 +--- + +Rechts von der Straße parken Autos (die Klötze). Irgendwo ist eine Lücke, und genau davor klebt eine blaue Markierung auf der Straße. Der mBot2 sucht die Lücke und parkt rückwärts ein, wie ein Auto. + +Hinten hat er keinen Sensor. Er schaut deshalb nach vorn auf die Wand gegenüber: Je weiter er rückwärts in die Lücke fährt, desto größer wird der Abstand dorthin. + +::: übung vb-einparken +titel: Rückwärts einparken +auftrag: Der mBot2 fährt in 10-cm-Schritten vor, bis er auf Blau steht. Dann dreht er sich nach links, sodass sein Heck zur Lücke zeigt. Er fährt rückwärts, solange der Abstand zur Wand vor ihm unter 45 cm ist. Zum Schluss leuchten die LEDs grün und er zeigt **Geparkt!**. Es gibt zwei Straßen mit verschiedenen Lücken. +welt: parken-1 -> ledOn, screen "Geparkt!" +welt: parken-2 -> ledOn, screen "Geparkt!" +braucht: whileSchleife +tipp: Zwei While-Schleifen hintereinander: erst \`!mbot.getColor().equals("blau")\` mit \`mbot.forward()\` darin, dann \`mbot.getDistance() < 45\` mit \`mbot.backward()\` darin. Dazwischen steht \`mbot.turnLeft()\`. +tipp: Am Ende: \`mbot.setLed(0, 255, 0)\` und \`mbot.showText("Geparkt!")\`. +lösung: vb-einparken-loesung.visustruct +::: +`,Fw='---\ntitel: Hindernis ausweichen\nnach: 16\nstufe: 2\n---\n\nAuf dem Weg zum roten Feld stehen Klötze im Weg. Der mBot2 fährt in 10-cm-Schritten vor. Taucht ein Klotz auf (näher als 20 cm), warnt er mit Licht und Ton und fährt außen herum: nach rechts drehen, 30 cm vor, nach links drehen. Dann geht es weiter geradeaus.\n\n::: übung vb-hindernis\ntitel: Hindernis ausweichen\nauftrag: Der mBot2 fährt, solange er nicht auf Rot steht. Ist ein Klotz näher als 20 cm, leuchten die LEDs orange (`mbot.setLed(255, 128, 0)`), er piept und weicht aus. Danach gehen die LEDs aus. Sonst fährt er 10 cm vor. Es gibt zwei Welten.\nwelt: hindernis-1 -> tone\nwelt: hindernis-2 -> tone\nbraucht: whileSchleife, verzweigung\ntipp: Außen eine While-Schleife mit `!mbot.getColor().equals("rot")`, darin eine Verzweigung mit `mbot.getDistance() < 20`.\ntipp: Im Ja-Zweig: `mbot.setLed(255, 128, 0)`, `mbot.playTone(880, 200)`, `mbot.turnRight()`, `mbot.forward(30)`, `mbot.turnLeft()`, `mbot.ledOff()`. Im Nein-Zweig: `mbot.forward()`.\nlösung: vb-hindernis-loesung.visustruct\n:::\n',Jw=`--- +titel: Knight Rider +nach: 15 +stufe: 2 +--- + +In der Fernsehserie „Knight Rider“ hat das sprechende Auto KITT vorn ein rotes Licht, das immer hin und her läuft. Das baust du mit den fünf LEDs nach. + +::: übung vb-knight-rider +titel: Knight Rider +auftrag: Ein rotes Licht läuft von LED 0 bis LED 4 und wieder zurück bis LED 1. Jede LED leuchtet 100 Millisekunden und geht dann aus. Benutze zwei For-Schleifen: eine zählt hoch, eine zählt runter. +befehle: ledColor 0 "rot", pause 100, ledColor 0 "aus", ledColor 1 "rot", pause 100, ledColor 1 "aus", ledColor 2 "rot", pause 100, ledColor 2 "aus", ledColor 3 "rot", pause 100, ledColor 3 "aus", ledColor 4 "rot", pause 100, ledColor 4 "aus", ledColor 3 "rot", pause 100, ledColor 3 "aus", ledColor 2 "rot", pause 100, ledColor 2 "aus", ledColor 1 "rot", pause 100, ledColor 1 "aus" +braucht: forSchleife +tipp: Die erste Schleife zählt \`i\` von 0 bis 4 hoch. Die zweite startet bei 3 und zählt mit \`i--\` runter, solange \`i > 0\`. +tipp: In beiden Schleifen: \`mbot.led(i).setColor("rot")\`, \`mbot.pause(100)\`, \`mbot.led(i).setColor("aus")\`. +lösung: vb-knight-rider-loesung.visustruct +::: +`,Rw=`--- +titel: Das Labyrinth +nach: 5 +stufe: 2 +--- + +Der mBot2 steht in einem Labyrinth. Das Ziel ist ein schwarzes Feld mit grüner Fahne. Die Gänge sind 30 cm breit. + +Eine einfache Regel bringt ihn hindurch: **Ist vorn frei, fahr vor. Sonst dreh dich nach rechts. Ist dort auch eine Wand, dreh dich ganz um.** + +Woran merkt der mBot2, dass er im Ziel ist? Der Liniensensor unten sieht das schwarze Feld: \`mbot.getLine()\` ist dann nicht mehr \`0\`. + +::: übung vb-labyrinth +titel: Das Labyrinth +auftrag: Programmiere den mBot2 so, dass er in beiden Labyrinthen ins Ziel findet, ohne anzustoßen. +welt: labyrinth-1, labyrinth-2 +braucht: whileSchleife, verzweigung +tipp: Außen eine While-Schleife mit der Bedingung \`mbot.getLine() == 0\`. Sie läuft, bis der mBot2 auf dem Ziel steht. +tipp: In der Schleife eine Verzweigung \`mbot.getDistance() > 15\`: Ja → \`mbot.forward()\`. Nein → \`mbot.turnRight()\`, danach noch eine Verzweigung \`mbot.getDistance() < 15\` mit \`mbot.turnRight(180)\`. +lösung: vb-labyrinth-loesung.visustruct +::: + +::: angeberwissen +Mit der Regel „Hand immer an der Wand“ findet man aus jedem Labyrinth, dessen Wände alle zusammenhängen. Schon die Griechen erzählten von Theseus, der sich im Labyrinth des Minotaurus mit einem Wollfaden half. +::: +`,Gw='---\ntitel: Linienfolger mit Stopp\nnach: 20\nstufe: 3\n---\n\nDer mBot2 folgt einer schwarzen Linie und hält am roten Feld an ihrem Ende an.\n\nDafür gibt er mit **Räder einzeln** Gas: `mbot.drive(40, 40)` lässt beide Räder gleich schnell drehen, er fährt geradeaus weiter, bis ein anderer Fahrbefehl kommt. `mbot.drive(10, 40)` macht eine Linkskurve, `mbot.drive(40, 10)` eine Rechtskurve. `mbot.stop()` hält ihn an.\n\nDie beiden mittleren Fühler des Liniensensors fragst du mit `mbot.isLineLeft()` und `mbot.isLineRight()` ab. Sehen beide die Linie, fährt er geradeaus. Sieht nur der linke sie, lenkt er nach links, sieht nur der rechte sie, nach rechts.\n\n::: übung vb-linienfolger-stopp\ntitel: Linienfolger mit Stopp\nauftrag: Solange der mBot2 nicht auf Rot steht, folgt er der Linie. Danach hält er an. In der zweiten Welt schlängelt sich die Linie.\nwelt: linie-rot-1, linie-rot-2\nbraucht: whileSchleife, verzweigung\ntipp: Außen eine While-Schleife mit `!mbot.getColor().equals("rot")`, danach **anhalten**.\ntipp: In der Schleife: Sind `mbot.isLineLeft() && mbot.isLineRight()`, dann `mbot.drive(40, 40)`. Sonst, wenn `mbot.isLineLeft()`, dann `mbot.drive(10, 40)`. Sonst, wenn `mbot.isLineRight()`, dann `mbot.drive(40, 10)`.\nlösung: vb-linienfolger-stopp-loesung.visustruct\n:::\n',Hw=`--- +titel: Morsen +nach: 15 +stufe: 2 +--- + +Früher haben Schiffe mit Licht Nachrichten geschickt, im **Morsecode**: Jeder Buchstabe besteht aus kurzen und langen Signalen. Der bekannteste Notruf ist **SOS**: S ist dreimal kurz, O ist dreimal lang. + +::: übung vb-morsen +titel: SOS morsen +auftrag: LED 2 morst SOS in Weiß. Kurz heißt: 200 Millisekunden an, dann 200 aus. Lang heißt: 600 Millisekunden an, dann 200 aus. Zwischen den Buchstaben wartet der mBot2 zusätzlich 400 Millisekunden. Benutze für jeden Buchstaben eine Schleife. +befehle: 3 x (ledColor 2 "weiß", pause 200, ledColor 2 "aus", pause 200), pause 400, 3 x (ledColor 2 "weiß", pause 600, ledColor 2 "aus", pause 200), pause 400, 3 x (ledColor 2 "weiß", pause 200, ledColor 2 "aus", pause 200) +braucht: forSchleife +tipp: Drei For-Schleifen hintereinander, jede läuft dreimal. Dazwischen steht jeweils **kurz warten** mit 400. +tipp: In der ersten und dritten Schleife: \`mbot.led(2).setColor("weiß")\`, \`mbot.pause(200)\`, \`mbot.led(2).setColor("aus")\`, \`mbot.pause(200)\`. In der mittleren wartet er nach dem Einschalten 600. +lösung: vb-morsen-loesung.visustruct +::: +`,Vw=`--- +titel: Der Nachtwächter +nach: 18 +stufe: 1 +--- + +Der mBot2 ist ein Nachtwächter. Solange es dunkel ist (Helligkeit unter 20), läuft er Streife: 30 cm vor und dann umdrehen. Sobald es hell wird, ist seine Schicht vorbei: Er zeigt **Zzz** auf dem Bildschirm und schläft. + +::: übung vb-nachtwaechter +titel: Der Nachtwächter +auftrag: Solange die Helligkeit unter 20 ist, fährt der mBot2 30 cm vor und dreht sich um 180°. Danach zeigt er **Zzz** auf dem Bildschirm. +messwerte: getBrightness=5/80 -> drives, screen "Zzz" +messwerte: getBrightness=80 -> none, screen "Zzz" +braucht: whileSchleife +tipp: Eine While-Schleife mit \`mbot.getBrightness() < 20\`. Darin \`mbot.forward(30)\` und \`mbot.turnRight(180)\`. +tipp: Nach der Schleife steht \`mbot.showText("Zzz")\`. +lösung: vb-nachtwaechter-loesung.visustruct +::: +`,qw=`--- +titel: Slalom +nach: 2 +stufe: 2 +--- + +Vor dem mBot2 stehen vier Pylonen in einer Reihe. Er fährt Slalom: am ersten Pylon oben vorbei, am zweiten unten, dann wieder oben und unten. Hinter dem letzten Pylon ist das Ziel. + +In dieser Welt ist ein Feld 30 cm groß, so breit wie der mBot2. Ein Schritt von Feld zu Feld ist also \`mbot.forward(30)\`. + +::: übung vb-slalom +titel: Slalom +auftrag: Fahre den Slalom bis ins Ziel, ohne einen Pylon zu berühren. Benutze eine Schleife. +welt: slalom +braucht: forSchleife +tipp: Überlege zuerst, wie der mBot2 oben um einen einzigen Pylon herumfährt: Er steht danach zwei Felder weiter in derselben Reihe und schaut wieder nach rechts. +tipp: Unten herum geht genauso, nur mit links und rechts vertauscht. „Oben herum, dann unten herum“ wiederholt sich zweimal. +lösung: vb-slalom-loesung.visustruct +::: +`,Qw=`--- +titel: Die Spirale +nach: 2 +stufe: 2 +--- + +Der mBot2 soll eine eckige Spirale fahren: Die erste Seite ist 10 cm lang, die zweite 20 cm, die dritte 30 cm und so weiter. Nach jeder Seite dreht er sich nach rechts. + +Die Zählvariable einer For-Schleife kannst du auch in der Schleife benutzen, zum Beispiel in der Klammer von **fahre vor**. Dort darf auch eine Rechnung stehen, etwa \`mbot.forward(i * 5)\`. + +::: übung vb-spirale +titel: Die Spirale +auftrag: Lass den mBot2 eine Spirale mit 8 Seiten fahren: 10 cm, 20 cm, 30 cm … bis 80 cm. Nach jeder Seite dreht er sich nach rechts. +fahrt: forward 10, turnRight, forward 20, turnRight, forward 30, turnRight, forward 40, turnRight, forward 50, turnRight, forward 60, turnRight, forward 70, turnRight, forward 80, turnRight +braucht: forSchleife +tipp: Lass die Zählvariable von 1 bis 8 laufen. Wie lang ist dann die Seite in jedem Durchlauf? +tipp: In der Klammer von **fahre vor** steht eine Rechnung mit der Zählvariable. +lösung: vb-spirale-loesung.visustruct +::: +`,Uw=`--- +titel: Die Treppe +nach: 2 +stufe: 1 +--- + +Der mBot2 steigt eine Treppe hinauf, von oben gesehen: Jede Stufe ist 20 cm tief und 20 cm breit. + +::: übung vb-treppe +titel: Die Treppe +auftrag: Lass den mBot2 drei Stufen fahren. Eine Stufe: 20 cm vor, nach links drehen, 20 cm vor, nach rechts drehen. Benutze eine Schleife. +fahrt: 3 x (forward 20, turnLeft, forward 20, turnRight) +braucht: forSchleife +tipp: Schreib zuerst eine Stufe auf. Dann packst du sie in eine For-Schleife, die dreimal läuft. +tipp: In der Schleife: \`mbot.forward(20)\`, \`mbot.turnLeft()\`, \`mbot.forward(20)\`, \`mbot.turnRight()\`. +lösung: vb-treppe-loesung.visustruct +::: +`,$w=`--- +titel: Der Tunnelsucher +nach: 5 +stufe: 3 +--- + +Der mBot2 soll im ersten **Tunnelfeld** anhalten: Das ist ein Feld mit einer Wand links **und** einer Wand rechts. Felder mit nur einer Wand zählen nicht. In der Simulation ist das richtige Feld hellgrün, der Liniensensor sieht es aber nicht. + +Der Ultraschallsensor schaut nur nach vorn. Um nach links zu schauen, dreht sich der mBot2 nach links, misst und dreht sich wieder zurück. + +Den Messwert merkst du dir in einer **Variable**, zum Beispiel in einer Anweisung \`links = mbot.getDistance()\`. Am Anfang legst du sie an: \`int links = 99\`. + +::: übung vb-tunnel +titel: Der Tunnelsucher +auftrag: Programmiere den mBot2 so, dass er in beiden Welten im ersten Tunnelfeld anhält. Ein Feld ist 30 cm groß. +welt: tunnel-1, tunnel-2 +braucht: doUntilSchleife +tipp: In jedem Durchlauf fährt der mBot2 ein Feld vor und schaut sich dann nach links und nach rechts um. Merk dir beide Abstände in Variablen. Am Ende schaut er wieder nach vorn. +tipp: Hier passt eine Schleife, die erst fährt und danach prüft. Sie läuft weiter, solange links **oder** rechts mindestens 20 cm frei ist: \`links >= 20 || rechts >= 20\`. +lösung: vb-tunnel-loesung.visustruct +::: +`,Yw=`--- +titel: Kleeblatt im Wald +nach: 5 +stufe: 2 +--- + +Das Ziel liegt geradeaus. Auf dem Weg stehen Bäume, aber nie zwei direkt hintereinander. Steht ein Baum vor dem mBot2, fährt er außen herum und dann weiter geradeaus. + +Ein Feld ist 30 cm groß. Steht ein Baum im nächsten Feld, misst der Ultraschallsensor weniger als 20 cm. + +::: übung vb-wald +titel: Kleeblatt im Wald +auftrag: Der mBot2 soll in beiden Welten bis zum Ziel fahren und dabei jeden Baum umfahren, ohne anzustoßen. +welt: wald-1, wald-2 +braucht: whileSchleife, verzweigung +tipp: Wie bei „Fahre bis zum Ziel“ läuft außen eine Schleife, bis der Liniensensor das Ziel sieht. In jedem Durchlauf gibt es zwei Möglichkeiten: Baum vorn oder frei. +tipp: Um einen Baum herum: nach links drehen, ein Feld vor, nach rechts drehen, zwei Felder vor, nach rechts drehen, ein Feld vor, nach links drehen. +lösung: vb-wald-loesung.visustruct +::: +`,Xw=`--- +titel: The alarm system +nach: 16 +stufe: 2 +--- + +The mBot2 guards your room. If someone comes closer than 20 cm **or** it gets loud (loudness above 60), it raises the alarm: the LEDs light up red and it beeps. Otherwise the LEDs are off. With button B you switch the alarm system off. + +::: übung vb-alarmanlage +titel: The alarm system +auftrag: As long as button B is not pressed, the mBot2 checks again and again: if the distance is below 20 cm or the loudness above 60, the LEDs light up red and it plays a tone. Otherwise the LEDs go off. Then it waits a moment. +messwerte: getDistance=10, isButtonB=false/true -> none, tone +messwerte: getLoudness=80, isButtonB=false/true -> none, tone +messwerte: getDistance=100, getLoudness=0, isButtonB=false/true -> none, noTone, ledOff +braucht: whileSchleife, verzweigung +tipp: On the outside is a while loop with \`!mbot.isButtonB()\`. Inside a branch and after it **wait a moment**. +tipp: The condition of the branch: \`mbot.getDistance() < 20 || mbot.getLoudness() > 60\`. In the yes branch \`mbot.setLed(255, 0, 0)\` and \`mbot.playTone(880, 200)\`, in the no branch \`mbot.ledOff()\`. +lösung: vb-alarmanlage-loesung.visustruct +::: +`,Kw=`--- +titel: Maze with exits +nach: 5 +stufe: 3 +--- + +The mBot2 stands at the bottom left and faces right. Above it are rows of walls. Each has exactly one gap, and each gap lies further right than the one below. The goal is at the very top. + +The mBot2 drives to the right and looks up in every square. If there is a gap, it drives through into the next corridor. + +::: übung vb-ausgang +titel: Maze with exits +auftrag: Program the mBot2 so that in both worlds it drives through all gaps to the goal without bumping into anything. One square is 30 cm. +welt: ausgang-1, ausgang-2 +braucht: whileSchleife, verzweigung +tipp: In each pass the mBot2 first turns left and measures. If the way up is free, it is more than 20 cm. +tipp: Through the gap it is two squares into the next corridor. Afterwards it should face right again. If there is a wall above, it turns back and drives one square further. +lösung: vb-ausgang-loesung.visustruct +::: +`,e9=`--- +titel: Counting in binary +nach: 15 +stufe: 3 +--- + +Computers calculate with only two digits: 0 and 1. That is called **binary**. With three LEDs you can show the numbers 0 to 7 in binary: LED 0 counts 1, LED 1 counts 2 and LED 2 counts 4. The number 5 is 4 + 1, so LED 2 and LED 0 light up. + +| Number | LED 2 (4) | LED 1 (2) | LED 0 (1) | +|---|---|---|---| +| 0 | off | off | off | +| 1 | off | off | on | +| 2 | off | on | off | +| 3 | off | on | on | +| 5 | on | off | on | + +::: übung vb-binaer-zaehlen +titel: Counting in binary +auftrag: A for loop counts \`number\` from 0 to 7. For each number, each of the LEDs 0, 1 and 2 lights up green or is off, exactly as in the table. Then the mBot2 waits 1000 milliseconds. Always switch the LEDs in the order 0, 1, 2. +befehle: ledColor 0 "off", ledColor 1 "off", ledColor 2 "off", pause 1000, ledColor 0 "green", ledColor 1 "off", ledColor 2 "off", pause 1000, ledColor 0 "off", ledColor 1 "green", ledColor 2 "off", pause 1000, ledColor 0 "green", ledColor 1 "green", ledColor 2 "off", pause 1000, ledColor 0 "off", ledColor 1 "off", ledColor 2 "green", pause 1000, ledColor 0 "green", ledColor 1 "off", ledColor 2 "green", pause 1000, ledColor 0 "off", ledColor 1 "green", ledColor 2 "green", pause 1000, ledColor 0 "green", ledColor 1 "green", ledColor 2 "green", pause 1000 +braucht: forSchleife, verzweigung +tipp: Whether LED 0 is on is given by the remainder when dividing by 2: \`number % 2 == 1\`. For LED 1 you first divide by 2: \`number / 2 % 2 == 1\`. For LED 2 by 4: \`number / 4 % 2 == 1\`. +tipp: The loop contains three branches and then **wait a moment**. In the yes branch, for example, \`mbot.led(0).setColor("green")\`, in the no branch \`mbot.led(0).setColor("off")\`. +lösung: vb-binaer-zaehlen-loesung.visustruct +::: +`,t9=`--- +titel: The triangle +nach: 2 +stufe: 1 +--- + +For the square the mBot2 turns four times by 90°. Together that is 360°, one full turn. For a triangle it also turns all the way around once, but in only three corners. + +Inside the brackets of **turn right** you can write how far it should turn: \`mbot.turnRight(45)\` turns only 45°. + +::: übung vb-dreieck +titel: The triangle +auftrag: Let the mBot2 drive a triangle with three sides of equal length. Each side is 30 cm long. Use a loop. +fahrt: 3 x (forward 30, turnRight 120) +braucht: forSchleife +tipp: How many degrees must one corner be so that three corners add up to a full turn (360°)? +tipp: In the loop the mBot2 drives one side and then turns by 120°. +lösung: vb-dreieck-loesung.visustruct +::: + +::: angeberwissen +The idea of drawing shapes with a driving robot is more than 50 years old: the language **Logo** was created in the late 1960s. Children used it to steer a "turtle" that rolled across paper with a pen. +::: +`,n9=`--- +titel: Reverse parking +nach: 16 +stufe: 2 +--- + +To the right of the road there are parked cars (the blocks). Somewhere there is a gap, and right in front of it a blue marking is stuck on the road. The mBot2 looks for the gap and reverses into it, like a car. + +It has no sensor at the back. So it looks forward at the wall opposite: the further it reverses into the gap, the bigger the distance to that wall gets. + +::: übung vb-einparken +titel: Reverse parking +auftrag: The mBot2 drives forward in steps of 10 cm until it is on blue. Then it turns left, so its rear points to the gap. It reverses as long as the distance to the wall in front of it is below 45 cm. Finally the LEDs light up green and it shows **Parked!**. There are two roads with different gaps. +welt: parken-1 -> ledOn, screen "Parked!" +welt: parken-2 -> ledOn, screen "Parked!" +braucht: whileSchleife +tipp: Two while loops one after the other: first \`!mbot.getColor().equals("blue")\` with \`mbot.forward()\` inside, then \`mbot.getDistance() < 45\` with \`mbot.backward()\` inside. In between is \`mbot.turnLeft()\`. +tipp: At the end: \`mbot.setLed(0, 255, 0)\` and \`mbot.showText("Parked!")\`. +lösung: vb-einparken-loesung.visustruct +::: +`,i9='---\ntitel: Avoid obstacles\nnach: 16\nstufe: 2\n---\n\nOn the way to the red field there are blocks in the way. The mBot2 drives forward in steps of 10 cm. If a block shows up (closer than 20 cm), it warns with light and sound and drives around it: turn right, 30 cm forward, turn left. Then it carries on straight ahead.\n\n::: übung vb-hindernis\ntitel: Avoid obstacles\nauftrag: The mBot2 drives as long as it is not on red. If a block is closer than 20 cm, the LEDs light up orange (`mbot.setLed(255, 128, 0)`), it beeps and drives around it. Then the LEDs go off. Otherwise it drives forward 10 cm. There are two worlds.\nwelt: hindernis-1 -> tone\nwelt: hindernis-2 -> tone\nbraucht: whileSchleife, verzweigung\ntipp: On the outside a while loop with `!mbot.getColor().equals("red")`, inside a branch with `mbot.getDistance() < 20`.\ntipp: In the yes branch: `mbot.setLed(255, 128, 0)`, `mbot.playTone(880, 200)`, `mbot.turnRight()`, `mbot.forward(30)`, `mbot.turnLeft()`, `mbot.ledOff()`. In the no branch: `mbot.forward()`.\nlösung: vb-hindernis-loesung.visustruct\n:::\n',a9=`--- +titel: Knight Rider +nach: 15 +stufe: 2 +--- + +In the TV series “Knight Rider”, the talking car KITT has a red light at the front that keeps running back and forth. You rebuild it with the five LEDs. + +::: übung vb-knight-rider +titel: Knight Rider +auftrag: A red light runs from LED 0 to LED 4 and back to LED 1. Each LED lights up for 100 milliseconds and then goes off. Use two for loops: one counts up, one counts down. +befehle: ledColor 0 "red", pause 100, ledColor 0 "off", ledColor 1 "red", pause 100, ledColor 1 "off", ledColor 2 "red", pause 100, ledColor 2 "off", ledColor 3 "red", pause 100, ledColor 3 "off", ledColor 4 "red", pause 100, ledColor 4 "off", ledColor 3 "red", pause 100, ledColor 3 "off", ledColor 2 "red", pause 100, ledColor 2 "off", ledColor 1 "red", pause 100, ledColor 1 "off" +braucht: forSchleife +tipp: The first loop counts \`i\` up from 0 to 4. The second starts at 3 and counts down with \`i--\` as long as \`i > 0\`. +tipp: In both loops: \`mbot.led(i).setColor("red")\`, \`mbot.pause(100)\`, \`mbot.led(i).setColor("off")\`. +lösung: vb-knight-rider-loesung.visustruct +::: +`,s9=`--- +titel: The maze +nach: 5 +stufe: 2 +--- + +The mBot2 is standing in a maze. The goal is a black square with a green flag. The corridors are 30 cm wide. + +A simple rule gets it through: **If the way ahead is free, drive forward. Otherwise turn right. If there is a wall there too, turn all the way around.** + +How does the mBot2 notice that it has reached the goal? The line sensor underneath sees the black square: \`mbot.getLine()\` is then no longer \`0\`. + +::: übung vb-labyrinth +titel: The maze +auftrag: Program the mBot2 so that it finds the goal in both mazes without bumping into a wall. +welt: labyrinth-1, labyrinth-2 +braucht: whileSchleife, verzweigung +tipp: On the outside a while loop with the condition \`mbot.getLine() == 0\`. It runs until the mBot2 is on the goal. +tipp: Inside the loop a branch \`mbot.getDistance() > 15\`: yes → \`mbot.forward()\`. No → \`mbot.turnRight()\`, then another branch \`mbot.getDistance() < 15\` with \`mbot.turnRight(180)\`. +lösung: vb-labyrinth-loesung.visustruct +::: + +::: angeberwissen +With the rule "always keep one hand on the wall" you get out of any maze whose walls are all connected. The ancient Greeks already told of Theseus, who found his way through the Minotaur's labyrinth with a ball of thread. +::: +`,r9='---\ntitel: Line follower with stop\nnach: 20\nstufe: 3\n---\n\nThe mBot2 follows a black line and stops at the red field at its end.\n\nFor this it steps on the gas with **wheels separately**: `mbot.drive(40, 40)` turns both wheels equally fast, it keeps driving straight ahead until another driving command comes. `mbot.drive(10, 40)` makes a left curve, `mbot.drive(40, 10)` a right curve. `mbot.stop()` stops it.\n\nYou ask the two middle probes of the line sensor with `mbot.isLineLeft()` and `mbot.isLineRight()`. If both see the line, it drives straight ahead. If only the left one sees it, it steers left, if only the right one sees it, right.\n\n::: übung vb-linienfolger-stopp\ntitel: Line follower with stop\nauftrag: As long as the mBot2 is not on red, it follows the line. Then it stops. In the second world the line winds about.\nwelt: linie-rot-1, linie-rot-2\nbraucht: whileSchleife, verzweigung\ntipp: On the outside a while loop with `!mbot.getColor().equals("red")`, after it **stop**.\ntipp: Inside the loop: if `mbot.isLineLeft() && mbot.isLineRight()`, then `mbot.drive(40, 40)`. Otherwise, if `mbot.isLineLeft()`, then `mbot.drive(10, 40)`. Otherwise, if `mbot.isLineRight()`, then `mbot.drive(40, 10)`.\nlösung: vb-linienfolger-stopp-loesung.visustruct\n:::\n',o9=`--- +titel: Morse code +nach: 15 +stufe: 2 +--- + +Ships used to send messages with light, in **Morse code**: every letter is made of short and long signals. The best-known distress call is **SOS**: S is three short, O is three long. + +::: übung vb-morsen +titel: Morse SOS +auftrag: LED 2 sends SOS in white. Short means: on for 200 milliseconds, then off for 200. Long means: on for 600 milliseconds, then off for 200. Between the letters the mBot2 waits another 400 milliseconds. Use a loop for each letter. +befehle: 3 x (ledColor 2 "white", pause 200, ledColor 2 "off", pause 200), pause 400, 3 x (ledColor 2 "white", pause 600, ledColor 2 "off", pause 200), pause 400, 3 x (ledColor 2 "white", pause 200, ledColor 2 "off", pause 200) +braucht: forSchleife +tipp: Three for loops one after the other, each runs three times. Between them there is **wait a moment** with 400. +tipp: In the first and third loop: \`mbot.led(2).setColor("white")\`, \`mbot.pause(200)\`, \`mbot.led(2).setColor("off")\`, \`mbot.pause(200)\`. In the middle one it waits 600 after switching on. +lösung: vb-morsen-loesung.visustruct +::: +`,l9=`--- +titel: The night watchman +nach: 18 +stufe: 1 +--- + +The mBot2 is a night watchman. As long as it is dark (brightness below 20), it goes on patrol: 30 cm forward and then turn around. As soon as it gets light, its shift is over: it shows **Zzz** on its screen and sleeps. + +::: übung vb-nachtwaechter +titel: The night watchman +auftrag: As long as the brightness is below 20, the mBot2 drives forward 30 cm and turns by 180°. Then it shows **Zzz** on its screen. +messwerte: getBrightness=5/80 -> drives, screen "Zzz" +messwerte: getBrightness=80 -> none, screen "Zzz" +braucht: whileSchleife +tipp: A while loop with \`mbot.getBrightness() < 20\`. Inside \`mbot.forward(30)\` and \`mbot.turnRight(180)\`. +tipp: After the loop is \`mbot.showText("Zzz")\`. +lösung: vb-nachtwaechter-loesung.visustruct +::: +`,u9=`--- +titel: Slalom +nach: 2 +stufe: 2 +--- + +Four cones stand in a row in front of the mBot2. It drives a slalom: past the first cone on the top side, past the second on the bottom side, then top and bottom again. Behind the last cone is the goal. + +In this world one square is 30 cm, as wide as the mBot2. One step from square to square is therefore \`mbot.forward(30)\`. + +::: übung vb-slalom +titel: Slalom +auftrag: Drive the slalom to the goal without touching a cone. Use a loop. +welt: slalom +braucht: forSchleife +tipp: First think about how the mBot2 drives around a single cone on the top side: afterwards it is two squares further along in the same row and faces right again. +tipp: Around the bottom works the same way, only with left and right swapped. "Top, then bottom" repeats twice. +lösung: vb-slalom-loesung.visustruct +::: +`,c9=`--- +titel: The spiral +nach: 2 +stufe: 2 +--- + +The mBot2 should drive a square spiral: the first side is 10 cm long, the second 20 cm, the third 30 cm and so on. After each side it turns right. + +You can also use the counter variable of a for loop inside the loop, for example in the brackets of **drive forward**. A calculation is allowed there too, such as \`mbot.forward(i * 5)\`. + +::: übung vb-spirale +titel: The spiral +auftrag: Let the mBot2 drive a spiral with 8 sides: 10 cm, 20 cm, 30 cm … up to 80 cm. After each side it turns right. +fahrt: forward 10, turnRight, forward 20, turnRight, forward 30, turnRight, forward 40, turnRight, forward 50, turnRight, forward 60, turnRight, forward 70, turnRight, forward 80, turnRight +braucht: forSchleife +tipp: Let the counter variable run from 1 to 8. How long is the side in each pass then? +tipp: The brackets of **drive forward** contain a calculation with the counter variable. +lösung: vb-spirale-loesung.visustruct +::: +`,m9=`--- +titel: The staircase +nach: 2 +stufe: 1 +--- + +The mBot2 climbs a staircase, seen from above: each step is 20 cm deep and 20 cm wide. + +::: übung vb-treppe +titel: The staircase +auftrag: Let the mBot2 drive three steps. One step: 20 cm forward, turn left, 20 cm forward, turn right. Use a loop. +fahrt: 3 x (forward 20, turnLeft, forward 20, turnRight) +braucht: forSchleife +tipp: Write down one step first. Then put it into a for loop that runs three times. +tipp: Inside the loop: \`mbot.forward(20)\`, \`mbot.turnLeft()\`, \`mbot.forward(20)\`, \`mbot.turnRight()\`. +lösung: vb-treppe-loesung.visustruct +::: +`,d9=`--- +titel: The tunnel finder +nach: 5 +stufe: 3 +--- + +The mBot2 should stop in the first **tunnel square**: a square with a wall on the left **and** a wall on the right. Squares with only one wall don't count. In the simulation the right square is light green, but the line sensor can't see it. + +The ultrasonic sensor only looks forward. To look left, the mBot2 turns left, measures and turns back again. + +You remember the measured value in a **variable**, for example with a statement \`left = mbot.getDistance()\`. At the start you create it: \`int left = 99\`. + +::: übung vb-tunnel +titel: The tunnel finder +auftrag: Program the mBot2 so that it stops in the first tunnel square in both worlds. One square is 30 cm. +welt: tunnel-1, tunnel-2 +braucht: doUntilSchleife +tipp: In each pass the mBot2 drives one square forward and then looks left and right. Remember both distances in variables. At the end it faces forward again. +tipp: A loop that drives first and checks afterwards fits here. It keeps going as long as at least 20 cm are free on the left **or** on the right: \`left >= 20 || right >= 20\`. +lösung: vb-tunnel-loesung.visustruct +::: +`,h9=`--- +titel: Clover in the forest +nach: 5 +stufe: 2 +--- + +The goal is straight ahead. There are trees on the way, but never two directly behind each other. If a tree stands in front of the mBot2, it drives around it and then continues straight ahead. + +One square is 30 cm. If there is a tree in the next square, the ultrasonic sensor measures less than 20 cm. + +::: übung vb-wald +titel: Clover in the forest +auftrag: In both worlds the mBot2 should drive to the goal and go around every tree without bumping into it. +welt: wald-1, wald-2 +braucht: whileSchleife, verzweigung +tipp: As in "Drive to the goal", a loop on the outside runs until the line sensor sees the goal. In each pass there are two possibilities: tree ahead or free. +tipp: Around a tree: turn left, one square forward, turn right, two squares forward, turn right, one square forward, turn left. +lösung: vb-wald-loesung.visustruct +::: +`,g9=` + + + 111;117;116;112;117;116;58;32;34;87;105;108;108;107;111;109;109;101;110;34; + + + 112;114;117;101;102;101;65;108;116;101;114;40;41; + + + 111;117;116;112;117;116;58;32;34;65;117;102;32;87;105;101;100;101;114;115;101;104;101;110;34; + + +`,p9=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; + + + 97;108;116;101;114;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;118;111;108;108;106;228;104;114;105;103;34; + + + + + 111;117;116;112;117;116;58;32;34;109;105;110;100;101;114;106;228;104;114;105;103;34; + + + + +`,f9=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;98;97;108;108;119;117;114;102;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 100;111;117;98;108;101;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;98;101;115;116;101;87;101;105;116;101;32;61;32;48; + + + 83;116;114;105;110;103;32;98;101;115;116;101;114;78;97;109;101;32;61;32;34;34; + + + 122;101;105;108;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;116;101;105;108;101;32;61;32;122;101;105;108;101;46;115;112;108;105;116;40;34;59;34;41; + + + 105;110;116;32;119;101;105;116;101;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;116;101;105;108;101;91;49;93;41; + + + 97;110;122;97;104;108;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;119;101;105;116;101; + + + 119;101;105;116;101;32;62;32;98;101;115;116;101;87;101;105;116;101; + + + 98;101;115;116;101;87;101;105;116;101;32;61;32;119;101;105;116;101; + + + 98;101;115;116;101;114;78;97;109;101;32;61;32;116;101;105;108;101;91;48;93; + + + + + 248; + + + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;115;101;114;46;99;108;111;115;101;40;41; + + + 100;111;117;98;108;101;32;115;99;104;110;105;116;116;32;61;32;115;117;109;109;101;32;47;32;97;110;122;97;104;108; + + + 111;117;116;112;117;116;58;32;34;84;101;105;108;110;101;104;109;101;114;58;32;34;32;43;32;97;110;122;97;104;108; + + + 111;117;116;112;117;116;58;32;34;83;99;104;110;105;116;116;58;32;34;32;43;32;115;99;104;110;105;116;116;32;43;32;34;32;109;34; + + + 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;115;105;101;103;101;114;46;116;120;116;34;41; + + + 97;117;115;46;112;114;105;110;116;108;110;40;34;83;105;101;103;101;114;58;32;34;32;43;32;98;101;115;116;101;114;78;97;109;101;32;43;32;34;32;40;34;32;43;32;98;101;115;116;101;87;101;105;116;101;32;43;32;34;32;109;41;34;41; + + + 97;117;115;46;99;108;111;115;101;40;41; + + +`,b9=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;98;97;108;108;119;117;114;102;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,x9=` + + + 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;117;110;107;116;101;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;80;117;110;107;116;101;63;34; + + + 112;117;110;107;116;101;91;105;93;32;61;32;122;97;104;108; + + + + + 105;110;116;32;100;117;114;99;104;103;97;110;103;32;61;32;49; + 100;117;114;99;104;103;97;110;103;32;60;32;112;117;110;107;116;101;46;108;101;110;103;116;104; + 100;117;114;99;104;103;97;110;103;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;117;110;107;116;101;46;108;101;110;103;116;104;32;45;32;100;117;114;99;104;103;97;110;103; + 105;43;43; + + + 112;117;110;107;116;101;91;105;93;32;60;32;112;117;110;107;116;101;91;105;32;43;32;49;93; + + + 105;110;116;32;104;105;108;102;32;61;32;112;117;110;107;116;101;91;105;93; + + + 112;117;110;107;116;101;91;105;93;32;61;32;112;117;110;107;116;101;91;105;32;43;32;49;93; + + + 112;117;110;107;116;101;91;105;32;43;32;49;93;32;61;32;104;105;108;102; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;117;110;107;116;101;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;116;32;112;108;97;116;122;32;61;32;105;32;43;32;49; + + + 111;117;116;112;117;116;58;32;112;108;97;116;122;32;43;32;34;46;32;34;32;43;32;112;117;110;107;116;101;91;105;93; + + + + +`,v9=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;71;97;110;122;101;32;90;97;104;108;32;101;105;110;103;101;98;101;110;34; + + + 83;116;114;105;110;103;32;98;105;110;97;101;114;32;61;32;34;34; + + + 122;97;104;108;32;62;32;48; + + + 105;110;116;32;114;101;115;116;32;61;32;122;97;104;108;32;37;32;50; + + + 98;105;110;97;101;114;32;61;32;114;101;115;116;32;43;32;98;105;110;97;101;114; + + + 122;97;104;108;32;61;32;122;97;104;108;32;47;32;50; + + + + + 111;117;116;112;117;116;58;32;98;105;110;97;101;114; + + +`,y9=` + + + 99;104;97;114;91;93;32;97;108;112;104;97;98;101;116;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;116;32;34;87;101;108;99;104;101;115;32;87;111;114;116;32;40;110;117;114;32;71;114;111;223;98;117;99;104;115;116;97;98;101;110;41;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;75;32;34;85;109;32;119;105;101;32;118;105;101;108;101;32;83;116;101;108;108;101;110;32;118;101;114;115;99;104;105;101;98;101;110;63;34; + + + 83;116;114;105;110;103;32;103;101;104;101;105;109;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;119;111;114;116;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 99;104;97;114;32;90;32;61;32;119;111;114;116;46;99;104;97;114;65;116;40;105;41; + + + 105;110;116;32;112;111;115;32;61;32;48; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;97;108;112;104;97;98;101;116;46;108;101;110;103;116;104; + 106;43;43; + + + 97;108;112;104;97;98;101;116;91;106;93;32;61;61;32;90; + + + 112;111;115;32;61;32;106; + + + + + 248; + + + + + + + 103;101;104;101;105;109;32;61;32;103;101;104;101;105;109;32;43;32;97;108;112;104;97;98;101;116;91;40;112;111;115;32;43;32;75;41;32;37;32;50;54;93; + + + + + 111;117;116;112;117;116;58;32;103;101;104;101;105;109; + + +`,w9=` + + + 99;104;97;114;91;93;32;97;108;112;104;97;98;101;116;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; + + +`,z9=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;116;32;34;87;101;108;99;104;101;115;32;87;111;114;116;32;40;110;117;114;32;71;114;111;223;98;117;99;104;115;116;97;98;101;110;41;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;75;32;34;85;109;32;119;105;101;32;118;105;101;108;101;32;83;116;101;108;108;101;110;32;118;101;114;115;99;104;105;101;98;101;110;63;34; + + + 83;116;114;105;110;103;32;103;101;104;101;105;109;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;119;111;114;116;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 105;110;116;32;99;111;100;101;32;61;32;40;105;110;116;41;32;119;111;114;116;46;99;104;97;114;65;116;40;105;41; + + + 99;111;100;101;32;61;32;40;99;111;100;101;32;45;32;54;53;32;43;32;75;41;32;37;32;50;54;32;43;32;54;53; + + + 103;101;104;101;105;109;32;61;32;103;101;104;101;105;109;32;43;32;40;99;104;97;114;41;32;99;111;100;101; + + + + + 111;117;116;112;117;116;58;32;103;101;104;101;105;109; + + +`,I9=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;103;101;104;101;105;109;32;34;87;101;108;99;104;101;114;32;71;101;104;101;105;109;116;101;120;116;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;75;32;34;85;109;32;119;105;101;32;118;105;101;108;101;32;83;116;101;108;108;101;110;32;118;101;114;115;99;104;105;101;98;101;110;63;34; + + + 83;116;114;105;110;103;32;107;108;97;114;116;101;120;116;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;103;101;104;101;105;109;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 105;110;116;32;99;111;100;101;32;61;32;40;105;110;116;41;32;103;101;104;101;105;109;46;99;104;97;114;65;116;40;105;41; + + + 99;111;100;101;32;61;32;40;99;111;100;101;32;45;32;54;53;32;45;32;75;32;43;32;50;54;41;32;37;32;50;54;32;43;32;54;53; + + + 107;108;97;114;116;101;120;116;32;61;32;107;108;97;114;116;101;120;116;32;43;32;40;99;104;97;114;41;32;99;111;100;101; + + + + + 111;117;116;112;117;116;58;32;107;108;97;114;116;101;120;116; + + +`,k9=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;32;101;105;110;103;101;98;101;110;34; + + + 105;110;116;32;115;99;104;114;105;116;116;101;32;61;32;48; + + + 122;97;104;108;32;33;61;32;49; + + + 122;97;104;108;32;37;32;50;32;61;61;32;48; + + + 122;97;104;108;32;61;32;122;97;104;108;32;47;32;50; + + + + + 122;97;104;108;32;61;32;122;97;104;108;32;42;32;51;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + 115;99;104;114;105;116;116;101;43;43; + + + + + 111;117;116;112;117;116;58;32;34;83;99;104;114;105;116;116;101;58;32;34;32;43;32;115;99;104;114;105;116;116;101; + + +`,S9=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;110;122;97;104;108;32;34;87;105;101;32;118;105;101;108;101;32;78;111;116;101;110;63;34; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;97;110;122;97;104;108; + 105;43;43; + + + 105;110;112;117;116;58;32;105;110;116;32;110;111;116;101;32;34;78;111;116;101;32;101;105;110;103;101;98;101;110;34; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;110;111;116;101; + + + + + 100;111;117;98;108;101;32;115;99;104;110;105;116;116;32;61;32;115;117;109;109;101;32;42;32;49;46;48;32;47;32;97;110;122;97;104;108; + + + 111;117;116;112;117;116;58;32;115;99;104;110;105;116;116; + + +`,T9=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;110;122;97;104;108;32;34;87;105;101;32;118;105;101;108;101;32;90;97;104;108;101;110;63;34; + + + 105;110;116;32;122;97;104;108;49;32;61;32;49; + + + 105;110;116;32;122;97;104;108;50;32;61;32;49; + + + 111;117;116;112;117;116;58;32;122;97;104;108;49; + + + 111;117;116;112;117;116;58;32;122;97;104;108;50; + + + 105;110;116;32;105;32;61;32;50; + 105;32;60;32;97;110;122;97;104;108; + 105;43;43; + + + 105;110;116;32;122;97;104;108;51;32;61;32;122;97;104;108;49;32;43;32;122;97;104;108;50; + + + 111;117;116;112;117;116;58;32;122;97;104;108;51; + + + 122;97;104;108;49;32;61;32;122;97;104;108;50; + + + 122;97;104;108;50;32;61;32;122;97;104;108;51; + + + + +`,_9=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;34; + + + 122;97;104;108;32;37;32;50;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;122;97;104;108;32;43;32;34;32;105;115;116;32;103;101;114;97;100;101;34; + + + + + 111;117;116;112;117;116;58;32;122;97;104;108;32;43;32;34;32;105;115;116;32;117;110;103;101;114;97;100;101;34; + + + + +`,A9=` + + + 99;111;110;115;116;32;100;111;117;98;108;101;32;77;87;83;84;32;61;32;48;46;49;57; + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;110;101;116;116;111;112;114;101;105;115;32;34;78;101;116;116;111;112;114;101;105;115;63;34; + + + 100;111;117;98;108;101;32;115;116;101;117;101;114;32;61;32;110;101;116;116;111;112;114;101;105;115;32;42;32;77;87;83;84; + + + 100;111;117;98;108;101;32;98;114;117;116;116;111;112;114;101;105;115;32;61;32;110;101;116;116;111;112;114;101;105;115;32;43;32;115;116;101;117;101;114; + + + 111;117;116;112;117;116;58;32;115;116;101;117;101;114; + + + 111;117;116;112;117;116;58;32;98;114;117;116;116;111;112;114;101;105;115; + + +`,O9=` + + + 105;110;116;32;112;105;110;32;61;32;48; + + + 105;110;116;32;118;101;114;115;117;99;104;101;32;61;32;48; + + + 112;105;110;32;33;61;32;49;50;51;52;32;38;38;32;118;101;114;115;117;99;104;101;32;60;32;51; + + + 105;110;112;117;116;58;32;105;110;116;32;101;105;110;103;97;98;101;32;34;80;73;78;32;101;105;110;103;101;98;101;110;34; + + + 112;105;110;32;61;32;101;105;110;103;97;98;101; + + + 118;101;114;115;117;99;104;101;43;43; + + + + + 112;105;110;32;61;61;32;49;50;51;52; + + + 111;117;116;112;117;116;58;32;34;80;73;78;32;114;105;99;104;116;105;103;34; + + + + + 111;117;116;112;117;116;58;32;34;75;97;114;116;101;32;103;101;115;112;101;114;114;116;34; + + + + +`,C9=` + + + 99;111;110;115;116;32;105;110;116;32;80;73;78;32;61;32;49;50;51;52; + + + 105;110;116;32;112;105;110;32;61;32;48; + + + 105;110;116;32;118;101;114;115;117;99;104;101;32;61;32;48; + + + 112;105;110;32;33;61;32;80;73;78;32;38;38;32;118;101;114;115;117;99;104;101;32;60;32;51; + + + 105;110;112;117;116;58;32;112;105;110;32;34;80;73;78;32;101;105;110;103;101;98;101;110;34; + + + 118;101;114;115;117;99;104;101;43;43; + + + + + 112;105;110;32;61;61;32;80;73;78; + + + 111;117;116;112;117;116;58;32;34;80;73;78;32;114;105;99;104;116;105;103;34; + + + + + 111;117;116;112;117;116;58;32;34;75;97;114;116;101;32;103;101;115;112;101;114;114;116;34; + + + + +`,j9=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;49;32;34;69;114;115;116;101;32;90;97;104;108;34; + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;50;32;34;90;119;101;105;116;101;32;90;97;104;108;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;122;101;105;99;104;101;110;32;34;82;101;99;104;101;110;122;101;105;99;104;101;110;32;40;43;44;32;45;32;111;100;101;114;32;42;41;34; + + + 122;101;105;99;104;101;110; + + + 105;110;116;32;101;114;103;101;98;110;105;115;32;61;32;122;97;104;108;49;32;43;32;122;97;104;108;50; + + + 111;117;116;112;117;116;58;32;101;114;103;101;98;110;105;115; + + + + + 105;110;116;32;101;114;103;101;98;110;105;115;32;61;32;122;97;104;108;49;32;45;32;122;97;104;108;50; + + + 111;117;116;112;117;116;58;32;101;114;103;101;98;110;105;115; + + + + + 105;110;116;32;101;114;103;101;98;110;105;115;32;61;32;122;97;104;108;49;32;42;32;122;97;104;108;50; + + + 111;117;116;112;117;116;58;32;101;114;103;101;98;110;105;115; + + + + + 111;117;116;112;117;116;58;32;34;85;110;98;101;107;97;110;110;116;101;115;32;82;101;99;104;101;110;122;101;105;99;104;101;110;34; + + + + +`,P9=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;109;101;101;114;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; + + + 109;101;101;114;91;48;93;91;49;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;48;93;91;51;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;50;93;91;52;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;51;93;91;52;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;52;93;91;48;93;32;61;32;116;114;117;101; + + + 83;116;114;105;110;103;91;93;32;115;112;97;108;116;101;110;32;61;32;123;34;65;34;44;32;34;66;34;44;32;34;67;34;44;32;34;68;34;44;32;34;69;34;125; + + + 105;110;116;32;114;101;105;104;101;32;61;32;48; + 114;101;105;104;101;32;60;32;109;101;101;114;46;108;101;110;103;116;104; + 114;101;105;104;101;43;43; + + + 105;110;116;32;115;112;97;108;116;101;32;61;32;48; + 115;112;97;108;116;101;32;60;32;109;101;101;114;91;114;101;105;104;101;93;46;108;101;110;103;116;104; + 115;112;97;108;116;101;43;43; + + + 109;101;101;114;91;114;101;105;104;101;93;91;115;112;97;108;116;101;93; + + + 111;117;116;112;117;116;58;32;115;112;97;108;116;101;110;91;115;112;97;108;116;101;93;32;43;32;40;114;101;105;104;101;32;43;32;49;41; + + + + + 248; + + + + + + + + +`,D9=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;109;101;101;114;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; + + + 109;101;101;114;91;48;93;91;49;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;48;93;91;51;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;50;93;91;52;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;51;93;91;52;93;32;61;32;116;114;117;101; + + + 109;101;101;114;91;52;93;91;48;93;32;61;32;116;114;117;101; + + + 83;116;114;105;110;103;91;93;32;115;112;97;108;116;101;110;32;61;32;123;34;65;34;44;32;34;66;34;44;32;34;67;34;44;32;34;68;34;44;32;34;69;34;125; + + +`,B9=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;109;101;114;32;34;87;101;108;99;104;101;115;32;71;101;114;105;99;104;116;63;32;40;49;44;32;50;32;111;100;101;114;32;51;41;34; + + + 110;117;109;109;101;114; + + + 111;117;116;112;117;116;58;32;34;71;114;105;101;99;104;105;115;99;104;101;114;32;83;97;108;97;116;34; + + + + + 111;117;116;112;117;116;58;32;34;82;101;105;115;45;66;111;119;108;34; + + + + + 111;117;116;112;117;116;58;32;34;70;97;108;97;102;101;108;45;87;114;97;112;34; + + + + + 111;117;116;112;117;116;58;32;34;66;105;116;116;101;32;101;105;110;101;32;103;252;108;116;105;103;101;32;78;117;109;109;101;114;32;119;228;104;108;101;110;34; + + + + +`,M9=` + + + 105;110;116;32;122;97;104;108;49;32;61;32;52; + + + 105;110;116;32;122;97;104;108;50;32;61;32;51; + + + 105;110;116;32;115;117;109;109;101;32;61;32;122;97;104;108;49;32;43;32;122;97;104;108;50; + + + 111;117;116;112;117;116;58;32;115;117;109;109;101; + + +`,Z9=` + + + 83;116;114;105;110;103;91;93;32;110;97;109;101;110;32;61;32;110;101;119;32;83;116;114;105;110;103;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;97;109;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;97;109;101;110;91;105;93;32;34;78;97;109;101;32;101;105;110;103;101;98;101;110;34; + + + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;109;101;114;32;34;76;111;115;110;117;109;109;101;114;32;40;49;32;98;105;115;32;53;41;34; + + + 111;117;116;112;117;116;58;32;34;84;97;102;101;108;100;105;101;110;115;116;58;32;34;32;43;32;110;97;109;101;110;91;110;117;109;109;101;114;32;45;32;49;93; + + +`,L9=` + + + 105;110;116;32;122;97;104;108;32;61;32;52; + + + 122;97;104;108;32;61;32;122;97;104;108;32;42;32;50; + + + 111;117;116;112;117;116;58;32;34;86;101;114;100;111;112;112;101;108;116;101;32;90;97;104;108;58;32;34;32;43;32;122;97;104;108; + + +`,E9=` + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;119;97;104;108;32;34;49;32;61;32;69;45;66;105;107;101;44;32;50;32;61;32;69;45;83;99;111;111;116;101;114;44;32;48;32;61;32;69;110;100;101;34; + + + 119;97;104;108;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;34;84;115;99;104;252;115;115;34; + + + -1; + + + + + 119;97;104;108;32;61;61;32;49; + + + 111;117;116;112;117;116;58;32;34;69;45;66;105;107;101;32;103;101;98;117;99;104;116;34; + + + + + 119;97;104;108;32;61;61;32;50; + + + 111;117;116;112;117;116;58;32;34;69;45;83;99;111;111;116;101;114;32;103;101;98;117;99;104;116;34; + + + + + 111;117;116;112;117;116;58;32;34;85;110;103;252;108;116;105;103;101;32;65;117;115;119;97;104;108;34; + + + + + + + + + + +`,W9=` + + + + + + 105;110;112;117;116;58;32;105;110;116;32;119;97;104;108;32;34;49;32;61;32;69;45;66;105;107;101;44;32;50;32;61;32;69;45;83;99;111;111;116;101;114;44;32;48;32;61;32;69;110;100;101;34; + + + 119;97;104;108; + + + 111;117;116;112;117;116;58;32;34;84;115;99;104;252;115;115;34; + + + 77;101;110;252;32;118;101;114;108;97;115;115;101;110; + + + + + 111;117;116;112;117;116;58;32;34;69;45;66;105;107;101;32;103;101;98;117;99;104;116;34; + + + + + 111;117;116;112;117;116;58;32;34;69;45;83;99;111;111;116;101;114;32;103;101;98;117;99;104;116;34; + + + + + 111;117;116;112;117;116;58;32;34;85;110;103;252;108;116;105;103;101;32;65;117;115;119;97;104;108;34; + + + + + + +`,N9=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;118;111;107;97;98;101;108;110;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 105;110;116;32;114;105;99;104;116;105;103;32;61;32;48; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 122;101;105;108;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;116;101;105;108;101;32;61;32;122;101;105;108;101;46;115;112;108;105;116;40;34;59;34;41; + + + 111;117;116;112;117;116;58;32;34;87;97;115;32;104;101;105;223;116;32;34;32;43;32;116;101;105;108;101;91;48;93;32;43;32;34;63;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;97;110;116;119;111;114;116; + + + 97;110;122;97;104;108;43;43; + + + 97;110;116;119;111;114;116;46;101;113;117;97;108;115;40;116;101;105;108;101;91;49;93;41; + + + 111;117;116;112;117;116;58;32;34;82;105;99;104;116;105;103;33;34; + + + 114;105;99;104;116;105;103;43;43; + + + + + 111;117;116;112;117;116;58;32;34;70;97;108;115;99;104;44;32;114;105;99;104;116;105;103;32;105;115;116;32;34;32;43;32;116;101;105;108;101;91;49;93;32;43;32;34;46;34; + + + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;115;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;114;105;99;104;116;105;103;32;43;32;34;32;118;111;110;32;34;32;43;32;97;110;122;97;104;108;32;43;32;34;32;114;105;99;104;116;105;103;34; + + +`,F9=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;118;111;107;97;98;101;108;110;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,J9=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; + + + 97;108;116;101;114;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;118;111;108;108;106;228;104;114;105;103;34; + + + + + 111;117;116;112;117;116;58;32;34;109;105;110;100;101;114;106;228;104;114;105;103;34; + + + + +`,R9=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 122;101;105;108;101;32;33;61;32;110;117;108;108; + + + 111;117;116;112;117;116;58;32;122;101;105;108;101; + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;115;101;114;46;99;108;111;115;101;40;41; + + +`,G9=` + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;34;90;111;114;97;59;49;59;50;59;50;34; + + + 83;116;114;105;110;103;91;93;32;116;101;105;108;101;32;61;32;122;101;105;108;101;46;115;112;108;105;116;40;34;59;34;41; + + + 83;116;114;105;110;103;32;110;97;109;101;32;61;32;116;101;105;108;101;91;48;93; + + + 105;110;116;32;109;97;116;104;101;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;116;101;105;108;101;91;49;93;41; + + + 111;117;116;112;117;116;58;32;110;97;109;101;32;43;32;34;32;104;97;116;32;105;110;32;77;97;116;104;101;32;101;105;110;101;32;34;32;43;32;109;97;116;104;101; + + +`,H9=` + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;34;123;92;34;110;97;109;101;92;34;58;32;92;34;90;111;114;97;92;34;44;32;92;34;97;114;116;92;34;58;32;92;34;90;105;101;103;101;92;34;44;32;92;34;97;108;116;101;114;92;34;58;32;54;125;44;34; + + + 105;110;116;32;115;116;97;114;116;32;61;32;122;101;105;108;101;46;105;110;100;101;120;79;102;40;34;92;34;110;97;109;101;92;34;58;32;92;34;34;41;32;43;32;57; + + + 105;110;116;32;101;110;100;101;32;61;32;122;101;105;108;101;46;105;110;100;101;120;79;102;40;34;92;34;34;44;32;115;116;97;114;116;41; + + + 83;116;114;105;110;103;32;110;97;109;101;32;61;32;122;101;105;108;101;46;115;117;98;115;116;114;105;110;103;40;115;116;97;114;116;44;32;101;110;100;101;41; + + + 111;117;116;112;117;116;58;32;110;97;109;101; + + +`,V9=` + + + 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; + + + 100;97;116;101;105;46;104;97;115;78;101;120;116;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;100;97;116;101;105;46;110;101;120;116;76;105;110;101;40;41; + + + 111;117;116;112;117;116;58;32;122;101;105;108;101; + + + + + 100;97;116;101;105;46;99;108;111;115;101;40;41; + + +`,q9=` + + + 111;117;116;112;117;116;58;32;34;87;101;108;99;111;109;101;34; + + + 99;104;101;99;107;65;103;101;40;41; + + + 111;117;116;112;117;116;58;32;34;71;111;111;100;98;121;101;34; + + +`,Q9=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; + + + 97;103;101;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;97;100;117;108;116;34; + + + + + 111;117;116;112;117;116;58;32;34;109;105;110;111;114;34; + + + + +`,U9=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;104;114;111;119;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 100;111;117;98;108;101;32;115;117;109;32;61;32;48; + + + 105;110;116;32;98;101;115;116;68;105;115;116;97;110;99;101;32;61;32;48; + + + 83;116;114;105;110;103;32;98;101;115;116;78;97;109;101;32;61;32;34;34; + + + 108;105;110;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;115;32;61;32;108;105;110;101;46;115;112;108;105;116;40;34;59;34;41; + + + 105;110;116;32;100;105;115;116;97;110;99;101;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;112;97;114;116;115;91;49;93;41; + + + 99;111;117;110;116;43;43; + + + 115;117;109;32;61;32;115;117;109;32;43;32;100;105;115;116;97;110;99;101; + + + 100;105;115;116;97;110;99;101;32;62;32;98;101;115;116;68;105;115;116;97;110;99;101; + + + 98;101;115;116;68;105;115;116;97;110;99;101;32;61;32;100;105;115;116;97;110;99;101; + + + 98;101;115;116;78;97;109;101;32;61;32;112;97;114;116;115;91;48;93; + + + + + 248; + + + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 114;101;97;100;101;114;46;99;108;111;115;101;40;41; + + + 100;111;117;98;108;101;32;97;118;101;114;97;103;101;32;61;32;115;117;109;32;47;32;99;111;117;110;116; + + + 111;117;116;112;117;116;58;32;34;80;97;114;116;105;99;105;112;97;110;116;115;58;32;34;32;43;32;99;111;117;110;116; + + + 111;117;116;112;117;116;58;32;34;65;118;101;114;97;103;101;58;32;34;32;43;32;97;118;101;114;97;103;101;32;43;32;34;32;109;34; + + + 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;119;105;110;110;101;114;46;116;120;116;34;41; + + + 111;117;116;46;112;114;105;110;116;108;110;40;34;87;105;110;110;101;114;58;32;34;32;43;32;98;101;115;116;78;97;109;101;32;43;32;34;32;40;34;32;43;32;98;101;115;116;68;105;115;116;97;110;99;101;32;43;32;34;32;109;41;34;41; + + + 111;117;116;46;99;108;111;115;101;40;41; + + +`,$9=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;104;114;111;119;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,Y9=` + + + 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;105;110;116;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;80;111;105;110;116;115;63;34; + + + 112;111;105;110;116;115;91;105;93;32;61;32;110;117;109;98;101;114; + + + + + 105;110;116;32;114;117;110;32;61;32;49; + 114;117;110;32;60;32;112;111;105;110;116;115;46;108;101;110;103;116;104; + 114;117;110;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;105;110;116;115;46;108;101;110;103;116;104;32;45;32;114;117;110; + 105;43;43; + + + 112;111;105;110;116;115;91;105;93;32;60;32;112;111;105;110;116;115;91;105;32;43;32;49;93; + + + 105;110;116;32;116;101;109;112;32;61;32;112;111;105;110;116;115;91;105;93; + + + 112;111;105;110;116;115;91;105;93;32;61;32;112;111;105;110;116;115;91;105;32;43;32;49;93; + + + 112;111;105;110;116;115;91;105;32;43;32;49;93;32;61;32;116;101;109;112; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;105;110;116;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;116;32;112;108;97;99;101;32;61;32;105;32;43;32;49; + + + 111;117;116;112;117;116;58;32;112;108;97;99;101;32;43;32;34;46;32;34;32;43;32;112;111;105;110;116;115;91;105;93; + + + + +`,X9=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;119;104;111;108;101;32;110;117;109;98;101;114;34; + + + 83;116;114;105;110;103;32;98;105;110;97;114;121;32;61;32;34;34; + + + 110;117;109;98;101;114;32;62;32;48; + + + 105;110;116;32;114;101;109;97;105;110;100;101;114;32;61;32;110;117;109;98;101;114;32;37;32;50; + + + 98;105;110;97;114;121;32;61;32;114;101;109;97;105;110;100;101;114;32;43;32;98;105;110;97;114;121; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;47;32;50; + + + + + 111;117;116;112;117;116;58;32;98;105;110;97;114;121; + + +`,K9=` + + + 99;104;97;114;91;93;32;97;108;112;104;97;98;101;116;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;100;32;34;87;104;105;99;104;32;119;111;114;100;32;40;99;97;112;105;116;97;108;32;108;101;116;116;101;114;115;32;111;110;108;121;41;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;75;32;34;83;104;105;102;116;32;98;121;32;104;111;119;32;109;97;110;121;32;112;108;97;99;101;115;63;34; + + + 83;116;114;105;110;103;32;115;101;99;114;101;116;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;119;111;114;100;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 99;104;97;114;32;90;32;61;32;119;111;114;100;46;99;104;97;114;65;116;40;105;41; + + + 105;110;116;32;112;111;115;32;61;32;48; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;97;108;112;104;97;98;101;116;46;108;101;110;103;116;104; + 106;43;43; + + + 97;108;112;104;97;98;101;116;91;106;93;32;61;61;32;90; + + + 112;111;115;32;61;32;106; + + + + + 248; + + + + + + + 115;101;99;114;101;116;32;61;32;115;101;99;114;101;116;32;43;32;97;108;112;104;97;98;101;116;91;40;112;111;115;32;43;32;75;41;32;37;32;50;54;93; + + + + + 111;117;116;112;117;116;58;32;115;101;99;114;101;116; + + +`,e5=` + + + 99;104;97;114;91;93;32;97;108;112;104;97;98;101;116;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; + + +`,t5=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;100;32;34;87;104;105;99;104;32;119;111;114;100;32;40;99;97;112;105;116;97;108;32;108;101;116;116;101;114;115;32;111;110;108;121;41;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;75;32;34;83;104;105;102;116;32;98;121;32;104;111;119;32;109;97;110;121;32;112;108;97;99;101;115;63;34; + + + 83;116;114;105;110;103;32;115;101;99;114;101;116;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;119;111;114;100;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 105;110;116;32;99;111;100;101;32;61;32;40;105;110;116;41;32;119;111;114;100;46;99;104;97;114;65;116;40;105;41; + + + 99;111;100;101;32;61;32;40;99;111;100;101;32;45;32;54;53;32;43;32;75;41;32;37;32;50;54;32;43;32;54;53; + + + 115;101;99;114;101;116;32;61;32;115;101;99;114;101;116;32;43;32;40;99;104;97;114;41;32;99;111;100;101; + + + + + 111;117;116;112;117;116;58;32;115;101;99;114;101;116; + + +`,n5=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;115;101;99;114;101;116;32;34;87;104;105;99;104;32;115;101;99;114;101;116;32;116;101;120;116;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;75;32;34;83;104;105;102;116;32;98;121;32;104;111;119;32;109;97;110;121;32;112;108;97;99;101;115;63;34; + + + 83;116;114;105;110;103;32;112;108;97;105;110;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;115;101;99;114;101;116;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 105;110;116;32;99;111;100;101;32;61;32;40;105;110;116;41;32;115;101;99;114;101;116;46;99;104;97;114;65;116;40;105;41; + + + 99;111;100;101;32;61;32;40;99;111;100;101;32;45;32;54;53;32;45;32;75;32;43;32;50;54;41;32;37;32;50;54;32;43;32;54;53; + + + 112;108;97;105;110;32;61;32;112;108;97;105;110;32;43;32;40;99;104;97;114;41;32;99;111;100;101; + + + + + 111;117;116;112;117;116;58;32;112;108;97;105;110; + + +`,i5=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;115;116;97;114;116;32;110;117;109;98;101;114;34; + + + 105;110;116;32;115;116;101;112;115;32;61;32;48; + + + 110;117;109;98;101;114;32;33;61;32;49; + + + 110;117;109;98;101;114;32;37;32;50;32;61;61;32;48; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;47;32;50; + + + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;42;32;51;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + + 115;116;101;112;115;43;43; + + + + + 111;117;116;112;117;116;58;32;34;83;116;101;112;115;58;32;34;32;43;32;115;116;101;112;115; + + +`,a5=` + + + 105;110;112;117;116;58;32;105;110;116;32;99;111;117;110;116;32;34;72;111;119;32;109;97;110;121;32;103;114;97;100;101;115;63;34; + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;111;117;110;116; + 105;43;43; + + + 105;110;112;117;116;58;32;105;110;116;32;103;114;97;100;101;32;34;69;110;116;101;114;32;97;32;103;114;97;100;101;34; + + + 115;117;109;32;61;32;115;117;109;32;43;32;103;114;97;100;101; + + + + + 100;111;117;98;108;101;32;97;118;101;114;97;103;101;32;61;32;115;117;109;32;42;32;49;46;48;32;47;32;99;111;117;110;116; + + + 111;117;116;112;117;116;58;32;97;118;101;114;97;103;101; + + +`,s5=` + + + 105;110;112;117;116;58;32;105;110;116;32;99;111;117;110;116;32;34;72;111;119;32;109;97;110;121;32;110;117;109;98;101;114;115;63;34; + + + 105;110;116;32;110;117;109;98;101;114;49;32;61;32;49; + + + 105;110;116;32;110;117;109;98;101;114;50;32;61;32;49; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114;49; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114;50; + + + 105;110;116;32;105;32;61;32;50; + 105;32;60;32;99;111;117;110;116; + 105;43;43; + + + 105;110;116;32;110;117;109;98;101;114;51;32;61;32;110;117;109;98;101;114;49;32;43;32;110;117;109;98;101;114;50; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114;51; + + + 110;117;109;98;101;114;49;32;61;32;110;117;109;98;101;114;50; + + + 110;117;109;98;101;114;50;32;61;32;110;117;109;98;101;114;51; + + + + +`,r5=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;34; + + + 110;117;109;98;101;114;32;37;32;50;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114;32;43;32;34;32;105;115;32;101;118;101;110;34; + + + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114;32;43;32;34;32;105;115;32;111;100;100;34; + + + + +`,o5=` + + + 99;111;110;115;116;32;100;111;117;98;108;101;32;86;65;84;32;61;32;48;46;49;57; + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;110;101;116;80;114;105;99;101;32;34;78;101;116;32;112;114;105;99;101;63;34; + + + 100;111;117;98;108;101;32;116;97;120;32;61;32;110;101;116;80;114;105;99;101;32;42;32;86;65;84; + + + 100;111;117;98;108;101;32;103;114;111;115;115;80;114;105;99;101;32;61;32;110;101;116;80;114;105;99;101;32;43;32;116;97;120; + + + 111;117;116;112;117;116;58;32;116;97;120; + + + 111;117;116;112;117;116;58;32;103;114;111;115;115;80;114;105;99;101; + + +`,l5=` + + + 105;110;116;32;112;105;110;32;61;32;48; + + + 105;110;116;32;97;116;116;101;109;112;116;115;32;61;32;48; + + + 112;105;110;32;33;61;32;49;50;51;52;32;38;38;32;97;116;116;101;109;112;116;115;32;60;32;51; + + + 105;110;112;117;116;58;32;105;110;116;32;101;110;116;101;114;101;100;32;34;69;110;116;101;114;32;80;73;78;34; + + + 112;105;110;32;61;32;101;110;116;101;114;101;100; + + + 97;116;116;101;109;112;116;115;43;43; + + + + + 112;105;110;32;61;61;32;49;50;51;52; + + + 111;117;116;112;117;116;58;32;34;80;73;78;32;99;111;114;114;101;99;116;34; + + + + + 111;117;116;112;117;116;58;32;34;67;97;114;100;32;98;108;111;99;107;101;100;34; + + + + +`,u5=` + + + 99;111;110;115;116;32;105;110;116;32;80;73;78;32;61;32;49;50;51;52; + + + 105;110;116;32;112;105;110;32;61;32;48; + + + 105;110;116;32;97;116;116;101;109;112;116;115;32;61;32;48; + + + 112;105;110;32;33;61;32;80;73;78;32;38;38;32;97;116;116;101;109;112;116;115;32;60;32;51; + + + 105;110;112;117;116;58;32;112;105;110;32;34;69;110;116;101;114;32;80;73;78;34; + + + 97;116;116;101;109;112;116;115;43;43; + + + + + 112;105;110;32;61;61;32;80;73;78; + + + 111;117;116;112;117;116;58;32;34;80;73;78;32;99;111;114;114;101;99;116;34; + + + + + 111;117;116;112;117;116;58;32;34;67;97;114;100;32;98;108;111;99;107;101;100;34; + + + + +`,c5=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;49;32;34;70;105;114;115;116;32;110;117;109;98;101;114;34; + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;50;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;111;112;101;114;97;116;111;114;32;34;79;112;101;114;97;116;111;114;32;40;43;44;32;45;32;111;114;32;42;41;34; + + + 111;112;101;114;97;116;111;114; + + + 105;110;116;32;114;101;115;117;108;116;32;61;32;110;117;109;98;101;114;49;32;43;32;110;117;109;98;101;114;50; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116; + + + + + 105;110;116;32;114;101;115;117;108;116;32;61;32;110;117;109;98;101;114;49;32;45;32;110;117;109;98;101;114;50; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116; + + + + + 105;110;116;32;114;101;115;117;108;116;32;61;32;110;117;109;98;101;114;49;32;42;32;110;117;109;98;101;114;50; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116; + + + + + 111;117;116;112;117;116;58;32;34;85;110;107;110;111;119;110;32;111;112;101;114;97;116;111;114;34; + + + + +`,m5=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; + + + 115;101;97;91;48;93;91;49;93;32;61;32;116;114;117;101; + + + 115;101;97;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 115;101;97;91;48;93;91;51;93;32;61;32;116;114;117;101; + + + 115;101;97;91;50;93;91;52;93;32;61;32;116;114;117;101; + + + 115;101;97;91;51;93;91;52;93;32;61;32;116;114;117;101; + + + 115;101;97;91;52;93;91;48;93;32;61;32;116;114;117;101; + + + 83;116;114;105;110;103;91;93;32;99;111;108;117;109;110;115;32;61;32;123;34;65;34;44;32;34;66;34;44;32;34;67;34;44;32;34;68;34;44;32;34;69;34;125; + + + 105;110;116;32;114;111;119;32;61;32;48; + 114;111;119;32;60;32;115;101;97;46;108;101;110;103;116;104; + 114;111;119;43;43; + + + 105;110;116;32;99;111;108;117;109;110;32;61;32;48; + 99;111;108;117;109;110;32;60;32;115;101;97;91;114;111;119;93;46;108;101;110;103;116;104; + 99;111;108;117;109;110;43;43; + + + 115;101;97;91;114;111;119;93;91;99;111;108;117;109;110;93; + + + 111;117;116;112;117;116;58;32;99;111;108;117;109;110;115;91;99;111;108;117;109;110;93;32;43;32;40;114;111;119;32;43;32;49;41; + + + + + 248; + + + + + + + + +`,d5=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; + + + 115;101;97;91;48;93;91;49;93;32;61;32;116;114;117;101; + + + 115;101;97;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 115;101;97;91;48;93;91;51;93;32;61;32;116;114;117;101; + + + 115;101;97;91;50;93;91;52;93;32;61;32;116;114;117;101; + + + 115;101;97;91;51;93;91;52;93;32;61;32;116;114;117;101; + + + 115;101;97;91;52;93;91;48;93;32;61;32;116;114;117;101; + + + 83;116;114;105;110;103;91;93;32;99;111;108;117;109;110;115;32;61;32;123;34;65;34;44;32;34;66;34;44;32;34;67;34;44;32;34;68;34;44;32;34;69;34;125; + + +`,h5=` + + + 105;110;112;117;116;58;32;105;110;116;32;112;105;99;107;32;34;87;104;105;99;104;32;100;105;115;104;63;32;40;49;44;32;50;32;111;114;32;51;41;34; + + + 112;105;99;107; + + + 111;117;116;112;117;116;58;32;34;71;114;101;101;107;32;115;97;108;97;100;34; + + + + + 111;117;116;112;117;116;58;32;34;82;105;99;101;32;98;111;119;108;34; + + + + + 111;117;116;112;117;116;58;32;34;70;97;108;97;102;101;108;32;119;114;97;112;34; + + + + + 111;117;116;112;117;116;58;32;34;80;108;101;97;115;101;32;99;104;111;111;115;101;32;97;32;118;97;108;105;100;32;110;117;109;98;101;114;34; + + + + +`,g5=` + + + 105;110;116;32;110;117;109;98;101;114;49;32;61;32;52; + + + 105;110;116;32;110;117;109;98;101;114;50;32;61;32;51; + + + 105;110;116;32;115;117;109;32;61;32;110;117;109;98;101;114;49;32;43;32;110;117;109;98;101;114;50; + + + 111;117;116;112;117;116;58;32;115;117;109; + + +`,p5=` + + + 83;116;114;105;110;103;91;93;32;110;97;109;101;115;32;61;32;110;101;119;32;83;116;114;105;110;103;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;97;109;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;97;109;101;115;91;105;93;32;34;69;110;116;101;114;32;97;32;110;97;109;101;34; + + + + + 105;110;112;117;116;58;32;105;110;116;32;112;105;99;107;32;34;68;114;97;119;32;110;117;109;98;101;114;32;40;49;32;116;111;32;53;41;34; + + + 111;117;116;112;117;116;58;32;34;66;111;97;114;100;32;100;117;116;121;58;32;34;32;43;32;110;97;109;101;115;91;112;105;99;107;32;45;32;49;93; + + +`,f5=` + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;52; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;42;32;50; + + + 111;117;116;112;117;116;58;32;34;68;111;117;98;108;101;100;32;110;117;109;98;101;114;58;32;34;32;43;32;110;117;109;98;101;114; + + +`,b5=` + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;99;104;111;105;99;101;32;34;49;32;61;32;101;45;98;105;107;101;44;32;50;32;61;32;101;45;115;99;111;111;116;101;114;44;32;48;32;61;32;113;117;105;116;34; + + + 99;104;111;105;99;101;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;34;66;121;101;34; + + + -1; + + + + + 99;104;111;105;99;101;32;61;61;32;49; + + + 111;117;116;112;117;116;58;32;34;69;45;98;105;107;101;32;98;111;111;107;101;100;34; + + + + + 99;104;111;105;99;101;32;61;61;32;50; + + + 111;117;116;112;117;116;58;32;34;69;45;115;99;111;111;116;101;114;32;98;111;111;107;101;100;34; + + + + + 111;117;116;112;117;116;58;32;34;73;110;118;97;108;105;100;32;99;104;111;105;99;101;34; + + + + + + + + + + +`,x5=` + + + + + + 105;110;112;117;116;58;32;105;110;116;32;99;104;111;105;99;101;32;34;49;32;61;32;101;45;98;105;107;101;44;32;50;32;61;32;101;45;115;99;111;111;116;101;114;44;32;48;32;61;32;113;117;105;116;34; + + + 99;104;111;105;99;101; + + + 111;117;116;112;117;116;58;32;34;66;121;101;34; + + + 76;101;97;118;101;32;116;104;101;32;109;101;110;117; + + + + + 111;117;116;112;117;116;58;32;34;69;45;98;105;107;101;32;98;111;111;107;101;100;34; + + + + + 111;117;116;112;117;116;58;32;34;69;45;115;99;111;111;116;101;114;32;98;111;111;107;101;100;34; + + + + + 111;117;116;112;117;116;58;32;34;73;110;118;97;108;105;100;32;99;104;111;105;99;101;34; + + + + + + +`,v5=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;119;111;114;100;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 105;110;116;32;114;105;103;104;116;32;61;32;48; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 108;105;110;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;115;32;61;32;108;105;110;101;46;115;112;108;105;116;40;34;59;34;41; + + + 111;117;116;112;117;116;58;32;34;87;104;97;116;32;105;115;32;34;32;43;32;112;97;114;116;115;91;48;93;32;43;32;34;32;105;110;32;71;101;114;109;97;110;63;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;97;110;115;119;101;114; + + + 99;111;117;110;116;43;43; + + + 97;110;115;119;101;114;46;101;113;117;97;108;115;40;112;97;114;116;115;91;49;93;41; + + + 111;117;116;112;117;116;58;32;34;82;105;103;104;116;33;34; + + + 114;105;103;104;116;43;43; + + + + + 111;117;116;112;117;116;58;32;34;87;114;111;110;103;44;32;105;116;32;105;115;32;34;32;43;32;112;97;114;116;115;91;49;93;32;43;32;34;46;34; + + + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 114;101;97;100;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;114;105;103;104;116;32;43;32;34;32;111;102;32;34;32;43;32;99;111;117;110;116;32;43;32;34;32;114;105;103;104;116;34; + + +`,y5=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;119;111;114;100;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,w5=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; + + + 97;103;101;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;97;100;117;108;116;34; + + + + + 111;117;116;112;117;116;58;32;34;109;105;110;111;114;34; + + + + +`,z5=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;101;32;33;61;32;110;117;108;108; + + + 111;117;116;112;117;116;58;32;108;105;110;101; + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 114;101;97;100;101;114;46;99;108;111;115;101;40;41; + + +`,I5=` + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;34;90;111;114;97;59;49;59;50;59;50;34; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;115;32;61;32;108;105;110;101;46;115;112;108;105;116;40;34;59;34;41; + + + 83;116;114;105;110;103;32;110;97;109;101;32;61;32;112;97;114;116;115;91;48;93; + + + 105;110;116;32;109;97;116;104;115;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;112;97;114;116;115;91;49;93;41; + + + 111;117;116;112;117;116;58;32;110;97;109;101;32;43;32;34;32;103;111;116;32;97;32;34;32;43;32;109;97;116;104;115;32;43;32;34;32;105;110;32;109;97;116;104;115;34; + + +`,k5=` + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;34;123;92;34;110;97;109;101;92;34;58;32;92;34;90;111;114;97;92;34;44;32;92;34;115;112;101;99;105;101;115;92;34;58;32;92;34;103;111;97;116;92;34;44;32;92;34;97;103;101;92;34;58;32;54;125;44;34; + + + 105;110;116;32;115;116;97;114;116;32;61;32;108;105;110;101;46;105;110;100;101;120;79;102;40;34;92;34;110;97;109;101;92;34;58;32;92;34;34;41;32;43;32;57; + + + 105;110;116;32;101;110;100;32;61;32;108;105;110;101;46;105;110;100;101;120;79;102;40;34;92;34;34;44;32;115;116;97;114;116;41; + + + 83;116;114;105;110;103;32;110;97;109;101;32;61;32;108;105;110;101;46;115;117;98;115;116;114;105;110;103;40;115;116;97;114;116;44;32;101;110;100;41; + + + 111;117;116;112;117;116;58;32;110;97;109;101; + + +`,S5=` + + + 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; + + + 102;105;108;101;46;104;97;115;78;101;120;116;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;102;105;108;101;46;110;101;120;116;76;105;110;101;40;41; + + + 111;117;116;112;117;116;58;32;108;105;110;101; + + + + + 102;105;108;101;46;99;108;111;115;101;40;41; + + +`,T5=` + + + 105;110;116;91;93;91;93;32;116;97;98;108;101;32;61;32;110;101;119;32;105;110;116;91;49;48;93;91;49;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;97;98;108;101;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;116;97;98;108;101;91;105;93;46;108;101;110;103;116;104; + 106;43;43; + + + 116;97;98;108;101;91;105;93;91;106;93;32;61;32;40;105;32;43;32;49;41;32;42;32;40;106;32;43;32;49;41; + + + + + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;32;40;49;32;116;111;32;49;48;41;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;32;40;49;32;116;111;32;49;48;41;34; + + + 111;117;116;112;117;116;58;32;97;32;43;32;34;32;183;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;116;97;98;108;101;91;97;32;45;32;49;93;91;98;32;45;32;49;93; + + +`,_5=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;101;97;116;115;91;48;93;91;48;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;50;93;91;51;93;32;61;32;116;114;117;101; + + + 105;110;116;32;102;114;101;101;32;61;32;48; + + + 105;110;116;32;114;111;119;32;61;32;48; + 114;111;119;32;60;32;115;101;97;116;115;46;108;101;110;103;116;104; + 114;111;119;43;43; + + + 105;110;116;32;115;101;97;116;32;61;32;48; + 115;101;97;116;32;60;32;115;101;97;116;115;91;114;111;119;93;46;108;101;110;103;116;104; + 115;101;97;116;43;43; + + + 33;115;101;97;116;115;91;114;111;119;93;91;115;101;97;116;93; + + + 102;114;101;101;32;61;32;102;114;101;101;32;43;32;49; + + + + + 248; + + + + + + + + + 111;117;116;112;117;116;58;32;34;70;114;101;101;58;32;34;32;43;32;102;114;101;101; + + +`,A5=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;101;97;116;115;91;48;93;91;48;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;50;93;91;51;93;32;61;32;116;114;117;101; + + +`,O5=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;101;97;116;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;49;93;91;51;93;32;61;32;116;114;117;101; + + + 105;110;112;117;116;58;32;105;110;116;32;114;111;119;32;34;82;111;119;34; + + + 105;110;112;117;116;58;32;105;110;116;32;115;101;97;116;32;34;83;101;97;116;34; + + + 115;101;97;116;115;91;114;111;119;93;91;115;101;97;116;93; + + + 111;117;116;112;117;116;58;32;34;65;108;114;101;97;100;121;32;115;111;108;100;34; + + + + + 115;101;97;116;115;91;114;111;119;93;91;115;101;97;116;93;32;61;32;116;114;117;101; + + + 111;117;116;112;117;116;58;32;34;83;111;108;100;58;32;114;111;119;32;34;32;43;32;114;111;119;32;43;32;34;44;32;115;101;97;116;32;34;32;43;32;115;101;97;116; + + + + +`,C5=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;101;97;116;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;49;93;91;51;93;32;61;32;116;114;117;101; + + + 105;110;112;117;116;58;32;105;110;116;32;114;111;119;32;34;82;111;119;34; + + + 105;110;112;117;116;58;32;105;110;116;32;115;101;97;116;32;34;83;101;97;116;34; + + +`,j5=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;101;97;116;115;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;49;93;91;49;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 105;110;116;32;114;111;119;32;61;32;48; + 114;111;119;32;60;32;115;101;97;116;115;46;108;101;110;103;116;104; + 114;111;119;43;43; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;34;34; + + + 105;110;116;32;115;101;97;116;32;61;32;48; + 115;101;97;116;32;60;32;115;101;97;116;115;91;114;111;119;93;46;108;101;110;103;116;104; + 115;101;97;116;43;43; + + + 115;101;97;116;115;91;114;111;119;93;91;115;101;97;116;93; + + + 108;105;110;101;32;61;32;108;105;110;101;32;43;32;34;88;34; + + + + + 108;105;110;101;32;61;32;108;105;110;101;32;43;32;34;79;34; + + + + + + + 111;117;116;112;117;116;58;32;108;105;110;101; + + + + +`,P5=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;101;97;116;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;101;97;116;115;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;49;93;91;49;93;32;61;32;116;114;117;101; + + + 115;101;97;116;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 111;117;116;112;117;116;58;32;34;82;111;119;115;58;32;34;32;43;32;115;101;97;116;115;46;108;101;110;103;116;104; + + + 111;117;116;112;117;116;58;32;34;83;101;97;116;115;32;112;101;114;32;114;111;119;58;32;34;32;43;32;115;101;97;116;115;91;48;93;46;108;101;110;103;116;104; + + + 111;117;116;112;117;116;58;32;34;82;111;119;32;49;44;32;115;101;97;116;32;50;32;115;111;108;100;63;32;34;32;43;32;115;101;97;116;115;91;49;93;91;50;93; + + +`,D5=` + + + 105;110;116;32;115;101;99;111;110;100;115;32;61;32;50;48;48; + + + 105;110;116;32;109;105;110;117;116;101;115;32;61;32;115;101;99;111;110;100;115;32;47;32;54;48; + + + 105;110;116;32;114;101;115;116;32;61;32;115;101;99;111;110;100;115;32;37;32;54;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;101;115;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;32;43;32;34;32;115;34; + + +`,B5=` + + + 105;110;116;32;115;101;99;111;110;100;115;32;61;32;50;48;48; + + + 105;110;116;32;109;105;110;117;116;101;115;32;61;32;115;101;99;111;110;100;115;32;37;32;54;48; + + + 105;110;116;32;114;101;115;116;32;61;32;115;101;99;111;110;100;115;32;47;32;54;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;101;115;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;32;43;32;34;32;115;34; + + +`,M5=` + + + 83;116;114;105;110;103;32;110;97;109;101;32;61;32;34;76;117;100;119;105;103;34; + + + 105;110;116;32;97;103;101;32;61;32;55; + + + 100;111;117;98;108;101;32;104;101;105;103;104;116;32;61;32;49;46;50; + + + 111;117;116;112;117;116;58;32;110;97;109;101;32;43;32;34;32;105;115;32;34;32;43;32;97;103;101;32;43;32;34;32;121;101;97;114;115;32;111;108;100;46;34; + + + 111;117;116;112;117;116;58;32;34;72;101;105;103;104;116;58;32;34;32;43;32;104;101;105;103;104;116;32;43;32;34;32;109;34; + + +`,Z5=` + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;51; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;42;32;50; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;43;32;49; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + +`,L5=` + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;50; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;43;32;51; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;42;32;52; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + +`,E5=` + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;42;32;52; + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;50; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;43;32;51; + + +`,W5=` + + + 83;116;114;105;110;103;32;108;101;102;116;32;61;32;34;106;117;105;99;101;34; + + + 83;116;114;105;110;103;32;114;105;103;104;116;32;61;32;34;119;97;116;101;114;34; + + + 83;116;114;105;110;103;32;116;101;109;112;32;61;32;108;101;102;116; + + + 108;101;102;116;32;61;32;114;105;103;104;116; + + + 114;105;103;104;116;32;61;32;116;101;109;112; + + + 111;117;116;112;117;116;58;32;34;76;101;102;116;58;32;34;32;43;32;108;101;102;116; + + + 111;117;116;112;117;116;58;32;34;82;105;103;104;116;58;32;34;32;43;32;114;105;103;104;116; + + +`,N5=` + + + 83;116;114;105;110;103;32;108;101;102;116;32;61;32;34;106;117;105;99;101;34; + + + 83;116;114;105;110;103;32;114;105;103;104;116;32;61;32;34;119;97;116;101;114;34; + + + 111;117;116;112;117;116;58;32;34;76;101;102;116;58;32;34;32;43;32;108;101;102;116; + + + 111;117;116;112;117;116;58;32;34;82;105;103;104;116;58;32;34;32;43;32;114;105;103;104;116; + + +`,F5=` + + + 105;110;116;32;97;32;61;32;53; + + + 105;110;116;32;98;32;61;32;57; + + + 105;110;116;32;116;101;109;112;32;61;32;97; + + + 97;32;61;32;98; + + + 98;32;61;32;116;101;109;112; + + + 111;117;116;112;117;116;58;32;34;97;32;61;32;34;32;43;32;97; + + + 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; + + +`,J5=` + + + 105;110;116;32;97;103;101;32;61;32;49;52; + + + 100;111;117;98;108;101;32;104;101;105;103;104;116;32;61;32;49;46;54;50; + + + 83;116;114;105;110;103;32;110;97;109;101;32;61;32;34;77;105;97;34; + + + 111;117;116;112;117;116;58;32;110;97;109;101;32;43;32;34;32;105;115;32;34;32;43;32;97;103;101;32;43;32;34;32;121;101;97;114;115;32;111;108;100;46;34; + + + 111;117;116;112;117;116;58;32;34;72;101;105;103;104;116;58;32;34;32;43;32;104;101;105;103;104;116;32;43;32;34;32;109;34; + + +`,R5=` + + + 105;110;116;32;109;105;110;117;116;101;115;32;61;32;49;51;53; + + + 105;110;116;32;104;111;117;114;115;32;61;32;109;105;110;117;116;101;115;32;47;32;54;48; + + + 105;110;116;32;114;101;109;97;105;110;100;101;114;32;61;32;109;105;110;117;116;101;115;32;37;32;54;48; + + + 111;117;116;112;117;116;58;32;104;111;117;114;115;32;43;32;34;32;104;111;117;114;115;32;97;110;100;32;34;32;43;32;114;101;109;97;105;110;100;101;114;32;43;32;34;32;109;105;110;117;116;101;115;34; + + +`,G5=` + + + 105;110;116;32;99;111;117;110;116;32;61;32;51; + + + 100;111;117;98;108;101;32;112;114;105;99;101;32;61;32;50;46;53; + + + 100;111;117;98;108;101;32;116;111;116;97;108;80;114;105;99;101;32;61;32;99;111;117;110;116;32;42;32;112;114;105;99;101; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108;80;114;105;99;101;32;43;32;34;32;101;117;114;111;115;34; + + +`,H5=` + + + 105;110;116;32;99;114;101;100;105;116;32;61;32;50;48; + + + 105;110;116;32;112;114;105;99;101;32;61;32;55; + + + 99;114;101;100;105;116;32;61;32;99;114;101;100;105;116;32;45;32;112;114;105;99;101; + + + 111;117;116;112;117;116;58;32;34;76;101;102;116;58;32;34;32;43;32;99;114;101;100;105;116; + + +`,V5=` + + + 105;110;116;32;99;114;101;100;105;116;32;61;32;50;48; + + + 105;110;116;32;112;114;105;99;101;32;61;32;55; + + + 111;117;116;112;117;116;58;32;34;76;101;102;116;58;32;34;32;43;32;99;114;101;100;105;116; + + + 99;114;101;100;105;116;32;61;32;99;114;101;100;105;116;32;45;32;112;114;105;99;101; + + +`,q5=` + + + 105;110;116;32;112;114;105;99;101;32;61;32;57; + + + 105;110;116;32;99;111;117;110;116;32;61;32;51; + + + 105;110;116;32;116;111;116;97;108;32;61;32;112;114;105;99;101;32;42;32;99;111;117;110;116; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + +`,Q5=` + + + 105;110;116;32;108;101;110;103;116;104;32;61;32;55; + + + 105;110;116;32;119;105;100;116;104;32;61;32;52; + + + 105;110;116;32;97;114;101;97;32;61;32;108;101;110;103;116;104;32;42;32;119;105;100;116;104; + + + 105;110;116;32;112;101;114;105;109;101;116;101;114;32;61;32;50;32;42;32;40;108;101;110;103;116;104;32;43;32;119;105;100;116;104;41; + + + 111;117;116;112;117;116;58;32;34;65;114;101;97;58;32;34;32;43;32;97;114;101;97; + + + 111;117;116;112;117;116;58;32;34;80;101;114;105;109;101;116;101;114;58;32;34;32;43;32;112;101;114;105;109;101;116;101;114; + + +`,U5=` + + + 105;110;116;32;115;101;99;111;110;100;115;32;61;32;50;48;48; + + + 105;110;116;32;109;105;110;117;116;101;115;32;61;32;115;101;99;111;110;100;115;32;47;32;54;48; + + + 105;110;116;32;114;101;109;97;105;110;100;101;114;32;61;32;115;101;99;111;110;100;115;32;37;32;54;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;101;115;32;43;32;34;32;109;105;110;117;116;101;115;32;97;110;100;32;34;32;43;32;114;101;109;97;105;110;100;101;114;32;43;32;34;32;115;101;99;111;110;100;115;34; + + +`,$5=` + + + 105;110;116;32;115;101;99;111;110;100;115;32;61;32;50;48;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;101;115;32;43;32;34;32;109;105;110;117;116;101;115;32;97;110;100;32;34;32;43;32;114;101;109;97;105;110;100;101;114;32;43;32;34;32;115;101;99;111;110;100;115;34; + + +`,Y5=` + + + 105;110;116;32;108;101;110;103;116;104;32;61;32;53; + + + 105;110;116;32;119;105;100;116;104;32;61;32;51; + + + 105;110;116;32;97;114;101;97;32;61;32;108;101;110;103;116;104;32;42;32;119;105;100;116;104; + + + 111;117;116;112;117;116;58;32;97;114;101;97; + + +`,X5=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;97;109;101;32;34;87;104;97;116;32;105;115;32;121;111;117;114;32;110;97;109;101;63;34; + + + 111;117;116;112;117;116;58;32;34;72;101;108;108;111;32;34;32;43;32;110;97;109;101;32;43;32;34;33;34; + + +`,K5=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;115;117;109;32;61;32;97;32;43;32;98; + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; + + +`,ez=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;63;34; + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;40;97;32;43;32;98;41; + + +`,tz=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;63;34; + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;97;32;43;32;98; + + +`,nz=` + + + 105;110;112;117;116;58;32;105;110;116;32;121;101;97;114;115;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; + + + 105;110;116;32;100;97;121;115;32;61;32;121;101;97;114;115;32;42;32;51;54;53; + + + 111;117;116;112;117;116;58;32;34;84;104;97;116;32;105;115;32;97;98;111;117;116;32;34;32;43;32;100;97;121;115;32;43;32;34;32;100;97;121;115;46;34; + + +`,iz=` + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;120;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;121;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;63;34; + + + 100;111;117;98;108;101;32;109;101;97;110;32;61;32;40;120;32;43;32;121;41;32;47;32;50; + + + 111;117;116;112;117;116;58;32;34;77;101;97;110;58;32;34;32;43;32;109;101;97;110; + + +`,az=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;115;117;109;32;61;32;97;32;43;32;98; + + + 105;110;116;32;112;114;111;100;117;99;116;32;61;32;97;32;42;32;98; + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; + + + 111;117;116;112;117;116;58;32;34;80;114;111;100;117;99;116;58;32;34;32;43;32;112;114;111;100;117;99;116; + + +`,sz=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; + + + 97;103;101;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;89;111;117;32;97;114;101;32;97;110;32;97;100;117;108;116;46;34; + + + + + 111;117;116;112;117;116;58;32;34;89;111;117;32;97;114;101;32;110;111;116;32;97;110;32;97;100;117;108;116;32;121;101;116;46;34; + + + + +`,rz=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;78;117;109;98;101;114;63;34; + + + 110;117;109;98;101;114;32;60;32;48; + + + 110;117;109;98;101;114;32;61;32;48;32;45;32;110;117;109;98;101;114; + + + + + 248; + + + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + +`,oz=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;78;117;109;98;101;114;63;34; + + + 110;117;109;98;101;114;32;37;32;50;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;34;101;118;101;110;34; + + + + + 111;117;116;112;117;116;58;32;34;111;100;100;34; + + + + +`,lz=` + + + 105;110;116;32;112;111;105;110;116;115;32;61;32;48; + + + 112;111;105;110;116;115;32;61;32;112;111;105;110;116;115;32;43;32;49;48; + + + 112;111;105;110;116;115;32;61;32;112;111;105;110;116;115;32;43;32;53; + + + 112;111;105;110;116;115;32;61;32;112;111;105;110;116;115;32;45;32;51; + + + 111;117;116;112;117;116;58;32;34;80;111;105;110;116;115;58;32;34;32;43;32;112;111;105;110;116;115; + + +`,uz=` + + + 105;110;116;32;112;111;105;110;116;115;32;61;32;48; + + + 112;111;105;110;116;115;32;61;32;112;111;105;110;116;115;32;43;32;49;48; + + + 112;111;105;110;116;115;32;61;32;112;111;105;110;116;115;32;43;32;53; + + + 112;111;105;110;116;115;32;61;32;51; + + + 111;117;116;112;117;116;58;32;34;80;111;105;110;116;115;58;32;34;32;43;32;112;111;105;110;116;115; + + +`,cz=` + + + 105;110;116;32;112;114;105;99;101;32;61;32;56; + + + 105;110;116;32;99;104;101;101;115;101;32;61;32;50; + + + 105;110;116;32;99;111;117;110;116;32;61;32;51; + + + 105;110;116;32;116;111;116;97;108;32;61;32;40;112;114;105;99;101;32;43;32;99;104;101;101;115;101;41;32;42;32;99;111;117;110;116; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + +`,mz=` + + + 105;110;116;32;112;114;105;99;101;32;61;32;56; + + + 105;110;116;32;99;104;101;101;115;101;32;61;32;50; + + + 105;110;116;32;99;111;117;110;116;32;61;32;51; + + + 105;110;116;32;116;111;116;97;108;32;61;32;112;114;105;99;101;32;43;32;99;104;101;101;115;101;32;42;32;99;111;117;110;116; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + +`,dz=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;63;34; + + + 97;32;62;32;98; + + + 111;117;116;112;117;116;58;32;97; + + + + + 111;117;116;112;117;116;58;32;98; + + + + +`,hz=` + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;112;114;105;99;101;32;34;80;114;105;99;101;32;105;110;32;101;117;114;111;115;63;34; + + + 112;114;105;99;101;32;62;32;53;48; + + + 112;114;105;99;101;32;61;32;112;114;105;99;101;32;45;32;53; + + + + + 248; + + + + + 111;117;116;112;117;116;58;32;34;84;111;32;112;97;121;58;32;34;32;43;32;112;114;105;99;101;32;43;32;34;32;101;117;114;111;115;34; + + +`,gz=` + + + 105;110;112;117;116;58;32;105;110;116;32;103;114;97;100;101;32;34;71;114;97;100;101;63;34; + + + 103;114;97;100;101;32;62;61;32;49;32;38;38;32;103;114;97;100;101;32;60;61;32;54; + + + 111;117;116;112;117;116;58;32;34;118;97;108;105;100;34; + + + + + 111;117;116;112;117;116;58;32;34;105;110;118;97;108;105;100;34; + + + + +`,pz=` + + + 105;110;112;117;116;58;32;105;110;116;32;112;111;105;110;116;115;32;34;72;111;119;32;109;97;110;121;32;112;111;105;110;116;115;63;34; + + + 112;111;105;110;116;115;32;62;61;32;53;48; + + + 111;117;116;112;117;116;58;32;34;112;97;115;115;101;100;34; + + + + + 111;117;116;112;117;116;58;32;34;110;111;116;32;112;97;115;115;101;100;34; + + + + +`,fz=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; + + + 97;103;101;32;60;32;54; + + + 111;117;116;112;117;116;58;32;34;70;114;101;101;32;101;110;116;114;121;34; + + + + + 111;117;116;112;117;116;58;32;34;52;32;101;117;114;111;115;34; + + + + +`,bz=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; + + + 97;103;101;32;60;61;32;54; + + + 111;117;116;112;117;116;58;32;34;70;114;101;101;32;101;110;116;114;121;34; + + + + + 111;117;116;112;117;116;58;32;34;52;32;101;117;114;111;115;34; + + + + +`,xz=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; + + + 97;103;101;32;62;61;32;49;50;32;38;38;32;97;103;101;32;60;32;49;56; + + + 111;117;116;112;117;116;58;32;34;89;111;117;116;104;32;116;105;99;107;101;116;34; + + + + + 111;117;116;112;117;116;58;32;34;78;111;32;121;111;117;116;104;32;116;105;99;107;101;116;34; + + + + +`,vz=` + + + 105;110;112;117;116;58;32;105;110;116;32;103;114;97;100;101;32;34;71;114;97;100;101;63;34; + + + 103;114;97;100;101;32;60;32;49;32;124;124;32;103;114;97;100;101;32;62;32;54; + + + 111;117;116;112;117;116;58;32;34;84;104;105;115;32;103;114;97;100;101;32;100;111;101;115;32;110;111;116;32;101;120;105;115;116;46;34; + + + + + 111;117;116;112;117;116;58;32;34;71;114;97;100;101;32;34;32;43;32;103;114;97;100;101;32;43;32;34;32;105;115;32;118;97;108;105;100;46;34; + + + + +`,yz=` + + + 105;110;112;117;116;58;32;105;110;116;32;121;101;97;114;32;34;89;101;97;114;63;34; + + + 40;121;101;97;114;32;37;32;52;32;61;61;32;48;32;38;38;32;121;101;97;114;32;37;32;49;48;48;32;33;61;32;48;41;32;124;124;32;121;101;97;114;32;37;32;52;48;48;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;34;76;101;97;112;32;121;101;97;114;34; + + + + + 111;117;116;112;117;116;58;32;34;78;111;116;32;97;32;108;101;97;112;32;121;101;97;114;34; + + + + +`,wz=` + + + 105;110;112;117;116;58;32;105;110;116;32;100;97;121;32;34;68;97;121;32;40;49;32;116;111;32;55;41;63;34; + + + 100;97;121;32;61;61;32;54;32;124;124;32;100;97;121;32;61;61;32;55; + + + 111;117;116;112;117;116;58;32;34;87;101;101;107;101;110;100;34; + + + + + 111;117;116;112;117;116;58;32;34;87;101;101;107;100;97;121;34; + + + + +`,zz=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;99;111;108;111;114;32;34;87;104;97;116;32;99;111;108;111;114;32;105;115;32;116;104;101;32;116;114;97;102;102;105;99;32;108;105;103;104;116;63;34; + + + 99;111;108;111;114; + + + 111;117;116;112;117;116;58;32;34;83;116;111;112;34; + + + + + 111;117;116;112;117;116;58;32;34;87;97;105;116;34; + + + + + 111;117;116;112;117;116;58;32;34;87;97;108;107;34; + + + + + 111;117;116;112;117;116;58;32;34;73;32;100;111;32;110;111;116;32;107;110;111;119;32;116;104;105;115;32;99;111;108;111;114;46;34; + + + + +`,Iz=` + + + 105;110;112;117;116;58;32;105;110;116;32;99;104;111;105;99;101;32;34;49;32;119;97;116;101;114;44;32;50;32;106;117;105;99;101;44;32;51;32;99;111;99;111;97;34; + + + 99;104;111;105;99;101; + + + 111;117;116;112;117;116;58;32;34;72;101;114;101;32;105;115;32;121;111;117;114;32;119;97;116;101;114;46;34; + + + + + 111;117;116;112;117;116;58;32;34;72;101;114;101;32;105;115;32;121;111;117;114;32;106;117;105;99;101;46;34; + + + + + 111;117;116;112;117;116;58;32;34;72;101;114;101;32;105;115;32;121;111;117;114;32;99;111;99;111;97;46;34; + + + + + 111;117;116;112;117;116;58;32;34;84;104;105;115;32;98;117;116;116;111;110;32;100;111;101;115;32;110;111;116;32;101;120;105;115;116;46;34; + + + + +`,kz=` + + + 105;110;112;117;116;58;32;105;110;116;32;100;97;121;32;34;87;104;105;99;104;32;100;97;121;32;40;49;32;116;111;32;55;41;63;34; + + + 100;97;121;32;61;61;32;54;32;124;124;32;100;97;121;32;61;61;32;55; + + + 111;117;116;112;117;116;58;32;34;110;111;32;115;99;104;111;111;108;34; + + + + + 111;117;116;112;117;116;58;32;34;115;99;104;111;111;108;34; + + + + +`,Sz=` + + + 105;110;112;117;116;58;32;105;110;116;32;100;97;121;32;34;87;104;105;99;104;32;100;97;121;32;40;49;32;116;111;32;55;41;63;34; + + + 100;97;121;32;61;61;32;54;32;38;38;32;100;97;121;32;61;61;32;55; + + + 111;117;116;112;117;116;58;32;34;110;111;32;115;99;104;111;111;108;34; + + + + + 111;117;116;112;117;116;58;32;34;115;99;104;111;111;108;34; + + + + +`,Tz=` + + + 105;110;112;117;116;58;32;105;110;116;32;104;111;117;114;32;34;87;104;97;116;32;116;105;109;101;32;105;115;32;105;116;32;40;106;117;115;116;32;116;104;101;32;104;111;117;114;41;63;34; + + + 104;111;117;114;32;62;61;32;56;32;38;38;32;104;111;117;114;32;60;61;32;49;53; + + + 111;117;116;112;117;116;58;32;34;83;99;104;111;111;108;34; + + + + + 111;117;116;112;117;116;58;32;34;70;114;101;101;32;116;105;109;101;34; + + + + +`,_z=` + + + 105;110;112;117;116;58;32;105;110;116;32;103;114;97;100;101;32;34;87;104;105;99;104;32;103;114;97;100;101;63;34; + + + 103;114;97;100;101; + + + 111;117;116;112;117;116;58;32;34;118;101;114;121;32;103;111;111;100;34; + + + + + 111;117;116;112;117;116;58;32;34;103;111;111;100;34; + + + + + 111;117;116;112;117;116;58;32;34;115;97;116;105;115;102;97;99;116;111;114;121;34; + + + + + 111;117;116;112;117;116;58;32;34;115;117;102;102;105;99;105;101;110;116;34; + + + + + 111;117;116;112;117;116;58;32;34;112;111;111;114;34; + + + + + 111;117;116;112;117;116;58;32;34;102;97;105;108;34; + + + + + 111;117;116;112;117;116;58;32;34;78;111;116;32;97;32;118;97;108;105;100;32;103;114;97;100;101;34; + + + + +`,Az=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;111;112;101;114;97;116;111;114;32;34;79;112;101;114;97;116;111;114;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;34; + + + 105;110;116;32;114;101;115;117;108;116;32;61;32;48; + + + 111;112;101;114;97;116;111;114; + + + 114;101;115;117;108;116;32;61;32;97;32;43;32;98; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116; + + + + + 114;101;115;117;108;116;32;61;32;97;32;45;32;98; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116; + + + + + 114;101;115;117;108;116;32;61;32;97;32;42;32;98; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116; + + + + + 111;117;116;112;117;116;58;32;34;85;110;107;110;111;119;110;32;111;112;101;114;97;116;111;114;34; + + + + +`,Oz=` + + + 105;110;112;117;116;58;32;105;110;116;32;99;104;111;105;99;101;32;34;49;32;119;97;116;101;114;44;32;50;32;106;117;105;99;101;44;32;51;32;99;111;99;111;97;34; + + + 99;104;111;105;99;101;32;61;61;32;49; + + + 111;117;116;112;117;116;58;32;34;72;101;114;101;32;105;115;32;121;111;117;114;32;119;97;116;101;114;46;34; + + + + + 99;104;111;105;99;101;32;61;61;32;50; + + + 111;117;116;112;117;116;58;32;34;72;101;114;101;32;105;115;32;121;111;117;114;32;106;117;105;99;101;46;34; + + + + + 99;104;111;105;99;101;32;61;61;32;51; + + + 111;117;116;112;117;116;58;32;34;72;101;114;101;32;105;115;32;121;111;117;114;32;99;111;99;111;97;46;34; + + + + + 111;117;116;112;117;116;58;32;34;84;104;105;115;32;98;117;116;116;111;110;32;100;111;101;115;32;110;111;116;32;101;120;105;115;116;46;34; + + + + + + + + +`,Cz=` + + + 80;117;116;32;97;32;99;117;112;32;111;110;32;116;104;101;32;116;97;98;108;101; + + + 83;117;103;97;114;32;119;97;110;116;101;100;63; + + + 65;100;100;32;115;117;103;97;114; + + + + + 248; + + + + + 84;101;97;32;115;116;105;108;108;32;116;111;111;32;104;111;116; + + + 87;97;105;116;32;49;32;109;105;110;117;116;101; + + + + + 68;114;105;110;107;32;116;104;101;32;116;101;97; + + +`,jz=` + + + 71;101;116;32;117;112; + + + 66;114;117;115;104;32;116;101;101;116;104; + + + 71;101;116;32;100;114;101;115;115;101;100; + + + 72;97;118;101;32;98;114;101;97;107;102;97;115;116; + + +`,Pz=` + + + 70;105;108;108;32;116;104;101;32;107;101;116;116;108;101;32;119;105;116;104;32;119;97;116;101;114; + + + 83;119;105;116;99;104;32;111;110;32;116;104;101;32;107;101;116;116;108;101; + + + 80;117;116;32;97;32;116;101;97;32;98;97;103;32;105;110;32;116;104;101;32;99;117;112; + + + 80;111;117;114;32;104;111;116;32;119;97;116;101;114;32;105;110;116;111;32;116;104;101;32;99;117;112; + + + 87;97;105;116;32;51;32;109;105;110;117;116;101;115; + + + 84;97;107;101;32;111;117;116;32;116;104;101;32;116;101;97;32;98;97;103; + + +`,Dz=` + + + 73;115;32;105;116;32;114;97;105;110;105;110;103;63; + + + 80;97;99;107;32;97;110;32;117;109;98;114;101;108;108;97; + + + + + 80;97;99;107;32;115;117;110;103;108;97;115;115;101;115; + + + + + 76;101;97;118;101; + + +`,Bz=` + + + 80;108;97;116;101;32;110;111;116;32;101;109;112;116;121; + + + 84;97;107;101;32;97;32;98;105;116;101; + + + + + 67;108;101;97;114;32;116;104;101;32;112;108;97;116;101; + + +`,Mz=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;67;111;117;110;116;32;117;112;32;116;111;63;34; + + + 105;110;116;32;105;32;61;32;49; + + + 105;32;60;61;32;110; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + +`,Zz=` + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;51; + + + 110;117;109;98;101;114;32;62;32;48; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;45;32;49; + + + + + 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; + + +`,Lz=` + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;51; + + + 110;117;109;98;101;114;32;62;32;48; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + + + + 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; + + +`,Ez=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;70;97;99;116;111;114;105;97;108;32;111;102;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;102;97;99;116;111;114;105;97;108;32;61;32;49; + + + 105;110;116;32;105;32;61;32;49; + + + 105;32;60;61;32;110; + + + 102;97;99;116;111;114;105;97;108;32;61;32;102;97;99;116;111;114;105;97;108;32;42;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;110;32;43;32;34;33;32;61;32;34;32;43;32;102;97;99;116;111;114;105;97;108; + + +`,Wz=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;99;104;111;105;99;101;32;34;49;32;112;108;117;115;44;32;50;32;109;105;110;117;115;44;32;51;32;116;105;109;101;115;63;34; + + + 99;104;111;105;99;101; + + + 111;117;116;112;117;116;58;32;97;32;43;32;98; + + + + + 111;117;116;112;117;116;58;32;97;32;45;32;98; + + + + + 111;117;116;112;117;116;58;32;97;32;42;32;98; + + + + + 111;117;116;112;117;116;58;32;34;78;111;116;32;97;110;32;111;112;116;105;111;110;34; + + + + +`,Nz=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;99;104;111;105;99;101;32;34;49;32;112;108;117;115;44;32;50;32;109;105;110;117;115;44;32;51;32;116;105;109;101;115;63;34; + + + 99;104;111;105;99;101; + + + 111;117;116;112;117;116;58;32;97;32;43;32;98; + + + + + 111;117;116;112;117;116;58;32;98;32;45;32;97; + + + + + 111;117;116;112;117;116;58;32;97;32;42;32;98; + + + + + 111;117;116;112;117;116;58;32;34;78;111;116;32;97;110;32;111;112;116;105;111;110;34; + + + + +`,Fz=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;87;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 110;117;109;98;101;114; + + + 111;117;116;112;117;116;58;32;34;111;110;101;34; + + + + + 111;117;116;112;117;116;58;32;34;116;119;111;34; + + + + + 111;117;116;112;117;116;58;32;34;116;104;114;101;101;34; + + + + + 111;117;116;112;117;116;58;32;34;117;110;107;110;111;119;110;34; + + + + +`,Jz=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;110;117;109;98;101;114;34; + + + 105;110;116;32;115;116;101;112;115;32;61;32;48; + + + 110;117;109;98;101;114;32;60;32;49;48;48; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;42;32;50; + + + 115;116;101;112;115;32;61;32;115;116;101;112;115;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;115;116;101;112;115; + + +`,Rz=` + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;48; + + + 110;117;109;98;101;114;32;60;32;49;32;124;124;32;110;117;109;98;101;114;32;62;32;49;48; + + + 105;110;112;117;116;58;32;110;117;109;98;101;114;32;34;78;117;109;98;101;114;32;102;114;111;109;32;49;32;116;111;32;49;48;34; + + + + + 111;117;116;112;117;116;58;32;34;84;104;97;110;107;32;121;111;117;33;34; + + +`,Gz=` + + + 105;110;116;32;105;32;61;32;49;48; + + + 105;32;60;32;53; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + +`,Hz=` + + + 105;110;112;117;116;58;32;105;110;116;32;103;111;97;108;32;34;83;97;118;105;110;103;115;32;103;111;97;108;63;34; + + + 105;110;116;32;109;111;110;101;121;32;61;32;48; + + + 105;110;116;32;119;101;101;107;115;32;61;32;48; + + + 109;111;110;101;121;32;60;32;103;111;97;108; + + + 109;111;110;101;121;32;61;32;109;111;110;101;121;32;43;32;53; + + + 119;101;101;107;115;32;61;32;119;101;101;107;115;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;87;101;101;107;115;58;32;34;32;43;32;119;101;101;107;115; + + +`,Vz=` + + + 105;110;112;117;116;58;32;105;110;116;32;103;111;97;108;32;34;83;97;118;105;110;103;115;32;103;111;97;108;63;34; + + + 105;110;116;32;109;111;110;101;121;32;61;32;48; + + + 105;110;116;32;119;101;101;107;115;32;61;32;48; + + + 109;111;110;101;121;32;60;61;32;103;111;97;108; + + + 109;111;110;101;121;32;61;32;109;111;110;101;121;32;43;32;53; + + + 119;101;101;107;115;32;61;32;119;101;101;107;115;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;87;101;101;107;115;58;32;34;32;43;32;119;101;101;107;115; + + +`,qz=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;101;114;101;63;34; + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;50; + + + 110;117;109;98;101;114;32;60;61;32;110; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;43;32;50; + + + + +`,Qz=` + + + 105;110;116;32;103;114;97;100;101;32;61;32;48; + + + 103;114;97;100;101;32;60;32;49;32;124;124;32;103;114;97;100;101;32;62;32;54; + + + 105;110;112;117;116;58;32;103;114;97;100;101;32;34;71;114;97;100;101;32;102;114;111;109;32;49;32;116;111;32;54;34; + + + + + 111;117;116;112;117;116;58;32;34;89;111;117;114;32;103;114;97;100;101;58;32;34;32;43;32;103;114;97;100;101; + + +`,Uz=` + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;48; + + + 110;117;109;98;101;114;32;33;61;32;48; + + + 105;110;112;117;116;58;32;110;117;109;98;101;114;32;34;78;117;109;98;101;114;32;40;48;32;115;116;111;112;115;41;34; + + + 115;117;109;32;61;32;115;117;109;32;43;32;110;117;109;98;101;114; + + + + + 111;117;116;112;117;116;58;32;115;117;109; + + +`,$z=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;83;116;97;114;116;32;110;117;109;98;101;114;34; + + + 105;110;116;32;105;32;61;32;110; + 105;32;62;61;32;49; + 105;45;45; + + + 111;117;116;112;117;116;58;32;105; + + + + + 111;117;116;112;117;116;58;32;34;71;111;33;34; + + +`,Yz=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;87;104;105;99;104;32;116;105;109;101;115;32;116;97;98;108;101;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;49;48; + 105;43;43; + + + 105;110;116;32;112;114;111;100;117;99;116;32;61;32;110;117;109;98;101;114;32;42;32;105; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114;32;43;32;34;32;120;32;34;32;43;32;105;32;43;32;34;32;61;32;34;32;43;32;112;114;111;100;117;99;116; + + + + +`,Xz=` + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;53; + 105;43;43; + + + 111;117;116;112;117;116;58;32;105; + + + + +`,Kz=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;110;117;109;98;101;114;63;34; + + + 110;117;109;98;101;114;32;62;32;48; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;47;32;50; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + + + +`,e6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;110;117;109;98;101;114;63;34; + + + 110;117;109;98;101;114;32;62;32;49; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;47;32;50; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + + + +`,t6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;110;117;109;98;101;114;63;34; + + + 110;117;109;98;101;114;32;60;32;49;48;48; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;42;32;50; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + + + +`,n6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 115;117;109;32;61;32;115;117;109;32;43;32;105; + + + + + 111;117;116;112;117;116;58;32;115;117;109; + + +`,i6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;72;111;119;32;109;97;110;121;32;108;105;110;101;115;63;34; + + + 105;110;116;32;108;105;110;101;32;61;32;49; + 108;105;110;101;32;60;61;32;110; + 108;105;110;101;43;43; + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;34;34; + + + 105;110;116;32;115;116;97;114;32;61;32;49; + 115;116;97;114;32;60;61;32;108;105;110;101; + 115;116;97;114;43;43; + + + 116;101;120;116;32;61;32;116;101;120;116;32;43;32;34;42;34; + + + + + 111;117;116;112;117;116;58;32;116;101;120;116; + + + + +`,a6=` + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;53; + 105;43;43; + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;34; + + + 110;117;109;98;101;114;32;37;32;50;32;61;61;32;48; + + + 99;111;117;110;116;43;43; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;99;111;117;110;116; + + +`,s6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 105;32;37;32;50;32;61;61;32;48; + + + 99;111;117;110;116;43;43; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;99;111;117;110;116; + + +`,r6=` + + + 105;110;112;117;116;58;32;105;110;116;32;114;111;119;32;34;87;104;105;99;104;32;116;105;109;101;115;32;116;97;98;108;101;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;49;48; + 105;43;43; + + + 111;117;116;112;117;116;58;32;114;111;119;32;42;32;105; + + + + +`,o6=` + + + 105;110;112;117;116;58;32;105;110;116;32;114;111;119;32;34;87;104;105;99;104;32;116;105;109;101;115;32;116;97;98;108;101;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;49;48; + 105;43;43; + + + 111;117;116;112;117;116;58;32;114;111;119;32;42;32;105; + + + + +`,l6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 111;117;116;112;117;116;58;32;105;32;42;32;105; + + + + +`,u6=` + + + 105;110;112;117;116;58;32;105;110;116;32;119;105;100;116;104;32;34;87;105;100;116;104;34; + + + 105;110;112;117;116;58;32;105;110;116;32;104;101;105;103;104;116;32;34;72;101;105;103;104;116;34; + + + 105;110;116;32;108;105;110;101;32;61;32;49; + 108;105;110;101;32;60;61;32;104;101;105;103;104;116; + 108;105;110;101;43;43; + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;34;34; + + + 105;110;116;32;99;111;108;117;109;110;32;61;32;49; + 99;111;108;117;109;110;32;60;61;32;119;105;100;116;104; + 99;111;108;117;109;110;43;43; + + + 116;101;120;116;32;61;32;116;101;120;116;32;43;32;34;35;34; + + + + + 111;117;116;112;117;116;58;32;116;101;120;116; + + + + +`,c6=` + + + 105;110;116;91;93;32;110;117;109;98;101;114;115;32;61;32;123;50;44;32;52;44;32;54;44;32;56;44;32;49;48;125; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;117;109;98;101;114;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114;115;91;105;93; + + + + +`,m6=` + + + 105;110;116;91;93;32;118;97;108;117;101;115;32;61;32;123;52;44;32;56;44;32;49;53;44;32;49;54;44;32;50;51;44;32;52;50;125; + + + 111;117;116;112;117;116;58;32;118;97;108;117;101;115;91;48;93; + + + 111;117;116;112;117;116;58;32;118;97;108;117;101;115;91;118;97;108;117;101;115;46;108;101;110;103;116;104;32;45;32;49;93; + + + 111;117;116;112;117;116;58;32;118;97;108;117;101;115;46;108;101;110;103;116;104; + + +`,d6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 105;32;37;32;51;32;61;61;32;48; + + + 99;111;117;110;116;32;61;32;99;111;117;110;116;32;43;32;49; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;67;111;117;110;116;58;32;34;32;43;32;99;111;117;110;116; + + +`,h6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 105;32;37;32;51;32;61;61;32;48; + + + 99;111;117;110;116;32;61;32;99;111;117;110;116;32;43;32;49; + + + + + 248; + + + + + 111;117;116;112;117;116;58;32;34;67;111;117;110;116;58;32;34;32;43;32;99;111;117;110;116; + + + + +`,g6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;72;111;119;32;109;97;110;121;32;115;116;101;112;115;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;34;34; + + + 105;110;116;32;106;32;61;32;49; + 106;32;60;61;32;105; + 106;43;43; + + + 108;105;110;101;32;61;32;108;105;110;101;32;43;32;34;42;34; + + + + + 111;117;116;112;117;116;58;32;108;105;110;101; + + + + +`,p6=` + + + 83;116;114;105;110;103;91;93;32;110;97;109;101;115;32;61;32;110;101;119;32;83;116;114;105;110;103;91;51;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;97;109;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;97;109;101;115;91;105;93;32;34;69;110;116;101;114;32;97;32;110;97;109;101;34; + + + + + 111;117;116;112;117;116;58;32;34;70;105;114;115;116;32;110;97;109;101;58;32;34;32;43;32;110;97;109;101;115;91;48;93; + + +`,f6=` + + + 105;110;116;91;93;32;110;117;109;98;101;114;115;32;61;32;110;101;119;32;105;110;116;91;52;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;117;109;98;101;114;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;117;109;98;101;114;115;91;105;93;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;34; + + + + + 105;110;116;32;105;32;61;32;110;117;109;98;101;114;115;46;108;101;110;103;116;104;32;45;32;49; + 105;32;62;61;32;48; + 105;45;45; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114;115;91;105;93; + + + + +`,b6=` + + + 105;110;116;91;93;32;110;117;109;98;101;114;115;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;117;109;98;101;114;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;117;109;98;101;114;115;91;105;93;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;34; + + + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;109;97;120;32;61;32;110;117;109;98;101;114;115;91;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;117;109;98;101;114;115;46;108;101;110;103;116;104; + 105;43;43; + + + 115;117;109;32;61;32;115;117;109;32;43;32;110;117;109;98;101;114;115;91;105;93; + + + 110;117;109;98;101;114;115;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;110;117;109;98;101;114;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; + + + 111;117;116;112;117;116;58;32;34;77;97;120;105;109;117;109;58;32;34;32;43;32;109;97;120; + + +`,x6=` + + + 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;123;49;50;44;32;55;44;32;49;57;44;32;52;125; + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;109;97;120;32;61;32;112;111;105;110;116;115;91;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;105;110;116;115;46;108;101;110;103;116;104; + 105;43;43; + + + 115;117;109;32;61;32;115;117;109;32;43;32;112;111;105;110;116;115;91;105;93; + + + 112;111;105;110;116;115;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;112;111;105;110;116;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; + + + 111;117;116;112;117;116;58;32;34;77;97;120;105;109;117;109;58;32;34;32;43;32;109;97;120; + + +`,v6=` + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;32;40;48;32;61;32;115;116;111;112;41;34; + + + 110;117;109;98;101;114;32;33;61;32;48; + + + 115;117;109;32;61;32;115;117;109;32;43;32;110;117;109;98;101;114; + + + 105;110;112;117;116;58;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;32;40;48;32;61;32;115;116;111;112;41;34; + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; + + +`,y6=` + + + 105;110;116;32;115;117;109;32;61;32;48; + + + + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;32;40;48;32;61;32;115;116;111;112;41;34; + + + 110;117;109;98;101;114;32;61;61;32;48; + + + 76;101;97;118;101;32;116;104;101;32;108;111;111;112; + + + + + 115;117;109;32;61;32;115;117;109;32;43;32;110;117;109;98;101;114; + + + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; + + +`,w6=` + + + 105;110;112;117;116;58;32;105;110;116;32;108;101;110;103;116;104;32;34;76;101;110;103;116;104;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;119;105;100;116;104;32;34;87;105;100;116;104;63;34; + + + 105;110;116;32;102;32;61;32;97;114;101;97;40;108;101;110;103;116;104;44;32;119;105;100;116;104;41; + + + 111;117;116;112;117;116;58;32;34;65;114;101;97;58;32;34;32;43;32;102; + + +`,z6=` + + + 114;101;116;117;114;110;32;97;32;42;32;98; + + +`,I6=` + + + 115;104;111;119;71;114;101;101;116;105;110;103;40;41; + + + 97;115;107;81;117;101;115;116;105;111;110;115;40;41; + + + 115;104;111;119;82;101;115;117;108;116;40;41; + + +`,k6=` + + + 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;101;115;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; + + + 105;110;116;32;109;97;120;32;61;32;116;101;109;112;101;114;97;116;117;114;101;115;91;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;101;109;112;101;114;97;116;117;114;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 116;101;109;112;101;114;97;116;117;114;101;115;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;116;101;109;112;101;114;97;116;117;114;101;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;72;105;103;104;101;115;116;32;116;101;109;112;101;114;97;116;117;114;101;58;32;34;32;43;32;109;97;120; + + +`,S6=` + + + 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;101;115;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; + + + 105;110;116;32;109;97;120;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;101;109;112;101;114;97;116;117;114;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 116;101;109;112;101;114;97;116;117;114;101;115;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;116;101;109;112;101;114;97;116;117;114;101;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;72;105;103;104;101;115;116;32;116;101;109;112;101;114;97;116;117;114;101;58;32;34;32;43;32;109;97;120; + + +`,T6=` + + + 105;110;116;91;93;32;103;114;97;100;101;115;32;61;32;123;50;44;32;51;44;32;49;44;32;52;125; + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;103;114;97;100;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 115;117;109;32;61;32;115;117;109;32;43;32;103;114;97;100;101;115;91;105;93; + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; + + +`,_6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;87;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;113;32;61;32;115;113;117;97;114;101;40;110;117;109;98;101;114;41; + + + 111;117;116;112;117;116;58;32;34;84;104;101;32;115;113;117;97;114;101;32;105;115;32;34;32;43;32;113; + + +`,A6=` + + + 105;110;116;32;114;101;115;117;108;116;32;61;32;120;32;42;32;120; + + + 114;101;116;117;114;110;32;114;101;115;117;108;116; + + +`,O6=` + + + 115;104;111;119;84;105;116;108;101;40;41; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;97;109;101;32;34;87;104;97;116;32;105;115;32;121;111;117;114;32;110;97;109;101;63;34; + + + 111;117;116;112;117;116;58;32;34;72;101;108;108;111;32;34;32;43;32;110;97;109;101; + + +`,C6=` + + + 111;117;116;112;117;116;58;32;34;87;101;108;99;111;109;101;32;116;111;32;116;104;101;32;113;117;105;122;33;34; + + + 111;117;116;112;117;116;58;32;34;89;111;117;32;103;101;116;32;116;104;114;101;101;32;113;117;101;115;116;105;111;110;115;46;34; + + +`,j6=` + + + 115;104;111;119;83;117;109;40;51;44;32;52;41; + + + 105;110;116;32;120;32;61;32;49;48; + + + 115;104;111;119;83;117;109;40;120;44;32;120;32;43;32;49;41; + + +`,P6=` + + + 105;110;116;32;115;117;109;32;61;32;97;32;43;32;98; + + + 111;117;116;112;117;116;58;32;97;32;43;32;34;32;43;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;115;117;109; + + +`,D6=` + + + 105;110;112;117;116;58;32;105;110;116;32;115;116;97;114;116;32;34;83;116;97;114;116;32;118;97;108;117;101;34; + + + 105;110;116;32;105;32;61;32;115;116;97;114;116; + + + 105;32;62;32;48; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;45;32;49; + + + + + 111;117;116;112;117;116;58;32;34;71;111;33;34; + + +`,B6=` + + + 105;110;112;117;116;58;32;105;110;116;32;115;116;97;114;116;32;34;83;116;97;114;116;32;118;97;108;117;101;34; + + + 105;110;116;32;105;32;61;32;115;116;97;114;116; + + + 105;32;62;32;48; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;71;111;34; + + +`,M6=` + + + 105;110;116;91;93;91;93;32;112;111;105;110;116;115;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; + + + 105;110;116;32;116;111;116;97;108;32;61;32;48; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;112;111;105;110;116;115;91;49;93;46;108;101;110;103;116;104; + 106;43;43; + + + 116;111;116;97;108;32;61;32;116;111;116;97;108;32;43;32;112;111;105;110;116;115;91;49;93;91;106;93; + + + + + 111;117;116;112;117;116;58;32;34;80;108;97;121;101;114;32;50;58;32;34;32;43;32;116;111;116;97;108; + + +`,Z6=` + + + 105;110;116;91;93;91;93;32;112;111;105;110;116;115;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; + + + 105;110;116;32;116;111;116;97;108;32;61;32;48; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;112;111;105;110;116;115;91;49;93;46;108;101;110;103;116;104; + 106;43;43; + + + 116;111;116;97;108;32;61;32;116;111;116;97;108;32;43;32;112;111;105;110;116;115;91;106;93;91;49;93; + + + + + 111;117;116;112;117;116;58;32;34;80;108;97;121;101;114;32;50;58;32;34;32;43;32;116;111;116;97;108; + + +`,L6=` + + + 105;110;116;91;93;91;93;32;112;111;105;110;116;115;32;61;32;123;123;51;44;32;53;125;44;32;123;52;44;32;49;125;44;32;123;50;44;32;50;125;125; + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;105;110;116;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;112;111;105;110;116;115;91;105;93;46;108;101;110;103;116;104; + 106;43;43; + + + 115;117;109;32;61;32;115;117;109;32;43;32;112;111;105;110;116;115;91;105;93;91;106;93; + + + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; + + +`,E6=` + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + + + 105;32;60;61;32;51; + + + 115;117;109;32;61;32;115;117;109;32;43;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;115;117;109; + + +`,W6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 115;117;109;32;61;32;115;117;109;32;43;32;105; + + + + + 111;117;116;112;117;116;58;32;115;117;109; + + +`,N6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;110; + 105;43;43; + + + 115;117;109;32;61;32;115;117;109;32;43;32;105; + + + + + 111;117;116;112;117;116;58;32;115;117;109; + + +`,F6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;87;104;105;99;104;32;116;105;109;101;115;32;116;97;98;108;101;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;51; + 105;43;43; + + + 105;110;116;32;114;101;115;117;108;116;32;61;32;110;117;109;98;101;114;32;42;32;105; + + + 111;117;116;112;117;116;58;32;105;32;43;32;34;32;116;105;109;101;115;32;34;32;43;32;110;117;109;98;101;114;32;43;32;34;32;61;32;34;32;43;32;114;101;115;117;108;116; + + + + + 110;117;109;98;101;114;32;62;32;49;48; + + + 111;117;116;112;117;116;58;32;34;84;104;97;116;32;119;97;115;32;104;97;114;100;33;34; + + + + + 111;117;116;112;117;116;58;32;34;84;104;97;116;32;119;97;115;32;101;97;115;121;46;34; + + + + +`,J6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;69;110;116;101;114;32;97;32;110;117;109;98;101;114;34; + + + 105;110;116;32;102;97;99;116;111;114;105;97;108;32;61;32;49; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 102;97;99;116;111;114;105;97;108;32;61;32;102;97;99;116;111;114;105;97;108;32;42;32;105; + + + + + 111;117;116;112;117;116;58;32;102;97;99;116;111;114;105;97;108; + + +`,R6=` + + + 83;116;114;105;110;103;32;108;101;116;116;101;114;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;101;116;116;101;114;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;101;115;32;61;32;108;101;116;116;101;114;46;115;112;108;105;116;40;34;92;110;34;41; + + + 111;117;116;112;117;116;58;32;34;76;105;110;101;115;58;32;34;32;43;32;108;105;110;101;115;46;108;101;110;103;116;104; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;108;105;110;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 108;105;110;101;115;91;105;93;46;99;111;110;116;97;105;110;115;40;34;102;111;120;34;41; + + + 111;117;116;112;117;116;58;32;34;70;111;120;32;105;110;32;108;105;110;101;32;34;32;43;32;40;105;32;43;32;49;41; + + + + + 248; + + + + + + +`,G6=` + + + 83;116;114;105;110;103;32;108;101;116;116;101;114;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;101;116;116;101;114;46;116;120;116;34;41;41; + + +`,H6=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;105;114;115;116;32;34;70;105;114;115;116;32;110;97;109;101;63;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;108;97;115;116;32;34;76;97;115;116;32;110;97;109;101;63;34; + + + 111;117;116;112;117;116;58;32;102;105;114;115;116;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;108;97;115;116;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; + + +`,V6=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;105;114;115;116;32;34;70;105;114;115;116;32;110;97;109;101;63;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;108;97;115;116;32;34;76;97;115;116;32;110;97;109;101;63;34; + + + 111;117;116;112;117;116;58;32;102;105;114;115;116;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;32;34;32;43;32;108;97;115;116;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;34; + + +`,q6=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;105;110;112;117;116;32;34;80;97;115;115;119;111;114;100;63;34; + + + 105;110;112;117;116;46;101;113;117;97;108;115;40;34;76;117;100;119;105;103;34;41; + + + 111;117;116;112;117;116;58;32;34;87;101;108;99;111;109;101;33;34; + + + + + 111;117;116;112;117;116;58;32;34;87;114;111;110;103;32;112;97;115;115;119;111;114;100;34; + + + + +`,Q6=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; + + + 97;103;101;32;60;32;54; + + + 111;117;116;112;117;116;58;32;34;70;114;101;101;32;101;110;116;114;121;34; + + + + + 97;103;101;32;60;32;49;56; + + + 111;117;116;112;117;116;58;32;34;67;104;105;108;100;32;116;105;99;107;101;116;58;32;52;32;101;117;114;111;115;34; + + + + + 111;117;116;112;117;116;58;32;34;65;100;117;108;116;32;116;105;99;107;101;116;58;32;56;32;101;117;114;111;115;34; + + + + + + +`,U6=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;98;101;114;32;34;83;116;97;114;116;32;118;97;108;117;101;63;34; + + + 110;117;109;98;101;114;32;62;32;48; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114; + + + 110;117;109;98;101;114;32;61;32;110;117;109;98;101;114;32;45;32;51; + + + + + 111;117;116;112;117;116;58;32;34;69;110;100;34; + + +`,$6=` + + + 105;110;116;32;116;114;105;101;115;32;61;32;48; + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;103;117;101;115;115;32;34;89;111;117;114;32;103;117;101;115;115;63;34; + + + 116;114;105;101;115;32;61;32;116;114;105;101;115;32;43;32;49; + + + 103;117;101;115;115;32;61;61;32;55; + + + -1; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;84;114;105;101;115;58;32;34;32;43;32;116;114;105;101;115; + + +`,Y6=` + + + 105;110;116;32;116;114;105;101;115;32;61;32;48; + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;103;117;101;115;115;32;34;89;111;117;114;32;103;117;101;115;115;63;34; + + + 103;117;101;115;115;32;61;61;32;55; + + + -1; + + + + + 248; + + + + + 116;114;105;101;115;32;61;32;116;114;105;101;115;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;84;114;105;101;115;58;32;34;32;43;32;116;114;105;101;115; + + +`,X6=` + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;105;99;101;32;34;80;114;105;99;101;63;32;40;48;32;61;32;101;110;100;41;34; + + + 112;114;105;99;101;32;61;61;32;48; + + + -1; + + + + + 248; + + + + + 115;117;109;32;61;32;115;117;109;32;43;32;112;114;105;99;101; + + + 99;111;117;110;116;32;61;32;99;111;117;110;116;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;73;116;101;109;115;58;32;34;32;43;32;99;111;117;110;116; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;115;117;109; + + +`,K6=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;103;101;32;34;72;111;119;32;111;108;100;32;97;114;101;32;121;111;117;63;34; + + + 97;103;101;32;62;61;32;49;54; + + + 111;117;116;112;117;116;58;32;34;89;111;117;32;109;97;121;32;118;111;116;101;46;34; + + + + + 105;110;116;32;121;101;97;114;115;32;61;32;49;54;32;45;32;97;103;101; + + + 111;117;116;112;117;116;58;32;34;87;97;105;116;32;34;32;43;32;121;101;97;114;115;32;43;32;34;32;109;111;114;101;32;121;101;97;114;115;46;34; + + + + +`,eI=` + + + 105;110;112;117;116;58;32;105;110;116;32;108;105;109;105;116;32;34;85;112;32;116;111;32;119;104;105;99;104;32;110;117;109;98;101;114;63;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;61;32;108;105;109;105;116; + 105;32;61;32;105;32;43;32;50; + + + 111;117;116;112;117;116;58;32;105; + + + + +`,tI=` + + + 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;119;97;110;116;101;100;32;34;87;104;105;99;104;32;99;97;114;100;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;105;32;61;32;48; + + + 112;111;115;105;116;105;111;110;32;61;61;32;45;49;32;38;38;32;105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + + + 99;97;114;100;115;91;105;93;32;61;61;32;119;97;110;116;101;100; + + + 112;111;115;105;116;105;111;110;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; + + +`,nI=` + + + 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;119;97;110;116;101;100;32;34;87;104;105;99;104;32;99;97;114;100;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;105;32;61;32;48; + + + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + + + 99;97;114;100;115;91;105;93;32;61;61;32;119;97;110;116;101;100; + + + 112;111;115;105;116;105;111;110;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; + + +`,iI=` + + + 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;119;97;110;116;101;100;32;34;87;104;105;99;104;32;99;97;114;100;63;34; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + 105;43;43; + + + 99;97;114;100;115;91;105;93;32;61;61;32;119;97;110;116;101;100; + + + 99;111;117;110;116;32;61;32;99;111;117;110;116;32;43;32;49; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;67;111;117;110;116;58;32;34;32;43;32;99;111;117;110;116; + + +`,aI=` + + + 111;117;116;112;117;116;58;32;34;71;111;111;100;32;109;111;114;110;105;110;103;34; + + + 111;117;116;112;117;116;58;32;34;84;111;100;97;121;32;119;101;32;108;101;97;114;110;32;115;116;114;117;99;116;117;114;101;32;99;104;97;114;116;115;46;34; + + +`,sI=` + + + 111;117;116;112;117;116;58;32;34;72;101;108;108;111;32;87;111;114;108;100;34; + + +`,rI=` + + + 111;117;116;112;117;116;58;32;34;72;101;108;108;111;34; + + + 111;117;116;112;117;116;58;32;34;73;32;97;109;32;108;101;97;114;110;105;110;103;32;115;116;114;117;99;116;117;114;101;32;99;104;97;114;116;115;34; + + +`,oI=` + + + 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;115;104;111;112;112;105;110;103;45;110;101;119;46;116;120;116;34;41; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 102;105;108;101;46;104;97;115;78;101;120;116;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;102;105;108;101;46;110;101;120;116;76;105;110;101;40;41; + + + 111;117;116;46;112;114;105;110;116;108;110;40;108;105;110;101;41; + + + 99;111;117;110;116;43;43; + + + + + 111;117;116;46;112;114;105;110;116;108;110;40;34;67;97;107;101;34;41; + + + 99;111;117;110;116;43;43; + + + 102;105;108;101;46;99;108;111;115;101;40;41; + + + 111;117;116;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;99;111;117;110;116;32;43;32;34;32;108;105;110;101;115;32;115;97;118;101;100;34; + + +`,lI=` + + + 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;115;104;111;112;112;105;110;103;45;110;101;119;46;116;120;116;34;41; + + +`,uI=` + + + 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;49; + + + 102;105;108;101;46;104;97;115;78;101;120;116;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;102;105;108;101;46;110;101;120;116;76;105;110;101;40;41; + + + 111;117;116;112;117;116;58;32;110;117;109;98;101;114;32;43;32;34;46;32;34;32;43;32;108;105;110;101; + + + 110;117;109;98;101;114;43;43; + + + + + 102;105;108;101;46;99;108;111;115;101;40;41; + + +`,cI=` + + + 83;99;97;110;110;101;114;32;102;105;108;101;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;115;104;111;112;112;105;110;103;46;116;120;116;34;41;41; + + +`,mI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;101;32;33;61;32;110;117;108;108; + + + 108;105;110;101;46;99;111;110;116;97;105;110;115;40;34;70;111;120;34;41; + + + 99;111;117;110;116;43;43; + + + + + 248; + + + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 114;101;97;100;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;34;70;111;120;58;32;34;32;43;32;99;111;117;110;116; + + +`,dI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,hI=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;101;115;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; + + + 83;116;114;105;110;103;32;108;111;110;103;101;115;116;32;61;32;108;105;110;101;115;91;48;93; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;108;105;110;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 108;105;110;101;115;91;105;93;46;108;101;110;103;116;104;40;41;32;62;32;108;111;110;103;101;115;116;46;108;101;110;103;116;104;40;41; + + + 108;111;110;103;101;115;116;32;61;32;108;105;110;101;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;76;111;110;103;101;115;116;32;101;110;116;114;121;58;32;34;32;43;32;108;111;110;103;101;115;116; + + +`,gI=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;111;103;98;111;111;107;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;101;115;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; + + +`,pI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;99;108;97;115;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;98;101;115;116;78;97;109;101;32;61;32;34;34; + + + 105;110;116;32;98;101;115;116;71;114;97;100;101;32;61;32;55; + + + 108;105;110;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;115;32;61;32;108;105;110;101;46;115;112;108;105;116;40;34;59;34;41; + + + 105;110;116;32;103;114;97;100;101;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;112;97;114;116;115;91;51;93;41; + + + 103;114;97;100;101;32;60;32;98;101;115;116;71;114;97;100;101; + + + 98;101;115;116;71;114;97;100;101;32;61;32;103;114;97;100;101; + + + 98;101;115;116;78;97;109;101;32;61;32;112;97;114;116;115;91;48;93; + + + + + 248; + + + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 114;101;97;100;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;34;66;101;115;116;32;103;114;97;100;101;32;105;110;32;69;110;103;108;105;115;104;58;32;34;32;43;32;98;101;115;116;78;97;109;101;32;43;32;34;32;40;34;32;43;32;98;101;115;116;71;114;97;100;101;32;43;32;34;41;34; + + +`,fI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;99;108;97;115;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,bI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;99;108;97;115;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 100;111;117;98;108;101;32;115;117;109;32;61;32;48; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 108;105;110;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;115;32;61;32;108;105;110;101;46;115;112;108;105;116;40;34;59;34;41; + + + 115;117;109;32;61;32;115;117;109;32;43;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;112;97;114;116;115;91;49;93;41; + + + 99;111;117;110;116;43;43; + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 114;101;97;100;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;34;77;97;116;104;115;32;97;118;101;114;97;103;101;58;32;34;32;43;32;115;117;109;32;47;32;99;111;117;110;116; + + +`,xI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;99;108;97;115;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,vI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;101;32;33;61;32;110;117;108;108; + + + 108;105;110;101;46;99;111;110;116;97;105;110;115;40;34;92;34;110;97;109;101;92;34;34;41; + + + 105;110;116;32;115;116;97;114;116;32;61;32;108;105;110;101;46;105;110;100;101;120;79;102;40;34;92;34;110;97;109;101;92;34;58;32;92;34;34;41;32;43;32;57; + + + 105;110;116;32;101;110;100;32;61;32;108;105;110;101;46;105;110;100;101;120;79;102;40;34;92;34;34;44;32;115;116;97;114;116;41; + + + 111;117;116;112;117;116;58;32;108;105;110;101;46;115;117;98;115;116;114;105;110;103;40;115;116;97;114;116;44;32;101;110;100;41; + + + + + 248; + + + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 114;101;97;100;101;114;46;99;108;111;115;101;40;41; + + +`,yI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,wI=` + + + 83;116;114;105;110;103;91;93;32;110;97;109;101;115;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;70;111;120;34;125; + + + 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;123;49;50;44;32;49;53;44;32;57;125; + + + 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;112;111;105;110;116;115;46;106;115;111;110;34;41; + + + 111;117;116;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;97;109;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 83;116;114;105;110;103;32;101;110;116;114;121;32;61;32;34;32;32;123;92;34;110;97;109;101;92;34;58;32;92;34;34;32;43;32;110;97;109;101;115;91;105;93;32;43;32;34;92;34;44;32;92;34;112;111;105;110;116;115;92;34;58;32;34;32;43;32;112;111;105;110;116;115;91;105;93;32;43;32;34;125;34; + + + 105;32;60;32;110;97;109;101;115;46;108;101;110;103;116;104;32;45;32;49; + + + 101;110;116;114;121;32;61;32;101;110;116;114;121;32;43;32;34;44;34; + + + + + 248; + + + + + 111;117;116;46;112;114;105;110;116;108;110;40;101;110;116;114;121;41; + + + + + 111;117;116;46;112;114;105;110;116;108;110;40;34;93;34;41; + + + 111;117;116;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;110;97;109;101;115;46;108;101;110;103;116;104;32;43;32;34;32;101;110;116;114;105;101;115;32;115;97;118;101;100;34; + + +`,zI=` + + + 83;116;114;105;110;103;91;93;32;110;97;109;101;115;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;70;111;120;34;125; + + + 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;123;49;50;44;32;49;53;44;32;57;125; + + + 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;112;111;105;110;116;115;46;106;115;111;110;34;41; + + + 111;117;116;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 111;117;116;46;99;108;111;115;101;40;41; + + +`,II=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;97;110;105;109;97;108;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;101;115;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;97;110;105;109;97;108;115;45;110;101;119;46;106;115;111;110;34;41; + + + 111;117;116;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;108;105;110;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;115;32;61;32;108;105;110;101;115;91;105;93;46;115;112;108;105;116;40;34;59;34;41; + + + 83;116;114;105;110;103;32;101;110;116;114;121;32;61;32;34;32;32;123;92;34;110;97;109;101;92;34;58;32;92;34;34;32;43;32;112;97;114;116;115;91;48;93;32;43;32;34;92;34;44;32;92;34;115;112;101;99;105;101;115;92;34;58;32;92;34;34;32;43;32;112;97;114;116;115;91;49;93;32;43;32;34;92;34;44;32;92;34;97;103;101;92;34;58;32;34;32;43;32;112;97;114;116;115;91;50;93;32;43;32;34;125;34; + + + 105;32;60;32;108;105;110;101;115;46;108;101;110;103;116;104;32;45;32;49; + + + 101;110;116;114;121;32;61;32;101;110;116;114;121;32;43;32;34;44;34; + + + + + 248; + + + + + 111;117;116;46;112;114;105;110;116;108;110;40;101;110;116;114;121;41; + + + + + 111;117;116;46;112;114;105;110;116;108;110;40;34;93;34;41; + + + 111;117;116;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;40;108;105;110;101;115;46;108;101;110;103;116;104;32;45;32;49;41;32;43;32;34;32;97;110;105;109;97;108;115;32;115;97;118;101;100;34; + + +`,kI=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;97;110;105;109;97;108;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;101;115;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;97;110;105;109;97;108;115;45;110;101;119;46;106;115;111;110;34;41; + + + 111;117;116;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 111;117;116;46;112;114;105;110;116;108;110;40;34;93;34;41; + + + 111;117;116;46;99;108;111;115;101;40;41; + + +`,SI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;97;110;105;109;97;108;115;46;99;115;118;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;115;101;110;116;101;110;99;101;115;46;116;120;116;34;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 108;105;110;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;115;32;61;32;108;105;110;101;46;115;112;108;105;116;40;34;59;34;41; + + + 111;117;116;46;112;114;105;110;116;108;110;40;112;97;114;116;115;91;48;93;32;43;32;34;32;40;34;32;43;32;112;97;114;116;115;91;49;93;32;43;32;34;41;32;105;115;32;34;32;43;32;112;97;114;116;115;91;50;93;32;43;32;34;32;121;101;97;114;115;32;111;108;100;46;34;41; + + + 99;111;117;110;116;43;43; + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 114;101;97;100;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;99;111;117;110;116;32;43;32;34;32;115;101;110;116;101;110;99;101;115;32;115;97;118;101;100;34; + + +`,TI=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;114;101;97;100;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;97;110;105;109;97;108;115;46;99;115;118;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;111;117;116;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;115;101;110;116;101;110;99;101;115;46;116;120;116;34;41; + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;101;32;61;32;114;101;97;100;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 114;101;97;100;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;46;99;108;111;115;101;40;41; + + +`,_I=` + + + 105;110;112;117;116;58;32;105;110;116;32;99;111;117;110;116;32;34;72;111;119;32;109;97;110;121;32;116;105;99;107;101;116;115;63;34; + + + 100;111;117;98;108;101;32;116;111;116;97;108;32;61;32;99;111;117;110;116;32;42;32;56;46;53; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + +`,AI=` + + + 105;110;112;117;116;58;32;105;110;116;32;99;111;117;110;116;32;34;72;111;119;32;109;97;110;121;32;116;105;99;107;101;116;115;63;34; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + + 100;111;117;98;108;101;32;116;111;116;97;108;32;61;32;99;111;117;110;116;32;42;32;56;46;53; + + +`,OI=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;34; + + + 105;110;116;32;116;101;109;112;32;61;32;97; + + + 97;32;61;32;98; + + + 98;32;61;32;116;101;109;112; + + + 111;117;116;112;117;116;58;32;97; + + + 111;117;116;112;117;116;58;32;98; + + +`,CI=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;70;105;114;115;116;32;110;117;109;98;101;114;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;99;111;110;100;32;110;117;109;98;101;114;34; + + + 97;32;61;32;98; + + + 98;32;61;32;97; + + + 111;117;116;112;117;116;58;32;97; + + + 111;117;116;112;117;116;58;32;98; + + +`,jI=` + + + 105;110;116;32;97;32;61;32;51; + + + 105;110;116;32;98;32;61;32;53; + + + 105;110;116;32;116;101;109;112;32;61;32;97; + + + 97;32;61;32;98; + + + 98;32;61;32;116;101;109;112; + + + 111;117;116;112;117;116;58;32;34;97;32;61;32;34;32;43;32;97; + + + 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; + + +`,PI=` + + + 105;110;116;91;93;32;99;97;114;100;115;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;99;97;114;100;115;91;105;93;32;34;69;110;116;101;114;32;97;32;99;97;114;100;34; + + + + + 105;110;116;32;114;111;117;110;100;32;61;32;49; + 114;111;117;110;100;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + 114;111;117;110;100;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104;32;45;32;114;111;117;110;100; + 105;43;43; + + + 99;97;114;100;115;91;105;93;32;60;32;99;97;114;100;115;91;105;32;43;32;49;93; + + + 105;110;116;32;116;101;109;112;32;61;32;99;97;114;100;115;91;105;93; + + + 99;97;114;100;115;91;105;93;32;61;32;99;97;114;100;115;91;105;32;43;32;49;93; + + + 99;97;114;100;115;91;105;32;43;32;49;93;32;61;32;116;101;109;112; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;99;97;114;100;115;91;105;93; + + + + +`,DI=` + + + 105;110;116;91;93;32;99;97;114;100;115;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;99;97;114;100;115;91;105;93;32;34;69;110;116;101;114;32;97;32;99;97;114;100;34; + + + + + 105;110;116;32;114;111;117;110;100;32;61;32;49; + 114;111;117;110;100;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + 114;111;117;110;100;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104;32;45;32;114;111;117;110;100; + 105;43;43; + + + 99;97;114;100;115;91;105;93;32;62;32;99;97;114;100;115;91;105;32;43;32;49;93; + + + 105;110;116;32;116;101;109;112;32;61;32;99;97;114;100;115;91;105;93; + + + 99;97;114;100;115;91;105;93;32;61;32;99;97;114;100;115;91;105;32;43;32;49;93; + + + 99;97;114;100;115;91;105;32;43;32;49;93;32;61;32;116;101;109;112; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;99;97;114;100;115;91;105;93; + + + + +`,BI=` + + + 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; + + + 105;110;112;117;116;58;32;105;110;116;32;116;97;114;103;101;116;32;34;87;104;105;99;104;32;99;97;114;100;32;97;114;101;32;121;111;117;32;108;111;111;107;105;110;103;32;102;111;114;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;99;111;109;112;97;114;105;115;111;110;115;32;61;32;48; + + + 105;110;116;32;108;101;102;116;32;61;32;48; + + + 105;110;116;32;114;105;103;104;116;32;61;32;99;97;114;100;115;46;108;101;110;103;116;104;32;45;32;49; + + + 105;110;116;32;109;105;100;100;108;101;32;61;32;48; + + + 112;111;115;105;116;105;111;110;32;61;61;32;45;49;32;38;38;32;108;101;102;116;32;60;61;32;114;105;103;104;116; + + + 109;105;100;100;108;101;32;61;32;40;108;101;102;116;32;43;32;114;105;103;104;116;41;32;47;32;50; + + + 99;111;109;112;97;114;105;115;111;110;115;32;61;32;99;111;109;112;97;114;105;115;111;110;115;32;43;32;49; + + + 99;97;114;100;115;91;109;105;100;100;108;101;93;32;61;61;32;116;97;114;103;101;116; + + + 112;111;115;105;116;105;111;110;32;61;32;109;105;100;100;108;101; + + + + + 99;97;114;100;115;91;109;105;100;100;108;101;93;32;60;32;116;97;114;103;101;116; + + + 108;101;102;116;32;61;32;109;105;100;100;108;101;32;43;32;49; + + + + + 114;105;103;104;116;32;61;32;109;105;100;100;108;101;32;45;32;49; + + + + + + + + + 112;111;115;105;116;105;111;110;32;62;61;32;48; + + + 111;117;116;112;117;116;58;32;34;70;111;117;110;100;32;97;116;32;112;111;115;105;116;105;111;110;32;34;32;43;32;112;111;115;105;116;105;111;110; + + + + + 111;117;116;112;117;116;58;32;34;78;111;116;32;102;111;117;110;100;34; + + + + + 111;117;116;112;117;116;58;32;34;67;111;109;112;97;114;105;115;111;110;115;58;32;34;32;43;32;99;111;109;112;97;114;105;115;111;110;115; + + +`,MI=` + + + 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;55;44;32;51;44;32;49;48;44;32;53;44;32;50;125; + + + 105;110;116;32;114;111;117;110;100;32;61;32;49; + 114;111;117;110;100;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + 114;111;117;110;100;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104;32;45;32;114;111;117;110;100; + 105;43;43; + + + 99;97;114;100;115;91;105;93;32;62;32;99;97;114;100;115;91;105;32;43;32;49;93; + + + 105;110;116;32;116;101;109;112;32;61;32;99;97;114;100;115;91;105;93; + + + 99;97;114;100;115;91;105;93;32;61;32;99;97;114;100;115;91;105;32;43;32;49;93; + + + 99;97;114;100;115;91;105;32;43;32;49;93;32;61;32;116;101;109;112; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;99;97;114;100;115;91;105;93; + + + + +`,ZI=` + + + 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;116;97;114;103;101;116;32;34;87;104;105;99;104;32;99;97;114;100;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;105;32;61;32;48; + + + 112;111;115;105;116;105;111;110;32;61;61;32;45;49;32;38;38;32;105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + + + 99;97;114;100;115;91;105;93;32;61;61;32;116;97;114;103;101;116; + + + 112;111;115;105;116;105;111;110;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 112;111;115;105;116;105;111;110;32;62;61;32;48; + + + 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; + + + + + 111;117;116;112;117;116;58;32;34;78;111;116;32;102;111;117;110;100;34; + + + + +`,LI=` + + + 105;110;116;91;93;32;99;97;114;100;115;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; + + + 105;110;112;117;116;58;32;105;110;116;32;116;97;114;103;101;116;32;34;87;104;105;99;104;32;99;97;114;100;32;97;114;101;32;121;111;117;32;108;111;111;107;105;110;103;32;102;111;114;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;99;111;109;112;97;114;105;115;111;110;115;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + + + 112;111;115;105;116;105;111;110;32;61;61;32;45;49;32;38;38;32;105;32;60;32;99;97;114;100;115;46;108;101;110;103;116;104; + + + 99;111;109;112;97;114;105;115;111;110;115;32;61;32;99;111;109;112;97;114;105;115;111;110;115;32;43;32;49; + + + 99;97;114;100;115;91;105;93;32;61;61;32;116;97;114;103;101;116; + + + 112;111;115;105;116;105;111;110;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 112;111;115;105;116;105;111;110;32;62;61;32;48; + + + 111;117;116;112;117;116;58;32;34;70;111;117;110;100;32;97;116;32;112;111;115;105;116;105;111;110;32;34;32;43;32;112;111;115;105;116;105;111;110; + + + + + 111;117;116;112;117;116;58;32;34;78;111;116;32;102;111;117;110;100;34; + + + + + 111;117;116;112;117;116;58;32;34;67;111;109;112;97;114;105;115;111;110;115;58;32;34;32;43;32;99;111;109;112;97;114;105;115;111;110;115; + + +`,EI=` + + + 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;123;51;44;32;53;44;32;56;125; + + + 98;111;110;117;115;40;112;111;105;110;116;115;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;105;110;116;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;112;111;105;110;116;115;91;105;93; + + + + +`,WI=` + + + 105;110;116;91;93;32;112;111;105;110;116;115;32;61;32;123;51;44;32;53;44;32;56;125; + + + 98;111;110;117;115;40;112;111;105;110;116;115;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;105;110;116;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;112;111;105;110;116;115;91;105;93; + + + + +`,NI=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;105;110;116;115;46;108;101;110;103;116;104; + 105;43;43; + + + 112;111;105;110;116;115;91;105;93;32;61;32;112;111;105;110;116;115;91;105;93;32;43;32;49; + + + + +`,FI=` + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;53; + + + 100;111;117;98;108;101;73;116;40;110;117;109;98;101;114;41; + + + 111;117;116;112;117;116;58;32;34;73;110;32;116;104;101;32;109;97;105;110;32;112;114;111;103;114;97;109;58;32;110;117;109;98;101;114;32;61;32;34;32;43;32;110;117;109;98;101;114; + + + 98;111;111;108;101;97;110;91;93;32;114;111;119;32;61;32;123;116;114;117;101;44;32;116;114;117;101;44;32;102;97;108;115;101;44;32;116;114;117;101;125; + + + 111;117;116;112;117;116;58;32;34;66;101;102;111;114;101;58;32;34;32;43;32;114;111;119;91;48;93;32;43;32;34;44;32;34;32;43;32;114;111;119;91;49;93; + + + 99;108;101;97;114;40;114;111;119;41; + + + 111;117;116;112;117;116;58;32;34;65;102;116;101;114;58;32;34;32;43;32;114;111;119;91;48;93;32;43;32;34;44;32;34;32;43;32;114;111;119;91;49;93; + + +`,JI=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;115;101;97;116;115;46;108;101;110;103;116;104; + 105;43;43; + + + 115;101;97;116;115;91;105;93;32;61;32;102;97;108;115;101; + + + + +`,RI=` + + + 120;32;61;32;120;32;42;32;50; + + + 111;117;116;112;117;116;58;32;34;73;110;32;116;104;101;32;115;117;98;112;114;111;103;114;97;109;58;32;120;32;61;32;34;32;43;32;120; + + +`,GI=` + + + 105;110;116;32;100;105;115;116;97;110;99;101;32;61;32;109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;68;105;115;116;97;110;99;101;58;32;34;32;43;32;100;105;115;116;97;110;99;101;32;43;32;34;32;99;109;34;41; + + +`,HI=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;49;48; + + + 109;98;111;116;46;98;97;99;107;119;97;114;100;40;41; + + + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;50;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 248; + + + + + + +`,VI=` + + + 33;109;98;111;116;46;105;115;66;117;116;116;111;110;66;40;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48;32;124;124;32;109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;62;32;54;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;50;48;48;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + +`,qI=` + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;50;48;48;44;32;48;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;50;53;53;44;32;48;41; + + +`,QI=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;50;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;54;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + + + + +`,UI=` + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;72;101;108;108;111;33;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;73;32;97;109;32;86;105;115;117;66;111;116;34;41; + + +`,$I=` + + + 105;110;116;32;110;117;109;98;101;114;32;61;32;48; + 110;117;109;98;101;114;32;60;32;56; + 110;117;109;98;101;114;43;43; + + + 110;117;109;98;101;114;32;37;32;50;32;61;61;32;49; + + + 109;98;111;116;46;108;101;100;40;48;41;46;115;101;116;67;111;108;111;114;40;34;103;114;101;101;110;34;41; + + + + + 109;98;111;116;46;108;101;100;40;48;41;46;115;101;116;67;111;108;111;114;40;34;111;102;102;34;41; + + + + + 110;117;109;98;101;114;32;47;32;50;32;37;32;50;32;61;61;32;49; + + + 109;98;111;116;46;108;101;100;40;49;41;46;115;101;116;67;111;108;111;114;40;34;103;114;101;101;110;34;41; + + + + + 109;98;111;116;46;108;101;100;40;49;41;46;115;101;116;67;111;108;111;114;40;34;111;102;102;34;41; + + + + + 110;117;109;98;101;114;32;47;32;52;32;37;32;50;32;61;61;32;49; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;103;114;101;101;110;34;41; + + + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;111;102;102;34;41; + + + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + + +`,YI=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;101;100;34;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,XI=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,KI=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,e7=` + + + 83;116;114;105;110;103;32;119;111;114;100;32;61;32;34;86;105;115;117;66;111;116;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;119;111;114;100;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;119;111;114;100;46;115;117;98;115;116;114;105;110;103;40;48;44;32;105;41;41; + + + 109;98;111;116;46;112;97;117;115;101;40;51;48;48;41; + + + + +`,t7=` + + + 109;98;111;116;46;108;101;100;40;48;41;46;115;101;116;67;111;108;111;114;40;34;114;101;100;34;41; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;121;101;108;108;111;119;34;41; + + + 109;98;111;116;46;108;101;100;40;52;41;46;115;101;116;67;111;108;111;114;40;34;103;114;101;101;110;34;41; + + +`,n7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;50;48;41; + + + + +`,i7=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;98;108;117;101;34;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;52;53; + + + 109;98;111;116;46;98;97;99;107;119;97;114;100;40;41; + + + + + 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;50;53;53;44;32;48;41; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;80;97;114;107;101;100;33;34;41; + + +`,a7=` + + + 83;116;114;105;110;103;91;93;32;99;111;108;111;117;114;115;32;61;32;123;34;114;101;100;34;44;32;34;121;101;108;108;111;119;34;44;32;34;103;114;101;101;110;34;44;32;34;98;108;117;101;34;44;32;34;112;117;114;112;108;101;34;125; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;111;108;111;117;114;115;46;108;101;110;103;116;104; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;99;111;108;111;117;114;115;91;105;93;41; + + + + +`,s7=` + + + 109;98;111;116;46;103;101;116;67;111;108;111;114;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;50;48;41; + + + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;50;48;48;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;49;48;41; + + + + +`,r7=` + + + 109;98;111;116;46;100;114;105;118;101;40;53;48;44;32;53;48;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + + 109;98;111;116;46;115;116;111;112;40;41; + + +`,o7=` + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + +`,l7=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;101;100;34;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;49;50;56;44;32;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;50;48;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + + +`,u7=` + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;66;97;116;116;101;114;121;58;32;34;32;43;32;109;98;111;116;46;103;101;116;66;97;116;116;101;114;121;40;41;32;43;32;34;32;37;34;41; + + + 109;98;111;116;46;103;101;116;66;97;116;116;101;114;121;40;41;32;60;32;50;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; + + + + + 248; + + + + +`,c7=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;98;108;117;101;34;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;103;114;101;101;110;34;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;50;48;48;41; + + + + + 248; + + + + + + +`,m7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;48;44;32;50;53;53;41; + + + 109;98;111;116;46;112;97;117;115;101;40;53;48;48;41; + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + 109;98;111;116;46;112;97;117;115;101;40;53;48;48;41; + + + + +`,d7=` + + + 105;110;116;32;105;32;61;32;51; + 105;32;62;61;32;49; + 105;45;45; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;105;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;71;111;33;34;41; + + +`,h7=` + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;53; + 105;43;43; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;105;32;42;32;50;48;48;44;32;50;48;48;41; + + + + +`,g7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;105;115;74;111;121;115;116;105;99;107;85;112;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;105;115;74;111;121;115;116;105;99;107;68;111;119;110;40;41; + + + 109;98;111;116;46;98;97;99;107;119;97;114;100;40;41; + + + + + 248; + + + + + + + + +`,p7=` + + + 109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;62;32;54;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + +`,f7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;98;108;117;101;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;111;102;102;34;41; + + + + +`,b7=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;105;115;76;105;110;101;76;101;102;116;40;41;32;38;38;32;109;98;111;116;46;105;115;76;105;110;101;82;105;103;104;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;52;48;44;32;52;48;41; + + + + + 109;98;111;116;46;105;115;76;105;110;101;76;101;102;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;49;48;44;32;52;48;41; + + + + + 109;98;111;116;46;105;115;76;105;110;101;82;105;103;104;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;52;48;44;32;49;48;41; + + + + + 248; + + + + + + + + + + + 109;98;111;116;46;115;116;111;112;40;41; + + +`,x7=` + + + 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;51;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;50;48;48;44;32;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;52;52;48;44;32;51;48;48;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + +`,v7=` + + + 105;110;116;32;115;116;101;112;115;32;61;32;48; + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 115;116;101;112;115;32;61;32;115;116;101;112;115;32;43;32;49; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;115;116;101;112;115; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,y7=` + + + 105;110;116;32;108;101;110;103;116;104;32;61;32;54;48; + + + 105;110;116;32;119;105;100;116;104;32;61;32;51;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;50; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;108;101;110;103;116;104;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;119;105;100;116;104;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,w7=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;34;72;101;108;108;111;32;99;108;97;115;115;34; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;116;101;120;116;32;43;32;34;32;40;34;32;43;32;116;101;120;116;46;108;101;110;103;116;104;40;41;32;43;32;34;41;34;41; + + +`,z7=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;52;52;48;44;32;51;48;48;41; + + +`,I7=` + + + 109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;62;32;45;53;32;38;38;32;109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;60;32;53;32;38;38;32;109;98;111;116;46;103;101;116;82;111;108;108;40;41;32;62;32;45;53;32;38;38;32;109;98;111;116;46;103;101;116;82;111;108;108;40;41;32;60;32;53; + + + 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;50;53;53;44;32;48;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + +`,k7=` + + + 109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;60;32;53;48; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + +`,S7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;114;101;100;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;111;102;102;34;41; + + + + + 105;110;116;32;105;32;61;32;51; + 105;32;62;32;48; + 105;45;45; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;114;101;100;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;111;102;102;34;41; + + + + +`,T7=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;49;53; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + + + + 248; + + + + + + + + +`,_7=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;101;100;34;41; + + + 109;98;111;116;46;105;115;76;105;110;101;76;101;102;116;40;41;32;38;38;32;109;98;111;116;46;105;115;76;105;110;101;82;105;103;104;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;52;48;44;32;52;48;41; + + + + + 109;98;111;116;46;105;115;76;105;110;101;76;101;102;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;49;48;44;32;52;48;41; + + + + + 109;98;111;116;46;105;115;76;105;110;101;82;105;103;104;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;52;48;44;32;49;48;41; + + + + + 248; + + + + + + + + + + + 109;98;111;116;46;115;116;111;112;40;41; + + +`,A7=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;49;48;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;67;114;111;115;115;32;108;105;110;101;33;34;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;53;41; + + + + +`,O7=` + + + 105;110;116;91;93;32;116;111;110;101;115;32;61;32;123;50;54;50;44;32;50;57;52;44;32;51;51;48;44;32;51;52;57;44;32;51;57;50;125; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;111;110;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;116;111;110;101;115;91;105;93;44;32;51;48;48;41; + + + + +`,C7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;119;104;105;116;101;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;111;102;102;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + + + 109;98;111;116;46;112;97;117;115;101;40;52;48;48;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;119;104;105;116;101;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;54;48;48;41; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;111;102;102;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + + + 109;98;111;116;46;112;97;117;115;101;40;52;48;48;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;119;104;105;116;101;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;111;102;102;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + + +`,j7=` + + + 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;51;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;50;53;53;44;32;50;53;53;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + +`,P7=` + + + 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;50;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;90;122;122;34;41; + + +`,D7=` + + + 105;110;112;117;116;58;32;105;110;116;32;103;114;97;100;101; + + + 103;114;97;100;101; + + + 111;117;116;112;117;116;58;32;34;118;101;114;121;32;103;111;111;100;34; + + + + + 111;117;116;112;117;116;58;32;34;103;111;111;100;34; + + + + + 111;117;116;112;117;116;58;32;34;115;97;116;105;115;102;97;99;116;111;114;121;34; + + + + + 111;117;116;112;117;116;58;32;34;111;116;104;101;114;32;103;114;97;100;101;34; + + + + +`,B7=` + + + 105;110;116;32;97;32;61;32;115;113;117;97;114;101;78;117;109;98;101;114;40;51;41; + + + 105;110;116;32;98;32;61;32;115;113;117;97;114;101;78;117;109;98;101;114;40;53;41; + + + 111;117;116;112;117;116;58;32;97; + + + 111;117;116;112;117;116;58;32;98; + + +`,M7=` + + + 114;101;116;117;114;110;32;120;32;42;32;120; + + +`,Z7=` + + + 83;116;114;105;110;103;32;119;111;114;100;32;61;32;34;76;117;100;119;105;103;34; + + + 83;116;114;105;110;103;32;98;97;99;107;119;97;114;100;115;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;119;111;114;100;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 98;97;99;107;119;97;114;100;115;32;61;32;119;111;114;100;46;99;104;97;114;65;116;40;105;41;32;43;32;98;97;99;107;119;97;114;100;115; + + + + + 111;117;116;112;117;116;58;32;98;97;99;107;119;97;114;100;115; + + +`,L7=` + + + 105;110;116;32;108;101;110;103;116;104;32;61;32;54;48; + + + 105;110;116;32;119;105;100;116;104;32;61;32;51;48; + + + 105;110;116;32;100;105;115;116;97;110;99;101;32;61;32;50;32;42;32;108;101;110;103;116;104;32;43;32;50;32;42;32;119;105;100;116;104; + + + 111;117;116;112;117;116;58;32;34;68;105;115;116;97;110;99;101;58;32;34;32;43;32;100;105;115;116;97;110;99;101;32;43;32;34;32;99;109;34; + + +`,E7=` + + + 105;110;116;91;93;32;103;114;97;100;101;115;32;61;32;123;50;44;32;49;44;32;51;44;32;50;125; + + + 105;110;116;32;115;117;109;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;103;114;97;100;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 115;117;109;32;61;32;115;117;109;32;43;32;103;114;97;100;101;115;91;105;93; + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;58;32;34;32;43;32;115;117;109; + + + 111;117;116;112;117;116;58;32;34;67;111;117;110;116;58;32;34;32;43;32;103;114;97;100;101;115;46;108;101;110;103;116;104; + + +`,W7=` + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + +`,N7=` + + + 115;113;117;97;114;101;40;51;48;41; + + + 115;113;117;97;114;101;40;53;48;41; + + +`,F7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + +`,J7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;52; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;115;105;100;101;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,R7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;52; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;53; + 106;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,G7=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + +`,H7=` + + + 109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;62;32;50;48;32;124;124;32;109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;60;32;45;50;48; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;51;48;48;41; + + + + + 248; + + + + +`,V7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;50; + 105;43;43; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;54;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;54;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,q7=` + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;56; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;105;32;42;32;49;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,Q7=` + + + 33;109;98;111;116;46;105;115;66;117;116;116;111;110;65;40;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + +`,U7=` + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;50;54;50;44;32;51;48;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;50;57;52;44;32;51;48;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;51;51;48;44;32;51;48;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;51;52;57;44;32;51;48;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;51;57;50;44;32;51;48;48;41; + + +`,$7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;50;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;50;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,Y7=` + + + 105;110;116;32;108;101;102;116;32;61;32;57;57; + + + 105;110;116;32;114;105;103;104;116;32;61;32;57;57; + + + 108;101;102;116;32;62;61;32;50;48;32;124;124;32;114;105;103;104;116;32;62;61;32;50;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 108;101;102;116;32;61;32;109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + + 114;105;103;104;116;32;61;32;109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + + +`,X7=` + + + 105;110;116;32;115;105;100;101;32;61;32;51;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;52; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;115;105;100;101;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,K7=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;52; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;52; + 106;43;43; + + + 105;110;116;32;107;32;61;32;48; + 107;32;60;32;53; + 107;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,ek=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;54;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + + + + +`,tk=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,nk=` + + + 109;98;111;116;46;114;101;115;101;116;84;105;109;101;114;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;53;48;44;32;53;48;41; + + + 109;98;111;116;46;103;101;116;84;105;109;101;114;40;41;32;60;32;50; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + + 109;98;111;116;46;115;116;111;112;40;41; + + +`,ik=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;105;114;115;116;78;97;109;101;32;34;70;105;114;115;116;32;110;97;109;101;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;108;97;115;116;78;97;109;101;32;34;76;97;115;116;32;110;97;109;101;34; + + + 111;117;116;112;117;116;58;32;102;105;114;115;116;78;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;108;97;115;116;78;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; + + +`,ak=` + + + 83;116;114;105;110;103;32;119;111;114;100;32;61;32;34;66;105;108;108;121;103;111;97;116;34; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;105;110;100;101;120;79;102;40;34;108;34;41; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;108;97;115;116;73;110;100;101;120;79;102;40;34;108;34;41; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;105;115;69;109;112;116;121;40;41; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;101;113;117;97;108;115;73;103;110;111;114;101;67;97;115;101;40;34;66;73;76;76;89;71;79;65;84;34;41; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;114;101;112;108;97;99;101;40;34;66;105;108;108;121;34;44;32;34;78;97;110;110;121;34;41; + + + 111;117;116;112;117;116;58;32;34;66;97;97;34;46;114;101;112;101;97;116;40;51;41; + + + 111;117;116;112;117;116;58;32;34;65;110;110;97;34;46;99;111;109;112;97;114;101;84;111;40;34;66;101;110;34;41; + + + 105;110;116;32;97;103;101;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;34;55;34;41; + + + 111;117;116;112;117;116;58;32;97;103;101;32;43;32;49; + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;83;116;114;105;110;103;46;118;97;108;117;101;79;102;40;97;103;101;41;32;43;32;34;32;121;101;97;114;115;34; + + + 111;117;116;112;117;116;58;32;116;101;120;116; + + +`,sk=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;100;32;34;69;110;116;101;114;32;97;32;119;111;114;100;34; + + + 83;116;114;105;110;103;32;98;97;99;107;119;97;114;100;115;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;119;111;114;100;46;108;101;110;103;116;104;40;41;32;45;32;49; + 105;32;62;61;32;48; + 105;45;45; + + + 98;97;99;107;119;97;114;100;115;32;61;32;98;97;99;107;119;97;114;100;115;32;43;32;119;111;114;100;46;99;104;97;114;65;116;40;105;41; + + + + + 111;117;116;112;117;116;58;32;98;97;99;107;119;97;114;100;115; + + +`,rk=` + + + 83;116;114;105;110;103;32;108;105;110;101;32;61;32;34;76;117;100;119;105;103;59;98;105;108;108;121;32;103;111;97;116;59;55;34; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;115;32;61;32;108;105;110;101;46;115;112;108;105;116;40;34;59;34;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;97;114;116;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;105;32;43;32;34;58;32;34;32;43;32;112;97;114;116;115;91;105;93; + + + + +`,ok=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;115;101;110;116;101;110;99;101;32;34;69;110;116;101;114;32;97;32;115;101;110;116;101;110;99;101;34; + + + 83;116;114;105;110;103;91;93;32;119;111;114;100;115;32;61;32;115;101;110;116;101;110;99;101;46;115;112;108;105;116;40;34;32;34;41; + + + 111;117;116;112;117;116;58;32;34;87;111;114;100;115;58;32;34;32;43;32;119;111;114;100;115;46;108;101;110;103;116;104; + + +`,lk=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;100;32;34;69;110;116;101;114;32;97;32;119;111;114;100;34; + + + 105;110;116;32;99;111;117;110;116;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;119;111;114;100;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 119;111;114;100;46;99;104;97;114;65;116;40;105;41;32;61;61;32;39;101;39; + + + 99;111;117;110;116;32;61;32;99;111;117;110;116;32;43;32;49; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;78;117;109;98;101;114;32;111;102;32;101;58;32;34;32;43;32;99;111;117;110;116; + + +`,uk=` + + + 83;116;114;105;110;103;32;119;111;114;100;32;61;32;34;66;105;108;108;121;103;111;97;116;34; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;108;101;110;103;116;104;40;41; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;99;104;97;114;65;116;40;48;41; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;115;117;98;115;116;114;105;110;103;40;48;44;32;53;41; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;115;117;98;115;116;114;105;110;103;40;53;41; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;105;110;100;101;120;79;102;40;34;103;111;97;116;34;41; + + + 111;117;116;112;117;116;58;32;119;111;114;100;46;116;111;85;112;112;101;114;67;97;115;101;40;41; + + +`,ck=` + + + 105;110;116;91;93;91;93;32;116;97;98;101;108;108;101;32;61;32;110;101;119;32;105;110;116;91;49;48;93;91;49;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;97;98;101;108;108;101;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;116;97;98;101;108;108;101;91;105;93;46;108;101;110;103;116;104; + 106;43;43; + + + 116;97;98;101;108;108;101;91;105;93;91;106;93;32;61;32;40;105;32;43;32;49;41;32;42;32;40;106;32;43;32;49;41; + + + + + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;32;40;49;32;98;105;115;32;49;48;41;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;32;40;49;32;98;105;115;32;49;48;41;34; + + + 111;117;116;112;117;116;58;32;97;32;43;32;34;32;183;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;116;97;98;101;108;108;101;91;97;32;45;32;49;93;91;98;32;45;32;49;93; + + +`,mk=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;105;116;122;101;91;48;93;91;48;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;50;93;91;51;93;32;61;32;116;114;117;101; + + + 105;110;116;32;102;114;101;105;32;61;32;48; + + + 105;110;116;32;114;101;105;104;101;32;61;32;48; + 114;101;105;104;101;32;60;32;115;105;116;122;101;46;108;101;110;103;116;104; + 114;101;105;104;101;43;43; + + + 105;110;116;32;112;108;97;116;122;32;61;32;48; + 112;108;97;116;122;32;60;32;115;105;116;122;101;91;114;101;105;104;101;93;46;108;101;110;103;116;104; + 112;108;97;116;122;43;43; + + + 33;115;105;116;122;101;91;114;101;105;104;101;93;91;112;108;97;116;122;93; + + + 102;114;101;105;32;61;32;102;114;101;105;32;43;32;49; + + + + + 248; + + + + + + + + + 111;117;116;112;117;116;58;32;34;70;114;101;105;58;32;34;32;43;32;102;114;101;105; + + +`,dk=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;105;116;122;101;91;48;93;91;48;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;50;93;91;51;93;32;61;32;116;114;117;101; + + +`,hk=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;105;116;122;101;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;49;93;91;51;93;32;61;32;116;114;117;101; + + + 105;110;112;117;116;58;32;105;110;116;32;114;101;105;104;101;32;34;82;101;105;104;101;34; + + + 105;110;112;117;116;58;32;105;110;116;32;112;108;97;116;122;32;34;80;108;97;116;122;34; + + + 115;105;116;122;101;91;114;101;105;104;101;93;91;112;108;97;116;122;93; + + + 111;117;116;112;117;116;58;32;34;83;99;104;111;110;32;118;101;114;107;97;117;102;116;34; + + + + + 115;105;116;122;101;91;114;101;105;104;101;93;91;112;108;97;116;122;93;32;61;32;116;114;117;101; + + + 111;117;116;112;117;116;58;32;34;86;101;114;107;97;117;102;116;58;32;82;101;105;104;101;32;34;32;43;32;114;101;105;104;101;32;43;32;34;44;32;80;108;97;116;122;32;34;32;43;32;112;108;97;116;122; + + + + +`,gk=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;105;116;122;101;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;49;93;91;51;93;32;61;32;116;114;117;101; + + + 105;110;112;117;116;58;32;105;110;116;32;114;101;105;104;101;32;34;82;101;105;104;101;34; + + + 105;110;112;117;116;58;32;105;110;116;32;112;108;97;116;122;32;34;80;108;97;116;122;34; + + +`,pk=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;105;116;122;101;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;49;93;91;49;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 105;110;116;32;114;101;105;104;101;32;61;32;48; + 114;101;105;104;101;32;60;32;115;105;116;122;101;46;108;101;110;103;116;104; + 114;101;105;104;101;43;43; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;34;34; + + + 105;110;116;32;112;108;97;116;122;32;61;32;48; + 112;108;97;116;122;32;60;32;115;105;116;122;101;91;114;101;105;104;101;93;46;108;101;110;103;116;104; + 112;108;97;116;122;43;43; + + + 115;105;116;122;101;91;114;101;105;104;101;93;91;112;108;97;116;122;93; + + + 122;101;105;108;101;32;61;32;122;101;105;108;101;32;43;32;34;88;34; + + + + + 122;101;105;108;101;32;61;32;122;101;105;108;101;32;43;32;34;79;34; + + + + + + + 111;117;116;112;117;116;58;32;122;101;105;108;101; + + + + +`,fk=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;115;105;116;122;101;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 115;105;116;122;101;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;49;93;91;49;93;32;61;32;116;114;117;101; + + + 115;105;116;122;101;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 111;117;116;112;117;116;58;32;34;82;101;105;104;101;110;58;32;34;32;43;32;115;105;116;122;101;46;108;101;110;103;116;104; + + + 111;117;116;112;117;116;58;32;34;80;108;228;116;122;101;32;112;114;111;32;82;101;105;104;101;58;32;34;32;43;32;115;105;116;122;101;91;48;93;46;108;101;110;103;116;104; + + + 111;117;116;112;117;116;58;32;34;82;101;105;104;101;32;49;44;32;80;108;97;116;122;32;50;32;118;101;114;107;97;117;102;116;63;32;34;32;43;32;115;105;116;122;101;91;49;93;91;50;93; + + +`,bk=` + + + 105;110;116;32;115;101;107;117;110;100;101;110;32;61;32;50;48;48; + + + 105;110;116;32;109;105;110;117;116;101;110;32;61;32;115;101;107;117;110;100;101;110;32;47;32;54;48; + + + 105;110;116;32;114;101;115;116;32;61;32;115;101;107;117;110;100;101;110;32;37;32;54;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;101;110;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;32;43;32;34;32;115;34; + + +`,xk=` + + + 105;110;116;32;115;101;107;117;110;100;101;110;32;61;32;50;48;48; + + + 105;110;116;32;109;105;110;117;116;101;110;32;61;32;115;101;107;117;110;100;101;110;32;37;32;54;48; + + + 105;110;116;32;114;101;115;116;32;61;32;115;101;107;117;110;100;101;110;32;47;32;54;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;101;110;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;32;43;32;34;32;115;34; + + +`,vk=` + + + 83;116;114;105;110;103;32;110;97;109;101;32;61;32;34;76;117;100;119;105;103;34; + + + 105;110;116;32;97;108;116;101;114;32;61;32;55; + + + 100;111;117;98;108;101;32;103;114;111;101;115;115;101;32;61;32;49;46;50; + + + 111;117;116;112;117;116;58;32;110;97;109;101;32;43;32;34;32;105;115;116;32;34;32;43;32;97;108;116;101;114;32;43;32;34;32;74;97;104;114;101;32;97;108;116;46;34; + + + 111;117;116;112;117;116;58;32;34;71;114;246;223;101;58;32;34;32;43;32;103;114;111;101;115;115;101;32;43;32;34;32;109;34; + + +`,yk=` + + + 105;110;116;32;122;97;104;108;32;61;32;51; + + + 122;97;104;108;32;61;32;122;97;104;108;32;42;32;50; + + + 122;97;104;108;32;61;32;122;97;104;108;32;43;32;49; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + +`,wk=` + + + 105;110;116;32;122;97;104;108;32;61;32;50; + + + 122;97;104;108;32;61;32;122;97;104;108;32;43;32;51; + + + 122;97;104;108;32;61;32;122;97;104;108;32;42;32;52; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + +`,zk=` + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + 122;97;104;108;32;61;32;122;97;104;108;32;42;32;52; + + + 105;110;116;32;122;97;104;108;32;61;32;50; + + + 122;97;104;108;32;61;32;122;97;104;108;32;43;32;51; + + +`,Ik=` + + + 83;116;114;105;110;103;32;108;105;110;107;115;32;61;32;34;83;97;102;116;34; + + + 83;116;114;105;110;103;32;114;101;99;104;116;115;32;61;32;34;87;97;115;115;101;114;34; + + + 83;116;114;105;110;103;32;104;105;108;102;32;61;32;108;105;110;107;115; + + + 108;105;110;107;115;32;61;32;114;101;99;104;116;115; + + + 114;101;99;104;116;115;32;61;32;104;105;108;102; + + + 111;117;116;112;117;116;58;32;34;76;105;110;107;115;58;32;34;32;43;32;108;105;110;107;115; + + + 111;117;116;112;117;116;58;32;34;82;101;99;104;116;115;58;32;34;32;43;32;114;101;99;104;116;115; + + +`,kk=` + + + 83;116;114;105;110;103;32;108;105;110;107;115;32;61;32;34;83;97;102;116;34; + + + 83;116;114;105;110;103;32;114;101;99;104;116;115;32;61;32;34;87;97;115;115;101;114;34; + + + 111;117;116;112;117;116;58;32;34;76;105;110;107;115;58;32;34;32;43;32;108;105;110;107;115; + + + 111;117;116;112;117;116;58;32;34;82;101;99;104;116;115;58;32;34;32;43;32;114;101;99;104;116;115; + + +`,Sk=` + + + 105;110;116;32;97;32;61;32;53; + + + 105;110;116;32;98;32;61;32;57; + + + 105;110;116;32;104;105;108;102;32;61;32;97; + + + 97;32;61;32;98; + + + 98;32;61;32;104;105;108;102; + + + 111;117;116;112;117;116;58;32;34;97;32;61;32;34;32;43;32;97; + + + 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; + + +`,Tk=` + + + 105;110;116;32;97;108;116;101;114;32;61;32;49;52; + + + 100;111;117;98;108;101;32;103;114;111;101;115;115;101;32;61;32;49;46;54;50; + + + 83;116;114;105;110;103;32;110;97;109;101;32;61;32;34;77;105;97;34; + + + 111;117;116;112;117;116;58;32;110;97;109;101;32;43;32;34;32;105;115;116;32;34;32;43;32;97;108;116;101;114;32;43;32;34;32;74;97;104;114;101;32;97;108;116;46;34; + + + 111;117;116;112;117;116;58;32;34;71;114;246;223;101;58;32;34;32;43;32;103;114;111;101;115;115;101;32;43;32;34;32;109;34; + + +`,_k=` + + + 105;110;116;32;109;105;110;117;116;101;110;32;61;32;49;51;53; + + + 105;110;116;32;115;116;117;110;100;101;110;32;61;32;109;105;110;117;116;101;110;32;47;32;54;48; + + + 105;110;116;32;114;101;115;116;32;61;32;109;105;110;117;116;101;110;32;37;32;54;48; + + + 111;117;116;112;117;116;58;32;115;116;117;110;100;101;110;32;43;32;34;32;83;116;117;110;100;101;110;32;117;110;100;32;34;32;43;32;114;101;115;116;32;43;32;34;32;77;105;110;117;116;101;110;34; + + +`,Ak=` + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;51; + + + 100;111;117;98;108;101;32;112;114;101;105;115;32;61;32;50;46;53; + + + 100;111;117;98;108;101;32;103;101;115;97;109;116;80;114;101;105;115;32;61;32;97;110;122;97;104;108;32;42;32;112;114;101;105;115; + + + 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116;80;114;101;105;115;32;43;32;34;32;69;117;114;111;34; + + +`,Ok=` + + + 105;110;116;32;103;117;116;104;97;98;101;110;32;61;32;50;48; + + + 105;110;116;32;112;114;101;105;115;32;61;32;55; + + + 103;117;116;104;97;98;101;110;32;61;32;103;117;116;104;97;98;101;110;32;45;32;112;114;101;105;115; + + + 111;117;116;112;117;116;58;32;34;220;98;114;105;103;58;32;34;32;43;32;103;117;116;104;97;98;101;110; + + +`,Ck=` + + + 105;110;116;32;103;117;116;104;97;98;101;110;32;61;32;50;48; + + + 105;110;116;32;112;114;101;105;115;32;61;32;55; + + + 111;117;116;112;117;116;58;32;34;220;98;114;105;103;58;32;34;32;43;32;103;117;116;104;97;98;101;110; + + + 103;117;116;104;97;98;101;110;32;61;32;103;117;116;104;97;98;101;110;32;45;32;112;114;101;105;115; + + +`,jk=` + + + 105;110;116;32;112;114;101;105;115;32;61;32;57; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;51; + + + 105;110;116;32;103;101;115;97;109;116;32;61;32;112;114;101;105;115;32;42;32;97;110;122;97;104;108; + + + 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116; + + +`,Pk=` + + + 105;110;116;32;108;97;101;110;103;101;32;61;32;55; + + + 105;110;116;32;98;114;101;105;116;101;32;61;32;52; + + + 105;110;116;32;102;108;97;101;99;104;101;32;61;32;108;97;101;110;103;101;32;42;32;98;114;101;105;116;101; + + + 105;110;116;32;117;109;102;97;110;103;32;61;32;50;32;42;32;40;108;97;101;110;103;101;32;43;32;98;114;101;105;116;101;41; + + + 111;117;116;112;117;116;58;32;34;70;108;228;99;104;101;58;32;34;32;43;32;102;108;97;101;99;104;101; + + + 111;117;116;112;117;116;58;32;34;85;109;102;97;110;103;58;32;34;32;43;32;117;109;102;97;110;103; + + +`,Dk=` + + + 105;110;116;32;115;101;107;117;110;100;101;110;32;61;32;50;48;48; + + + 105;110;116;32;109;105;110;117;116;101;110;32;61;32;115;101;107;117;110;100;101;110;32;47;32;54;48; + + + 105;110;116;32;114;101;115;116;32;61;32;115;101;107;117;110;100;101;110;32;37;32;54;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;101;110;32;43;32;34;32;77;105;110;117;116;101;110;32;117;110;100;32;34;32;43;32;114;101;115;116;32;43;32;34;32;83;101;107;117;110;100;101;110;34; + + +`,Bk=` + + + 105;110;116;32;115;101;107;117;110;100;101;110;32;61;32;50;48;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;101;110;32;43;32;34;32;77;105;110;117;116;101;110;32;117;110;100;32;34;32;43;32;114;101;115;116;32;43;32;34;32;83;101;107;117;110;100;101;110;34; + + +`,Mk=` + + + 105;110;116;32;108;97;101;110;103;101;32;61;32;53; + + + 105;110;116;32;98;114;101;105;116;101;32;61;32;51; + + + 105;110;116;32;102;108;97;101;99;104;101;32;61;32;108;97;101;110;103;101;32;42;32;98;114;101;105;116;101; + + + 111;117;116;112;117;116;58;32;102;108;97;101;99;104;101; + + +`,Zk=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;97;109;101;32;34;87;105;101;32;104;101;105;223;116;32;100;117;63;34; + + + 111;117;116;112;117;116;58;32;34;72;97;108;108;111;32;34;32;43;32;110;97;109;101;32;43;32;34;33;34; + + +`,Lk=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;63;34; + + + 105;110;116;32;115;117;109;109;101;32;61;32;97;32;43;32;98; + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; + + +`,Ek=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;63;34; + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;40;97;32;43;32;98;41; + + +`,Wk=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;63;34; + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;97;32;43;32;98; + + +`,Nk=` + + + 105;110;112;117;116;58;32;105;110;116;32;106;97;104;114;101;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; + + + 105;110;116;32;116;97;103;101;32;61;32;106;97;104;114;101;32;42;32;51;54;53; + + + 111;117;116;112;117;116;58;32;34;68;97;115;32;115;105;110;100;32;101;116;119;97;32;34;32;43;32;116;97;103;101;32;43;32;34;32;84;97;103;101;46;34; + + +`,Fk=` + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;120;32;34;69;114;115;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;121;32;34;90;119;101;105;116;101;32;90;97;104;108;63;34; + + + 100;111;117;98;108;101;32;109;105;116;116;101;108;32;61;32;40;120;32;43;32;121;41;32;47;32;50; + + + 111;117;116;112;117;116;58;32;34;77;105;116;116;101;108;119;101;114;116;58;32;34;32;43;32;109;105;116;116;101;108; + + +`,Jk=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;63;34; + + + 105;110;116;32;115;117;109;109;101;32;61;32;97;32;43;32;98; + + + 105;110;116;32;112;114;111;100;117;107;116;32;61;32;97;32;42;32;98; + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; + + + 111;117;116;112;117;116;58;32;34;80;114;111;100;117;107;116;58;32;34;32;43;32;112;114;111;100;117;107;116; + + +`,Rk=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; + + + 97;108;116;101;114;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;68;117;32;98;105;115;116;32;118;111;108;108;106;228;104;114;105;103;46;34; + + + + + 111;117;116;112;117;116;58;32;34;68;117;32;98;105;115;116;32;110;111;99;104;32;110;105;99;104;116;32;118;111;108;108;106;228;104;114;105;103;46;34; + + + + +`,Gk=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;90;97;104;108;63;34; + + + 122;97;104;108;32;60;32;48; + + + 122;97;104;108;32;61;32;48;32;45;32;122;97;104;108; + + + + + 248; + + + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + +`,Hk=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;90;97;104;108;63;34; + + + 122;97;104;108;32;37;32;50;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;34;103;101;114;97;100;101;34; + + + + + 111;117;116;112;117;116;58;32;34;117;110;103;101;114;97;100;101;34; + + + + +`,Vk=` + + + 105;110;116;32;112;117;110;107;116;101;32;61;32;48; + + + 112;117;110;107;116;101;32;61;32;112;117;110;107;116;101;32;43;32;49;48; + + + 112;117;110;107;116;101;32;61;32;112;117;110;107;116;101;32;43;32;53; + + + 112;117;110;107;116;101;32;61;32;112;117;110;107;116;101;32;45;32;51; + + + 111;117;116;112;117;116;58;32;34;80;117;110;107;116;101;58;32;34;32;43;32;112;117;110;107;116;101; + + +`,qk=` + + + 105;110;116;32;112;117;110;107;116;101;32;61;32;48; + + + 112;117;110;107;116;101;32;61;32;112;117;110;107;116;101;32;43;32;49;48; + + + 112;117;110;107;116;101;32;61;32;112;117;110;107;116;101;32;43;32;53; + + + 112;117;110;107;116;101;32;61;32;51; + + + 111;117;116;112;117;116;58;32;34;80;117;110;107;116;101;58;32;34;32;43;32;112;117;110;107;116;101; + + +`,Qk=` + + + 105;110;116;32;112;114;101;105;115;32;61;32;56; + + + 105;110;116;32;107;97;101;115;101;32;61;32;50; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;51; + + + 105;110;116;32;103;101;115;97;109;116;32;61;32;40;112;114;101;105;115;32;43;32;107;97;101;115;101;41;32;42;32;97;110;122;97;104;108; + + + 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116; + + +`,Uk=` + + + 105;110;116;32;112;114;101;105;115;32;61;32;56; + + + 105;110;116;32;107;97;101;115;101;32;61;32;50; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;51; + + + 105;110;116;32;103;101;115;97;109;116;32;61;32;112;114;101;105;115;32;43;32;107;97;101;115;101;32;42;32;97;110;122;97;104;108; + + + 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116; + + +`,$k=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;63;34; + + + 97;32;62;32;98; + + + 111;117;116;112;117;116;58;32;97; + + + + + 111;117;116;112;117;116;58;32;98; + + + + +`,Yk=` + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;112;114;101;105;115;32;34;80;114;101;105;115;32;105;110;32;69;117;114;111;63;34; + + + 112;114;101;105;115;32;62;32;53;48; + + + 112;114;101;105;115;32;61;32;112;114;101;105;115;32;45;32;53; + + + + + 248; + + + + + 111;117;116;112;117;116;58;32;34;90;117;32;122;97;104;108;101;110;58;32;34;32;43;32;112;114;101;105;115;32;43;32;34;32;69;117;114;111;34; + + +`,Xk=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;111;116;101;32;34;78;111;116;101;63;34; + + + 110;111;116;101;32;62;61;32;49;32;38;38;32;110;111;116;101;32;60;61;32;54; + + + 111;117;116;112;117;116;58;32;34;103;252;108;116;105;103;34; + + + + + 111;117;116;112;117;116;58;32;34;117;110;103;252;108;116;105;103;34; + + + + +`,Kk=` + + + 105;110;112;117;116;58;32;105;110;116;32;112;117;110;107;116;101;32;34;87;105;101;32;118;105;101;108;101;32;80;117;110;107;116;101;63;34; + + + 112;117;110;107;116;101;32;62;61;32;53;48; + + + 111;117;116;112;117;116;58;32;34;98;101;115;116;97;110;100;101;110;34; + + + + + 111;117;116;112;117;116;58;32;34;110;105;99;104;116;32;98;101;115;116;97;110;100;101;110;34; + + + + +`,e8=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; + + + 97;108;116;101;114;32;60;32;54; + + + 111;117;116;112;117;116;58;32;34;69;105;110;116;114;105;116;116;32;102;114;101;105;34; + + + + + 111;117;116;112;117;116;58;32;34;52;32;69;117;114;111;34; + + + + +`,t8=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; + + + 97;108;116;101;114;32;60;61;32;54; + + + 111;117;116;112;117;116;58;32;34;69;105;110;116;114;105;116;116;32;102;114;101;105;34; + + + + + 111;117;116;112;117;116;58;32;34;52;32;69;117;114;111;34; + + + + +`,n8=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; + + + 97;108;116;101;114;32;62;61;32;49;50;32;38;38;32;97;108;116;101;114;32;60;32;49;56; + + + 111;117;116;112;117;116;58;32;34;74;117;103;101;110;100;116;105;99;107;101;116;34; + + + + + 111;117;116;112;117;116;58;32;34;75;101;105;110;32;74;117;103;101;110;100;116;105;99;107;101;116;34; + + + + +`,i8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;111;116;101;32;34;78;111;116;101;63;34; + + + 110;111;116;101;32;60;32;49;32;124;124;32;110;111;116;101;32;62;32;54; + + + 111;117;116;112;117;116;58;32;34;68;105;101;115;101;32;78;111;116;101;32;103;105;98;116;32;101;115;32;110;105;99;104;116;46;34; + + + + + 111;117;116;112;117;116;58;32;34;78;111;116;101;32;34;32;43;32;110;111;116;101;32;43;32;34;32;105;115;116;32;103;252;108;116;105;103;46;34; + + + + +`,a8=` + + + 105;110;112;117;116;58;32;105;110;116;32;106;97;104;114;32;34;74;97;104;114;63;34; + + + 40;106;97;104;114;32;37;32;52;32;61;61;32;48;32;38;38;32;106;97;104;114;32;37;32;49;48;48;32;33;61;32;48;41;32;124;124;32;106;97;104;114;32;37;32;52;48;48;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;34;83;99;104;97;108;116;106;97;104;114;34; + + + + + 111;117;116;112;117;116;58;32;34;107;101;105;110;32;83;99;104;97;108;116;106;97;104;114;34; + + + + +`,s8=` + + + 105;110;112;117;116;58;32;105;110;116;32;116;97;103;32;34;84;97;103;32;40;49;32;98;105;115;32;55;41;63;34; + + + 116;97;103;32;61;61;32;54;32;124;124;32;116;97;103;32;61;61;32;55; + + + 111;117;116;112;117;116;58;32;34;87;111;99;104;101;110;101;110;100;101;34; + + + + + 111;117;116;112;117;116;58;32;34;87;101;114;107;116;97;103;34; + + + + +`,r8=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;97;114;98;101;32;34;87;101;108;99;104;101;32;70;97;114;98;101;32;104;97;116;32;100;105;101;32;65;109;112;101;108;63;34; + + + 102;97;114;98;101; + + + 111;117;116;112;117;116;58;32;34;83;116;101;104;101;110;32;98;108;101;105;98;101;110;34; + + + + + 111;117;116;112;117;116;58;32;34;87;97;114;116;101;110;34; + + + + + 111;117;116;112;117;116;58;32;34;71;101;104;101;110;34; + + + + + 111;117;116;112;117;116;58;32;34;68;105;101;115;101;32;70;97;114;98;101;32;107;101;110;110;101;32;105;99;104;32;110;105;99;104;116;46;34; + + + + +`,o8=` + + + 105;110;112;117;116;58;32;105;110;116;32;119;97;104;108;32;34;49;32;87;97;115;115;101;114;44;32;50;32;83;97;102;116;44;32;51;32;75;97;107;97;111;34; + + + 119;97;104;108; + + + 111;117;116;112;117;116;58;32;34;72;105;101;114;32;105;115;116;32;100;101;105;110;32;87;97;115;115;101;114;46;34; + + + + + 111;117;116;112;117;116;58;32;34;72;105;101;114;32;105;115;116;32;100;101;105;110;32;83;97;102;116;46;34; + + + + + 111;117;116;112;117;116;58;32;34;72;105;101;114;32;105;115;116;32;100;101;105;110;32;75;97;107;97;111;46;34; + + + + + 111;117;116;112;117;116;58;32;34;68;105;101;115;101;32;84;97;115;116;101;32;103;105;98;116;32;101;115;32;110;105;99;104;116;46;34; + + + + +`,l8=` + + + 105;110;112;117;116;58;32;105;110;116;32;116;97;103;32;34;87;101;108;99;104;101;114;32;84;97;103;32;40;49;32;98;105;115;32;55;41;63;34; + + + 116;97;103;32;61;61;32;54;32;124;124;32;116;97;103;32;61;61;32;55; + + + 111;117;116;112;117;116;58;32;34;115;99;104;117;108;102;114;101;105;34; + + + + + 111;117;116;112;117;116;58;32;34;83;99;104;117;108;101;34; + + + + +`,u8=` + + + 105;110;112;117;116;58;32;105;110;116;32;116;97;103;32;34;87;101;108;99;104;101;114;32;84;97;103;32;40;49;32;98;105;115;32;55;41;63;34; + + + 116;97;103;32;61;61;32;54;32;38;38;32;116;97;103;32;61;61;32;55; + + + 111;117;116;112;117;116;58;32;34;115;99;104;117;108;102;114;101;105;34; + + + + + 111;117;116;112;117;116;58;32;34;83;99;104;117;108;101;34; + + + + +`,c8=` + + + 105;110;112;117;116;58;32;105;110;116;32;115;116;117;110;100;101;32;34;87;105;101;32;115;112;228;116;32;105;115;116;32;101;115;32;40;110;117;114;32;100;105;101;32;83;116;117;110;100;101;41;63;34; + + + 115;116;117;110;100;101;32;62;61;32;56;32;38;38;32;115;116;117;110;100;101;32;60;61;32;49;53; + + + 111;117;116;112;117;116;58;32;34;83;99;104;117;108;101;34; + + + + + 111;117;116;112;117;116;58;32;34;70;114;101;105;122;101;105;116;34; + + + + +`,m8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;111;116;101;32;34;87;101;108;99;104;101;32;78;111;116;101;63;34; + + + 110;111;116;101; + + + 111;117;116;112;117;116;58;32;34;115;101;104;114;32;103;117;116;34; + + + + + 111;117;116;112;117;116;58;32;34;103;117;116;34; + + + + + 111;117;116;112;117;116;58;32;34;98;101;102;114;105;101;100;105;103;101;110;100;34; + + + + + 111;117;116;112;117;116;58;32;34;97;117;115;114;101;105;99;104;101;110;100;34; + + + + + 111;117;116;112;117;116;58;32;34;109;97;110;103;101;108;104;97;102;116;34; + + + + + 111;117;116;112;117;116;58;32;34;117;110;103;101;110;252;103;101;110;100;34; + + + + + 111;117;116;112;117;116;58;32;34;75;101;105;110;101;32;103;252;108;116;105;103;101;32;78;111;116;101;34; + + + + +`,d8=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;122;101;105;99;104;101;110;32;34;82;101;99;104;101;110;122;101;105;99;104;101;110;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;34; + + + 105;110;116;32;101;114;103;101;98;110;105;115;32;61;32;48; + + + 122;101;105;99;104;101;110; + + + 101;114;103;101;98;110;105;115;32;61;32;97;32;43;32;98; + + + 111;117;116;112;117;116;58;32;101;114;103;101;98;110;105;115; + + + + + 101;114;103;101;98;110;105;115;32;61;32;97;32;45;32;98; + + + 111;117;116;112;117;116;58;32;101;114;103;101;98;110;105;115; + + + + + 101;114;103;101;98;110;105;115;32;61;32;97;32;42;32;98; + + + 111;117;116;112;117;116;58;32;101;114;103;101;98;110;105;115; + + + + + 111;117;116;112;117;116;58;32;34;85;110;98;101;107;97;110;110;116;101;115;32;82;101;99;104;101;110;122;101;105;99;104;101;110;34; + + + + +`,h8=` + + + 105;110;112;117;116;58;32;105;110;116;32;119;97;104;108;32;34;49;32;87;97;115;115;101;114;44;32;50;32;83;97;102;116;44;32;51;32;75;97;107;97;111;34; + + + 119;97;104;108;32;61;61;32;49; + + + 111;117;116;112;117;116;58;32;34;72;105;101;114;32;105;115;116;32;100;101;105;110;32;87;97;115;115;101;114;46;34; + + + + + 119;97;104;108;32;61;61;32;50; + + + 111;117;116;112;117;116;58;32;34;72;105;101;114;32;105;115;116;32;100;101;105;110;32;83;97;102;116;46;34; + + + + + 119;97;104;108;32;61;61;32;51; + + + 111;117;116;112;117;116;58;32;34;72;105;101;114;32;105;115;116;32;100;101;105;110;32;75;97;107;97;111;46;34; + + + + + 111;117;116;112;117;116;58;32;34;68;105;101;115;101;32;84;97;115;116;101;32;103;105;98;116;32;101;115;32;110;105;99;104;116;46;34; + + + + + + + + +`,g8=` + + + 84;97;115;115;101;32;97;117;102;32;100;101;110;32;84;105;115;99;104;32;115;116;101;108;108;101;110; + + + 90;117;99;107;101;114;32;103;101;119;252;110;115;99;104;116;63; + + + 90;117;99;107;101;114;32;104;105;110;101;105;110;103;101;98;101;110; + + + + + 248; + + + + + 84;101;101;32;110;111;99;104;32;122;117;32;104;101;105;223; + + + 49;32;77;105;110;117;116;101;32;119;97;114;116;101;110; + + + + + 84;101;101;32;116;114;105;110;107;101;110; + + +`,p8=` + + + 65;117;102;115;116;101;104;101;110; + + + 90;228;104;110;101;32;112;117;116;122;101;110; + + + 65;110;122;105;101;104;101;110; + + + 70;114;252;104;115;116;252;99;107;101;110; + + +`,f8=` + + + 87;97;115;115;101;114;32;105;110;32;100;101;110;32;87;97;115;115;101;114;107;111;99;104;101;114;32;102;252;108;108;101;110; + + + 87;97;115;115;101;114;107;111;99;104;101;114;32;101;105;110;115;99;104;97;108;116;101;110; + + + 84;101;101;98;101;117;116;101;108;32;105;110;32;100;105;101;32;84;97;115;115;101;32;108;101;103;101;110; + + + 72;101;105;223;101;115;32;87;97;115;115;101;114;32;105;110;32;100;105;101;32;84;97;115;115;101;32;103;105;101;223;101;110; + + + 51;32;77;105;110;117;116;101;110;32;119;97;114;116;101;110; + + + 84;101;101;98;101;117;116;101;108;32;104;101;114;97;117;115;110;101;104;109;101;110; + + +`,b8=` + + + 82;101;103;110;101;116;32;101;115;63; + + + 82;101;103;101;110;115;99;104;105;114;109;32;101;105;110;112;97;99;107;101;110; + + + + + 83;111;110;110;101;110;98;114;105;108;108;101;32;101;105;110;112;97;99;107;101;110; + + + + + 76;111;115;103;101;104;101;110; + + +`,x8=` + + + 84;101;108;108;101;114;32;110;105;99;104;116;32;108;101;101;114; + + + 69;105;110;101;110;32;66;105;115;115;101;110;32;101;115;115;101;110; + + + + + 84;101;108;108;101;114;32;97;98;114;228;117;109;101;110; + + +`,v8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;119;111;104;105;110;32;122;228;104;108;101;110;63;34; + + + 105;110;116;32;105;32;61;32;49; + + + 105;32;60;61;32;110; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + +`,y8=` + + + 105;110;116;32;122;97;104;108;32;61;32;51; + + + 122;97;104;108;32;62;32;48; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + 122;97;104;108;32;61;32;122;97;104;108;32;45;32;49; + + + + + 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; + + +`,w8=` + + + 105;110;116;32;122;97;104;108;32;61;32;51; + + + 122;97;104;108;32;62;32;48; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + + + 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; + + +`,z8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;70;97;107;117;108;116;228;116;32;118;111;110;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; + + + 105;110;116;32;102;97;107;117;108;116;97;101;116;32;61;32;49; + + + 105;110;116;32;105;32;61;32;49; + + + 105;32;60;61;32;110; + + + 102;97;107;117;108;116;97;101;116;32;61;32;102;97;107;117;108;116;97;101;116;32;42;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;110;32;43;32;34;33;32;61;32;34;32;43;32;102;97;107;117;108;116;97;101;116; + + +`,I8=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;119;97;104;108;32;34;49;32;112;108;117;115;44;32;50;32;109;105;110;117;115;44;32;51;32;109;97;108;63;34; + + + 119;97;104;108; + + + 111;117;116;112;117;116;58;32;97;32;43;32;98; + + + + + 111;117;116;112;117;116;58;32;97;32;45;32;98; + + + + + 111;117;116;112;117;116;58;32;97;32;42;32;98; + + + + + 111;117;116;112;117;116;58;32;34;71;105;98;116;32;101;115;32;110;105;99;104;116;34; + + + + +`,k8=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;119;97;104;108;32;34;49;32;112;108;117;115;44;32;50;32;109;105;110;117;115;44;32;51;32;109;97;108;63;34; + + + 119;97;104;108; + + + 111;117;116;112;117;116;58;32;97;32;43;32;98; + + + + + 111;117;116;112;117;116;58;32;98;32;45;32;97; + + + + + 111;117;116;112;117;116;58;32;97;32;42;32;98; + + + + + 111;117;116;112;117;116;58;32;34;71;105;98;116;32;101;115;32;110;105;99;104;116;34; + + + + +`,S8=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;87;101;108;99;104;101;32;90;97;104;108;63;34; + + + 122;97;104;108; + + + 111;117;116;112;117;116;58;32;34;101;105;110;115;34; + + + + + 111;117;116;112;117;116;58;32;34;122;119;101;105;34; + + + + + 111;117;116;112;117;116;58;32;34;100;114;101;105;34; + + + + + 111;117;116;112;117;116;58;32;34;107;101;110;110;101;32;105;99;104;32;110;105;99;104;116;34; + + + + +`,T8=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;34; + + + 105;110;116;32;115;99;104;114;105;116;116;101;32;61;32;48; + + + 122;97;104;108;32;60;32;49;48;48; + + + 122;97;104;108;32;61;32;122;97;104;108;32;42;32;50; + + + 115;99;104;114;105;116;116;101;32;61;32;115;99;104;114;105;116;116;101;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;115;99;104;114;105;116;116;101; + + +`,_8=` + + + 105;110;116;32;122;97;104;108;32;61;32;48; + + + 122;97;104;108;32;60;32;49;32;124;124;32;122;97;104;108;32;62;32;49;48; + + + 105;110;112;117;116;58;32;122;97;104;108;32;34;90;97;104;108;32;118;111;110;32;49;32;98;105;115;32;49;48;34; + + + + + 111;117;116;112;117;116;58;32;34;68;97;110;107;101;33;34; + + +`,A8=` + + + 105;110;116;32;105;32;61;32;49;48; + + + 105;32;60;32;53; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + +`,O8=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;105;101;108;32;34;83;112;97;114;122;105;101;108;63;34; + + + 105;110;116;32;103;101;108;100;32;61;32;48; + + + 105;110;116;32;119;111;99;104;101;110;32;61;32;48; + + + 103;101;108;100;32;60;32;122;105;101;108; + + + 103;101;108;100;32;61;32;103;101;108;100;32;43;32;53; + + + 119;111;99;104;101;110;32;61;32;119;111;99;104;101;110;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;87;111;99;104;101;110;58;32;34;32;43;32;119;111;99;104;101;110; + + +`,C8=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;105;101;108;32;34;83;112;97;114;122;105;101;108;63;34; + + + 105;110;116;32;103;101;108;100;32;61;32;48; + + + 105;110;116;32;119;111;99;104;101;110;32;61;32;48; + + + 103;101;108;100;32;60;61;32;122;105;101;108; + + + 103;101;108;100;32;61;32;103;101;108;100;32;43;32;53; + + + 119;111;99;104;101;110;32;61;32;119;111;99;104;101;110;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;87;111;99;104;101;110;58;32;34;32;43;32;119;111;99;104;101;110; + + +`,j8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;119;111;104;105;110;63;34; + + + 105;110;116;32;122;97;104;108;32;61;32;50; + + + 122;97;104;108;32;60;61;32;110; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + 122;97;104;108;32;61;32;122;97;104;108;32;43;32;50; + + + + +`,P8=` + + + 105;110;116;32;110;111;116;101;32;61;32;48; + + + 110;111;116;101;32;60;32;49;32;124;124;32;110;111;116;101;32;62;32;54; + + + 105;110;112;117;116;58;32;110;111;116;101;32;34;78;111;116;101;32;118;111;110;32;49;32;98;105;115;32;54;34; + + + + + 111;117;116;112;117;116;58;32;34;68;101;105;110;101;32;78;111;116;101;58;32;34;32;43;32;110;111;116;101; + + +`,D8=` + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;122;97;104;108;32;61;32;48; + + + 122;97;104;108;32;33;61;32;48; + + + 105;110;112;117;116;58;32;122;97;104;108;32;34;90;97;104;108;32;40;48;32;98;101;101;110;100;101;116;41;34; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;122;97;104;108; + + + + + 111;117;116;112;117;116;58;32;115;117;109;109;101; + + +`,B8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;83;116;97;114;116;122;97;104;108;34; + + + 105;110;116;32;105;32;61;32;110; + 105;32;62;61;32;49; + 105;45;45; + + + 111;117;116;112;117;116;58;32;105; + + + + + 111;117;116;112;117;116;58;32;34;76;111;115;33;34; + + +`,M8=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;87;101;108;99;104;101;32;82;101;105;104;101;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;49;48; + 105;43;43; + + + 105;110;116;32;112;114;111;100;117;107;116;32;61;32;122;97;104;108;32;42;32;105; + + + 111;117;116;112;117;116;58;32;122;97;104;108;32;43;32;34;32;120;32;34;32;43;32;105;32;43;32;34;32;61;32;34;32;43;32;112;114;111;100;117;107;116; + + + + +`,Z8=` + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;53; + 105;43;43; + + + 111;117;116;112;117;116;58;32;105; + + + + +`,L8=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;63;34; + + + 122;97;104;108;32;62;32;48; + + + 122;97;104;108;32;61;32;122;97;104;108;32;47;32;50; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + + +`,E8=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;63;34; + + + 122;97;104;108;32;62;32;49; + + + 122;97;104;108;32;61;32;122;97;104;108;32;47;32;50; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + + +`,W8=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;63;34; + + + 122;97;104;108;32;60;32;49;48;48; + + + 122;97;104;108;32;61;32;122;97;104;108;32;42;32;50; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + + +`,N8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;105; + + + + + 111;117;116;112;117;116;58;32;115;117;109;109;101; + + +`,F8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;87;105;101;32;118;105;101;108;101;32;90;101;105;108;101;110;63;34; + + + 105;110;116;32;122;101;105;108;101;32;61;32;49; + 122;101;105;108;101;32;60;61;32;110; + 122;101;105;108;101;43;43; + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;34;34; + + + 105;110;116;32;115;116;101;114;110;32;61;32;49; + 115;116;101;114;110;32;60;61;32;122;101;105;108;101; + 115;116;101;114;110;43;43; + + + 116;101;120;116;32;61;32;116;101;120;116;32;43;32;34;42;34; + + + + + 111;117;116;112;117;116;58;32;116;101;120;116; + + + + +`,J8=` + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;53; + 105;43;43; + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;34; + + + 122;97;104;108;32;37;32;50;32;61;61;32;48; + + + 97;110;122;97;104;108;43;43; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;97;110;122;97;104;108; + + +`,R8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 105;32;37;32;50;32;61;61;32;48; + + + 97;110;122;97;104;108;43;43; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;97;110;122;97;104;108; + + +`,G8=` + + + 105;110;112;117;116;58;32;105;110;116;32;114;101;105;104;101;32;34;87;101;108;99;104;101;32;82;101;105;104;101;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;49;48; + 105;43;43; + + + 111;117;116;112;117;116;58;32;114;101;105;104;101;32;42;32;105; + + + + +`,H8=` + + + 105;110;112;117;116;58;32;105;110;116;32;114;101;105;104;101;32;34;87;101;108;99;104;101;32;82;101;105;104;101;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;49;48; + 105;43;43; + + + 111;117;116;112;117;116;58;32;114;101;105;104;101;32;42;32;105; + + + + +`,V8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 111;117;116;112;117;116;58;32;105;32;42;32;105; + + + + +`,q8=` + + + 105;110;112;117;116;58;32;105;110;116;32;98;114;101;105;116;101;32;34;66;114;101;105;116;101;34; + + + 105;110;112;117;116;58;32;105;110;116;32;104;111;101;104;101;32;34;72;246;104;101;34; + + + 105;110;116;32;122;101;105;108;101;32;61;32;49; + 122;101;105;108;101;32;60;61;32;104;111;101;104;101; + 122;101;105;108;101;43;43; + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;34;34; + + + 105;110;116;32;115;112;97;108;116;101;32;61;32;49; + 115;112;97;108;116;101;32;60;61;32;98;114;101;105;116;101; + 115;112;97;108;116;101;43;43; + + + 116;101;120;116;32;61;32;116;101;120;116;32;43;32;34;35;34; + + + + + 111;117;116;112;117;116;58;32;116;101;120;116; + + + + +`,Q8=` + + + 105;110;116;91;93;32;122;97;104;108;101;110;32;61;32;123;50;44;32;52;44;32;54;44;32;56;44;32;49;48;125; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;122;97;104;108;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;122;97;104;108;101;110;91;105;93; + + + + +`,U8=` + + + 105;110;116;91;93;32;119;101;114;116;101;32;61;32;123;52;44;32;56;44;32;49;53;44;32;49;54;44;32;50;51;44;32;52;50;125; + + + 111;117;116;112;117;116;58;32;119;101;114;116;101;91;48;93; + + + 111;117;116;112;117;116;58;32;119;101;114;116;101;91;119;101;114;116;101;46;108;101;110;103;116;104;32;45;32;49;93; + + + 111;117;116;112;117;116;58;32;119;101;114;116;101;46;108;101;110;103;116;104; + + +`,$8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 105;32;37;32;51;32;61;61;32;48; + + + 97;110;122;97;104;108;32;61;32;97;110;122;97;104;108;32;43;32;49; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;65;110;122;97;104;108;58;32;34;32;43;32;97;110;122;97;104;108; + + +`,Y8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;122;117;32;119;101;108;99;104;101;114;32;90;97;104;108;63;34; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 105;32;37;32;51;32;61;61;32;48; + + + 97;110;122;97;104;108;32;61;32;97;110;122;97;104;108;32;43;32;49; + + + + + 248; + + + + + 111;117;116;112;117;116;58;32;34;65;110;122;97;104;108;58;32;34;32;43;32;97;110;122;97;104;108; + + + + +`,X8=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;87;105;101;32;118;105;101;108;101;32;83;116;117;102;101;110;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;34;34; + + + 105;110;116;32;106;32;61;32;49; + 106;32;60;61;32;105; + 106;43;43; + + + 122;101;105;108;101;32;61;32;122;101;105;108;101;32;43;32;34;42;34; + + + + + 111;117;116;112;117;116;58;32;122;101;105;108;101; + + + + +`,K8=` + + + 83;116;114;105;110;103;91;93;32;110;97;109;101;110;32;61;32;110;101;119;32;83;116;114;105;110;103;91;51;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;97;109;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;97;109;101;110;91;105;93;32;34;78;97;109;101;32;101;105;110;103;101;98;101;110;34; + + + + + 111;117;116;112;117;116;58;32;34;69;114;115;116;101;114;32;78;97;109;101;58;32;34;32;43;32;110;97;109;101;110;91;48;93; + + +`,eS=` + + + 105;110;116;91;93;32;122;97;104;108;101;110;32;61;32;110;101;119;32;105;110;116;91;52;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;122;97;104;108;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;122;97;104;108;101;110;91;105;93;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;34; + + + + + 105;110;116;32;105;32;61;32;122;97;104;108;101;110;46;108;101;110;103;116;104;32;45;32;49; + 105;32;62;61;32;48; + 105;45;45; + + + 111;117;116;112;117;116;58;32;122;97;104;108;101;110;91;105;93; + + + + +`,tS=` + + + 105;110;116;91;93;32;122;97;104;108;101;110;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;122;97;104;108;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;122;97;104;108;101;110;91;105;93;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;34; + + + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;109;97;120;32;61;32;122;97;104;108;101;110;91;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;122;97;104;108;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;122;97;104;108;101;110;91;105;93; + + + 122;97;104;108;101;110;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;122;97;104;108;101;110;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; + + + 111;117;116;112;117;116;58;32;34;77;97;120;105;109;117;109;58;32;34;32;43;32;109;97;120; + + +`,nS=` + + + 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;123;49;50;44;32;55;44;32;49;57;44;32;52;125; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;109;97;120;32;61;32;112;117;110;107;116;101;91;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;117;110;107;116;101;46;108;101;110;103;116;104; + 105;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;112;117;110;107;116;101;91;105;93; + + + 112;117;110;107;116;101;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;112;117;110;107;116;101;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; + + + 111;117;116;112;117;116;58;32;34;77;97;120;105;109;117;109;58;32;34;32;43;32;109;97;120; + + +`,iS=` + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;32;40;48;32;61;32;69;110;100;101;41;34; + + + 122;97;104;108;32;33;61;32;48; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;122;97;104;108; + + + 105;110;112;117;116;58;32;122;97;104;108;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;32;40;48;32;61;32;69;110;100;101;41;34; + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; + + +`,aS=` + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;32;40;48;32;61;32;69;110;100;101;41;34; + + + 122;97;104;108;32;61;61;32;48; + + + 83;99;104;108;101;105;102;101;32;118;101;114;108;97;115;115;101;110; + + + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;122;97;104;108; + + + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; + + +`,sS=` + + + 105;110;112;117;116;58;32;105;110;116;32;108;97;101;110;103;101;32;34;76;228;110;103;101;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;114;101;105;116;101;32;34;66;114;101;105;116;101;63;34; + + + 105;110;116;32;102;32;61;32;102;108;97;101;99;104;101;40;108;97;101;110;103;101;44;32;98;114;101;105;116;101;41; + + + 111;117;116;112;117;116;58;32;34;70;108;228;99;104;101;58;32;34;32;43;32;102; + + +`,rS=` + + + 114;101;116;117;114;110;32;97;32;42;32;98; + + +`,oS=` + + + 122;101;105;103;101;66;101;103;114;117;101;115;115;117;110;103;40;41; + + + 115;116;101;108;108;101;70;114;97;103;101;110;40;41; + + + 122;101;105;103;101;69;114;103;101;98;110;105;115;40;41; + + +`,lS=` + + + 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;101;110;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; + + + 105;110;116;32;109;97;120;32;61;32;116;101;109;112;101;114;97;116;117;114;101;110;91;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;101;109;112;101;114;97;116;117;114;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 116;101;109;112;101;114;97;116;117;114;101;110;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;116;101;109;112;101;114;97;116;117;114;101;110;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;72;246;99;104;115;116;101;32;84;101;109;112;101;114;97;116;117;114;58;32;34;32;43;32;109;97;120; + + +`,uS=` + + + 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;101;110;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; + + + 105;110;116;32;109;97;120;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;101;109;112;101;114;97;116;117;114;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 116;101;109;112;101;114;97;116;117;114;101;110;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;116;101;109;112;101;114;97;116;117;114;101;110;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;72;246;99;104;115;116;101;32;84;101;109;112;101;114;97;116;117;114;58;32;34;32;43;32;109;97;120; + + +`,cS=` + + + 105;110;116;91;93;32;110;111;116;101;110;32;61;32;123;50;44;32;51;44;32;49;44;32;52;125; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;111;116;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;110;111;116;101;110;91;105;93; + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; + + +`,mS=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;87;101;108;99;104;101;32;90;97;104;108;63;34; + + + 105;110;116;32;113;32;61;32;113;117;97;100;114;97;116;40;122;97;104;108;41; + + + 111;117;116;112;117;116;58;32;34;68;97;115;32;81;117;97;100;114;97;116;32;105;115;116;32;34;32;43;32;113; + + +`,dS=` + + + 105;110;116;32;101;114;103;101;98;110;105;115;32;61;32;120;32;42;32;120; + + + 114;101;116;117;114;110;32;101;114;103;101;98;110;105;115; + + +`,hS=` + + + 122;101;105;103;101;84;105;116;101;108;40;41; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;97;109;101;32;34;87;105;101;32;104;101;105;223;116;32;100;117;63;34; + + + 111;117;116;112;117;116;58;32;34;72;97;108;108;111;32;34;32;43;32;110;97;109;101; + + +`,gS=` + + + 111;117;116;112;117;116;58;32;34;87;105;108;108;107;111;109;109;101;110;32;122;117;109;32;81;117;105;122;33;34; + + + 111;117;116;112;117;116;58;32;34;68;117;32;98;101;107;111;109;109;115;116;32;100;114;101;105;32;70;114;97;103;101;110;46;34; + + +`,pS=` + + + 122;101;105;103;101;83;117;109;109;101;40;51;44;32;52;41; + + + 105;110;116;32;120;32;61;32;49;48; + + + 122;101;105;103;101;83;117;109;109;101;40;120;44;32;120;32;43;32;49;41; + + +`,fS=` + + + 105;110;116;32;115;117;109;109;101;32;61;32;97;32;43;32;98; + + + 111;117;116;112;117;116;58;32;97;32;43;32;34;32;43;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;115;117;109;109;101; + + +`,bS=` + + + 105;110;112;117;116;58;32;105;110;116;32;115;116;97;114;116;32;34;83;116;97;114;116;119;101;114;116;34; + + + 105;110;116;32;105;32;61;32;115;116;97;114;116; + + + 105;32;62;32;48; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;45;32;49; + + + + + 111;117;116;112;117;116;58;32;34;76;111;115;33;34; + + +`,xS=` + + + 105;110;112;117;116;58;32;105;110;116;32;115;116;97;114;116;32;34;83;116;97;114;116;119;101;114;116;34; + + + 105;110;116;32;105;32;61;32;115;116;97;114;116; + + + 105;32;62;32;48; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;76;111;115;34; + + +`,vS=` + + + 105;110;116;91;93;91;93;32;112;117;110;107;116;101;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;112;117;110;107;116;101;91;49;93;46;108;101;110;103;116;104; + 106;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;112;117;110;107;116;101;91;49;93;91;106;93; + + + + + 111;117;116;112;117;116;58;32;34;83;112;105;101;108;101;114;32;50;58;32;34;32;43;32;115;117;109;109;101; + + +`,yS=` + + + 105;110;116;91;93;91;93;32;112;117;110;107;116;101;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;112;117;110;107;116;101;91;49;93;46;108;101;110;103;116;104; + 106;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;112;117;110;107;116;101;91;106;93;91;49;93; + + + + + 111;117;116;112;117;116;58;32;34;83;112;105;101;108;101;114;32;50;58;32;34;32;43;32;115;117;109;109;101; + + +`,wS=` + + + 105;110;116;91;93;91;93;32;112;117;110;107;116;101;32;61;32;123;123;51;44;32;53;125;44;32;123;52;44;32;49;125;44;32;123;50;44;32;50;125;125; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;117;110;107;116;101;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;112;117;110;107;116;101;91;105;93;46;108;101;110;103;116;104; + 106;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;112;117;110;107;116;101;91;105;93;91;106;93; + + + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; + + +`,zS=` + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + + + 105;32;60;61;32;51; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;115;117;109;109;101; + + +`,IS=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;119;111;104;105;110;63;34; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;105; + + + + + 111;117;116;112;117;116;58;32;115;117;109;109;101; + + +`,kS=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;66;105;115;32;119;111;104;105;110;63;34; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;110; + 105;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;105; + + + + + 111;117;116;112;117;116;58;32;115;117;109;109;101; + + +`,SS=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;87;101;108;99;104;101;32;82;101;105;104;101;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;51; + 105;43;43; + + + 105;110;116;32;101;114;103;101;98;110;105;115;32;61;32;122;97;104;108;32;42;32;105; + + + 111;117;116;112;117;116;58;32;105;32;43;32;34;32;109;97;108;32;34;32;43;32;122;97;104;108;32;43;32;34;32;61;32;34;32;43;32;101;114;103;101;98;110;105;115; + + + + + 122;97;104;108;32;62;32;49;48; + + + 111;117;116;112;117;116;58;32;34;68;97;115;32;119;97;114;32;115;99;104;119;101;114;33;34; + + + + + 111;117;116;112;117;116;58;32;34;68;97;115;32;119;97;114;32;108;101;105;99;104;116;46;34; + + + + +`,TS=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;90;97;104;108;32;101;105;110;103;101;98;101;110;34; + + + 105;110;116;32;102;97;107;117;108;116;97;101;116;32;61;32;49; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 102;97;107;117;108;116;97;101;116;32;61;32;102;97;107;117;108;116;97;101;116;32;42;32;105; + + + + + 111;117;116;112;117;116;58;32;102;97;107;117;108;116;97;101;116; + + +`,_S=` + + + 83;116;114;105;110;103;32;98;114;105;101;102;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;98;114;105;101;102;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;91;93;32;122;101;105;108;101;110;32;61;32;98;114;105;101;102;46;115;112;108;105;116;40;34;92;110;34;41; + + + 111;117;116;112;117;116;58;32;34;90;101;105;108;101;110;58;32;34;32;43;32;122;101;105;108;101;110;46;108;101;110;103;116;104; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;122;101;105;108;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 122;101;105;108;101;110;91;105;93;46;99;111;110;116;97;105;110;115;40;34;70;117;99;104;115;34;41; + + + 111;117;116;112;117;116;58;32;34;70;117;99;104;115;32;105;110;32;90;101;105;108;101;32;34;32;43;32;40;105;32;43;32;49;41; + + + + + 248; + + + + + + +`,AS=` + + + 83;116;114;105;110;103;32;98;114;105;101;102;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;98;114;105;101;102;46;116;120;116;34;41;41; + + +`,OS=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;118;111;114;110;97;109;101;32;34;86;111;114;110;97;109;101;63;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;97;99;104;110;97;109;101;32;34;78;97;99;104;110;97;109;101;63;34; + + + 111;117;116;112;117;116;58;32;118;111;114;110;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;110;97;99;104;110;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; + + +`,CS=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;118;111;114;110;97;109;101;32;34;86;111;114;110;97;109;101;63;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;97;99;104;110;97;109;101;32;34;78;97;99;104;110;97;109;101;63;34; + + + 111;117;116;112;117;116;58;32;118;111;114;110;97;109;101;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;32;34;32;43;32;110;97;99;104;110;97;109;101;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;34; + + +`,jS=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;101;105;110;103;97;98;101;32;34;80;97;115;115;119;111;114;116;63;34; + + + 101;105;110;103;97;98;101;46;101;113;117;97;108;115;40;34;76;117;100;119;105;103;34;41; + + + 111;117;116;112;117;116;58;32;34;87;105;108;108;107;111;109;109;101;110;33;34; + + + + + 111;117;116;112;117;116;58;32;34;70;97;108;115;99;104;101;115;32;80;97;115;115;119;111;114;116;34; + + + + +`,PS=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; + + + 97;108;116;101;114;32;60;32;54; + + + 111;117;116;112;117;116;58;32;34;69;105;110;116;114;105;116;116;32;102;114;101;105;34; + + + + + 97;108;116;101;114;32;60;32;49;56; + + + 111;117;116;112;117;116;58;32;34;75;105;110;100;101;114;116;105;99;107;101;116;58;32;52;32;69;117;114;111;34; + + + + + 111;117;116;112;117;116;58;32;34;69;114;119;97;99;104;115;101;110;101;110;116;105;99;107;101;116;58;32;56;32;69;117;114;111;34; + + + + + + +`,DS=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;119;101;114;116;63;34; + + + 122;97;104;108;32;62;32;48; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + 122;97;104;108;32;61;32;122;97;104;108;32;45;32;51; + + + + + 111;117;116;112;117;116;58;32;34;69;110;100;101;34; + + +`,BS=` + + + 105;110;116;32;118;101;114;115;117;99;104;101;32;61;32;48; + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;116;105;112;112;32;34;68;101;105;110;32;84;105;112;112;63;34; + + + 118;101;114;115;117;99;104;101;32;61;32;118;101;114;115;117;99;104;101;32;43;32;49; + + + 116;105;112;112;32;61;61;32;55; + + + -1; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;86;101;114;115;117;99;104;101;58;32;34;32;43;32;118;101;114;115;117;99;104;101; + + +`,MS=` + + + 105;110;116;32;118;101;114;115;117;99;104;101;32;61;32;48; + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;116;105;112;112;32;34;68;101;105;110;32;84;105;112;112;63;34; + + + 116;105;112;112;32;61;61;32;55; + + + -1; + + + + + 248; + + + + + 118;101;114;115;117;99;104;101;32;61;32;118;101;114;115;117;99;104;101;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;86;101;114;115;117;99;104;101;58;32;34;32;43;32;118;101;114;115;117;99;104;101; + + +`,ZS=` + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;101;105;115;32;34;80;114;101;105;115;63;32;40;48;32;61;32;69;110;100;101;41;34; + + + 112;114;101;105;115;32;61;61;32;48; + + + -1; + + + + + 248; + + + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;112;114;101;105;115; + + + 97;110;122;97;104;108;32;61;32;97;110;122;97;104;108;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;65;114;116;105;107;101;108;58;32;34;32;43;32;97;110;122;97;104;108; + + + 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;115;117;109;109;101; + + +`,LS=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;108;116;101;114;32;34;87;105;101;32;97;108;116;32;98;105;115;116;32;100;117;63;34; + + + 97;108;116;101;114;32;62;61;32;49;54; + + + 111;117;116;112;117;116;58;32;34;68;117;32;100;97;114;102;115;116;32;119;228;104;108;101;110;46;34; + + + + + 105;110;116;32;106;97;104;114;101;32;61;32;49;54;32;45;32;97;108;116;101;114; + + + 111;117;116;112;117;116;58;32;34;78;111;99;104;32;34;32;43;32;106;97;104;114;101;32;43;32;34;32;74;97;104;114;101;32;119;97;114;116;101;110;46;34; + + + + +`,ES=` + + + 105;110;112;117;116;58;32;105;110;116;32;103;114;101;110;122;101;32;34;66;105;115;32;119;111;104;105;110;63;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;61;32;103;114;101;110;122;101; + 105;32;61;32;105;32;43;32;50; + + + 111;117;116;112;117;116;58;32;105; + + + + +`,WS=` + + + 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;103;101;115;117;99;104;116;32;34;87;101;108;99;104;101;32;75;97;114;116;101;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;105;32;61;32;48; + + + 112;111;115;105;116;105;111;110;32;61;61;32;45;49;32;38;38;32;105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + + + 107;97;114;116;101;110;91;105;93;32;61;61;32;103;101;115;117;99;104;116; + + + 112;111;115;105;116;105;111;110;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; + + +`,NS=` + + + 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;103;101;115;117;99;104;116;32;34;87;101;108;99;104;101;32;75;97;114;116;101;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;105;32;61;32;48; + + + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + + + 107;97;114;116;101;110;91;105;93;32;61;61;32;103;101;115;117;99;104;116; + + + 112;111;115;105;116;105;111;110;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; + + +`,FS=` + + + 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;103;101;115;117;99;104;116;32;34;87;101;108;99;104;101;32;75;97;114;116;101;63;34; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 107;97;114;116;101;110;91;105;93;32;61;61;32;103;101;115;117;99;104;116; + + + 97;110;122;97;104;108;32;61;32;97;110;122;97;104;108;32;43;32;49; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;65;110;122;97;104;108;58;32;34;32;43;32;97;110;122;97;104;108; + + +`,JS=` + + + 111;117;116;112;117;116;58;32;34;71;117;116;101;110;32;77;111;114;103;101;110;34; + + + 111;117;116;112;117;116;58;32;34;72;101;117;116;101;32;108;101;114;110;101;110;32;119;105;114;32;83;116;114;117;107;116;111;103;114;97;109;109;101;46;34; + + +`,RS=` + + + 111;117;116;112;117;116;58;32;34;72;97;108;108;111;32;87;101;108;116;34; + + +`,GS=` + + + 111;117;116;112;117;116;58;32;34;72;97;108;108;111;34; + + + 111;117;116;112;117;116;58;32;34;73;99;104;32;108;101;114;110;101;32;83;116;114;117;107;116;111;103;114;97;109;109;101;34; + + +`,HS=` + + + 105;110;112;117;116;58;32;105;110;116;32;122;97;104;108;32;34;83;116;97;114;116;122;97;104;108;63;34; + + + 122;97;104;108;32;62;32;48; + + + 111;117;116;112;117;116;58;32;122;97;104;108; + + + 122;97;104;108;32;61;32;122;97;104;108;32;45;32;49; + + + + + 111;117;116;112;117;116;58;32;34;83;116;97;114;116;33;34; + + +`,VS=` + + + 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;101;105;110;107;97;117;102;45;110;101;117;46;116;120;116;34;41; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 100;97;116;101;105;46;104;97;115;78;101;120;116;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;100;97;116;101;105;46;110;101;120;116;76;105;110;101;40;41; + + + 97;117;115;46;112;114;105;110;116;108;110;40;122;101;105;108;101;41; + + + 97;110;122;97;104;108;43;43; + + + + + 97;117;115;46;112;114;105;110;116;108;110;40;34;75;117;99;104;101;110;34;41; + + + 97;110;122;97;104;108;43;43; + + + 100;97;116;101;105;46;99;108;111;115;101;40;41; + + + 97;117;115;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;97;110;122;97;104;108;32;43;32;34;32;90;101;105;108;101;110;32;103;101;115;112;101;105;99;104;101;114;116;34; + + +`,qS=` + + + 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;101;105;110;107;97;117;102;45;110;101;117;46;116;120;116;34;41; + + +`,QS=` + + + 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; + + + 105;110;116;32;110;117;109;109;101;114;32;61;32;49; + + + 100;97;116;101;105;46;104;97;115;78;101;120;116;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;100;97;116;101;105;46;110;101;120;116;76;105;110;101;40;41; + + + 111;117;116;112;117;116;58;32;110;117;109;109;101;114;32;43;32;34;46;32;34;32;43;32;122;101;105;108;101; + + + 110;117;109;109;101;114;43;43; + + + + + 100;97;116;101;105;46;99;108;111;115;101;40;41; + + +`,US=` + + + 83;99;97;110;110;101;114;32;100;97;116;101;105;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;101;105;110;107;97;117;102;46;116;120;116;34;41;41; + + +`,$S=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 122;101;105;108;101;32;33;61;32;110;117;108;108; + + + 122;101;105;108;101;46;99;111;110;116;97;105;110;115;40;34;70;117;99;104;115;34;41; + + + 97;110;122;97;104;108;43;43; + + + + + 248; + + + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;115;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;34;70;117;99;104;115;58;32;34;32;43;32;97;110;122;97;104;108; + + +`,YS=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,XS=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;91;93;32;122;101;105;108;101;110;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; + + + 83;116;114;105;110;103;32;108;97;101;110;103;115;116;101;114;32;61;32;122;101;105;108;101;110;91;48;93; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;122;101;105;108;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 122;101;105;108;101;110;91;105;93;46;108;101;110;103;116;104;40;41;32;62;32;108;97;101;110;103;115;116;101;114;46;108;101;110;103;116;104;40;41; + + + 108;97;101;110;103;115;116;101;114;32;61;32;122;101;105;108;101;110;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;76;228;110;103;115;116;101;114;32;69;105;110;116;114;97;103;58;32;34;32;43;32;108;97;101;110;103;115;116;101;114; + + +`,KS=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;108;111;103;98;117;99;104;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;91;93;32;122;101;105;108;101;110;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; + + +`,eT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;107;108;97;115;115;101;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;98;101;115;116;101;114;78;97;109;101;32;61;32;34;34; + + + 105;110;116;32;98;101;115;116;101;78;111;116;101;32;61;32;55; + + + 122;101;105;108;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;116;101;105;108;101;32;61;32;122;101;105;108;101;46;115;112;108;105;116;40;34;59;34;41; + + + 105;110;116;32;110;111;116;101;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;116;101;105;108;101;91;51;93;41; + + + 110;111;116;101;32;60;32;98;101;115;116;101;78;111;116;101; + + + 98;101;115;116;101;78;111;116;101;32;61;32;110;111;116;101; + + + 98;101;115;116;101;114;78;97;109;101;32;61;32;116;101;105;108;101;91;48;93; + + + + + 248; + + + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;115;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;34;66;101;115;116;101;32;78;111;116;101;32;105;110;32;69;110;103;108;105;115;99;104;58;32;34;32;43;32;98;101;115;116;101;114;78;97;109;101;32;43;32;34;32;40;34;32;43;32;98;101;115;116;101;78;111;116;101;32;43;32;34;41;34; + + +`,tT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;107;108;97;115;115;101;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,nT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;107;108;97;115;115;101;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 100;111;117;98;108;101;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 122;101;105;108;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;116;101;105;108;101;32;61;32;122;101;105;108;101;46;115;112;108;105;116;40;34;59;34;41; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;116;101;105;108;101;91;49;93;41; + + + 97;110;122;97;104;108;43;43; + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;115;101;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;34;83;99;104;110;105;116;116;32;77;97;116;104;101;58;32;34;32;43;32;115;117;109;109;101;32;47;32;97;110;122;97;104;108; + + +`,iT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;107;108;97;115;115;101;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,aT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 122;101;105;108;101;32;33;61;32;110;117;108;108; + + + 122;101;105;108;101;46;99;111;110;116;97;105;110;115;40;34;92;34;110;97;109;101;92;34;34;41; + + + 105;110;116;32;115;116;97;114;116;32;61;32;122;101;105;108;101;46;105;110;100;101;120;79;102;40;34;92;34;110;97;109;101;92;34;58;32;92;34;34;41;32;43;32;57; + + + 105;110;116;32;101;110;100;101;32;61;32;122;101;105;108;101;46;105;110;100;101;120;79;102;40;34;92;34;34;44;32;115;116;97;114;116;41; + + + 111;117;116;112;117;116;58;32;122;101;105;108;101;46;115;117;98;115;116;114;105;110;103;40;115;116;97;114;116;44;32;101;110;100;101;41; + + + + + 248; + + + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;115;101;114;46;99;108;111;115;101;40;41; + + +`,sT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,rT=` + + + 83;116;114;105;110;103;91;93;32;110;97;109;101;110;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;70;117;99;104;115;34;125; + + + 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;123;49;50;44;32;49;53;44;32;57;125; + + + 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;112;117;110;107;116;101;46;106;115;111;110;34;41; + + + 97;117;115;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;97;109;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 83;116;114;105;110;103;32;101;105;110;116;114;97;103;32;61;32;34;32;32;123;92;34;110;97;109;101;92;34;58;32;92;34;34;32;43;32;110;97;109;101;110;91;105;93;32;43;32;34;92;34;44;32;92;34;112;117;110;107;116;101;92;34;58;32;34;32;43;32;112;117;110;107;116;101;91;105;93;32;43;32;34;125;34; + + + 105;32;60;32;110;97;109;101;110;46;108;101;110;103;116;104;32;45;32;49; + + + 101;105;110;116;114;97;103;32;61;32;101;105;110;116;114;97;103;32;43;32;34;44;34; + + + + + 248; + + + + + 97;117;115;46;112;114;105;110;116;108;110;40;101;105;110;116;114;97;103;41; + + + + + 97;117;115;46;112;114;105;110;116;108;110;40;34;93;34;41; + + + 97;117;115;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;110;97;109;101;110;46;108;101;110;103;116;104;32;43;32;34;32;69;105;110;116;114;228;103;101;32;103;101;115;112;101;105;99;104;101;114;116;34; + + +`,oT=` + + + 83;116;114;105;110;103;91;93;32;110;97;109;101;110;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;70;117;99;104;115;34;125; + + + 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;123;49;50;44;32;49;53;44;32;57;125; + + + 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;112;117;110;107;116;101;46;106;115;111;110;34;41; + + + 97;117;115;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 97;117;115;46;99;108;111;115;101;40;41; + + +`,lT=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;116;105;101;114;101;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;91;93;32;122;101;105;108;101;110;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;116;105;101;114;101;45;110;101;117;46;106;115;111;110;34;41; + + + 97;117;115;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;122;101;105;108;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 83;116;114;105;110;103;91;93;32;116;101;105;108;101;32;61;32;122;101;105;108;101;110;91;105;93;46;115;112;108;105;116;40;34;59;34;41; + + + 83;116;114;105;110;103;32;101;105;110;116;114;97;103;32;61;32;34;32;32;123;92;34;110;97;109;101;92;34;58;32;92;34;34;32;43;32;116;101;105;108;101;91;48;93;32;43;32;34;92;34;44;32;92;34;97;114;116;92;34;58;32;92;34;34;32;43;32;116;101;105;108;101;91;49;93;32;43;32;34;92;34;44;32;92;34;97;108;116;101;114;92;34;58;32;34;32;43;32;116;101;105;108;101;91;50;93;32;43;32;34;125;34; + + + 105;32;60;32;122;101;105;108;101;110;46;108;101;110;103;116;104;32;45;32;49; + + + 101;105;110;116;114;97;103;32;61;32;101;105;110;116;114;97;103;32;43;32;34;44;34; + + + + + 248; + + + + + 97;117;115;46;112;114;105;110;116;108;110;40;101;105;110;116;114;97;103;41; + + + + + 97;117;115;46;112;114;105;110;116;108;110;40;34;93;34;41; + + + 97;117;115;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;40;122;101;105;108;101;110;46;108;101;110;103;116;104;32;45;32;49;41;32;43;32;34;32;84;105;101;114;101;32;103;101;115;112;101;105;99;104;101;114;116;34; + + +`,uT=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;116;105;101;114;101;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;91;93;32;122;101;105;108;101;110;32;61;32;116;101;120;116;46;115;112;108;105;116;40;34;92;110;34;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;116;105;101;114;101;45;110;101;117;46;106;115;111;110;34;41; + + + 97;117;115;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 97;117;115;46;112;114;105;110;116;108;110;40;34;93;34;41; + + + 97;117;115;46;99;108;111;115;101;40;41; + + +`,cT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;105;101;114;101;46;99;115;118;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;115;97;101;116;122;101;46;116;120;116;34;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 122;101;105;108;101;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;116;101;105;108;101;32;61;32;122;101;105;108;101;46;115;112;108;105;116;40;34;59;34;41; + + + 97;117;115;46;112;114;105;110;116;108;110;40;116;101;105;108;101;91;48;93;32;43;32;34;32;40;34;32;43;32;116;101;105;108;101;91;49;93;32;43;32;34;41;32;105;115;116;32;34;32;43;32;116;101;105;108;101;91;50;93;32;43;32;34;32;74;97;104;114;101;32;97;108;116;46;34;41; + + + 97;110;122;97;104;108;43;43; + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;115;101;114;46;99;108;111;115;101;40;41; + + + 97;117;115;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;97;110;122;97;104;108;32;43;32;34;32;83;228;116;122;101;32;103;101;115;112;101;105;99;104;101;114;116;34; + + +`,mT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;115;101;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;105;101;114;101;46;99;115;118;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;97;117;115;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;115;97;101;116;122;101;46;116;120;116;34;41; + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 122;101;105;108;101;32;61;32;108;101;115;101;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;101;115;101;114;46;99;108;111;115;101;40;41; + + + 97;117;115;46;99;108;111;115;101;40;41; + + +`,dT=` + + + 111;117;116;112;117;116;58;32;34;66;101;109;45;118;105;110;100;111;34; + + + 118;101;114;105;102;105;99;97;114;73;100;97;100;101;40;41; + + + 111;117;116;112;117;116;58;32;34;65;100;101;117;115;34; + + +`,hT=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; + + + 105;100;97;100;101;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;109;97;105;111;114;32;100;101;32;105;100;97;100;101;34; + + + + + 111;117;116;112;117;116;58;32;34;109;101;110;111;114;32;100;101;32;105;100;97;100;101;34; + + + + +`,gT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;97;110;99;97;109;101;110;116;111;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 105;110;116;32;99;111;110;116;97;103;101;109;32;61;32;48; + + + 100;111;117;98;108;101;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;109;101;108;104;111;114;68;105;115;116;97;110;99;105;97;32;61;32;48; + + + 83;116;114;105;110;103;32;109;101;108;104;111;114;78;111;109;101;32;61;32;34;34; + + + 108;105;110;104;97;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;101;115;32;61;32;108;105;110;104;97;46;115;112;108;105;116;40;34;59;34;41; + + + 105;110;116;32;100;105;115;116;97;110;99;105;97;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;112;97;114;116;101;115;91;49;93;41; + + + 99;111;110;116;97;103;101;109;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;100;105;115;116;97;110;99;105;97; + + + 100;105;115;116;97;110;99;105;97;32;62;32;109;101;108;104;111;114;68;105;115;116;97;110;99;105;97; + + + 109;101;108;104;111;114;68;105;115;116;97;110;99;105;97;32;61;32;100;105;115;116;97;110;99;105;97; + + + 109;101;108;104;111;114;78;111;109;101;32;61;32;112;97;114;116;101;115;91;48;93; + + + + + 248; + + + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;105;116;111;114;46;99;108;111;115;101;40;41; + + + 100;111;117;98;108;101;32;109;101;100;105;97;32;61;32;115;111;109;97;32;47;32;99;111;110;116;97;103;101;109; + + + 111;117;116;112;117;116;58;32;34;80;97;114;116;105;99;105;112;97;110;116;101;115;58;32;34;32;43;32;99;111;110;116;97;103;101;109; + + + 111;117;116;112;117;116;58;32;34;77;233;100;105;97;58;32;34;32;43;32;109;101;100;105;97;32;43;32;34;32;109;34; + + + 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;118;101;110;99;101;100;111;114;46;116;120;116;34;41; + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;34;86;101;110;99;101;100;111;114;58;32;34;32;43;32;109;101;108;104;111;114;78;111;109;101;32;43;32;34;32;40;34;32;43;32;109;101;108;104;111;114;68;105;115;116;97;110;99;105;97;32;43;32;34;32;109;41;34;41; + + + 115;97;105;100;97;46;99;108;111;115;101;40;41; + + +`,pT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;108;97;110;99;97;109;101;110;116;111;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,fT=` + + + 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;110;116;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;80;111;110;116;111;115;63;34; + + + 112;111;110;116;111;115;91;105;93;32;61;32;110;117;109;101;114;111; + + + + + 105;110;116;32;112;97;115;115;97;103;101;109;32;61;32;49; + 112;97;115;115;97;103;101;109;32;60;32;112;111;110;116;111;115;46;108;101;110;103;116;104; + 112;97;115;115;97;103;101;109;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;110;116;111;115;46;108;101;110;103;116;104;32;45;32;112;97;115;115;97;103;101;109; + 105;43;43; + + + 112;111;110;116;111;115;91;105;93;32;60;32;112;111;110;116;111;115;91;105;32;43;32;49;93; + + + 105;110;116;32;97;117;120;32;61;32;112;111;110;116;111;115;91;105;93; + + + 112;111;110;116;111;115;91;105;93;32;61;32;112;111;110;116;111;115;91;105;32;43;32;49;93; + + + 112;111;110;116;111;115;91;105;32;43;32;49;93;32;61;32;97;117;120; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;110;116;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;116;32;108;117;103;97;114;32;61;32;105;32;43;32;49; + + + 111;117;116;112;117;116;58;32;108;117;103;97;114;32;43;32;34;46;32;34;32;43;32;112;111;110;116;111;115;91;105;93; + + + + +`,bT=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;32;105;110;116;101;105;114;111;34; + + + 83;116;114;105;110;103;32;98;105;110;97;114;105;111;32;61;32;34;34; + + + 110;117;109;101;114;111;32;62;32;48; + + + 105;110;116;32;114;101;115;116;111;32;61;32;110;117;109;101;114;111;32;37;32;50; + + + 98;105;110;97;114;105;111;32;61;32;114;101;115;116;111;32;43;32;98;105;110;97;114;105;111; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;47;32;50; + + + + + 111;117;116;112;117;116;58;32;98;105;110;97;114;105;111; + + +`,xT=` + + + 99;104;97;114;91;93;32;97;108;102;97;98;101;116;111;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;34;81;117;101;32;112;97;108;97;118;114;97;32;40;115;243;32;109;97;105;250;115;99;117;108;97;115;41;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;75;32;34;68;101;115;108;111;99;97;114;32;113;117;97;110;116;97;115;32;112;111;115;105;231;245;101;115;63;34; + + + 83;116;114;105;110;103;32;115;101;103;114;101;100;111;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;97;108;97;118;114;97;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 99;104;97;114;32;90;32;61;32;112;97;108;97;118;114;97;46;99;104;97;114;65;116;40;105;41; + + + 105;110;116;32;112;111;115;32;61;32;48; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;97;108;102;97;98;101;116;111;46;108;101;110;103;116;104; + 106;43;43; + + + 97;108;102;97;98;101;116;111;91;106;93;32;61;61;32;90; + + + 112;111;115;32;61;32;106; + + + + + 248; + + + + + + + 115;101;103;114;101;100;111;32;61;32;115;101;103;114;101;100;111;32;43;32;97;108;102;97;98;101;116;111;91;40;112;111;115;32;43;32;75;41;32;37;32;50;54;93; + + + + + 111;117;116;112;117;116;58;32;115;101;103;114;101;100;111; + + +`,vT=` + + + 99;104;97;114;91;93;32;97;108;102;97;98;101;116;111;32;61;32;123;39;65;39;44;32;39;66;39;44;32;39;67;39;44;32;39;68;39;44;32;39;69;39;44;32;39;70;39;44;32;39;71;39;44;32;39;72;39;44;32;39;73;39;44;32;39;74;39;44;32;39;75;39;44;32;39;76;39;44;32;39;77;39;44;32;39;78;39;44;32;39;79;39;44;32;39;80;39;44;32;39;81;39;44;32;39;82;39;44;32;39;83;39;44;32;39;84;39;44;32;39;85;39;44;32;39;86;39;44;32;39;87;39;44;32;39;88;39;44;32;39;89;39;44;32;39;90;39;125; + + +`,yT=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;34;81;117;101;32;112;97;108;97;118;114;97;32;40;115;243;32;109;97;105;250;115;99;117;108;97;115;41;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;75;32;34;68;101;115;108;111;99;97;114;32;113;117;97;110;116;97;115;32;112;111;115;105;231;245;101;115;63;34; + + + 83;116;114;105;110;103;32;115;101;103;114;101;100;111;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;97;108;97;118;114;97;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 105;110;116;32;99;111;100;105;103;111;32;61;32;40;105;110;116;41;32;112;97;108;97;118;114;97;46;99;104;97;114;65;116;40;105;41; + + + 99;111;100;105;103;111;32;61;32;40;99;111;100;105;103;111;32;45;32;54;53;32;43;32;75;41;32;37;32;50;54;32;43;32;54;53; + + + 115;101;103;114;101;100;111;32;61;32;115;101;103;114;101;100;111;32;43;32;40;99;104;97;114;41;32;99;111;100;105;103;111; + + + + + 111;117;116;112;117;116;58;32;115;101;103;114;101;100;111; + + +`,wT=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;115;101;103;114;101;100;111;32;34;81;117;97;108;32;233;32;111;32;116;101;120;116;111;32;99;105;102;114;97;100;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;75;32;34;68;101;115;108;111;99;97;114;32;113;117;97;110;116;97;115;32;112;111;115;105;231;245;101;115;63;34; + + + 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;115;101;103;114;101;100;111;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 105;110;116;32;99;111;100;105;103;111;32;61;32;40;105;110;116;41;32;115;101;103;114;101;100;111;46;99;104;97;114;65;116;40;105;41; + + + 99;111;100;105;103;111;32;61;32;40;99;111;100;105;103;111;32;45;32;54;53;32;45;32;75;32;43;32;50;54;41;32;37;32;50;54;32;43;32;54;53; + + + 116;101;120;116;111;32;61;32;116;101;120;116;111;32;43;32;40;99;104;97;114;41;32;99;111;100;105;103;111; + + + + + 111;117;116;112;117;116;58;32;116;101;120;116;111; + + +`,zT=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;32;105;110;105;99;105;97;108;34; + + + 105;110;116;32;112;97;115;115;111;115;32;61;32;48; + + + 110;117;109;101;114;111;32;33;61;32;49; + + + 110;117;109;101;114;111;32;37;32;50;32;61;61;32;48; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;47;32;50; + + + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;42;32;51;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + + 112;97;115;115;111;115;43;43; + + + + + 111;117;116;112;117;116;58;32;34;80;97;115;115;111;115;58;32;34;32;43;32;112;97;115;115;111;115; + + +`,IT=` + + + 105;110;112;117;116;58;32;105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;34;81;117;97;110;116;97;115;32;110;111;116;97;115;63;34; + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;113;117;97;110;116;105;100;97;100;101; + 105;43;43; + + + 105;110;112;117;116;58;32;105;110;116;32;110;111;116;97;32;34;73;110;116;114;111;100;117;122;32;117;109;97;32;110;111;116;97;34; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;110;111;116;97; + + + + + 100;111;117;98;108;101;32;109;101;100;105;97;32;61;32;115;111;109;97;32;42;32;49;46;48;32;47;32;113;117;97;110;116;105;100;97;100;101; + + + 111;117;116;112;117;116;58;32;109;101;100;105;97; + + +`,kT=` + + + 105;110;112;117;116;58;32;105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;110;250;109;101;114;111;115;63;34; + + + 105;110;116;32;110;117;109;101;114;111;49;32;61;32;49; + + + 105;110;116;32;110;117;109;101;114;111;50;32;61;32;49; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111;49; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111;50; + + + 105;110;116;32;105;32;61;32;50; + 105;32;60;32;113;117;97;110;116;105;100;97;100;101; + 105;43;43; + + + 105;110;116;32;110;117;109;101;114;111;51;32;61;32;110;117;109;101;114;111;49;32;43;32;110;117;109;101;114;111;50; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111;51; + + + 110;117;109;101;114;111;49;32;61;32;110;117;109;101;114;111;50; + + + 110;117;109;101;114;111;50;32;61;32;110;117;109;101;114;111;51; + + + + +`,ST=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;34; + + + 110;117;109;101;114;111;32;37;32;50;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111;32;43;32;34;32;233;32;112;97;114;34; + + + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111;32;43;32;34;32;233;32;237;109;112;97;114;34; + + + + +`,TT=` + + + 99;111;110;115;116;32;100;111;117;98;108;101;32;73;86;65;32;61;32;48;46;50;51; + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;112;114;101;99;111;83;101;109;73;118;97;32;34;80;114;101;231;111;32;115;101;109;32;73;86;65;63;34; + + + 100;111;117;98;108;101;32;105;109;112;111;115;116;111;32;61;32;112;114;101;99;111;83;101;109;73;118;97;32;42;32;73;86;65; + + + 100;111;117;98;108;101;32;112;114;101;99;111;67;111;109;73;118;97;32;61;32;112;114;101;99;111;83;101;109;73;118;97;32;43;32;105;109;112;111;115;116;111; + + + 111;117;116;112;117;116;58;32;105;109;112;111;115;116;111; + + + 111;117;116;112;117;116;58;32;112;114;101;99;111;67;111;109;73;118;97; + + +`,_T=` + + + 105;110;116;32;112;105;110;32;61;32;48; + + + 105;110;116;32;116;101;110;116;97;116;105;118;97;115;32;61;32;48; + + + 112;105;110;32;33;61;32;49;50;51;52;32;38;38;32;116;101;110;116;97;116;105;118;97;115;32;60;32;51; + + + 105;110;112;117;116;58;32;105;110;116;32;101;110;116;114;97;100;97;32;34;73;110;116;114;111;100;117;122;32;111;32;80;73;78;34; + + + 112;105;110;32;61;32;101;110;116;114;97;100;97; + + + 116;101;110;116;97;116;105;118;97;115;43;43; + + + + + 112;105;110;32;61;61;32;49;50;51;52; + + + 111;117;116;112;117;116;58;32;34;80;73;78;32;99;111;114;114;101;116;111;34; + + + + + 111;117;116;112;117;116;58;32;34;67;97;114;116;227;111;32;98;108;111;113;117;101;97;100;111;34; + + + + +`,AT=` + + + 99;111;110;115;116;32;105;110;116;32;80;73;78;32;61;32;49;50;51;52; + + + 105;110;116;32;112;105;110;32;61;32;48; + + + 105;110;116;32;116;101;110;116;97;116;105;118;97;115;32;61;32;48; + + + 112;105;110;32;33;61;32;80;73;78;32;38;38;32;116;101;110;116;97;116;105;118;97;115;32;60;32;51; + + + 105;110;112;117;116;58;32;112;105;110;32;34;73;110;116;114;111;100;117;122;32;111;32;80;73;78;34; + + + 116;101;110;116;97;116;105;118;97;115;43;43; + + + + + 112;105;110;32;61;61;32;80;73;78; + + + 111;117;116;112;117;116;58;32;34;80;73;78;32;99;111;114;114;101;116;111;34; + + + + + 111;117;116;112;117;116;58;32;34;67;97;114;116;227;111;32;98;108;111;113;117;101;97;100;111;34; + + + + +`,OT=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;49;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;34; + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;50;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;111;112;101;114;97;100;111;114;32;34;79;112;101;114;97;100;111;114;32;40;43;44;32;45;32;111;117;32;42;41;34; + + + 111;112;101;114;97;100;111;114; + + + 105;110;116;32;114;101;115;117;108;116;97;100;111;32;61;32;110;117;109;101;114;111;49;32;43;32;110;117;109;101;114;111;50; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116;97;100;111; + + + + + 105;110;116;32;114;101;115;117;108;116;97;100;111;32;61;32;110;117;109;101;114;111;49;32;45;32;110;117;109;101;114;111;50; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116;97;100;111; + + + + + 105;110;116;32;114;101;115;117;108;116;97;100;111;32;61;32;110;117;109;101;114;111;49;32;42;32;110;117;109;101;114;111;50; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116;97;100;111; + + + + + 111;117;116;112;117;116;58;32;34;79;112;101;114;97;100;111;114;32;100;101;115;99;111;110;104;101;99;105;100;111;34; + + + + +`,CT=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;109;97;114;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; + + + 109;97;114;91;48;93;91;49;93;32;61;32;116;114;117;101; + + + 109;97;114;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 109;97;114;91;48;93;91;51;93;32;61;32;116;114;117;101; + + + 109;97;114;91;50;93;91;52;93;32;61;32;116;114;117;101; + + + 109;97;114;91;51;93;91;52;93;32;61;32;116;114;117;101; + + + 109;97;114;91;52;93;91;48;93;32;61;32;116;114;117;101; + + + 83;116;114;105;110;103;91;93;32;99;111;108;117;110;97;115;32;61;32;123;34;65;34;44;32;34;66;34;44;32;34;67;34;44;32;34;68;34;44;32;34;69;34;125; + + + 105;110;116;32;102;105;108;97;32;61;32;48; + 102;105;108;97;32;60;32;109;97;114;46;108;101;110;103;116;104; + 102;105;108;97;43;43; + + + 105;110;116;32;99;111;108;117;110;97;32;61;32;48; + 99;111;108;117;110;97;32;60;32;109;97;114;91;102;105;108;97;93;46;108;101;110;103;116;104; + 99;111;108;117;110;97;43;43; + + + 109;97;114;91;102;105;108;97;93;91;99;111;108;117;110;97;93; + + + 111;117;116;112;117;116;58;32;99;111;108;117;110;97;115;91;99;111;108;117;110;97;93;32;43;32;40;102;105;108;97;32;43;32;49;41; + + + + + 248; + + + + + + + + +`,jT=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;109;97;114;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;53;93;91;53;93; + + + 109;97;114;91;48;93;91;49;93;32;61;32;116;114;117;101; + + + 109;97;114;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 109;97;114;91;48;93;91;51;93;32;61;32;116;114;117;101; + + + 109;97;114;91;50;93;91;52;93;32;61;32;116;114;117;101; + + + 109;97;114;91;51;93;91;52;93;32;61;32;116;114;117;101; + + + 109;97;114;91;52;93;91;48;93;32;61;32;116;114;117;101; + + + 83;116;114;105;110;103;91;93;32;99;111;108;117;110;97;115;32;61;32;123;34;65;34;44;32;34;66;34;44;32;34;67;34;44;32;34;68;34;44;32;34;69;34;125; + + +`,PT=` + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;97;116;111;32;34;81;117;101;32;112;114;97;116;111;63;32;40;49;44;32;50;32;111;117;32;51;41;34; + + + 112;114;97;116;111; + + + 111;117;116;112;117;116;58;32;34;83;97;108;97;100;97;32;103;114;101;103;97;34; + + + + + 111;117;116;112;117;116;58;32;34;66;97;99;97;108;104;97;117;32;224;32;66;114;225;115;34; + + + + + 111;117;116;112;117;116;58;32;34;87;114;97;112;32;100;101;32;102;97;108;97;102;101;108;34; + + + + + 111;117;116;112;117;116;58;32;34;69;115;99;111;108;104;101;32;117;109;32;110;250;109;101;114;111;32;118;225;108;105;100;111;34; + + + + +`,DT=` + + + 105;110;116;32;110;117;109;101;114;111;49;32;61;32;52; + + + 105;110;116;32;110;117;109;101;114;111;50;32;61;32;51; + + + 105;110;116;32;115;111;109;97;32;61;32;110;117;109;101;114;111;49;32;43;32;110;117;109;101;114;111;50; + + + 111;117;116;112;117;116;58;32;115;111;109;97; + + +`,BT=` + + + 83;116;114;105;110;103;91;93;32;110;111;109;101;115;32;61;32;110;101;119;32;83;116;114;105;110;103;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;111;109;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;111;109;101;115;91;105;93;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;111;109;101;34; + + + + + 105;110;112;117;116;58;32;105;110;116;32;115;111;114;116;101;97;100;111;32;34;78;250;109;101;114;111;32;115;111;114;116;101;97;100;111;32;40;49;32;97;32;53;41;34; + + + 111;117;116;112;117;116;58;32;34;76;105;109;112;97;32;111;32;113;117;97;100;114;111;58;32;34;32;43;32;110;111;109;101;115;91;115;111;114;116;101;97;100;111;32;45;32;49;93; + + +`,MT=` + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;52; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;42;32;50; + + + 111;117;116;112;117;116;58;32;34;78;250;109;101;114;111;32;100;117;112;108;105;99;97;100;111;58;32;34;32;43;32;110;117;109;101;114;111; + + +`,ZT=` + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;101;115;99;111;108;104;97;32;34;49;32;61;32;98;105;99;105;99;108;101;116;97;32;101;108;233;116;114;105;99;97;44;32;50;32;61;32;116;114;111;116;105;110;101;116;101;32;101;108;233;116;114;105;99;97;44;32;48;32;61;32;115;97;105;114;34; + + + 101;115;99;111;108;104;97;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;34;65;100;101;117;115;34; + + + -1; + + + + + 101;115;99;111;108;104;97;32;61;61;32;49; + + + 111;117;116;112;117;116;58;32;34;66;105;99;105;99;108;101;116;97;32;114;101;115;101;114;118;97;100;97;34; + + + + + 101;115;99;111;108;104;97;32;61;61;32;50; + + + 111;117;116;112;117;116;58;32;34;84;114;111;116;105;110;101;116;101;32;114;101;115;101;114;118;97;100;97;34; + + + + + 111;117;116;112;117;116;58;32;34;69;115;99;111;108;104;97;32;105;110;118;225;108;105;100;97;34; + + + + + + + + + + +`,LT=` + + + + + + 105;110;112;117;116;58;32;105;110;116;32;101;115;99;111;108;104;97;32;34;49;32;61;32;98;105;99;105;99;108;101;116;97;32;101;108;233;116;114;105;99;97;44;32;50;32;61;32;116;114;111;116;105;110;101;116;101;32;101;108;233;116;114;105;99;97;44;32;48;32;61;32;115;97;105;114;34; + + + 101;115;99;111;108;104;97; + + + 111;117;116;112;117;116;58;32;34;65;100;101;117;115;34; + + + 83;97;105;114;32;100;111;32;109;101;110;117; + + + + + 111;117;116;112;117;116;58;32;34;66;105;99;105;99;108;101;116;97;32;114;101;115;101;114;118;97;100;97;34; + + + + + 111;117;116;112;117;116;58;32;34;84;114;111;116;105;110;101;116;101;32;114;101;115;101;114;118;97;100;97;34; + + + + + 111;117;116;112;117;116;58;32;34;69;115;99;111;108;104;97;32;105;110;118;225;108;105;100;97;34; + + + + + + +`,ET=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;118;111;99;97;98;117;108;97;114;105;111;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 105;110;116;32;99;101;114;116;97;115;32;61;32;48; + + + 105;110;116;32;99;111;110;116;97;103;101;109;32;61;32;48; + + + 108;105;110;104;97;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;101;115;32;61;32;108;105;110;104;97;46;115;112;108;105;116;40;34;59;34;41; + + + 111;117;116;112;117;116;58;32;34;67;111;109;111;32;115;101;32;100;105;122;32;34;32;43;32;112;97;114;116;101;115;91;48;93;32;43;32;34;32;101;109;32;105;110;103;108;234;115;63;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;114;101;115;112;111;115;116;97; + + + 99;111;110;116;97;103;101;109;43;43; + + + 114;101;115;112;111;115;116;97;46;101;113;117;97;108;115;40;112;97;114;116;101;115;91;49;93;41; + + + 111;117;116;112;117;116;58;32;34;67;101;114;116;111;33;34; + + + 99;101;114;116;97;115;43;43; + + + + + 111;117;116;112;117;116;58;32;34;69;114;114;97;100;111;44;32;233;32;34;32;43;32;112;97;114;116;101;115;91;49;93;32;43;32;34;46;34; + + + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;105;116;111;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;99;101;114;116;97;115;32;43;32;34;32;100;101;32;34;32;43;32;99;111;110;116;97;103;101;109;32;43;32;34;32;99;101;114;116;97;115;34; + + +`,WT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;118;111;99;97;98;117;108;97;114;105;111;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,NT=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; + + + 105;100;97;100;101;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;109;97;105;111;114;32;100;101;32;105;100;97;100;101;34; + + + + + 111;117;116;112;117;116;58;32;34;109;101;110;111;114;32;100;101;32;105;100;97;100;101;34; + + + + +`,FT=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;104;97;32;33;61;32;110;117;108;108; + + + 111;117;116;112;117;116;58;32;108;105;110;104;97; + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;105;116;111;114;46;99;108;111;115;101;40;41; + + +`,JT=` + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;34;90;111;114;97;59;49;59;50;59;50;34; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;101;115;32;61;32;108;105;110;104;97;46;115;112;108;105;116;40;34;59;34;41; + + + 83;116;114;105;110;103;32;110;111;109;101;32;61;32;112;97;114;116;101;115;91;48;93; + + + 105;110;116;32;109;97;116;101;109;97;116;105;99;97;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;112;97;114;116;101;115;91;49;93;41; + + + 111;117;116;112;117;116;58;32;110;111;109;101;32;43;32;34;32;116;101;109;32;34;32;43;32;109;97;116;101;109;97;116;105;99;97;32;43;32;34;32;97;32;77;97;116;101;109;225;116;105;99;97;34; + + +`,RT=` + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;34;123;92;34;110;111;109;101;92;34;58;32;92;34;90;111;114;97;92;34;44;32;92;34;101;115;112;101;99;105;101;92;34;58;32;92;34;99;97;98;114;97;92;34;44;32;92;34;105;100;97;100;101;92;34;58;32;54;125;44;34; + + + 105;110;116;32;105;110;105;99;105;111;32;61;32;108;105;110;104;97;46;105;110;100;101;120;79;102;40;34;92;34;110;111;109;101;92;34;58;32;92;34;34;41;32;43;32;57; + + + 105;110;116;32;102;105;109;32;61;32;108;105;110;104;97;46;105;110;100;101;120;79;102;40;34;92;34;34;44;32;105;110;105;99;105;111;41; + + + 83;116;114;105;110;103;32;110;111;109;101;32;61;32;108;105;110;104;97;46;115;117;98;115;116;114;105;110;103;40;105;110;105;99;105;111;44;32;102;105;109;41; + + + 111;117;116;112;117;116;58;32;110;111;109;101; + + +`,GT=` + + + 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; + + + 102;105;99;104;101;105;114;111;46;104;97;115;78;101;120;116;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;102;105;99;104;101;105;114;111;46;110;101;120;116;76;105;110;101;40;41; + + + 111;117;116;112;117;116;58;32;108;105;110;104;97; + + + + + 102;105;99;104;101;105;114;111;46;99;108;111;115;101;40;41; + + +`,HT=` + + + 105;110;116;91;93;91;93;32;116;97;98;101;108;97;32;61;32;110;101;119;32;105;110;116;91;49;48;93;91;49;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;97;98;101;108;97;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;116;97;98;101;108;97;91;105;93;46;108;101;110;103;116;104; + 106;43;43; + + + 116;97;98;101;108;97;91;105;93;91;106;93;32;61;32;40;105;32;43;32;49;41;32;42;32;40;106;32;43;32;49;41; + + + + + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;32;40;49;32;97;32;49;48;41;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;32;40;49;32;97;32;49;48;41;34; + + + 111;117;116;112;117;116;58;32;97;32;43;32;34;32;183;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;116;97;98;101;108;97;91;97;32;45;32;49;93;91;98;32;45;32;49;93; + + +`,VT=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 108;117;103;97;114;101;115;91;48;93;91;48;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;50;93;91;51;93;32;61;32;116;114;117;101; + + + 105;110;116;32;108;105;118;114;101;115;32;61;32;48; + + + 105;110;116;32;102;105;108;97;32;61;32;48; + 102;105;108;97;32;60;32;108;117;103;97;114;101;115;46;108;101;110;103;116;104; + 102;105;108;97;43;43; + + + 105;110;116;32;108;117;103;97;114;32;61;32;48; + 108;117;103;97;114;32;60;32;108;117;103;97;114;101;115;91;102;105;108;97;93;46;108;101;110;103;116;104; + 108;117;103;97;114;43;43; + + + 33;108;117;103;97;114;101;115;91;102;105;108;97;93;91;108;117;103;97;114;93; + + + 108;105;118;114;101;115;32;61;32;108;105;118;114;101;115;32;43;32;49; + + + + + 248; + + + + + + + + + 111;117;116;112;117;116;58;32;34;76;105;118;114;101;115;58;32;34;32;43;32;108;105;118;114;101;115; + + +`,qT=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 108;117;103;97;114;101;115;91;48;93;91;48;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;50;93;91;51;93;32;61;32;116;114;117;101; + + +`,QT=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 108;117;103;97;114;101;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;49;93;91;51;93;32;61;32;116;114;117;101; + + + 105;110;112;117;116;58;32;105;110;116;32;102;105;108;97;32;34;70;105;108;97;34; + + + 105;110;112;117;116;58;32;105;110;116;32;108;117;103;97;114;32;34;76;117;103;97;114;34; + + + 108;117;103;97;114;101;115;91;102;105;108;97;93;91;108;117;103;97;114;93; + + + 111;117;116;112;117;116;58;32;34;74;225;32;118;101;110;100;105;100;111;34; + + + + + 108;117;103;97;114;101;115;91;102;105;108;97;93;91;108;117;103;97;114;93;32;61;32;116;114;117;101; + + + 111;117;116;112;117;116;58;32;34;86;101;110;100;105;100;111;58;32;102;105;108;97;32;34;32;43;32;102;105;108;97;32;43;32;34;44;32;108;117;103;97;114;32;34;32;43;32;108;117;103;97;114; + + + + +`,UT=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 108;117;103;97;114;101;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;49;93;91;51;93;32;61;32;116;114;117;101; + + + 105;110;112;117;116;58;32;105;110;116;32;102;105;108;97;32;34;70;105;108;97;34; + + + 105;110;112;117;116;58;32;105;110;116;32;108;117;103;97;114;32;34;76;117;103;97;114;34; + + +`,$T=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 108;117;103;97;114;101;115;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;49;93;91;49;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 105;110;116;32;102;105;108;97;32;61;32;48; + 102;105;108;97;32;60;32;108;117;103;97;114;101;115;46;108;101;110;103;116;104; + 102;105;108;97;43;43; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;34;34; + + + 105;110;116;32;108;117;103;97;114;32;61;32;48; + 108;117;103;97;114;32;60;32;108;117;103;97;114;101;115;91;102;105;108;97;93;46;108;101;110;103;116;104; + 108;117;103;97;114;43;43; + + + 108;117;103;97;114;101;115;91;102;105;108;97;93;91;108;117;103;97;114;93; + + + 108;105;110;104;97;32;61;32;108;105;110;104;97;32;43;32;34;88;34; + + + + + 108;105;110;104;97;32;61;32;108;105;110;104;97;32;43;32;34;79;34; + + + + + + + 111;117;116;112;117;116;58;32;108;105;110;104;97; + + + + +`,YT=` + + + 98;111;111;108;101;97;110;91;93;91;93;32;108;117;103;97;114;101;115;32;61;32;110;101;119;32;98;111;111;108;101;97;110;91;51;93;91;53;93; + + + 108;117;103;97;114;101;115;91;48;93;91;50;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;49;93;91;49;93;32;61;32;116;114;117;101; + + + 108;117;103;97;114;101;115;91;49;93;91;50;93;32;61;32;116;114;117;101; + + + 111;117;116;112;117;116;58;32;34;70;105;108;97;115;58;32;34;32;43;32;108;117;103;97;114;101;115;46;108;101;110;103;116;104; + + + 111;117;116;112;117;116;58;32;34;76;117;103;97;114;101;115;32;112;111;114;32;102;105;108;97;58;32;34;32;43;32;108;117;103;97;114;101;115;91;48;93;46;108;101;110;103;116;104; + + + 111;117;116;112;117;116;58;32;34;70;105;108;97;32;49;44;32;108;117;103;97;114;32;50;32;118;101;110;100;105;100;111;63;32;34;32;43;32;108;117;103;97;114;101;115;91;49;93;91;50;93; + + +`,XT=` + + + 105;110;116;32;115;101;103;117;110;100;111;115;32;61;32;50;48;48; + + + 105;110;116;32;109;105;110;117;116;111;115;32;61;32;115;101;103;117;110;100;111;115;32;47;32;54;48; + + + 105;110;116;32;114;101;115;116;111;32;61;32;115;101;103;117;110;100;111;115;32;37;32;54;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;111;115;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;115;34; + + +`,KT=` + + + 105;110;116;32;115;101;103;117;110;100;111;115;32;61;32;50;48;48; + + + 105;110;116;32;109;105;110;117;116;111;115;32;61;32;115;101;103;117;110;100;111;115;32;37;32;54;48; + + + 105;110;116;32;114;101;115;116;111;32;61;32;115;101;103;117;110;100;111;115;32;47;32;54;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;111;115;32;43;32;34;32;109;105;110;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;115;34; + + +`,e_=` + + + 83;116;114;105;110;103;32;110;111;109;101;32;61;32;34;76;117;100;119;105;103;34; + + + 105;110;116;32;105;100;97;100;101;32;61;32;55; + + + 100;111;117;98;108;101;32;97;108;116;117;114;97;32;61;32;49;46;50; + + + 111;117;116;112;117;116;58;32;110;111;109;101;32;43;32;34;32;116;101;109;32;34;32;43;32;105;100;97;100;101;32;43;32;34;32;97;110;111;115;46;34; + + + 111;117;116;112;117;116;58;32;34;65;108;116;117;114;97;58;32;34;32;43;32;97;108;116;117;114;97;32;43;32;34;32;109;34; + + +`,t_=` + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;51; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;42;32;50; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;43;32;49; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + +`,n_=` + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;50; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;43;32;51; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;42;32;52; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + +`,i_=` + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;42;32;52; + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;50; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;43;32;51; + + +`,a_=` + + + 83;116;114;105;110;103;32;101;115;113;117;101;114;100;97;32;61;32;34;115;117;109;111;34; + + + 83;116;114;105;110;103;32;100;105;114;101;105;116;97;32;61;32;34;225;103;117;97;34; + + + 83;116;114;105;110;103;32;97;117;120;32;61;32;101;115;113;117;101;114;100;97; + + + 101;115;113;117;101;114;100;97;32;61;32;100;105;114;101;105;116;97; + + + 100;105;114;101;105;116;97;32;61;32;97;117;120; + + + 111;117;116;112;117;116;58;32;34;69;115;113;117;101;114;100;97;58;32;34;32;43;32;101;115;113;117;101;114;100;97; + + + 111;117;116;112;117;116;58;32;34;68;105;114;101;105;116;97;58;32;34;32;43;32;100;105;114;101;105;116;97; + + +`,s_=` + + + 83;116;114;105;110;103;32;101;115;113;117;101;114;100;97;32;61;32;34;115;117;109;111;34; + + + 83;116;114;105;110;103;32;100;105;114;101;105;116;97;32;61;32;34;225;103;117;97;34; + + + 111;117;116;112;117;116;58;32;34;69;115;113;117;101;114;100;97;58;32;34;32;43;32;101;115;113;117;101;114;100;97; + + + 111;117;116;112;117;116;58;32;34;68;105;114;101;105;116;97;58;32;34;32;43;32;100;105;114;101;105;116;97; + + +`,r_=` + + + 105;110;116;32;97;32;61;32;53; + + + 105;110;116;32;98;32;61;32;57; + + + 105;110;116;32;97;117;120;32;61;32;97; + + + 97;32;61;32;98; + + + 98;32;61;32;97;117;120; + + + 111;117;116;112;117;116;58;32;34;97;32;61;32;34;32;43;32;97; + + + 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; + + +`,o_=` + + + 105;110;116;32;105;100;97;100;101;32;61;32;49;52; + + + 100;111;117;98;108;101;32;97;108;116;117;114;97;32;61;32;49;46;54;50; + + + 83;116;114;105;110;103;32;110;111;109;101;32;61;32;34;73;110;234;115;34; + + + 111;117;116;112;117;116;58;32;110;111;109;101;32;43;32;34;32;116;101;109;32;34;32;43;32;105;100;97;100;101;32;43;32;34;32;97;110;111;115;46;34; + + + 111;117;116;112;117;116;58;32;34;65;108;116;117;114;97;58;32;34;32;43;32;97;108;116;117;114;97;32;43;32;34;32;109;34; + + +`,l_=` + + + 105;110;116;32;109;105;110;117;116;111;115;32;61;32;49;51;53; + + + 105;110;116;32;104;111;114;97;115;32;61;32;109;105;110;117;116;111;115;32;47;32;54;48; + + + 105;110;116;32;114;101;115;116;111;32;61;32;109;105;110;117;116;111;115;32;37;32;54;48; + + + 111;117;116;112;117;116;58;32;104;111;114;97;115;32;43;32;34;32;104;111;114;97;115;32;101;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;109;105;110;117;116;111;115;34; + + +`,u_=` + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;51; + + + 100;111;117;98;108;101;32;112;114;101;99;111;32;61;32;50;46;53; + + + 100;111;117;98;108;101;32;112;114;101;99;111;84;111;116;97;108;32;61;32;113;117;97;110;116;105;100;97;100;101;32;42;32;112;114;101;99;111; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;112;114;101;99;111;84;111;116;97;108;32;43;32;34;32;101;117;114;111;115;34; + + +`,c_=` + + + 105;110;116;32;115;97;108;100;111;32;61;32;50;48; + + + 105;110;116;32;112;114;101;99;111;32;61;32;55; + + + 115;97;108;100;111;32;61;32;115;97;108;100;111;32;45;32;112;114;101;99;111; + + + 111;117;116;112;117;116;58;32;34;82;101;115;116;97;58;32;34;32;43;32;115;97;108;100;111; + + +`,m_=` + + + 105;110;116;32;115;97;108;100;111;32;61;32;50;48; + + + 105;110;116;32;112;114;101;99;111;32;61;32;55; + + + 111;117;116;112;117;116;58;32;34;82;101;115;116;97;58;32;34;32;43;32;115;97;108;100;111; + + + 115;97;108;100;111;32;61;32;115;97;108;100;111;32;45;32;112;114;101;99;111; + + +`,d_=` + + + 105;110;116;32;112;114;101;99;111;32;61;32;57; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;51; + + + 105;110;116;32;116;111;116;97;108;32;61;32;112;114;101;99;111;32;42;32;113;117;97;110;116;105;100;97;100;101; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + +`,h_=` + + + 105;110;116;32;99;111;109;112;114;105;109;101;110;116;111;32;61;32;55; + + + 105;110;116;32;108;97;114;103;117;114;97;32;61;32;52; + + + 105;110;116;32;97;114;101;97;32;61;32;99;111;109;112;114;105;109;101;110;116;111;32;42;32;108;97;114;103;117;114;97; + + + 105;110;116;32;112;101;114;105;109;101;116;114;111;32;61;32;50;32;42;32;40;99;111;109;112;114;105;109;101;110;116;111;32;43;32;108;97;114;103;117;114;97;41; + + + 111;117;116;112;117;116;58;32;34;193;114;101;97;58;32;34;32;43;32;97;114;101;97; + + + 111;117;116;112;117;116;58;32;34;80;101;114;237;109;101;116;114;111;58;32;34;32;43;32;112;101;114;105;109;101;116;114;111; + + +`,g_=` + + + 105;110;116;32;115;101;103;117;110;100;111;115;32;61;32;50;48;48; + + + 105;110;116;32;109;105;110;117;116;111;115;32;61;32;115;101;103;117;110;100;111;115;32;47;32;54;48; + + + 105;110;116;32;114;101;115;116;111;32;61;32;115;101;103;117;110;100;111;115;32;37;32;54;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;111;115;32;43;32;34;32;109;105;110;117;116;111;115;32;101;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;115;101;103;117;110;100;111;115;34; + + +`,p_=` + + + 105;110;116;32;115;101;103;117;110;100;111;115;32;61;32;50;48;48; + + + 111;117;116;112;117;116;58;32;109;105;110;117;116;111;115;32;43;32;34;32;109;105;110;117;116;111;115;32;101;32;34;32;43;32;114;101;115;116;111;32;43;32;34;32;115;101;103;117;110;100;111;115;34; + + +`,f_=` + + + 105;110;116;32;99;111;109;112;114;105;109;101;110;116;111;32;61;32;53; + + + 105;110;116;32;108;97;114;103;117;114;97;32;61;32;51; + + + 105;110;116;32;97;114;101;97;32;61;32;99;111;109;112;114;105;109;101;110;116;111;32;42;32;108;97;114;103;117;114;97; + + + 111;117;116;112;117;116;58;32;97;114;101;97; + + +`,b_=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;111;109;101;32;34;67;111;109;111;32;116;101;32;99;104;97;109;97;115;63;34; + + + 111;117;116;112;117;116;58;32;34;79;108;225;32;34;32;43;32;110;111;109;101;32;43;32;34;33;34; + + +`,x_=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;115;111;109;97;32;61;32;97;32;43;32;98; + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; + + +`,v_=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;63;34; + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;40;97;32;43;32;98;41; + + +`,y_=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;63;34; + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;97;32;43;32;98; + + +`,w_=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;110;111;115;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; + + + 105;110;116;32;100;105;97;115;32;61;32;97;110;111;115;32;42;32;51;54;53; + + + 111;117;116;112;117;116;58;32;34;83;227;111;32;99;101;114;99;97;32;100;101;32;34;32;43;32;100;105;97;115;32;43;32;34;32;100;105;97;115;46;34; + + +`,z_=` + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;120;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;121;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;63;34; + + + 100;111;117;98;108;101;32;109;101;100;105;97;32;61;32;40;120;32;43;32;121;41;32;47;32;50; + + + 111;117;116;112;117;116;58;32;34;77;233;100;105;97;58;32;34;32;43;32;109;101;100;105;97; + + +`,I_=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;115;111;109;97;32;61;32;97;32;43;32;98; + + + 105;110;116;32;112;114;111;100;117;116;111;32;61;32;97;32;42;32;98; + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; + + + 111;117;116;112;117;116;58;32;34;80;114;111;100;117;116;111;58;32;34;32;43;32;112;114;111;100;117;116;111; + + +`,k_=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; + + + 105;100;97;100;101;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;201;115;32;109;97;105;111;114;32;100;101;32;105;100;97;100;101;46;34; + + + + + 111;117;116;112;117;116;58;32;34;65;105;110;100;97;32;110;227;111;32;233;115;32;109;97;105;111;114;32;100;101;32;105;100;97;100;101;46;34; + + + + +`,S_=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;63;34; + + + 110;117;109;101;114;111;32;60;32;48; + + + 110;117;109;101;114;111;32;61;32;48;32;45;32;110;117;109;101;114;111; + + + + + 248; + + + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + +`,T_=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;63;34; + + + 110;117;109;101;114;111;32;37;32;50;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;34;112;97;114;34; + + + + + 111;117;116;112;117;116;58;32;34;237;109;112;97;114;34; + + + + +`,__=` + + + 105;110;116;32;112;111;110;116;111;115;32;61;32;48; + + + 112;111;110;116;111;115;32;61;32;112;111;110;116;111;115;32;43;32;49;48; + + + 112;111;110;116;111;115;32;61;32;112;111;110;116;111;115;32;43;32;53; + + + 112;111;110;116;111;115;32;61;32;112;111;110;116;111;115;32;45;32;51; + + + 111;117;116;112;117;116;58;32;34;80;111;110;116;111;115;58;32;34;32;43;32;112;111;110;116;111;115; + + +`,A_=` + + + 105;110;116;32;112;111;110;116;111;115;32;61;32;48; + + + 112;111;110;116;111;115;32;61;32;112;111;110;116;111;115;32;43;32;49;48; + + + 112;111;110;116;111;115;32;61;32;112;111;110;116;111;115;32;43;32;53; + + + 112;111;110;116;111;115;32;61;32;51; + + + 111;117;116;112;117;116;58;32;34;80;111;110;116;111;115;58;32;34;32;43;32;112;111;110;116;111;115; + + +`,O_=` + + + 105;110;116;32;112;114;101;99;111;32;61;32;56; + + + 105;110;116;32;113;117;101;105;106;111;32;61;32;50; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;51; + + + 105;110;116;32;116;111;116;97;108;32;61;32;40;112;114;101;99;111;32;43;32;113;117;101;105;106;111;41;32;42;32;113;117;97;110;116;105;100;97;100;101; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + +`,C_=` + + + 105;110;116;32;112;114;101;99;111;32;61;32;56; + + + 105;110;116;32;113;117;101;105;106;111;32;61;32;50; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;51; + + + 105;110;116;32;116;111;116;97;108;32;61;32;112;114;101;99;111;32;43;32;113;117;101;105;106;111;32;42;32;113;117;97;110;116;105;100;97;100;101; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + +`,j_=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;63;34; + + + 97;32;62;32;98; + + + 111;117;116;112;117;116;58;32;97; + + + + + 111;117;116;112;117;116;58;32;98; + + + + +`,P_=` + + + 105;110;112;117;116;58;32;100;111;117;98;108;101;32;112;114;101;99;111;32;34;80;114;101;231;111;32;101;109;32;101;117;114;111;115;63;34; + + + 112;114;101;99;111;32;62;32;53;48; + + + 112;114;101;99;111;32;61;32;112;114;101;99;111;32;45;32;53; + + + + + 248; + + + + + 111;117;116;112;117;116;58;32;34;65;32;112;97;103;97;114;58;32;34;32;43;32;112;114;101;99;111;32;43;32;34;32;101;117;114;111;115;34; + + +`,D_=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;111;116;97;32;34;78;111;116;97;63;34; + + + 110;111;116;97;32;62;61;32;49;32;38;38;32;110;111;116;97;32;60;61;32;53; + + + 111;117;116;112;117;116;58;32;34;118;225;108;105;100;97;34; + + + + + 111;117;116;112;117;116;58;32;34;105;110;118;225;108;105;100;97;34; + + + + +`,B_=` + + + 105;110;112;117;116;58;32;105;110;116;32;112;111;110;116;111;115;32;34;81;117;97;110;116;111;115;32;112;111;110;116;111;115;63;34; + + + 112;111;110;116;111;115;32;62;61;32;53;48; + + + 111;117;116;112;117;116;58;32;34;97;112;114;111;118;97;100;111;34; + + + + + 111;117;116;112;117;116;58;32;34;114;101;112;114;111;118;97;100;111;34; + + + + +`,M_=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;101;32;105;100;97;100;101;32;116;101;110;115;63;34; + + + 105;100;97;100;101;32;60;32;54; + + + 111;117;116;112;117;116;58;32;34;69;110;116;114;97;100;97;32;103;114;97;116;117;105;116;97;34; + + + + + 111;117;116;112;117;116;58;32;34;52;32;101;117;114;111;115;34; + + + + +`,Z_=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;101;32;105;100;97;100;101;32;116;101;110;115;63;34; + + + 105;100;97;100;101;32;60;61;32;54; + + + 111;117;116;112;117;116;58;32;34;69;110;116;114;97;100;97;32;103;114;97;116;117;105;116;97;34; + + + + + 111;117;116;112;117;116;58;32;34;52;32;101;117;114;111;115;34; + + + + +`,L_=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; + + + 105;100;97;100;101;32;62;61;32;49;50;32;38;38;32;105;100;97;100;101;32;60;32;49;56; + + + 111;117;116;112;117;116;58;32;34;66;105;108;104;101;116;101;32;106;111;118;101;109;34; + + + + + 111;117;116;112;117;116;58;32;34;83;101;109;32;98;105;108;104;101;116;101;32;106;111;118;101;109;34; + + + + +`,E_=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;111;116;97;32;34;78;111;116;97;63;34; + + + 110;111;116;97;32;60;32;49;32;124;124;32;110;111;116;97;32;62;32;53; + + + 111;117;116;112;117;116;58;32;34;69;115;116;97;32;110;111;116;97;32;110;227;111;32;101;120;105;115;116;101;46;34; + + + + + 111;117;116;112;117;116;58;32;34;65;32;110;111;116;97;32;34;32;43;32;110;111;116;97;32;43;32;34;32;233;32;118;225;108;105;100;97;46;34; + + + + +`,W_=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;110;111;32;34;65;110;111;63;34; + + + 40;97;110;111;32;37;32;52;32;61;61;32;48;32;38;38;32;97;110;111;32;37;32;49;48;48;32;33;61;32;48;41;32;124;124;32;97;110;111;32;37;32;52;48;48;32;61;61;32;48; + + + 111;117;116;112;117;116;58;32;34;65;110;111;32;98;105;115;115;101;120;116;111;34; + + + + + 111;117;116;112;117;116;58;32;34;78;227;111;32;233;32;97;110;111;32;98;105;115;115;101;120;116;111;34; + + + + +`,N_=` + + + 105;110;112;117;116;58;32;105;110;116;32;100;105;97;32;34;68;105;97;32;40;49;32;97;32;55;41;63;34; + + + 100;105;97;32;61;61;32;54;32;124;124;32;100;105;97;32;61;61;32;55; + + + 111;117;116;112;117;116;58;32;34;70;105;109;32;100;101;32;115;101;109;97;110;97;34; + + + + + 111;117;116;112;117;116;58;32;34;68;105;97;32;250;116;105;108;34; + + + + +`,F_=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;99;111;114;32;34;68;101;32;113;117;101;32;99;111;114;32;101;115;116;225;32;111;32;115;101;109;225;102;111;114;111;63;34; + + + 99;111;114; + + + 111;117;116;112;117;116;58;32;34;80;97;114;97;34; + + + + + 111;117;116;112;117;116;58;32;34;69;115;112;101;114;97;34; + + + + + 111;117;116;112;117;116;58;32;34;65;118;97;110;231;97;34; + + + + + 111;117;116;112;117;116;58;32;34;78;227;111;32;99;111;110;104;101;231;111;32;101;115;116;97;32;99;111;114;46;34; + + + + +`,J_=` + + + 105;110;112;117;116;58;32;105;110;116;32;101;115;99;111;108;104;97;32;34;49;32;225;103;117;97;44;32;50;32;115;117;109;111;44;32;51;32;99;104;111;99;111;108;97;116;101;32;113;117;101;110;116;101;34; + + + 101;115;99;111;108;104;97; + + + 111;117;116;112;117;116;58;32;34;65;113;117;105;32;101;115;116;225;32;97;32;116;117;97;32;225;103;117;97;46;34; + + + + + 111;117;116;112;117;116;58;32;34;65;113;117;105;32;101;115;116;225;32;111;32;116;101;117;32;115;117;109;111;46;34; + + + + + 111;117;116;112;117;116;58;32;34;65;113;117;105;32;101;115;116;225;32;111;32;116;101;117;32;99;104;111;99;111;108;97;116;101;32;113;117;101;110;116;101;46;34; + + + + + 111;117;116;112;117;116;58;32;34;69;115;116;101;32;98;111;116;227;111;32;110;227;111;32;101;120;105;115;116;101;46;34; + + + + +`,R_=` + + + 105;110;112;117;116;58;32;105;110;116;32;100;105;97;32;34;81;117;101;32;100;105;97;32;40;49;32;97;32;55;41;63;34; + + + 100;105;97;32;61;61;32;54;32;124;124;32;100;105;97;32;61;61;32;55; + + + 111;117;116;112;117;116;58;32;34;115;101;109;32;101;115;99;111;108;97;34; + + + + + 111;117;116;112;117;116;58;32;34;101;115;99;111;108;97;34; + + + + +`,G_=` + + + 105;110;112;117;116;58;32;105;110;116;32;100;105;97;32;34;81;117;101;32;100;105;97;32;40;49;32;97;32;55;41;63;34; + + + 100;105;97;32;61;61;32;54;32;38;38;32;100;105;97;32;61;61;32;55; + + + 111;117;116;112;117;116;58;32;34;115;101;109;32;101;115;99;111;108;97;34; + + + + + 111;117;116;112;117;116;58;32;34;101;115;99;111;108;97;34; + + + + +`,H_=` + + + 105;110;112;117;116;58;32;105;110;116;32;104;111;114;97;32;34;81;117;101;32;104;111;114;97;115;32;115;227;111;32;40;115;243;32;97;32;104;111;114;97;41;63;34; + + + 104;111;114;97;32;62;61;32;56;32;38;38;32;104;111;114;97;32;60;61;32;49;53; + + + 111;117;116;112;117;116;58;32;34;69;115;99;111;108;97;34; + + + + + 111;117;116;112;117;116;58;32;34;84;101;109;112;111;32;108;105;118;114;101;34; + + + + +`,V_=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;111;116;97;32;34;81;117;101;32;110;111;116;97;63;34; + + + 110;111;116;97; + + + 111;117;116;112;117;116;58;32;34;109;117;105;116;111;32;105;110;115;117;102;105;99;105;101;110;116;101;34; + + + + + 111;117;116;112;117;116;58;32;34;105;110;115;117;102;105;99;105;101;110;116;101;34; + + + + + 111;117;116;112;117;116;58;32;34;115;117;102;105;99;105;101;110;116;101;34; + + + + + 111;117;116;112;117;116;58;32;34;98;111;109;34; + + + + + 111;117;116;112;117;116;58;32;34;109;117;105;116;111;32;98;111;109;34; + + + + + 111;117;116;112;117;116;58;32;34;78;111;116;97;32;105;110;118;225;108;105;100;97;34; + + + + +`,q_=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;111;112;101;114;97;100;111;114;32;34;79;112;101;114;97;100;111;114;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;34; + + + 105;110;116;32;114;101;115;117;108;116;97;100;111;32;61;32;48; + + + 111;112;101;114;97;100;111;114; + + + 114;101;115;117;108;116;97;100;111;32;61;32;97;32;43;32;98; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116;97;100;111; + + + + + 114;101;115;117;108;116;97;100;111;32;61;32;97;32;45;32;98; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116;97;100;111; + + + + + 114;101;115;117;108;116;97;100;111;32;61;32;97;32;42;32;98; + + + 111;117;116;112;117;116;58;32;114;101;115;117;108;116;97;100;111; + + + + + 111;117;116;112;117;116;58;32;34;79;112;101;114;97;100;111;114;32;100;101;115;99;111;110;104;101;99;105;100;111;34; + + + + +`,Q_=` + + + 105;110;112;117;116;58;32;105;110;116;32;101;115;99;111;108;104;97;32;34;49;32;225;103;117;97;44;32;50;32;115;117;109;111;44;32;51;32;99;104;111;99;111;108;97;116;101;32;113;117;101;110;116;101;34; + + + 101;115;99;111;108;104;97;32;61;61;32;49; + + + 111;117;116;112;117;116;58;32;34;65;113;117;105;32;101;115;116;225;32;97;32;116;117;97;32;225;103;117;97;46;34; + + + + + 101;115;99;111;108;104;97;32;61;61;32;50; + + + 111;117;116;112;117;116;58;32;34;65;113;117;105;32;101;115;116;225;32;111;32;116;101;117;32;115;117;109;111;46;34; + + + + + 101;115;99;111;108;104;97;32;61;61;32;51; + + + 111;117;116;112;117;116;58;32;34;65;113;117;105;32;101;115;116;225;32;111;32;116;101;117;32;99;104;111;99;111;108;97;116;101;32;113;117;101;110;116;101;46;34; + + + + + 111;117;116;112;117;116;58;32;34;69;115;116;101;32;98;111;116;227;111;32;110;227;111;32;101;120;105;115;116;101;46;34; + + + + + + + + +`,U_=` + + + 80;244;114;32;117;109;97;32;99;104;225;118;101;110;97;32;110;97;32;109;101;115;97; + + + 81;117;101;114;32;97;231;250;99;97;114;63; + + + 74;117;110;116;97;114;32;97;231;250;99;97;114; + + + + + 248; + + + + + 67;104;225;32;97;105;110;100;97;32;100;101;109;97;115;105;97;100;111;32;113;117;101;110;116;101; + + + 69;115;112;101;114;97;114;32;49;32;109;105;110;117;116;111; + + + + + 66;101;98;101;114;32;111;32;99;104;225; + + +`,$_=` + + + 76;101;118;97;110;116;97;114; + + + 76;97;118;97;114;32;111;115;32;100;101;110;116;101;115; + + + 86;101;115;116;105;114; + + + 84;111;109;97;114;32;111;32;112;101;113;117;101;110;111;45;97;108;109;111;231;111; + + +`,Y_=` + + + 69;110;99;104;101;114;32;97;32;99;104;97;108;101;105;114;97;32;99;111;109;32;225;103;117;97; + + + 76;105;103;97;114;32;97;32;99;104;97;108;101;105;114;97; + + + 80;244;114;32;117;109;97;32;115;97;113;117;101;116;97;32;100;101;32;99;104;225;32;110;97;32;99;104;225;118;101;110;97; + + + 68;101;105;116;97;114;32;225;103;117;97;32;113;117;101;110;116;101;32;110;97;32;99;104;225;118;101;110;97; + + + 69;115;112;101;114;97;114;32;51;32;109;105;110;117;116;111;115; + + + 84;105;114;97;114;32;97;32;115;97;113;117;101;116;97;32;100;101;32;99;104;225; + + +`,X_=` + + + 69;115;116;225;32;97;32;99;104;111;118;101;114;63; + + + 76;101;118;97;114;32;103;117;97;114;100;97;45;99;104;117;118;97; + + + + + 76;101;118;97;114;32;243;99;117;108;111;115;32;100;101;32;115;111;108; + + + + + 83;97;105;114; + + +`,K_=` + + + 80;114;97;116;111;32;110;227;111;32;118;97;122;105;111; + + + 68;97;114;32;117;109;97;32;103;97;114;102;97;100;97; + + + + + 76;101;118;97;110;116;97;114;32;111;32;112;114;97;116;111; + + +`,eA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;67;111;110;116;97;114;32;97;116;233;63;34; + + + 105;110;116;32;105;32;61;32;49; + + + 105;32;60;61;32;110; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + +`,tA=` + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;51; + + + 110;117;109;101;114;111;32;62;32;48; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;45;32;49; + + + + + 111;117;116;112;117;116;58;32;34;80;97;114;116;105;100;97;33;34; + + +`,nA=` + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;51; + + + 110;117;109;101;114;111;32;62;32;48; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + + + + 111;117;116;112;117;116;58;32;34;80;97;114;116;105;100;97;33;34; + + +`,iA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;70;97;116;111;114;105;97;108;32;100;101;32;113;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;102;97;116;111;114;105;97;108;32;61;32;49; + + + 105;110;116;32;105;32;61;32;49; + + + 105;32;60;61;32;110; + + + 102;97;116;111;114;105;97;108;32;61;32;102;97;116;111;114;105;97;108;32;42;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;110;32;43;32;34;33;32;61;32;34;32;43;32;102;97;116;111;114;105;97;108; + + +`,aA=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;111;112;99;97;111;32;34;49;32;109;97;105;115;44;32;50;32;109;101;110;111;115;44;32;51;32;118;101;122;101;115;63;34; + + + 111;112;99;97;111; + + + 111;117;116;112;117;116;58;32;97;32;43;32;98; + + + + + 111;117;116;112;117;116;58;32;97;32;45;32;98; + + + + + 111;117;116;112;117;116;58;32;97;32;42;32;98; + + + + + 111;117;116;112;117;116;58;32;34;78;227;111;32;101;120;105;115;116;101;34; + + + + +`,sA=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;111;112;99;97;111;32;34;49;32;109;97;105;115;44;32;50;32;109;101;110;111;115;44;32;51;32;118;101;122;101;115;63;34; + + + 111;112;99;97;111; + + + 111;117;116;112;117;116;58;32;97;32;43;32;98; + + + + + 111;117;116;112;117;116;58;32;98;32;45;32;97; + + + + + 111;117;116;112;117;116;58;32;97;32;42;32;98; + + + + + 111;117;116;112;117;116;58;32;34;78;227;111;32;101;120;105;115;116;101;34; + + + + +`,rA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;81;117;101;32;110;250;109;101;114;111;63;34; + + + 110;117;109;101;114;111; + + + 111;117;116;112;117;116;58;32;34;117;109;34; + + + + + 111;117;116;112;117;116;58;32;34;100;111;105;115;34; + + + + + 111;117;116;112;117;116;58;32;34;116;114;234;115;34; + + + + + 111;117;116;112;117;116;58;32;34;110;227;111;32;99;111;110;104;101;231;111;34; + + + + +`,oA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;34; + + + 105;110;116;32;112;97;115;115;111;115;32;61;32;48; + + + 110;117;109;101;114;111;32;60;32;49;48;48; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;42;32;50; + + + 112;97;115;115;111;115;32;61;32;112;97;115;115;111;115;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;112;97;115;115;111;115; + + +`,lA=` + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;48; + + + 110;117;109;101;114;111;32;60;32;49;32;124;124;32;110;117;109;101;114;111;32;62;32;49;48; + + + 105;110;112;117;116;58;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;100;101;32;49;32;97;32;49;48;34; + + + + + 111;117;116;112;117;116;58;32;34;79;98;114;105;103;97;100;111;33;34; + + +`,uA=` + + + 105;110;116;32;105;32;61;32;49;48; + + + 105;32;60;32;53; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + +`,cA=` + + + 105;110;112;117;116;58;32;105;110;116;32;111;98;106;101;116;105;118;111;32;34;79;98;106;101;116;105;118;111;63;34; + + + 105;110;116;32;100;105;110;104;101;105;114;111;32;61;32;48; + + + 105;110;116;32;115;101;109;97;110;97;115;32;61;32;48; + + + 100;105;110;104;101;105;114;111;32;60;32;111;98;106;101;116;105;118;111; + + + 100;105;110;104;101;105;114;111;32;61;32;100;105;110;104;101;105;114;111;32;43;32;53; + + + 115;101;109;97;110;97;115;32;61;32;115;101;109;97;110;97;115;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;83;101;109;97;110;97;115;58;32;34;32;43;32;115;101;109;97;110;97;115; + + +`,mA=` + + + 105;110;112;117;116;58;32;105;110;116;32;111;98;106;101;116;105;118;111;32;34;79;98;106;101;116;105;118;111;63;34; + + + 105;110;116;32;100;105;110;104;101;105;114;111;32;61;32;48; + + + 105;110;116;32;115;101;109;97;110;97;115;32;61;32;48; + + + 100;105;110;104;101;105;114;111;32;60;61;32;111;98;106;101;116;105;118;111; + + + 100;105;110;104;101;105;114;111;32;61;32;100;105;110;104;101;105;114;111;32;43;32;53; + + + 115;101;109;97;110;97;115;32;61;32;115;101;109;97;110;97;115;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;83;101;109;97;110;97;115;58;32;34;32;43;32;115;101;109;97;110;97;115; + + +`,dA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;111;110;100;101;63;34; + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;50; + + + 110;117;109;101;114;111;32;60;61;32;110; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;43;32;50; + + + + +`,hA=` + + + 105;110;116;32;110;111;116;97;32;61;32;48; + + + 110;111;116;97;32;60;32;49;32;124;124;32;110;111;116;97;32;62;32;53; + + + 105;110;112;117;116;58;32;110;111;116;97;32;34;78;111;116;97;32;100;101;32;49;32;97;32;53;34; + + + + + 111;117;116;112;117;116;58;32;34;65;32;116;117;97;32;110;111;116;97;58;32;34;32;43;32;110;111;116;97; + + +`,gA=` + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;48; + + + 110;117;109;101;114;111;32;33;61;32;48; + + + 105;110;112;117;116;58;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;40;48;32;116;101;114;109;105;110;97;41;34; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;110;117;109;101;114;111; + + + + + 111;117;116;112;117;116;58;32;115;111;109;97; + + +`,pA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;34; + + + 105;110;116;32;105;32;61;32;110; + 105;32;62;61;32;49; + 105;45;45; + + + 111;117;116;112;117;116;58;32;105; + + + + + 111;117;116;112;117;116;58;32;34;74;225;33;34; + + +`,fA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;81;117;101;32;116;97;98;117;97;100;97;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;49;48; + 105;43;43; + + + 105;110;116;32;112;114;111;100;117;116;111;32;61;32;110;117;109;101;114;111;32;42;32;105; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111;32;43;32;34;32;120;32;34;32;43;32;105;32;43;32;34;32;61;32;34;32;43;32;112;114;111;100;117;116;111; + + + + +`,bA=` + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;53; + 105;43;43; + + + 111;117;116;112;117;116;58;32;105; + + + + +`,xA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;63;34; + + + 110;117;109;101;114;111;32;62;32;48; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;47;32;50; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + + + +`,vA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;63;34; + + + 110;117;109;101;114;111;32;62;32;49; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;47;32;50; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + + + +`,yA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;78;250;109;101;114;111;32;105;110;105;99;105;97;108;63;34; + + + 110;117;109;101;114;111;32;60;32;49;48;48; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;42;32;50; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + + + +`,wA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;105; + + + + + 111;117;116;112;117;116;58;32;115;111;109;97; + + +`,zA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;81;117;97;110;116;97;115;32;108;105;110;104;97;115;63;34; + + + 105;110;116;32;108;105;110;104;97;32;61;32;49; + 108;105;110;104;97;32;60;61;32;110; + 108;105;110;104;97;43;43; + + + 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;34;34; + + + 105;110;116;32;101;115;116;114;101;108;97;32;61;32;49; + 101;115;116;114;101;108;97;32;60;61;32;108;105;110;104;97; + 101;115;116;114;101;108;97;43;43; + + + 116;101;120;116;111;32;61;32;116;101;120;116;111;32;43;32;34;42;34; + + + + + 111;117;116;112;117;116;58;32;116;101;120;116;111; + + + + +`,IA=` + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;53; + 105;43;43; + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;34; + + + 110;117;109;101;114;111;32;37;32;50;32;61;61;32;48; + + + 113;117;97;110;116;105;100;97;100;101;43;43; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;113;117;97;110;116;105;100;97;100;101; + + +`,kA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 105;32;37;32;50;32;61;61;32;48; + + + 113;117;97;110;116;105;100;97;100;101;43;43; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;113;117;97;110;116;105;100;97;100;101; + + +`,SA=` + + + 105;110;112;117;116;58;32;105;110;116;32;116;97;98;117;97;100;97;32;34;81;117;101;32;116;97;98;117;97;100;97;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;49;48; + 105;43;43; + + + 111;117;116;112;117;116;58;32;116;97;98;117;97;100;97;32;42;32;105; + + + + +`,TA=` + + + 105;110;112;117;116;58;32;105;110;116;32;116;97;98;117;97;100;97;32;34;81;117;101;32;116;97;98;117;97;100;97;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;49;48; + 105;43;43; + + + 111;117;116;112;117;116;58;32;116;97;98;117;97;100;97;32;42;32;105; + + + + +`,_A=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 111;117;116;112;117;116;58;32;105;32;42;32;105; + + + + +`,AA=` + + + 105;110;112;117;116;58;32;105;110;116;32;108;97;114;103;117;114;97;32;34;76;97;114;103;117;114;97;34; + + + 105;110;112;117;116;58;32;105;110;116;32;97;108;116;117;114;97;32;34;65;108;116;117;114;97;34; + + + 105;110;116;32;108;105;110;104;97;32;61;32;49; + 108;105;110;104;97;32;60;61;32;97;108;116;117;114;97; + 108;105;110;104;97;43;43; + + + 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;34;34; + + + 105;110;116;32;99;111;108;117;110;97;32;61;32;49; + 99;111;108;117;110;97;32;60;61;32;108;97;114;103;117;114;97; + 99;111;108;117;110;97;43;43; + + + 116;101;120;116;111;32;61;32;116;101;120;116;111;32;43;32;34;35;34; + + + + + 111;117;116;112;117;116;58;32;116;101;120;116;111; + + + + +`,OA=` + + + 105;110;116;91;93;32;110;117;109;101;114;111;115;32;61;32;123;50;44;32;52;44;32;54;44;32;56;44;32;49;48;125; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;117;109;101;114;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111;115;91;105;93; + + + + +`,CA=` + + + 105;110;116;91;93;32;118;97;108;111;114;101;115;32;61;32;123;52;44;32;56;44;32;49;53;44;32;49;54;44;32;50;51;44;32;52;50;125; + + + 111;117;116;112;117;116;58;32;118;97;108;111;114;101;115;91;48;93; + + + 111;117;116;112;117;116;58;32;118;97;108;111;114;101;115;91;118;97;108;111;114;101;115;46;108;101;110;103;116;104;32;45;32;49;93; + + + 111;117;116;112;117;116;58;32;118;97;108;111;114;101;115;46;108;101;110;103;116;104; + + +`,jA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 105;32;37;32;51;32;61;61;32;48; + + + 113;117;97;110;116;105;100;97;100;101;32;61;32;113;117;97;110;116;105;100;97;100;101;32;43;32;49; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;81;117;97;110;116;105;100;97;100;101;58;32;34;32;43;32;113;117;97;110;116;105;100;97;100;101; + + +`,PA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 105;32;37;32;51;32;61;61;32;48; + + + 113;117;97;110;116;105;100;97;100;101;32;61;32;113;117;97;110;116;105;100;97;100;101;32;43;32;49; + + + + + 248; + + + + + 111;117;116;112;117;116;58;32;34;81;117;97;110;116;105;100;97;100;101;58;32;34;32;43;32;113;117;97;110;116;105;100;97;100;101; + + + + +`,DA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;81;117;97;110;116;111;115;32;100;101;103;114;97;117;115;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;34;34; + + + 105;110;116;32;106;32;61;32;49; + 106;32;60;61;32;105; + 106;43;43; + + + 108;105;110;104;97;32;61;32;108;105;110;104;97;32;43;32;34;42;34; + + + + + 111;117;116;112;117;116;58;32;108;105;110;104;97; + + + + +`,BA=` + + + 83;116;114;105;110;103;91;93;32;110;111;109;101;115;32;61;32;110;101;119;32;83;116;114;105;110;103;91;51;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;111;109;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;111;109;101;115;91;105;93;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;111;109;101;34; + + + + + 111;117;116;112;117;116;58;32;34;80;114;105;109;101;105;114;111;32;110;111;109;101;58;32;34;32;43;32;110;111;109;101;115;91;48;93; + + +`,MA=` + + + 105;110;116;91;93;32;110;117;109;101;114;111;115;32;61;32;110;101;119;32;105;110;116;91;52;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;117;109;101;114;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;117;109;101;114;111;115;91;105;93;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;34; + + + + + 105;110;116;32;105;32;61;32;110;117;109;101;114;111;115;46;108;101;110;103;116;104;32;45;32;49; + 105;32;62;61;32;48; + 105;45;45; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111;115;91;105;93; + + + + +`,ZA=` + + + 105;110;116;91;93;32;110;117;109;101;114;111;115;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;117;109;101;114;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;110;117;109;101;114;111;115;91;105;93;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;34; + + + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;109;97;120;32;61;32;110;117;109;101;114;111;115;91;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;117;109;101;114;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;110;117;109;101;114;111;115;91;105;93; + + + 110;117;109;101;114;111;115;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;110;117;109;101;114;111;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; + + + 111;117;116;112;117;116;58;32;34;77;225;120;105;109;111;58;32;34;32;43;32;109;97;120; + + +`,LA=` + + + 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;123;49;50;44;32;55;44;32;49;57;44;32;52;125; + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;109;97;120;32;61;32;112;111;110;116;111;115;91;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;110;116;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;112;111;110;116;111;115;91;105;93; + + + 112;111;110;116;111;115;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;112;111;110;116;111;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; + + + 111;117;116;112;117;116;58;32;34;77;225;120;105;109;111;58;32;34;32;43;32;109;97;120; + + +`,EA=` + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;32;40;48;32;61;32;112;97;114;97;114;41;34; + + + 110;117;109;101;114;111;32;33;61;32;48; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;110;117;109;101;114;111; + + + 105;110;112;117;116;58;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;32;40;48;32;61;32;112;97;114;97;114;41;34; + + + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; + + +`,WA=` + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;32;40;48;32;61;32;112;97;114;97;114;41;34; + + + 110;117;109;101;114;111;32;61;61;32;48; + + + 83;97;105;114;32;100;111;32;99;105;99;108;111; + + + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;110;117;109;101;114;111; + + + + + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; + + +`,NA=` + + + 105;110;112;117;116;58;32;105;110;116;32;99;111;109;112;114;105;109;101;110;116;111;32;34;67;111;109;112;114;105;109;101;110;116;111;63;34; + + + 105;110;112;117;116;58;32;105;110;116;32;108;97;114;103;117;114;97;32;34;76;97;114;103;117;114;97;63;34; + + + 105;110;116;32;102;32;61;32;97;114;101;97;40;99;111;109;112;114;105;109;101;110;116;111;44;32;108;97;114;103;117;114;97;41; + + + 111;117;116;112;117;116;58;32;34;193;114;101;97;58;32;34;32;43;32;102; + + +`,FA=` + + + 109;111;115;116;114;97;114;66;111;97;115;86;105;110;100;97;115;40;41; + + + 102;97;122;101;114;80;101;114;103;117;110;116;97;115;40;41; + + + 109;111;115;116;114;97;114;82;101;115;117;108;116;97;100;111;40;41; + + +`,JA=` + + + 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;97;115;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; + + + 105;110;116;32;109;97;120;32;61;32;116;101;109;112;101;114;97;116;117;114;97;115;91;48;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;101;109;112;101;114;97;116;117;114;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 116;101;109;112;101;114;97;116;117;114;97;115;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;116;101;109;112;101;114;97;116;117;114;97;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;84;101;109;112;101;114;97;116;117;114;97;32;109;97;105;115;32;97;108;116;97;58;32;34;32;43;32;109;97;120; + + +`,RA=` + + + 105;110;116;91;93;32;116;101;109;112;101;114;97;116;117;114;97;115;32;61;32;123;45;53;44;32;45;50;44;32;45;56;44;32;45;51;125; + + + 105;110;116;32;109;97;120;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;101;109;112;101;114;97;116;117;114;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 116;101;109;112;101;114;97;116;117;114;97;115;91;105;93;32;62;32;109;97;120; + + + 109;97;120;32;61;32;116;101;109;112;101;114;97;116;117;114;97;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;84;101;109;112;101;114;97;116;117;114;97;32;109;97;105;115;32;97;108;116;97;58;32;34;32;43;32;109;97;120; + + +`,GA=` + + + 105;110;116;91;93;32;110;111;116;97;115;32;61;32;123;50;44;32;51;44;32;49;44;32;52;125; + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;111;116;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;110;111;116;97;115;91;105;93; + + + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; + + +`,HA=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;81;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;113;32;61;32;113;117;97;100;114;97;100;111;40;110;117;109;101;114;111;41; + + + 111;117;116;112;117;116;58;32;34;79;32;113;117;97;100;114;97;100;111;32;233;32;34;32;43;32;113; + + +`,VA=` + + + 105;110;116;32;114;101;115;117;108;116;97;100;111;32;61;32;120;32;42;32;120; + + + 114;101;116;117;114;110;32;114;101;115;117;108;116;97;100;111; + + +`,qA=` + + + 109;111;115;116;114;97;114;84;105;116;117;108;111;40;41; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;111;109;101;32;34;67;111;109;111;32;116;101;32;99;104;97;109;97;115;63;34; + + + 111;117;116;112;117;116;58;32;34;79;108;225;32;34;32;43;32;110;111;109;101; + + +`,QA=` + + + 111;117;116;112;117;116;58;32;34;66;101;109;45;118;105;110;100;111;32;97;111;32;113;117;105;122;33;34; + + + 111;117;116;112;117;116;58;32;34;86;97;105;115;32;116;101;114;32;116;114;234;115;32;112;101;114;103;117;110;116;97;115;46;34; + + +`,UA=` + + + 109;111;115;116;114;97;114;83;111;109;97;40;51;44;32;52;41; + + + 105;110;116;32;120;32;61;32;49;48; + + + 109;111;115;116;114;97;114;83;111;109;97;40;120;44;32;120;32;43;32;49;41; + + +`,$A=` + + + 105;110;116;32;115;111;109;97;32;61;32;97;32;43;32;98; + + + 111;117;116;112;117;116;58;32;97;32;43;32;34;32;43;32;34;32;43;32;98;32;43;32;34;32;61;32;34;32;43;32;115;111;109;97; + + +`,YA=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;110;105;99;105;111;32;34;86;97;108;111;114;32;105;110;105;99;105;97;108;34; + + + 105;110;116;32;105;32;61;32;105;110;105;99;105;111; + + + 105;32;62;32;48; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;45;32;49; + + + + + 111;117;116;112;117;116;58;32;34;74;225;33;34; + + +`,XA=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;110;105;99;105;111;32;34;86;97;108;111;114;32;105;110;105;99;105;97;108;34; + + + 105;110;116;32;105;32;61;32;105;110;105;99;105;111; + + + 105;32;62;32;48; + + + 111;117;116;112;117;116;58;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;74;225;34; + + +`,KA=` + + + 105;110;116;91;93;91;93;32;112;111;110;116;111;115;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;112;111;110;116;111;115;91;49;93;46;108;101;110;103;116;104; + 106;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;112;111;110;116;111;115;91;49;93;91;106;93; + + + + + 111;117;116;112;117;116;58;32;34;74;111;103;97;100;111;114;32;50;58;32;34;32;43;32;115;111;109;97; + + +`,eO=` + + + 105;110;116;91;93;91;93;32;112;111;110;116;111;115;32;61;32;123;123;51;44;32;53;44;32;50;125;44;32;123;52;44;32;49;44;32;54;125;125; + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;112;111;110;116;111;115;91;49;93;46;108;101;110;103;116;104; + 106;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;112;111;110;116;111;115;91;106;93;91;49;93; + + + + + 111;117;116;112;117;116;58;32;34;74;111;103;97;100;111;114;32;50;58;32;34;32;43;32;115;111;109;97; + + +`,tO=` + + + 105;110;116;91;93;91;93;32;112;111;110;116;111;115;32;61;32;123;123;51;44;32;53;125;44;32;123;52;44;32;49;125;44;32;123;50;44;32;50;125;125; + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;110;116;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;112;111;110;116;111;115;91;105;93;46;108;101;110;103;116;104; + 106;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;112;111;110;116;111;115;91;105;93;91;106;93; + + + + + + + 111;117;116;112;117;116;58;32;34;83;111;109;97;58;32;34;32;43;32;115;111;109;97; + + +`,nO=` + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + + + 105;32;60;61;32;51; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;105; + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;115;111;109;97; + + +`,iO=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;105; + + + + + 111;117;116;112;117;116;58;32;115;111;109;97; + + +`,aO=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;110; + 105;43;43; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;105; + + + + + 111;117;116;112;117;116;58;32;115;111;109;97; + + +`,sO=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;81;117;101;32;116;97;98;117;97;100;97;63;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;51; + 105;43;43; + + + 105;110;116;32;114;101;115;117;108;116;97;100;111;32;61;32;110;117;109;101;114;111;32;42;32;105; + + + 111;117;116;112;117;116;58;32;105;32;43;32;34;32;118;101;122;101;115;32;34;32;43;32;110;117;109;101;114;111;32;43;32;34;32;61;32;34;32;43;32;114;101;115;117;108;116;97;100;111; + + + + + 110;117;109;101;114;111;32;62;32;49;48; + + + 111;117;116;112;117;116;58;32;34;69;115;116;97;32;102;111;105;32;100;105;102;237;99;105;108;33;34; + + + + + 111;117;116;112;117;116;58;32;34;69;115;116;97;32;102;111;105;32;102;225;99;105;108;46;34; + + + + +`,rO=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;32;34;73;110;116;114;111;100;117;122;32;117;109;32;110;250;109;101;114;111;34; + + + 105;110;116;32;102;97;116;111;114;105;97;108;32;61;32;49; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;110; + 105;43;43; + + + 102;97;116;111;114;105;97;108;32;61;32;102;97;116;111;114;105;97;108;32;42;32;105; + + + + + 111;117;116;112;117;116;58;32;102;97;116;111;114;105;97;108; + + +`,oO=` + + + 83;116;114;105;110;103;32;99;97;114;116;97;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;99;97;114;116;97;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;104;97;115;32;61;32;99;97;114;116;97;46;115;112;108;105;116;40;34;92;110;34;41; + + + 111;117;116;112;117;116;58;32;34;76;105;110;104;97;115;58;32;34;32;43;32;108;105;110;104;97;115;46;108;101;110;103;116;104; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;108;105;110;104;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 108;105;110;104;97;115;91;105;93;46;99;111;110;116;97;105;110;115;40;34;114;97;112;111;115;97;34;41; + + + 111;117;116;112;117;116;58;32;34;82;97;112;111;115;97;32;110;97;32;108;105;110;104;97;32;34;32;43;32;40;105;32;43;32;49;41; + + + + + 248; + + + + + + +`,lO=` + + + 83;116;114;105;110;103;32;99;97;114;116;97;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;99;97;114;116;97;46;116;120;116;34;41;41; + + +`,uO=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;111;109;101;32;34;78;111;109;101;32;112;114;243;112;114;105;111;63;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;97;112;101;108;105;100;111;32;34;65;112;101;108;105;100;111;63;34; + + + 111;117;116;112;117;116;58;32;110;111;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;97;112;101;108;105;100;111;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; + + +`,cO=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;111;109;101;32;34;78;111;109;101;32;112;114;243;112;114;105;111;63;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;97;112;101;108;105;100;111;32;34;65;112;101;108;105;100;111;63;34; + + + 111;117;116;112;117;116;58;32;110;111;109;101;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;32;34;32;43;32;97;112;101;108;105;100;111;46;99;104;97;114;65;116;40;49;41;32;43;32;34;46;34; + + +`,mO=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;101;110;116;114;97;100;97;32;34;80;97;108;97;118;114;97;45;112;97;115;115;101;63;34; + + + 101;110;116;114;97;100;97;46;101;113;117;97;108;115;40;34;76;117;100;119;105;103;34;41; + + + 111;117;116;112;117;116;58;32;34;66;101;109;45;118;105;110;100;111;33;34; + + + + + 111;117;116;112;117;116;58;32;34;80;97;108;97;118;114;97;45;112;97;115;115;101;32;101;114;114;97;100;97;34; + + + + +`,dO=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; + + + 105;100;97;100;101;32;60;32;54; + + + 111;117;116;112;117;116;58;32;34;69;110;116;114;97;100;97;32;103;114;97;116;117;105;116;97;34; + + + + + 105;100;97;100;101;32;60;32;49;56; + + + 111;117;116;112;117;116;58;32;34;66;105;108;104;101;116;101;32;100;101;32;99;114;105;97;110;231;97;58;32;52;32;101;117;114;111;115;34; + + + + + 111;117;116;112;117;116;58;32;34;66;105;108;104;101;116;101;32;100;101;32;97;100;117;108;116;111;58;32;56;32;101;117;114;111;115;34; + + + + + + +`,hO=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;117;109;101;114;111;32;34;86;97;108;111;114;32;105;110;105;99;105;97;108;63;34; + + + 110;117;109;101;114;111;32;62;32;48; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111; + + + 110;117;109;101;114;111;32;61;32;110;117;109;101;114;111;32;45;32;51; + + + + + 111;117;116;112;117;116;58;32;34;70;105;109;34; + + +`,gO=` + + + 105;110;116;32;116;101;110;116;97;116;105;118;97;115;32;61;32;48; + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;112;97;108;112;105;116;101;32;34;79;32;116;101;117;32;112;97;108;112;105;116;101;63;34; + + + 116;101;110;116;97;116;105;118;97;115;32;61;32;116;101;110;116;97;116;105;118;97;115;32;43;32;49; + + + 112;97;108;112;105;116;101;32;61;61;32;55; + + + -1; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;84;101;110;116;97;116;105;118;97;115;58;32;34;32;43;32;116;101;110;116;97;116;105;118;97;115; + + +`,pO=` + + + 105;110;116;32;116;101;110;116;97;116;105;118;97;115;32;61;32;48; + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;112;97;108;112;105;116;101;32;34;79;32;116;101;117;32;112;97;108;112;105;116;101;63;34; + + + 112;97;108;112;105;116;101;32;61;61;32;55; + + + -1; + + + + + 248; + + + + + 116;101;110;116;97;116;105;118;97;115;32;61;32;116;101;110;116;97;116;105;118;97;115;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;84;101;110;116;97;116;105;118;97;115;58;32;34;32;43;32;116;101;110;116;97;116;105;118;97;115; + + +`,fO=` + + + 105;110;116;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;97;114;116;105;103;111;115;32;61;32;48; + + + -1; + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;101;99;111;32;34;80;114;101;231;111;63;32;40;48;32;61;32;102;105;109;41;34; + + + 112;114;101;99;111;32;61;61;32;48; + + + -1; + + + + + 248; + + + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;112;114;101;99;111; + + + 97;114;116;105;103;111;115;32;61;32;97;114;116;105;103;111;115;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;65;114;116;105;103;111;115;58;32;34;32;43;32;97;114;116;105;103;111;115; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;115;111;109;97; + + +`,bO=` + + + 105;110;112;117;116;58;32;105;110;116;32;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;97;110;111;115;32;116;101;110;115;63;34; + + + 105;100;97;100;101;32;62;61;32;49;56; + + + 111;117;116;112;117;116;58;32;34;80;111;100;101;115;32;118;111;116;97;114;46;34; + + + + + 105;110;116;32;97;110;111;115;32;61;32;49;56;32;45;32;105;100;97;100;101; + + + 111;117;116;112;117;116;58;32;34;69;115;112;101;114;97;32;109;97;105;115;32;34;32;43;32;97;110;111;115;32;43;32;34;32;97;110;111;115;46;34; + + + + +`,xO=` + + + 105;110;112;117;116;58;32;105;110;116;32;108;105;109;105;116;101;32;34;65;116;233;32;113;117;101;32;110;250;109;101;114;111;63;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;61;32;108;105;109;105;116;101; + 105;32;61;32;105;32;43;32;50; + + + 111;117;116;112;117;116;58;32;105; + + + + +`,vO=` + + + 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;111;99;117;114;97;100;97;32;34;81;117;101;32;99;97;114;116;97;63;34; + + + 105;110;116;32;112;111;115;105;99;97;111;32;61;32;45;49; + + + 105;110;116;32;105;32;61;32;48; + + + 112;111;115;105;99;97;111;32;61;61;32;45;49;32;38;38;32;105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + + + 99;97;114;116;97;115;91;105;93;32;61;61;32;112;114;111;99;117;114;97;100;97; + + + 112;111;115;105;99;97;111;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;80;111;115;105;231;227;111;58;32;34;32;43;32;112;111;115;105;99;97;111; + + +`,yO=` + + + 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;111;99;117;114;97;100;97;32;34;81;117;101;32;99;97;114;116;97;63;34; + + + 105;110;116;32;112;111;115;105;99;97;111;32;61;32;45;49; + + + 105;110;116;32;105;32;61;32;48; + + + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + + + 99;97;114;116;97;115;91;105;93;32;61;61;32;112;114;111;99;117;114;97;100;97; + + + 112;111;115;105;99;97;111;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 111;117;116;112;117;116;58;32;34;80;111;115;105;231;227;111;58;32;34;32;43;32;112;111;115;105;99;97;111; + + +`,wO=` + + + 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;111;99;117;114;97;100;97;32;34;81;117;101;32;99;97;114;116;97;63;34; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 99;97;114;116;97;115;91;105;93;32;61;61;32;112;114;111;99;117;114;97;100;97; + + + 113;117;97;110;116;105;100;97;100;101;32;61;32;113;117;97;110;116;105;100;97;100;101;32;43;32;49; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;81;117;97;110;116;105;100;97;100;101;58;32;34;32;43;32;113;117;97;110;116;105;100;97;100;101; + + +`,zO=` + + + 111;117;116;112;117;116;58;32;34;66;111;109;32;100;105;97;34; + + + 111;117;116;112;117;116;58;32;34;72;111;106;101;32;97;112;114;101;110;100;101;109;111;115;32;101;115;116;114;117;116;111;103;114;97;109;97;115;46;34; + + +`,IO=` + + + 111;117;116;112;117;116;58;32;34;79;108;225;32;77;117;110;100;111;34; + + +`,kO=` + + + 111;117;116;112;117;116;58;32;34;79;108;225;34; + + + 111;117;116;112;117;116;58;32;34;69;115;116;111;117;32;97;32;97;112;114;101;110;100;101;114;32;101;115;116;114;117;116;111;103;114;97;109;97;115;34; + + +`,SO=` + + + 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;99;111;109;112;114;97;115;45;110;111;118;97;46;116;120;116;34;41; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 102;105;99;104;101;105;114;111;46;104;97;115;78;101;120;116;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;102;105;99;104;101;105;114;111;46;110;101;120;116;76;105;110;101;40;41; + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;108;105;110;104;97;41; + + + 113;117;97;110;116;105;100;97;100;101;43;43; + + + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;34;66;111;108;111;34;41; + + + 113;117;97;110;116;105;100;97;100;101;43;43; + + + 102;105;99;104;101;105;114;111;46;99;108;111;115;101;40;41; + + + 115;97;105;100;97;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;113;117;97;110;116;105;100;97;100;101;32;43;32;34;32;108;105;110;104;97;115;32;103;117;97;114;100;97;100;97;115;34; + + +`,TO=` + + + 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;99;111;109;112;114;97;115;45;110;111;118;97;46;116;120;116;34;41; + + +`,_O=` + + + 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;49; + + + 102;105;99;104;101;105;114;111;46;104;97;115;78;101;120;116;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;102;105;99;104;101;105;114;111;46;110;101;120;116;76;105;110;101;40;41; + + + 111;117;116;112;117;116;58;32;110;117;109;101;114;111;32;43;32;34;46;32;34;32;43;32;108;105;110;104;97; + + + 110;117;109;101;114;111;43;43; + + + + + 102;105;99;104;101;105;114;111;46;99;108;111;115;101;40;41; + + +`,AO=` + + + 83;99;97;110;110;101;114;32;102;105;99;104;101;105;114;111;32;61;32;110;101;119;32;83;99;97;110;110;101;114;40;110;101;119;32;70;105;108;101;40;34;99;111;109;112;114;97;115;46;116;120;116;34;41;41; + + +`,OO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;104;97;32;33;61;32;110;117;108;108; + + + 108;105;110;104;97;46;99;111;110;116;97;105;110;115;40;34;82;97;112;111;115;97;34;41; + + + 113;117;97;110;116;105;100;97;100;101;43;43; + + + + + 248; + + + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;105;116;111;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;34;82;97;112;111;115;97;58;32;34;32;43;32;113;117;97;110;116;105;100;97;100;101; + + +`,CO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,jO=` + + + 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;104;97;115;32;61;32;116;101;120;116;111;46;115;112;108;105;116;40;34;92;110;34;41; + + + 83;116;114;105;110;103;32;109;97;105;115;76;111;110;103;97;32;61;32;108;105;110;104;97;115;91;48;93; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;108;105;110;104;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 108;105;110;104;97;115;91;105;93;46;108;101;110;103;116;104;40;41;32;62;32;109;97;105;115;76;111;110;103;97;46;108;101;110;103;116;104;40;41; + + + 109;97;105;115;76;111;110;103;97;32;61;32;108;105;110;104;97;115;91;105;93; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;69;110;116;114;97;100;97;32;109;97;105;115;32;108;111;110;103;97;58;32;34;32;43;32;109;97;105;115;76;111;110;103;97; + + +`,PO=` + + + 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;100;105;97;114;105;111;46;116;120;116;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;104;97;115;32;61;32;116;101;120;116;111;46;115;112;108;105;116;40;34;92;110;34;41; + + +`,DO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;117;114;109;97;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 83;116;114;105;110;103;32;109;101;108;104;111;114;78;111;109;101;32;61;32;34;34; + + + 105;110;116;32;109;101;108;104;111;114;78;111;116;97;32;61;32;55; + + + 108;105;110;104;97;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;101;115;32;61;32;108;105;110;104;97;46;115;112;108;105;116;40;34;59;34;41; + + + 105;110;116;32;110;111;116;97;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;112;97;114;116;101;115;91;51;93;41; + + + 110;111;116;97;32;60;32;109;101;108;104;111;114;78;111;116;97; + + + 109;101;108;104;111;114;78;111;116;97;32;61;32;110;111;116;97; + + + 109;101;108;104;111;114;78;111;109;101;32;61;32;112;97;114;116;101;115;91;48;93; + + + + + 248; + + + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;105;116;111;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;34;77;101;108;104;111;114;32;110;111;116;97;32;97;32;73;110;103;108;234;115;58;32;34;32;43;32;109;101;108;104;111;114;78;111;109;101;32;43;32;34;32;40;34;32;43;32;109;101;108;104;111;114;78;111;116;97;32;43;32;34;41;34; + + +`,BO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;117;114;109;97;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,MO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;117;114;109;97;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 100;111;117;98;108;101;32;115;111;109;97;32;61;32;48; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 108;105;110;104;97;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;101;115;32;61;32;108;105;110;104;97;46;115;112;108;105;116;40;34;59;34;41; + + + 115;111;109;97;32;61;32;115;111;109;97;32;43;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;112;97;114;116;101;115;91;49;93;41; + + + 113;117;97;110;116;105;100;97;100;101;43;43; + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;105;116;111;114;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;34;77;233;100;105;97;32;100;101;32;77;97;116;101;109;225;116;105;99;97;58;32;34;32;43;32;115;111;109;97;32;47;32;113;117;97;110;116;105;100;97;100;101; + + +`,ZO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;116;117;114;109;97;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,LO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;104;97;32;33;61;32;110;117;108;108; + + + 108;105;110;104;97;46;99;111;110;116;97;105;110;115;40;34;92;34;110;111;109;101;92;34;34;41; + + + 105;110;116;32;105;110;105;99;105;111;32;61;32;108;105;110;104;97;46;105;110;100;101;120;79;102;40;34;92;34;110;111;109;101;92;34;58;32;92;34;34;41;32;43;32;57; + + + 105;110;116;32;102;105;109;32;61;32;108;105;110;104;97;46;105;110;100;101;120;79;102;40;34;92;34;34;44;32;105;110;105;99;105;111;41; + + + 111;117;116;112;117;116;58;32;108;105;110;104;97;46;115;117;98;115;116;114;105;110;103;40;105;110;105;99;105;111;44;32;102;105;109;41; + + + + + 248; + + + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;105;116;111;114;46;99;108;111;115;101;40;41; + + +`,EO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;122;111;111;46;106;115;111;110;34;41;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + +`,WO=` + + + 83;116;114;105;110;103;91;93;32;110;111;109;101;115;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;82;97;112;111;115;97;34;125; + + + 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;123;49;50;44;32;49;53;44;32;57;125; + + + 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;112;111;110;116;111;115;46;106;115;111;110;34;41; + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;111;109;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 83;116;114;105;110;103;32;101;110;116;114;97;100;97;32;61;32;34;32;32;123;92;34;110;111;109;101;92;34;58;32;92;34;34;32;43;32;110;111;109;101;115;91;105;93;32;43;32;34;92;34;44;32;92;34;112;111;110;116;111;115;92;34;58;32;34;32;43;32;112;111;110;116;111;115;91;105;93;32;43;32;34;125;34; + + + 105;32;60;32;110;111;109;101;115;46;108;101;110;103;116;104;32;45;32;49; + + + 101;110;116;114;97;100;97;32;61;32;101;110;116;114;97;100;97;32;43;32;34;44;34; + + + + + 248; + + + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;101;110;116;114;97;100;97;41; + + + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;34;93;34;41; + + + 115;97;105;100;97;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;110;111;109;101;115;46;108;101;110;103;116;104;32;43;32;34;32;101;110;116;114;97;100;97;115;32;103;117;97;114;100;97;100;97;115;34; + + +`,NO=` + + + 83;116;114;105;110;103;91;93;32;110;111;109;101;115;32;61;32;123;34;76;117;100;119;105;103;34;44;32;34;90;111;114;97;34;44;32;34;82;97;112;111;115;97;34;125; + + + 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;123;49;50;44;32;49;53;44;32;57;125; + + + 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;112;111;110;116;111;115;46;106;115;111;110;34;41; + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 115;97;105;100;97;46;99;108;111;115;101;40;41; + + +`,FO=` + + + 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;97;110;105;109;97;105;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;104;97;115;32;61;32;116;101;120;116;111;46;115;112;108;105;116;40;34;92;110;34;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;97;110;105;109;97;105;115;45;110;111;118;111;115;46;106;115;111;110;34;41; + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;32;108;105;110;104;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;101;115;32;61;32;108;105;110;104;97;115;91;105;93;46;115;112;108;105;116;40;34;59;34;41; + + + 83;116;114;105;110;103;32;101;110;116;114;97;100;97;32;61;32;34;32;32;123;92;34;110;111;109;101;92;34;58;32;92;34;34;32;43;32;112;97;114;116;101;115;91;48;93;32;43;32;34;92;34;44;32;92;34;101;115;112;101;99;105;101;92;34;58;32;92;34;34;32;43;32;112;97;114;116;101;115;91;49;93;32;43;32;34;92;34;44;32;92;34;105;100;97;100;101;92;34;58;32;34;32;43;32;112;97;114;116;101;115;91;50;93;32;43;32;34;125;34; + + + 105;32;60;32;108;105;110;104;97;115;46;108;101;110;103;116;104;32;45;32;49; + + + 101;110;116;114;97;100;97;32;61;32;101;110;116;114;97;100;97;32;43;32;34;44;34; + + + + + 248; + + + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;101;110;116;114;97;100;97;41; + + + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;34;93;34;41; + + + 115;97;105;100;97;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;40;108;105;110;104;97;115;46;108;101;110;103;116;104;32;45;32;49;41;32;43;32;34;32;97;110;105;109;97;105;115;32;103;117;97;114;100;97;100;111;115;34; + + +`,JO=` + + + 83;116;114;105;110;103;32;116;101;120;116;111;32;61;32;70;105;108;101;115;46;114;101;97;100;83;116;114;105;110;103;40;80;97;116;104;46;111;102;40;34;97;110;105;109;97;105;115;46;99;115;118;34;41;41; + + + 83;116;114;105;110;103;91;93;32;108;105;110;104;97;115;32;61;32;116;101;120;116;111;46;115;112;108;105;116;40;34;92;110;34;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;97;110;105;109;97;105;115;45;110;111;118;111;115;46;106;115;111;110;34;41; + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;34;91;34;41; + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;34;93;34;41; + + + 115;97;105;100;97;46;99;108;111;115;101;40;41; + + +`,RO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;97;110;105;109;97;105;115;46;99;115;118;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;102;114;97;115;101;115;46;116;120;116;34;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 108;105;110;104;97;32;33;61;32;110;117;108;108; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;101;115;32;61;32;108;105;110;104;97;46;115;112;108;105;116;40;34;59;34;41; + + + 115;97;105;100;97;46;112;114;105;110;116;108;110;40;112;97;114;116;101;115;91;48;93;32;43;32;34;32;40;34;32;43;32;112;97;114;116;101;115;91;49;93;32;43;32;34;41;32;116;101;109;32;34;32;43;32;112;97;114;116;101;115;91;50;93;32;43;32;34;32;97;110;111;115;46;34;41; + + + 113;117;97;110;116;105;100;97;100;101;43;43; + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + + + 108;101;105;116;111;114;46;99;108;111;115;101;40;41; + + + 115;97;105;100;97;46;99;108;111;115;101;40;41; + + + 111;117;116;112;117;116;58;32;113;117;97;110;116;105;100;97;100;101;32;43;32;34;32;102;114;97;115;101;115;32;103;117;97;114;100;97;100;97;115;34; + + +`,GO=` + + + 66;117;102;102;101;114;101;100;82;101;97;100;101;114;32;108;101;105;116;111;114;32;61;32;110;101;119;32;66;117;102;102;101;114;101;100;82;101;97;100;101;114;40;110;101;119;32;70;105;108;101;82;101;97;100;101;114;40;34;97;110;105;109;97;105;115;46;99;115;118;34;41;41; + + + 80;114;105;110;116;87;114;105;116;101;114;32;115;97;105;100;97;32;61;32;110;101;119;32;80;114;105;110;116;87;114;105;116;101;114;40;34;102;114;97;115;101;115;46;116;120;116;34;41; + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;105;110;104;97;32;61;32;108;101;105;116;111;114;46;114;101;97;100;76;105;110;101;40;41; + + + 108;101;105;116;111;114;46;99;108;111;115;101;40;41; + + + 115;97;105;100;97;46;99;108;111;115;101;40;41; + + +`,HO=` + + + 105;110;112;117;116;58;32;105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;98;105;108;104;101;116;101;115;63;34; + + + 100;111;117;98;108;101;32;116;111;116;97;108;32;61;32;113;117;97;110;116;105;100;97;100;101;32;42;32;56;46;53; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + +`,VO=` + + + 105;110;112;117;116;58;32;105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;34;81;117;97;110;116;111;115;32;98;105;108;104;101;116;101;115;63;34; + + + 111;117;116;112;117;116;58;32;34;84;111;116;97;108;58;32;34;32;43;32;116;111;116;97;108; + + + 100;111;117;98;108;101;32;116;111;116;97;108;32;61;32;113;117;97;110;116;105;100;97;100;101;32;42;32;56;46;53; + + +`,qO=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;34; + + + 105;110;116;32;97;117;120;32;61;32;97; + + + 97;32;61;32;98; + + + 98;32;61;32;97;117;120; + + + 111;117;116;112;117;116;58;32;97; + + + 111;117;116;112;117;116;58;32;98; + + +`,QO=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;80;114;105;109;101;105;114;111;32;110;250;109;101;114;111;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;83;101;103;117;110;100;111;32;110;250;109;101;114;111;34; + + + 97;32;61;32;98; + + + 98;32;61;32;97; + + + 111;117;116;112;117;116;58;32;97; + + + 111;117;116;112;117;116;58;32;98; + + +`,UO=` + + + 105;110;116;32;97;32;61;32;51; + + + 105;110;116;32;98;32;61;32;53; + + + 105;110;116;32;97;117;120;32;61;32;97; + + + 97;32;61;32;98; + + + 98;32;61;32;97;117;120; + + + 111;117;116;112;117;116;58;32;34;97;32;61;32;34;32;43;32;97; + + + 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; + + +`,$O=` + + + 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;99;97;114;116;97;115;91;105;93;32;34;73;110;116;114;111;100;117;122;32;117;109;97;32;99;97;114;116;97;34; + + + + + 105;110;116;32;114;111;110;100;97;32;61;32;49; + 114;111;110;100;97;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + 114;111;110;100;97;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104;32;45;32;114;111;110;100;97; + 105;43;43; + + + 99;97;114;116;97;115;91;105;93;32;60;32;99;97;114;116;97;115;91;105;32;43;32;49;93; + + + 105;110;116;32;97;117;120;32;61;32;99;97;114;116;97;115;91;105;93; + + + 99;97;114;116;97;115;91;105;93;32;61;32;99;97;114;116;97;115;91;105;32;43;32;49;93; + + + 99;97;114;116;97;115;91;105;32;43;32;49;93;32;61;32;97;117;120; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;99;97;114;116;97;115;91;105;93; + + + + +`,YO=` + + + 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;99;97;114;116;97;115;91;105;93;32;34;73;110;116;114;111;100;117;122;32;117;109;97;32;99;97;114;116;97;34; + + + + + 105;110;116;32;114;111;110;100;97;32;61;32;49; + 114;111;110;100;97;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + 114;111;110;100;97;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104;32;45;32;114;111;110;100;97; + 105;43;43; + + + 99;97;114;116;97;115;91;105;93;32;62;32;99;97;114;116;97;115;91;105;32;43;32;49;93; + + + 105;110;116;32;97;117;120;32;61;32;99;97;114;116;97;115;91;105;93; + + + 99;97;114;116;97;115;91;105;93;32;61;32;99;97;114;116;97;115;91;105;32;43;32;49;93; + + + 99;97;114;116;97;115;91;105;32;43;32;49;93;32;61;32;97;117;120; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;99;97;114;116;97;115;91;105;93; + + + + +`,XO=` + + + 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;111;99;117;114;97;100;97;32;34;81;117;101;32;99;97;114;116;97;32;112;114;111;99;117;114;97;115;63;34; + + + 105;110;116;32;112;111;115;105;99;97;111;32;61;32;45;49; + + + 105;110;116;32;99;111;109;112;97;114;97;99;111;101;115;32;61;32;48; + + + 105;110;116;32;101;115;113;117;101;114;100;97;32;61;32;48; + + + 105;110;116;32;100;105;114;101;105;116;97;32;61;32;99;97;114;116;97;115;46;108;101;110;103;116;104;32;45;32;49; + + + 105;110;116;32;109;101;105;111;32;61;32;48; + + + 112;111;115;105;99;97;111;32;61;61;32;45;49;32;38;38;32;101;115;113;117;101;114;100;97;32;60;61;32;100;105;114;101;105;116;97; + + + 109;101;105;111;32;61;32;40;101;115;113;117;101;114;100;97;32;43;32;100;105;114;101;105;116;97;41;32;47;32;50; + + + 99;111;109;112;97;114;97;99;111;101;115;32;61;32;99;111;109;112;97;114;97;99;111;101;115;32;43;32;49; + + + 99;97;114;116;97;115;91;109;101;105;111;93;32;61;61;32;112;114;111;99;117;114;97;100;97; + + + 112;111;115;105;99;97;111;32;61;32;109;101;105;111; + + + + + 99;97;114;116;97;115;91;109;101;105;111;93;32;60;32;112;114;111;99;117;114;97;100;97; + + + 101;115;113;117;101;114;100;97;32;61;32;109;101;105;111;32;43;32;49; + + + + + 100;105;114;101;105;116;97;32;61;32;109;101;105;111;32;45;32;49; + + + + + + + + + 112;111;115;105;99;97;111;32;62;61;32;48; + + + 111;117;116;112;117;116;58;32;34;69;110;99;111;110;116;114;97;100;97;32;110;97;32;112;111;115;105;231;227;111;32;34;32;43;32;112;111;115;105;99;97;111; + + + + + 111;117;116;112;117;116;58;32;34;78;227;111;32;101;110;99;111;110;116;114;97;100;111;34; + + + + + 111;117;116;112;117;116;58;32;34;67;111;109;112;97;114;97;231;245;101;115;58;32;34;32;43;32;99;111;109;112;97;114;97;99;111;101;115; + + +`,KO=` + + + 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;55;44;32;51;44;32;49;48;44;32;53;44;32;50;125; + + + 105;110;116;32;114;111;110;100;97;32;61;32;49; + 114;111;110;100;97;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + 114;111;110;100;97;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104;32;45;32;114;111;110;100;97; + 105;43;43; + + + 99;97;114;116;97;115;91;105;93;32;62;32;99;97;114;116;97;115;91;105;32;43;32;49;93; + + + 105;110;116;32;97;117;120;32;61;32;99;97;114;116;97;115;91;105;93; + + + 99;97;114;116;97;115;91;105;93;32;61;32;99;97;114;116;97;115;91;105;32;43;32;49;93; + + + 99;97;114;116;97;115;91;105;32;43;32;49;93;32;61;32;97;117;120; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;99;97;114;116;97;115;91;105;93; + + + + +`,eC=` + + + 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;111;99;117;114;97;100;97;32;34;81;117;101;32;99;97;114;116;97;63;34; + + + 105;110;116;32;112;111;115;105;99;97;111;32;61;32;45;49; + + + 105;110;116;32;105;32;61;32;48; + + + 112;111;115;105;99;97;111;32;61;61;32;45;49;32;38;38;32;105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + + + 99;97;114;116;97;115;91;105;93;32;61;61;32;112;114;111;99;117;114;97;100;97; + + + 112;111;115;105;99;97;111;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 112;111;115;105;99;97;111;32;62;61;32;48; + + + 111;117;116;112;117;116;58;32;34;80;111;115;105;231;227;111;58;32;34;32;43;32;112;111;115;105;99;97;111; + + + + + 111;117;116;112;117;116;58;32;34;78;227;111;32;101;110;99;111;110;116;114;97;100;111;34; + + + + +`,tC=` + + + 105;110;116;91;93;32;99;97;114;116;97;115;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; + + + 105;110;112;117;116;58;32;105;110;116;32;112;114;111;99;117;114;97;100;97;32;34;81;117;101;32;99;97;114;116;97;32;112;114;111;99;117;114;97;115;63;34; + + + 105;110;116;32;112;111;115;105;99;97;111;32;61;32;45;49; + + + 105;110;116;32;99;111;109;112;97;114;97;99;111;101;115;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + + + 112;111;115;105;99;97;111;32;61;61;32;45;49;32;38;38;32;105;32;60;32;99;97;114;116;97;115;46;108;101;110;103;116;104; + + + 99;111;109;112;97;114;97;99;111;101;115;32;61;32;99;111;109;112;97;114;97;99;111;101;115;32;43;32;49; + + + 99;97;114;116;97;115;91;105;93;32;61;61;32;112;114;111;99;117;114;97;100;97; + + + 112;111;115;105;99;97;111;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 112;111;115;105;99;97;111;32;62;61;32;48; + + + 111;117;116;112;117;116;58;32;34;69;110;99;111;110;116;114;97;100;97;32;110;97;32;112;111;115;105;231;227;111;32;34;32;43;32;112;111;115;105;99;97;111; + + + + + 111;117;116;112;117;116;58;32;34;78;227;111;32;101;110;99;111;110;116;114;97;100;111;34; + + + + + 111;117;116;112;117;116;58;32;34;67;111;109;112;97;114;97;231;245;101;115;58;32;34;32;43;32;99;111;109;112;97;114;97;99;111;101;115; + + +`,nC=` + + + 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;123;51;44;32;53;44;32;56;125; + + + 98;111;110;117;115;40;112;111;110;116;111;115;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;110;116;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;112;111;110;116;111;115;91;105;93; + + + + +`,iC=` + + + 105;110;116;91;93;32;112;111;110;116;111;115;32;61;32;123;51;44;32;53;44;32;56;125; + + + 98;111;110;117;115;40;112;111;110;116;111;115;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;110;116;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;112;111;110;116;111;115;91;105;93; + + + + +`,aC=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;111;110;116;111;115;46;108;101;110;103;116;104; + 105;43;43; + + + 112;111;110;116;111;115;91;105;93;32;61;32;112;111;110;116;111;115;91;105;93;32;43;32;49; + + + + +`,sC=` + + + 105;110;116;32;110;117;109;101;114;111;32;61;32;53; + + + 100;117;112;108;105;99;97;114;40;110;117;109;101;114;111;41; + + + 111;117;116;112;117;116;58;32;34;78;111;32;112;114;111;103;114;97;109;97;32;112;114;105;110;99;105;112;97;108;58;32;110;117;109;101;114;111;32;61;32;34;32;43;32;110;117;109;101;114;111; + + + 98;111;111;108;101;97;110;91;93;32;102;105;108;97;32;61;32;123;116;114;117;101;44;32;116;114;117;101;44;32;102;97;108;115;101;44;32;116;114;117;101;125; + + + 111;117;116;112;117;116;58;32;34;65;110;116;101;115;58;32;34;32;43;32;102;105;108;97;91;48;93;32;43;32;34;44;32;34;32;43;32;102;105;108;97;91;49;93; + + + 108;105;109;112;97;114;40;102;105;108;97;41; + + + 111;117;116;112;117;116;58;32;34;68;101;112;111;105;115;58;32;34;32;43;32;102;105;108;97;91;48;93;32;43;32;34;44;32;34;32;43;32;102;105;108;97;91;49;93; + + +`,rC=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;108;117;103;97;114;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 108;117;103;97;114;101;115;91;105;93;32;61;32;102;97;108;115;101; + + + + +`,oC=` + + + 120;32;61;32;120;32;42;32;50; + + + 111;117;116;112;117;116;58;32;34;78;111;32;115;117;98;112;114;111;103;114;97;109;97;58;32;120;32;61;32;34;32;43;32;120; + + +`,lC=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;111;109;101;32;34;78;111;109;101;32;112;114;243;112;114;105;111;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;97;112;101;108;105;100;111;32;34;65;112;101;108;105;100;111;34; + + + 111;117;116;112;117;116;58;32;110;111;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;97;112;101;108;105;100;111;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; + + +`,uC=` + + + 83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;61;32;34;80;97;115;115;97;116;101;109;112;111;34; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;105;110;100;101;120;79;102;40;34;97;34;41; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;108;97;115;116;73;110;100;101;120;79;102;40;34;97;34;41; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;105;115;69;109;112;116;121;40;41; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;101;113;117;97;108;115;73;103;110;111;114;101;67;97;115;101;40;34;80;65;83;83;65;84;69;77;80;79;34;41; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;114;101;112;108;97;99;101;40;34;116;101;109;112;111;34;44;32;34;112;111;114;116;101;34;41; + + + 111;117;116;112;117;116;58;32;34;77;233;34;46;114;101;112;101;97;116;40;51;41; + + + 111;117;116;112;117;116;58;32;34;65;110;110;97;34;46;99;111;109;112;97;114;101;84;111;40;34;66;101;110;34;41; + + + 105;110;116;32;105;100;97;100;101;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;34;55;34;41; + + + 111;117;116;112;117;116;58;32;105;100;97;100;101;32;43;32;49; + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;83;116;114;105;110;103;46;118;97;108;117;101;79;102;40;105;100;97;100;101;41;32;43;32;34;32;97;110;111;115;34; + + + 111;117;116;112;117;116;58;32;116;101;120;116; + + +`,cC=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;34;73;110;116;114;111;100;117;122;32;117;109;97;32;112;97;108;97;118;114;97;34; + + + 83;116;114;105;110;103;32;105;110;118;101;114;116;105;100;97;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;112;97;108;97;118;114;97;46;108;101;110;103;116;104;40;41;32;45;32;49; + 105;32;62;61;32;48; + 105;45;45; + + + 105;110;118;101;114;116;105;100;97;32;61;32;105;110;118;101;114;116;105;100;97;32;43;32;112;97;108;97;118;114;97;46;99;104;97;114;65;116;40;105;41; + + + + + 111;117;116;112;117;116;58;32;105;110;118;101;114;116;105;100;97; + + +`,mC=` + + + 83;116;114;105;110;103;32;108;105;110;104;97;32;61;32;34;76;117;100;119;105;103;59;98;111;100;101;59;55;34; + + + 83;116;114;105;110;103;91;93;32;112;97;114;116;101;115;32;61;32;108;105;110;104;97;46;115;112;108;105;116;40;34;59;34;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;97;114;116;101;115;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;105;32;43;32;34;58;32;34;32;43;32;112;97;114;116;101;115;91;105;93; + + + + +`,dC=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;102;114;97;115;101;32;34;73;110;116;114;111;100;117;122;32;117;109;97;32;102;114;97;115;101;34; + + + 83;116;114;105;110;103;91;93;32;112;97;108;97;118;114;97;115;32;61;32;102;114;97;115;101;46;115;112;108;105;116;40;34;32;34;41; + + + 111;117;116;112;117;116;58;32;34;80;97;108;97;118;114;97;115;58;32;34;32;43;32;112;97;108;97;118;114;97;115;46;108;101;110;103;116;104; + + +`,hC=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;34;73;110;116;114;111;100;117;122;32;117;109;97;32;112;97;108;97;118;114;97;34; + + + 105;110;116;32;113;117;97;110;116;105;100;97;100;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;97;108;97;118;114;97;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 112;97;108;97;118;114;97;46;99;104;97;114;65;116;40;105;41;32;61;61;32;39;97;39; + + + 113;117;97;110;116;105;100;97;100;101;32;61;32;113;117;97;110;116;105;100;97;100;101;32;43;32;49; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;78;250;109;101;114;111;32;100;101;32;97;58;32;34;32;43;32;113;117;97;110;116;105;100;97;100;101; + + +`,gC=` + + + 83;116;114;105;110;103;32;112;97;108;97;118;114;97;32;61;32;34;80;97;115;115;97;116;101;109;112;111;34; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;108;101;110;103;116;104;40;41; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;99;104;97;114;65;116;40;48;41; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;115;117;98;115;116;114;105;110;103;40;48;44;32;53;41; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;115;117;98;115;116;114;105;110;103;40;53;41; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;105;110;100;101;120;79;102;40;34;116;101;109;112;111;34;41; + + + 111;117;116;112;117;116;58;32;112;97;108;97;118;114;97;46;116;111;85;112;112;101;114;67;97;115;101;40;41; + + +`,pC=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;110;122;97;104;108;32;34;87;105;101;32;118;105;101;108;101;32;75;97;114;116;101;110;63;34; + + + 100;111;117;98;108;101;32;103;101;115;97;109;116;32;61;32;97;110;122;97;104;108;32;42;32;56;46;53; + + + 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116; + + +`,fC=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;110;122;97;104;108;32;34;87;105;101;32;118;105;101;108;101;32;75;97;114;116;101;110;63;34; + + + 111;117;116;112;117;116;58;32;34;71;101;115;97;109;116;58;32;34;32;43;32;103;101;115;97;109;116; + + + 100;111;117;98;108;101;32;103;101;115;97;109;116;32;61;32;97;110;122;97;104;108;32;42;32;56;46;53; + + +`,bC=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;34; + + + 105;110;116;32;104;105;108;102;32;61;32;97; + + + 97;32;61;32;98; + + + 98;32;61;32;104;105;108;102; + + + 111;117;116;112;117;116;58;32;97; + + + 111;117;116;112;117;116;58;32;98; + + +`,xC=` + + + 105;110;112;117;116;58;32;105;110;116;32;97;32;34;69;114;115;116;101;32;90;97;104;108;34; + + + 105;110;112;117;116;58;32;105;110;116;32;98;32;34;90;119;101;105;116;101;32;90;97;104;108;34; + + + 97;32;61;32;98; + + + 98;32;61;32;97; + + + 111;117;116;112;117;116;58;32;97; + + + 111;117;116;112;117;116;58;32;98; + + +`,vC=` + + + 105;110;116;32;97;32;61;32;51; + + + 105;110;116;32;98;32;61;32;53; + + + 105;110;116;32;104;105;108;102;32;61;32;97; + + + 97;32;61;32;98; + + + 98;32;61;32;104;105;108;102; + + + 111;117;116;112;117;116;58;32;34;97;32;61;32;34;32;43;32;97; + + + 111;117;116;112;117;116;58;32;34;98;32;61;32;34;32;43;32;98; + + +`,yC=` + + + 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;107;97;114;116;101;110;91;105;93;32;34;75;97;114;116;101;32;101;105;110;103;101;98;101;110;34; + + + + + 105;110;116;32;114;117;110;100;101;32;61;32;49; + 114;117;110;100;101;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + 114;117;110;100;101;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104;32;45;32;114;117;110;100;101; + 105;43;43; + + + 107;97;114;116;101;110;91;105;93;32;60;32;107;97;114;116;101;110;91;105;32;43;32;49;93; + + + 105;110;116;32;104;105;108;102;32;61;32;107;97;114;116;101;110;91;105;93; + + + 107;97;114;116;101;110;91;105;93;32;61;32;107;97;114;116;101;110;91;105;32;43;32;49;93; + + + 107;97;114;116;101;110;91;105;32;43;32;49;93;32;61;32;104;105;108;102; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;107;97;114;116;101;110;91;105;93; + + + + +`,wC=` + + + 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;110;101;119;32;105;110;116;91;53;93; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 105;110;112;117;116;58;32;107;97;114;116;101;110;91;105;93;32;34;75;97;114;116;101;32;101;105;110;103;101;98;101;110;34; + + + + + 105;110;116;32;114;117;110;100;101;32;61;32;49; + 114;117;110;100;101;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + 114;117;110;100;101;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104;32;45;32;114;117;110;100;101; + 105;43;43; + + + 107;97;114;116;101;110;91;105;93;32;62;32;107;97;114;116;101;110;91;105;32;43;32;49;93; + + + 105;110;116;32;104;105;108;102;32;61;32;107;97;114;116;101;110;91;105;93; + + + 107;97;114;116;101;110;91;105;93;32;61;32;107;97;114;116;101;110;91;105;32;43;32;49;93; + + + 107;97;114;116;101;110;91;105;32;43;32;49;93;32;61;32;104;105;108;102; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;107;97;114;116;101;110;91;105;93; + + + + +`,zC=` + + + 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; + + + 105;110;112;117;116;58;32;105;110;116;32;103;101;115;117;99;104;116;32;34;87;101;108;99;104;101;32;75;97;114;116;101;32;115;117;99;104;115;116;32;100;117;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;118;101;114;103;108;101;105;99;104;101;32;61;32;48; + + + 105;110;116;32;108;105;110;107;115;32;61;32;48; + + + 105;110;116;32;114;101;99;104;116;115;32;61;32;107;97;114;116;101;110;46;108;101;110;103;116;104;32;45;32;49; + + + 105;110;116;32;109;105;116;116;101;32;61;32;48; + + + 112;111;115;105;116;105;111;110;32;61;61;32;45;49;32;38;38;32;108;105;110;107;115;32;60;61;32;114;101;99;104;116;115; + + + 109;105;116;116;101;32;61;32;40;108;105;110;107;115;32;43;32;114;101;99;104;116;115;41;32;47;32;50; + + + 118;101;114;103;108;101;105;99;104;101;32;61;32;118;101;114;103;108;101;105;99;104;101;32;43;32;49; + + + 107;97;114;116;101;110;91;109;105;116;116;101;93;32;61;61;32;103;101;115;117;99;104;116; + + + 112;111;115;105;116;105;111;110;32;61;32;109;105;116;116;101; + + + + + 107;97;114;116;101;110;91;109;105;116;116;101;93;32;60;32;103;101;115;117;99;104;116; + + + 108;105;110;107;115;32;61;32;109;105;116;116;101;32;43;32;49; + + + + + 114;101;99;104;116;115;32;61;32;109;105;116;116;101;32;45;32;49; + + + + + + + + + 112;111;115;105;116;105;111;110;32;62;61;32;48; + + + 111;117;116;112;117;116;58;32;34;71;101;102;117;110;100;101;110;32;97;110;32;80;111;115;105;116;105;111;110;32;34;32;43;32;112;111;115;105;116;105;111;110; + + + + + 111;117;116;112;117;116;58;32;34;78;105;99;104;116;32;103;101;102;117;110;100;101;110;34; + + + + + 111;117;116;112;117;116;58;32;34;86;101;114;103;108;101;105;99;104;101;58;32;34;32;43;32;118;101;114;103;108;101;105;99;104;101; + + +`,IC=` + + + 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;55;44;32;51;44;32;49;48;44;32;53;44;32;50;125; + + + 105;110;116;32;114;117;110;100;101;32;61;32;49; + 114;117;110;100;101;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + 114;117;110;100;101;43;43; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104;32;45;32;114;117;110;100;101; + 105;43;43; + + + 107;97;114;116;101;110;91;105;93;32;62;32;107;97;114;116;101;110;91;105;32;43;32;49;93; + + + 105;110;116;32;104;105;108;102;32;61;32;107;97;114;116;101;110;91;105;93; + + + 107;97;114;116;101;110;91;105;93;32;61;32;107;97;114;116;101;110;91;105;32;43;32;49;93; + + + 107;97;114;116;101;110;91;105;32;43;32;49;93;32;61;32;104;105;108;102; + + + + + 248; + + + + + + + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;107;97;114;116;101;110;91;105;93; + + + + +`,kC=` + + + 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;56;44;32;52;44;32;49;49;44;32;52;44;32;54;125; + + + 105;110;112;117;116;58;32;105;110;116;32;103;101;115;117;99;104;116;32;34;87;101;108;99;104;101;32;75;97;114;116;101;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;105;32;61;32;48; + + + 112;111;115;105;116;105;111;110;32;61;61;32;45;49;32;38;38;32;105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + + + 107;97;114;116;101;110;91;105;93;32;61;61;32;103;101;115;117;99;104;116; + + + 112;111;115;105;116;105;111;110;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 112;111;115;105;116;105;111;110;32;62;61;32;48; + + + 111;117;116;112;117;116;58;32;34;80;111;115;105;116;105;111;110;58;32;34;32;43;32;112;111;115;105;116;105;111;110; + + + + + 111;117;116;112;117;116;58;32;34;78;105;99;104;116;32;103;101;102;117;110;100;101;110;34; + + + + +`,SC=` + + + 105;110;116;91;93;32;107;97;114;116;101;110;32;61;32;123;50;44;32;51;44;32;53;44;32;55;44;32;56;44;32;49;48;44;32;49;50;44;32;49;51;44;32;49;53;44;32;49;56;44;32;50;48;44;32;50;49;44;32;50;52;44;32;50;55;44;32;51;48;125; + + + 105;110;112;117;116;58;32;105;110;116;32;103;101;115;117;99;104;116;32;34;87;101;108;99;104;101;32;75;97;114;116;101;32;115;117;99;104;115;116;32;100;117;63;34; + + + 105;110;116;32;112;111;115;105;116;105;111;110;32;61;32;45;49; + + + 105;110;116;32;118;101;114;103;108;101;105;99;104;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + + + 112;111;115;105;116;105;111;110;32;61;61;32;45;49;32;38;38;32;105;32;60;32;107;97;114;116;101;110;46;108;101;110;103;116;104; + + + 118;101;114;103;108;101;105;99;104;101;32;61;32;118;101;114;103;108;101;105;99;104;101;32;43;32;49; + + + 107;97;114;116;101;110;91;105;93;32;61;61;32;103;101;115;117;99;104;116; + + + 112;111;115;105;116;105;111;110;32;61;32;105; + + + + + 248; + + + + + 105;32;61;32;105;32;43;32;49; + + + + + 112;111;115;105;116;105;111;110;32;62;61;32;48; + + + 111;117;116;112;117;116;58;32;34;71;101;102;117;110;100;101;110;32;97;110;32;80;111;115;105;116;105;111;110;32;34;32;43;32;112;111;115;105;116;105;111;110; + + + + + 111;117;116;112;117;116;58;32;34;78;105;99;104;116;32;103;101;102;117;110;100;101;110;34; + + + + + 111;117;116;112;117;116;58;32;34;86;101;114;103;108;101;105;99;104;101;58;32;34;32;43;32;118;101;114;103;108;101;105;99;104;101; + + +`,TC=` + + + 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;123;51;44;32;53;44;32;56;125; + + + 98;111;110;117;115;40;112;117;110;107;116;101;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;117;110;107;116;101;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;112;117;110;107;116;101;91;105;93; + + + + +`,_C=` + + + 105;110;116;91;93;32;112;117;110;107;116;101;32;61;32;123;51;44;32;53;44;32;56;125; + + + 98;111;110;117;115;40;112;117;110;107;116;101;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;117;110;107;116;101;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;112;117;110;107;116;101;91;105;93; + + + + +`,AC=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;117;110;107;116;101;46;108;101;110;103;116;104; + 105;43;43; + + + 112;117;110;107;116;101;91;105;93;32;61;32;112;117;110;107;116;101;91;105;93;32;43;32;49; + + + + +`,OC=` + + + 105;110;116;32;122;97;104;108;32;61;32;53; + + + 118;101;114;100;111;112;112;108;101;40;122;97;104;108;41; + + + 111;117;116;112;117;116;58;32;34;73;109;32;72;97;117;112;116;112;114;111;103;114;97;109;109;58;32;122;97;104;108;32;61;32;34;32;43;32;122;97;104;108; + + + 98;111;111;108;101;97;110;91;93;32;114;101;105;104;101;32;61;32;123;116;114;117;101;44;32;116;114;117;101;44;32;102;97;108;115;101;44;32;116;114;117;101;125; + + + 111;117;116;112;117;116;58;32;34;86;111;114;104;101;114;58;32;34;32;43;32;114;101;105;104;101;91;48;93;32;43;32;34;44;32;34;32;43;32;114;101;105;104;101;91;49;93; + + + 108;101;101;114;101;110;40;114;101;105;104;101;41; + + + 111;117;116;112;117;116;58;32;34;78;97;99;104;104;101;114;58;32;34;32;43;32;114;101;105;104;101;91;48;93;32;43;32;34;44;32;34;32;43;32;114;101;105;104;101;91;49;93; + + +`,CC=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;112;108;97;101;116;122;101;46;108;101;110;103;116;104; + 105;43;43; + + + 112;108;97;101;116;122;101;91;105;93;32;61;32;102;97;108;115;101; + + + + +`,jC=` + + + 120;32;61;32;120;32;42;32;50; + + + 111;117;116;112;117;116;58;32;34;73;109;32;85;110;116;101;114;112;114;111;103;114;97;109;109;58;32;120;32;61;32;34;32;43;32;120; + + +`,PC=` + + + 105;110;116;32;97;98;115;116;97;110;100;32;61;32;109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;65;98;115;116;97;110;100;58;32;34;32;43;32;97;98;115;116;97;110;100;32;43;32;34;32;99;109;34;41; + + +`,DC=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;49;48; + + + 109;98;111;116;46;98;97;99;107;119;97;114;100;40;41; + + + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;50;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 248; + + + + + + +`,BC=` + + + 33;109;98;111;116;46;105;115;66;117;116;116;111;110;66;40;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48;32;124;124;32;109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;62;32;54;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;50;48;48;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + +`,MC=` + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;50;48;48;44;32;48;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;50;53;53;44;32;48;41; + + +`,ZC=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;50;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;54;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + + + + +`,LC=` + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;72;97;108;108;111;33;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;73;99;104;32;98;105;110;32;86;105;115;117;66;111;116;34;41; + + +`,EC=` + + + 105;110;116;32;122;97;104;108;32;61;32;48; + 122;97;104;108;32;60;32;56; + 122;97;104;108;43;43; + + + 122;97;104;108;32;37;32;50;32;61;61;32;49; + + + 109;98;111;116;46;108;101;100;40;48;41;46;115;101;116;67;111;108;111;114;40;34;103;114;252;110;34;41; + + + + + 109;98;111;116;46;108;101;100;40;48;41;46;115;101;116;67;111;108;111;114;40;34;97;117;115;34;41; + + + + + 122;97;104;108;32;47;32;50;32;37;32;50;32;61;61;32;49; + + + 109;98;111;116;46;108;101;100;40;49;41;46;115;101;116;67;111;108;111;114;40;34;103;114;252;110;34;41; + + + + + 109;98;111;116;46;108;101;100;40;49;41;46;115;101;116;67;111;108;111;114;40;34;97;117;115;34;41; + + + + + 122;97;104;108;32;47;32;52;32;37;32;50;32;61;61;32;49; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;103;114;252;110;34;41; + + + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;97;117;115;34;41; + + + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + + +`,WC=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;111;116;34;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,NC=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,FC=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,JC=` + + + 83;116;114;105;110;103;32;119;111;114;116;32;61;32;34;86;105;115;117;66;111;116;34; + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;119;111;114;116;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;119;111;114;116;46;115;117;98;115;116;114;105;110;103;40;48;44;32;105;41;41; + + + 109;98;111;116;46;112;97;117;115;101;40;51;48;48;41; + + + + +`,RC=` + + + 109;98;111;116;46;108;101;100;40;48;41;46;115;101;116;67;111;108;111;114;40;34;114;111;116;34;41; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;103;101;108;98;34;41; + + + 109;98;111;116;46;108;101;100;40;52;41;46;115;101;116;67;111;108;111;114;40;34;103;114;252;110;34;41; + + +`,GC=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;50;48;41; + + + + +`,HC=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;98;108;97;117;34;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;52;53; + + + 109;98;111;116;46;98;97;99;107;119;97;114;100;40;41; + + + + + 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;50;53;53;44;32;48;41; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;71;101;112;97;114;107;116;33;34;41; + + +`,VC=` + + + 83;116;114;105;110;103;91;93;32;102;97;114;98;101;110;32;61;32;123;34;114;111;116;34;44;32;34;103;101;108;98;34;44;32;34;103;114;252;110;34;44;32;34;98;108;97;117;34;44;32;34;108;105;108;97;34;125; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;102;97;114;98;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;102;97;114;98;101;110;91;105;93;41; + + + + +`,qC=` + + + 109;98;111;116;46;103;101;116;67;111;108;111;114;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;50;48;41; + + + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;50;48;48;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;49;48;41; + + + + +`,QC=` + + + 109;98;111;116;46;100;114;105;118;101;40;53;48;44;32;53;48;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + + 109;98;111;116;46;115;116;111;112;40;41; + + +`,UC=` + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + +`,$C=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;111;116;34;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;49;50;56;44;32;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;50;48;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + + +`,YC=` + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;65;107;107;117;58;32;34;32;43;32;109;98;111;116;46;103;101;116;66;97;116;116;101;114;121;40;41;32;43;32;34;32;37;34;41; + + + 109;98;111;116;46;103;101;116;66;97;116;116;101;114;121;40;41;32;60;32;50;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; + + + + + 248; + + + + +`,XC=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;98;108;97;117;34;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;103;114;252;110;34;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;50;48;48;41; + + + + + 248; + + + + + + +`,KC=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;48;44;32;50;53;53;41; + + + 109;98;111;116;46;112;97;117;115;101;40;53;48;48;41; + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + 109;98;111;116;46;112;97;117;115;101;40;53;48;48;41; + + + + +`,ej=` + + + 105;110;116;32;105;32;61;32;51; + 105;32;62;61;32;49; + 105;45;45; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;105;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;48;41; + + + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;76;111;115;33;34;41; + + +`,tj=` + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;53; + 105;43;43; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;105;32;42;32;50;48;48;44;32;50;48;48;41; + + + + +`,nj=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;105;115;74;111;121;115;116;105;99;107;85;112;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;105;115;74;111;121;115;116;105;99;107;68;111;119;110;40;41; + + + 109;98;111;116;46;98;97;99;107;119;97;114;100;40;41; + + + + + 248; + + + + + + + + +`,ij=` + + + 109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;62;32;54;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;48;44;32;48;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + +`,aj=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;98;108;97;117;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;97;117;115;34;41; + + + + +`,sj=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;105;115;76;105;110;101;76;101;102;116;40;41;32;38;38;32;109;98;111;116;46;105;115;76;105;110;101;82;105;103;104;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;52;48;44;32;52;48;41; + + + + + 109;98;111;116;46;105;115;76;105;110;101;76;101;102;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;49;48;44;32;52;48;41; + + + + + 109;98;111;116;46;105;115;76;105;110;101;82;105;103;104;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;52;48;44;32;49;48;41; + + + + + 248; + + + + + + + + + + + 109;98;111;116;46;115;116;111;112;40;41; + + +`,rj=` + + + 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;51;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;50;48;48;44;32;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;52;52;48;44;32;51;48;48;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + +`,oj=` + + + 105;110;116;32;115;99;104;114;105;116;116;101;32;61;32;48; + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 115;99;104;114;105;116;116;101;32;61;32;115;99;104;114;105;116;116;101;32;43;32;49; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;115;99;104;114;105;116;116;101; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,lj=` + + + 105;110;116;32;108;97;101;110;103;101;32;61;32;54;48; + + + 105;110;116;32;98;114;101;105;116;101;32;61;32;51;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;50; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;108;97;101;110;103;101;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;98;114;101;105;116;101;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,uj=` + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;34;72;97;108;108;111;32;75;108;97;115;115;101;34; + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;116;101;120;116;32;43;32;34;32;40;34;32;43;32;116;101;120;116;46;108;101;110;103;116;104;40;41;32;43;32;34;41;34;41; + + +`,cj=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;52;52;48;44;32;51;48;48;41; + + +`,mj=` + + + 109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;62;32;45;53;32;38;38;32;109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;60;32;53;32;38;38;32;109;98;111;116;46;103;101;116;82;111;108;108;40;41;32;62;32;45;53;32;38;38;32;109;98;111;116;46;103;101;116;82;111;108;108;40;41;32;60;32;53; + + + 109;98;111;116;46;115;101;116;76;101;100;40;48;44;32;50;53;53;44;32;48;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + +`,dj=` + + + 109;98;111;116;46;103;101;116;76;111;117;100;110;101;115;115;40;41;32;60;32;53;48; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + +`,hj=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;114;111;116;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;97;117;115;34;41; + + + + + 105;110;116;32;105;32;61;32;51; + 105;32;62;32;48; + 105;45;45; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;114;111;116;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + 109;98;111;116;46;108;101;100;40;105;41;46;115;101;116;67;111;108;111;114;40;34;97;117;115;34;41; + + + + +`,gj=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;62;32;49;53; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;49;53; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + + + + 248; + + + + + + + + +`,pj=` + + + 33;109;98;111;116;46;103;101;116;67;111;108;111;114;40;41;46;101;113;117;97;108;115;40;34;114;111;116;34;41; + + + 109;98;111;116;46;105;115;76;105;110;101;76;101;102;116;40;41;32;38;38;32;109;98;111;116;46;105;115;76;105;110;101;82;105;103;104;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;52;48;44;32;52;48;41; + + + + + 109;98;111;116;46;105;115;76;105;110;101;76;101;102;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;49;48;44;32;52;48;41; + + + + + 109;98;111;116;46;105;115;76;105;110;101;82;105;103;104;116;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;52;48;44;32;49;48;41; + + + + + 248; + + + + + + + + + + + 109;98;111;116;46;115;116;111;112;40;41; + + +`,fj=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;49;48;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;81;117;101;114;108;105;110;105;101;33;34;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;53;41; + + + + +`,bj=` + + + 105;110;116;91;93;32;116;111;101;110;101;32;61;32;123;50;54;50;44;32;50;57;52;44;32;51;51;48;44;32;51;52;57;44;32;51;57;50;125; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;111;101;110;101;46;108;101;110;103;116;104; + 105;43;43; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;116;111;101;110;101;91;105;93;44;32;51;48;48;41; + + + + +`,xj=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;119;101;105;223;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;97;117;115;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + + + 109;98;111;116;46;112;97;117;115;101;40;52;48;48;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;119;101;105;223;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;54;48;48;41; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;97;117;115;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + + + 109;98;111;116;46;112;97;117;115;101;40;52;48;48;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;119;101;105;223;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + 109;98;111;116;46;108;101;100;40;50;41;46;115;101;116;67;111;108;111;114;40;34;97;117;115;34;41; + + + 109;98;111;116;46;112;97;117;115;101;40;50;48;48;41; + + + + +`,vj=` + + + 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;51;48; + + + 109;98;111;116;46;115;101;116;76;101;100;40;50;53;53;44;32;50;53;53;44;32;50;53;53;41; + + + + + 109;98;111;116;46;108;101;100;79;102;102;40;41; + + + + +`,yj=` + + + 109;98;111;116;46;103;101;116;66;114;105;103;104;116;110;101;115;115;40;41;32;60;32;50;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + + + + 109;98;111;116;46;115;104;111;119;84;101;120;116;40;34;90;122;122;34;41; + + +`,wj=` + + + 105;110;112;117;116;58;32;105;110;116;32;110;111;116;101; + + + 110;111;116;101; + + + 111;117;116;112;117;116;58;32;34;115;101;104;114;32;103;117;116;34; + + + + + 111;117;116;112;117;116;58;32;34;103;117;116;34; + + + + + 111;117;116;112;117;116;58;32;34;98;101;102;114;105;101;100;105;103;101;110;100;34; + + + + + 111;117;116;112;117;116;58;32;34;97;110;100;101;114;101;32;78;111;116;101;34; + + + + +`,zj=` + + + 105;110;116;32;97;32;61;32;113;117;97;100;114;97;116;122;97;104;108;40;51;41; + + + 105;110;116;32;98;32;61;32;113;117;97;100;114;97;116;122;97;104;108;40;53;41; + + + 111;117;116;112;117;116;58;32;97; + + + 111;117;116;112;117;116;58;32;98; + + +`,Ij=` + + + 114;101;116;117;114;110;32;120;32;42;32;120; + + +`,kj=` + + + 83;116;114;105;110;103;32;119;111;114;116;32;61;32;34;76;117;100;119;105;103;34; + + + 83;116;114;105;110;103;32;114;117;101;99;107;119;97;101;114;116;115;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;119;111;114;116;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 114;117;101;99;107;119;97;101;114;116;115;32;61;32;119;111;114;116;46;99;104;97;114;65;116;40;105;41;32;43;32;114;117;101;99;107;119;97;101;114;116;115; + + + + + 111;117;116;112;117;116;58;32;114;117;101;99;107;119;97;101;114;116;115; + + +`,Sj=` + + + 105;110;116;32;108;97;101;110;103;101;32;61;32;54;48; + + + 105;110;116;32;98;114;101;105;116;101;32;61;32;51;48; + + + 105;110;116;32;115;116;114;101;99;107;101;32;61;32;50;32;42;32;108;97;101;110;103;101;32;43;32;50;32;42;32;98;114;101;105;116;101; + + + 111;117;116;112;117;116;58;32;34;83;116;114;101;99;107;101;58;32;34;32;43;32;115;116;114;101;99;107;101;32;43;32;34;32;99;109;34; + + +`,Tj=` + + + 105;110;116;91;93;32;110;111;116;101;110;32;61;32;123;50;44;32;49;44;32;51;44;32;50;125; + + + 105;110;116;32;115;117;109;109;101;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;110;111;116;101;110;46;108;101;110;103;116;104; + 105;43;43; + + + 115;117;109;109;101;32;61;32;115;117;109;109;101;32;43;32;110;111;116;101;110;91;105;93; + + + + + 111;117;116;112;117;116;58;32;34;83;117;109;109;101;58;32;34;32;43;32;115;117;109;109;101; + + + 111;117;116;112;117;116;58;32;34;65;110;122;97;104;108;58;32;34;32;43;32;110;111;116;101;110;46;108;101;110;103;116;104; + + +`,_j=` + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + +`,Aj=` + + + 113;117;97;100;114;97;116;40;51;48;41; + + + 113;117;97;100;114;97;116;40;53;48;41; + + +`,Oj=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;53; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + +`,Cj=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;52; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;115;101;105;116;101;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,jj=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;52; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;53; + 106;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,Pj=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + +`,Dj=` + + + 109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;62;32;50;48;32;124;124;32;109;98;111;116;46;103;101;116;80;105;116;99;104;40;41;32;60;32;45;50;48; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;56;56;48;44;32;51;48;48;41; + + + + + 248; + + + + +`,Bj=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;50; + 105;43;43; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;54;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;54;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,Mj=` + + + 105;110;116;32;105;32;61;32;49; + 105;32;60;61;32;56; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;105;32;42;32;49;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,Zj=` + + + 33;109;98;111;116;46;105;115;66;117;116;116;111;110;65;40;41; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + +`,Lj=` + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;50;54;50;44;32;51;48;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;50;57;52;44;32;51;48;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;51;51;48;44;32;51;48;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;51;52;57;44;32;51;48;48;41; + + + 109;98;111;116;46;112;108;97;121;84;111;110;101;40;51;57;50;44;32;51;48;48;41; + + +`,Ej=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;51; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;50;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;50;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,Wj=` + + + 105;110;116;32;108;105;110;107;115;32;61;32;57;57; + + + 105;110;116;32;114;101;99;104;116;115;32;61;32;57;57; + + + 108;105;110;107;115;32;62;61;32;50;48;32;124;124;32;114;101;99;104;116;115;32;62;61;32;50;48; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 108;105;110;107;115;32;61;32;109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;49;56;48;41; + + + 114;101;99;104;116;115;32;61;32;109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + + +`,Nj=` + + + 105;110;116;32;115;101;105;116;101;32;61;32;51;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;52; + 105;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;115;101;105;116;101;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,Fj=` + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;52; + 105;43;43; + + + 105;110;116;32;106;32;61;32;48; + 106;32;60;32;52; + 106;43;43; + + + 105;110;116;32;107;32;61;32;48; + 107;32;60;32;53; + 107;43;43; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + +`,Jj=` + + + 109;98;111;116;46;103;101;116;76;105;110;101;40;41;32;61;61;32;48; + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;54;48;41; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + 109;98;111;116;46;116;117;114;110;76;101;102;116;40;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;51;48;41; + + + + + + +`,Rj=` + + + 109;98;111;116;46;103;101;116;68;105;115;116;97;110;99;101;40;41;32;60;32;50;48; + + + 109;98;111;116;46;116;117;114;110;82;105;103;104;116;40;41; + + + + + 109;98;111;116;46;102;111;114;119;97;114;100;40;41; + + + + +`,Gj=` + + + 109;98;111;116;46;114;101;115;101;116;84;105;109;101;114;40;41; + + + 109;98;111;116;46;100;114;105;118;101;40;53;48;44;32;53;48;41; + + + 109;98;111;116;46;103;101;116;84;105;109;101;114;40;41;32;60;32;50; + + + 109;98;111;116;46;112;97;117;115;101;40;49;48;48;41; + + + + + 109;98;111;116;46;115;116;111;112;40;41; + + +`,Hj=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;118;111;114;110;97;109;101;32;34;86;111;114;110;97;109;101;34; + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;110;97;99;104;110;97;109;101;32;34;78;97;99;104;110;97;109;101;34; + + + 111;117;116;112;117;116;58;32;118;111;114;110;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;32;34;32;43;32;110;97;99;104;110;97;109;101;46;99;104;97;114;65;116;40;48;41;32;43;32;34;46;34; + + +`,Vj=` + + + 83;116;114;105;110;103;32;119;111;114;116;32;61;32;34;90;105;101;103;101;110;98;111;99;107;34; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;105;110;100;101;120;79;102;40;34;101;34;41; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;108;97;115;116;73;110;100;101;120;79;102;40;34;101;34;41; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;105;115;69;109;112;116;121;40;41; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;101;113;117;97;108;115;73;103;110;111;114;101;67;97;115;101;40;34;90;73;69;71;69;78;66;79;67;75;34;41; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;114;101;112;108;97;99;101;40;34;98;111;99;107;34;44;32;34;107;228;115;101;34;41; + + + 111;117;116;112;117;116;58;32;34;77;228;104;34;46;114;101;112;101;97;116;40;51;41; + + + 111;117;116;112;117;116;58;32;34;65;110;110;97;34;46;99;111;109;112;97;114;101;84;111;40;34;66;101;110;34;41; + + + 105;110;116;32;97;108;116;101;114;32;61;32;73;110;116;101;103;101;114;46;112;97;114;115;101;73;110;116;40;34;55;34;41; + + + 111;117;116;112;117;116;58;32;97;108;116;101;114;32;43;32;49; + + + 83;116;114;105;110;103;32;116;101;120;116;32;61;32;83;116;114;105;110;103;46;118;97;108;117;101;79;102;40;97;108;116;101;114;41;32;43;32;34;32;74;97;104;114;101;34; + + + 111;117;116;112;117;116;58;32;116;101;120;116; + + +`,qj=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;116;32;34;87;111;114;116;32;101;105;110;103;101;98;101;110;34; + + + 83;116;114;105;110;103;32;114;117;101;99;107;119;97;101;114;116;115;32;61;32;34;34; + + + 105;110;116;32;105;32;61;32;119;111;114;116;46;108;101;110;103;116;104;40;41;32;45;32;49; + 105;32;62;61;32;48; + 105;45;45; + + + 114;117;101;99;107;119;97;101;114;116;115;32;61;32;114;117;101;99;107;119;97;101;114;116;115;32;43;32;119;111;114;116;46;99;104;97;114;65;116;40;105;41; + + + + + 111;117;116;112;117;116;58;32;114;117;101;99;107;119;97;101;114;116;115; + + +`,Qj=` + + + 83;116;114;105;110;103;32;122;101;105;108;101;32;61;32;34;76;117;100;119;105;103;59;71;101;105;223;98;111;99;107;59;55;34; + + + 83;116;114;105;110;103;91;93;32;116;101;105;108;101;32;61;32;122;101;105;108;101;46;115;112;108;105;116;40;34;59;34;41; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;116;101;105;108;101;46;108;101;110;103;116;104; + 105;43;43; + + + 111;117;116;112;117;116;58;32;105;32;43;32;34;58;32;34;32;43;32;116;101;105;108;101;91;105;93; + + + + +`,Uj=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;115;97;116;122;32;34;83;97;116;122;32;101;105;110;103;101;98;101;110;34; + + + 83;116;114;105;110;103;91;93;32;119;111;101;114;116;101;114;32;61;32;115;97;116;122;46;115;112;108;105;116;40;34;32;34;41; + + + 111;117;116;112;117;116;58;32;34;87;246;114;116;101;114;58;32;34;32;43;32;119;111;101;114;116;101;114;46;108;101;110;103;116;104; + + +`,$j=` + + + 105;110;112;117;116;58;32;83;116;114;105;110;103;32;119;111;114;116;32;34;87;111;114;116;32;101;105;110;103;101;98;101;110;34; + + + 105;110;116;32;97;110;122;97;104;108;32;61;32;48; + + + 105;110;116;32;105;32;61;32;48; + 105;32;60;32;119;111;114;116;46;108;101;110;103;116;104;40;41; + 105;43;43; + + + 119;111;114;116;46;99;104;97;114;65;116;40;105;41;32;61;61;32;39;101;39; + + + 97;110;122;97;104;108;32;61;32;97;110;122;97;104;108;32;43;32;49; + + + + + 248; + + + + + + + 111;117;116;112;117;116;58;32;34;65;110;122;97;104;108;32;101;58;32;34;32;43;32;97;110;122;97;104;108; + + +`,Yj=` + + + 83;116;114;105;110;103;32;119;111;114;116;32;61;32;34;71;101;105;223;98;111;99;107;34; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;108;101;110;103;116;104;40;41; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;99;104;97;114;65;116;40;48;41; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;115;117;98;115;116;114;105;110;103;40;48;44;32;52;41; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;115;117;98;115;116;114;105;110;103;40;52;41; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;105;110;100;101;120;79;102;40;34;98;111;99;107;34;41; + + + 111;117;116;112;117;116;58;32;119;111;114;116;46;116;111;85;112;112;101;114;67;97;115;101;40;41; + + +`,Xj=`// Labyrinth mit Ausgängen (nach Kara): jede Wandreihe hat genau eine Lücke, immer weiter rechts. Ein Zeichen = 30 cm. +raster: 3 +.......Z +#####.## +........ +##.##### +>....... +`,Kj=`// Labyrinth mit Ausgängen, drei Reihen. Ein Zeichen = 30 cm. +raster: 3 +........Z +######.## +......... +####.#### +......... +.######## +>........ +`,eP=`// Um die Ecke (Sequenz im Kurs, Lektion 5): ein Zeichen = 30 cm. +raster: 3 +Z.... +###.. +..... +..### +^.... +`,tP=`// Fahre bis Rot: kurzer Weg +..... +..r.. +..... +..... +..^.. +`,nP=`// Fahre bis Rot: erst kommt ein grünes Feld +..... +..r.. +..... +..... +..g.. +..... +..... +..^.. +`,iP=`// Bis Blau, bei Grün piepen +..... +..b.. +..... +..g.. +..... +..^.. +`,aP=`// Bis Blau, ohne grünes Feld +..... +..b.. +..... +..... +..... +..^.. +`,sP=`// Hindernis ausweichen: ein Klotz im Weg, das rote Feld liegt dahinter. +......... +.....r... +.....o... +.....o... +......... +..#...... +......... +......... +......... +..^...... +`,rP=`// Hindernis ausweichen: zwei Klötze im Weg. +......... +.......r. +.......o. +.......o. +......... +....#.... +......... +......... +......... +.#....... +......... +......... +......... +.^....... +`,oP=`// Labyrinth: Gänge 30 cm breit, Wände 10 cm dick. Ziel oben links. +........... +.Z......... +........... +########... +........... +........... +........... +...######## +........... +.........<. +........... +`,lP=`// Labyrinth: Gänge 30 cm breit, Wände 10 cm dick. Ziel oben rechts. +........... +.........Z. +........... +...######## +........... +........... +........... +########... +........... +.>......... +........... +`,uP=`// Linienfolger: Die Linie biegt nach rechts ab und endet vor der Wand. +######### +......... +......... +....o.... +....o.... +......... +......... +......... +......... +......... +......... +......... +..^...... +linie: 2,12 2,8 4,5 4,0.6 +`,cP=`// Linienfolger: Die Linie biegt nach links ab und endet vor der Wand. +######### +......... +......... +....o.... +....o.... +......... +......... +......... +......... +......... +......... +......... +......^.. +linie: 6,12 6,8 4,5 4,0.6 +`,mP=`// Linienfolger mit Stopp: Am Ende der Linie liegt ein rotes Feld. +......... +.....r... +.....o... +.....o... +......... +......... +......... +......... +......... +......... +......... +..^...... +linie: 2,11 2,8 5,4 5,1.5 +`,dP=`// Linienfolger mit Stopp: Die Linie schlängelt sich zum roten Feld. +........... +...r....... +...o....... +...o....... +........... +........... +........... +........... +........... +........... +........... +........... +........... +.......^... +linie: 7,13 7,10 5,8 5,7 3,5 3,1.5 +`,hP=`// Einparken: rechts parken Autos (Klötze), die blaue Markierung zeigt die Lücke. +#....#### +#....#### +#....#### +#..b....# +#.....o.# +#.......# +#....#### +#....#### +#....#### +#....#### +#....#### +#..^.#### +`,gP=`// Einparken: Die Lücke liegt weiter vorn. +#....#### +#..b....# +#.....o.# +#.......# +#....#### +#....#### +#....#### +#....#### +#....#### +#....#### +#....#### +#..^.#### +`,pP=`// Bis zur Linie: der schwarze Rand ist nah +..... +===== +..... +..... +..^.. +..... +`,fP=`// Bis zur Linie: der schwarze Rand ist weiter weg +..... +===== +..... +..... +..... +..... +..... +..^.. +..... +`,bP=`// Slalom: ein Zeichen = 30 cm. Vier Pylonen, abwechselnd oben und unten herum, Ziel am Ende. +raster: 3 +......... +>#.#.#.#Z +......... +`,xP=`// Tunnelsucher (nach Kara): Halt im ersten Feld mit Wand links UND rechts (hellgrün). Ein Zeichen = 30 cm. +raster: 3 +..#..###. +>....o... +....##### +`,vP=`// Tunnelsucher, nach oben. Ein Zeichen = 30 cm. +raster: 3 +.#.#. +.#o#. +...#. +.#... +..... +..^.. +`,yP=`// Kleeblatt im Wald (nach Kara): Bäume liegen auf dem Weg zum Ziel, nie zwei nebeneinander. Ein Zeichen = 30 cm. +raster: 3 +.......... +>..#.#..#Z +.......... +`,wP=`// Kleeblatt im Wald, nach oben. Ein Zeichen = 30 cm. +raster: 3 +.Z. +.#. +... +.#. +... +... +.^. +`,zP=`// Wand vorn? Vor dem mBot2 ist viel Platz. +##### +..... +..... +..... +..... +..... +..... +..^.. +..... +`,IP=`// Bis zur Wand: kurzer Weg +##### +..... +..Z.. +..... +..... +..^.. +`,kP=`// Bis zur Wand: langer Weg +##### +..... +..Z.. +..... +..... +..... +..... +..... +..... +..... +..... +..... +..... +..... +..^.. +`,SP=`// Bis zur Wand: mittlerer Weg +##### +..... +..Z.. +..... +..... +..... +..... +..... +..... +..^.. +`,TP=`// Wand vorn? Die Wand steht direkt vor dem mBot2. +##### +..... +..^.. +..... +`,_P=`// Zwei Sekunden mit halber Kraft: Wo bleibt er stehen? +..... +..... +..... +..o.. +..... +..^.. +`,AP=`// Fahre bis zum Ziel: kurzer Weg, keine Wand +..... +..Z.. +..... +..... +..^.. +..... +`,OP=`// Fahre bis zum Ziel: langer Weg, keine Wand +..... +..Z.. +..... +..... +..... +..... +..... +..... +..... +..... +..^.. +..... +`,CP=""+new URL("aufgabe-mehrwertsteuer-C-TFTrWz.svg",import.meta.url).href,jP=""+new URL("ben-shneiderman-Cev5hrqS.jpg",import.meta.url).href,PP=""+new URL("caesar-ascii-Bix93F5i.svg",import.meta.url).href,DP=""+new URL("caesar-scheibe-CMRPZI6Y.svg",import.meta.url).href,BP=""+new URL("caesar-verschiebung-DIR-lDbs.svg",import.meta.url).href,MP=""+new URL("aufgabe-mehrwertsteuer-CnrZ00ny.svg",import.meta.url).href,ZP=""+new URL("kino-saal-C8zaJk4X.svg",import.meta.url).href,LP=""+new URL("kino-schleifen-D7sfo9iK.svg",import.meta.url).href,EP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDkyIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iNDkyIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiPgogICAgPCEtLSBTdGFydCAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMTAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjgiIHJ4PSIxNCIgZmlsbD0iI2QxZjJkOSIvPgogICAgPGxpbmUgeDE9IjE1MCIgeTE9IjM4IiB4Mj0iMTUwIiB5Mj0iNTQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gQW53ZWlzdW5nIC0tPgogICAgPHJlY3QgeD0iNTAiIHk9IjU2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iODYiIHgyPSIxNTAiIHkyPSI5OCIgbWFya2VyLWVuZD0idXJsKCNhKSIvPgogICAgPCEtLSBSYXV0ZSAxIC0tPgogICAgPHBhdGggZD0iTTE1MCAxMDAgTDIzNSAxMjggTDE1MCAxNTYgTDY1IDEyOCBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMTU2IiB4Mj0iMTUwIiB5Mj0iMTcyIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8cmVjdCB4PSI1MCIgeT0iMTc0IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMjA0IiB4Mj0iMTUwIiB5Mj0iMjUwIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIG5laW4tV2VnIHVtIGRlbiBLYXN0ZW4gaGVydW0gLS0+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIyMzUsMTI4IDI4NSwxMjggMjg1LDIyMiAxNTAsMjIyIiBmaWxsPSJub25lIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIFJhdXRlIDIgLS0+CiAgICA8cGF0aCBkPSJNMTUwIDI1MiBMMjM1IDI4MCBMMTUwIDMwOCBMNjUgMjgwIFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxsaW5lIHgxPSIyMzUiIHkxPSIyODAiIHgyPSIyNjgiIHkyPSIyODAiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjI3MCIgeT0iMjY1IiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8IS0tIHp1csO8Y2sgenVyIFByw7xmdW5nIC0tPgogICAgPHBvbHlsaW5lIHBvaW50cz0iMzI3LDI2NSAzMjcsMjM4IDE1MCwyMzgiIGZpbGw9Im5vbmUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzMDgiIHgyPSIxNTAiIHkyPSIzMjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjUwIiB5PSIzMjgiIHdpZHRoPSIyMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNlNWYwZmYiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzNTgiIHgyPSIxNTAiIHkyPSIzNzQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gRW5kZSAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjI4IiByeD0iMTQiIGZpbGw9IiNkMWYyZDkiLz4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSI+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI5Ij5TdGFydDwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iNzYiPlB1dCBhIGN1cCBvbiB0aGUgdGFibGU8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjEzMyI+U3VnYXIgd2FudGVkPzwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTk0Ij5BZGQgc3VnYXI8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI4NSI+VGVhIHN0aWxsIHRvbyBob3Q/PC90ZXh0PgogICAgPHRleHQgeD0iMzI3LjUiIHk9IjI4NSI+V2FpdCAxIG1pbnV0ZTwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzQ4Ij5EcmluayB0aGUgdGVhPC90ZXh0PgogICAgPHRleHQgeD0iMTUwIiB5PSIzOTUiPkVuZDwvdGV4dD4KICA8L2c+CiAgPGcgZm9udC1zaXplPSIxMiIgZm9udC13ZWlnaHQ9IjYwMCI+CiAgICA8dGV4dCB4PSIxNTYiIHk9IjE2OCIgZmlsbD0iIzI0OGEzZCI+eWVzPC90ZXh0PgogICAgPHRleHQgeD0iMjQyIiB5PSIxMjIiIGZpbGw9IiNkNzAwMTUiPm5vPC90ZXh0PgogICAgPHRleHQgeD0iMjQwIiB5PSIyNzQiIGZpbGw9IiMyNDhhM2QiPnllczwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1NiIgeT0iMzIwIiBmaWxsPSIjZDcwMDE1Ij5ubzwvdGV4dD4KICA8L2c+CiAgPCEtLSBMZWdlbmRlIC0tPgogIDxsaW5lIHgxPSIxMCIgeTE9IjQxOCIgeDI9IjM5MCIgeTI9IjQxOCIgc3Ryb2tlPSIjZDFkMWQ2Ii8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuNSI+CiAgICA8cmVjdCB4PSI0MCIgeT0iNDMwIiB3aWR0aD0iMzYiIGhlaWdodD0iMTgiIHJ4PSI5IiBmaWxsPSIjZDFmMmQ5Ii8+CiAgICA8cmVjdCB4PSIyMjAiIHk9IjQzMCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjE4IiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8cGF0aCBkPSJNNTggNDU4IEw3NiA0NjkgTDU4IDQ4MCBMNDAgNDY5IFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxwYXRoIGQ9Ik0yMjYgNDYwIEwyNTYgNDYwIEwyNTAgNDc4IEwyMjAgNDc4IFoiIGZpbGw9IiNmMmU2ZmYiLz4KICA8L2c+CiAgPGcgZm9udC1zaXplPSIxMiIgZmlsbD0iIzNhM2EzYyI+CiAgICA8dGV4dCB4PSI4NiIgeT0iNDQzIj5TdGFydCBvciBlbmQ8L3RleHQ+CiAgICA8dGV4dCB4PSIyNjYiIHk9IjQ0MyI+U3RhdGVtZW50PC90ZXh0PgogICAgPHRleHQgeD0iODYiIHk9IjQ3MyI+RGVjaXNpb248L3RleHQ+CiAgICA8dGV4dCB4PSIyNjYiIHk9IjQ3MyI+SW5wdXQgb3Igb3V0cHV0PC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",WP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE5MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwIiB5PSIyNCIgZm9udC13ZWlnaHQ9IjYwMCI+V2hlcmUgZG9lcyB0aGUgZWxlbWVudCBsYW5kPzwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iNDAiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkYmVhZmUiLz4KICA8cmVjdCB4PSIyMCIgeT0iNzUiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkY2ZjZTciLz4KICA8bGluZSB4MT0iMjAiIHkxPSI3NSIgeDI9IjIxMCIgeTI9Ijc1IiBzdHJva2U9IiM2ZTZlNzMiIHN0cm9rZS1kYXNoYXJyYXk9IjQgMyIvPgogIDxyZWN0IHg9IjIwIiB5PSI0MCIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjYyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMWQ0ZWQ4Ij50b3AgaGFsZjwvdGV4dD4KICA8dGV4dCB4PSIxMTUiIHk9Ijk3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMTU4MDNkIj5ib3R0b20gaGFsZjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9IjYyIj7ihpIgZ29lcyA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+aW4gZnJvbnQ8L3RzcGFuPjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9Ijk3Ij7ihpIgZ29lcyA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+YWZ0ZXI8L3RzcGFuPjwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iMTMyIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjExNSIgeT0iMTU3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2Ij7DuDwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9IjE1NyI+4oaSIDx0c3BhbiBmb250LXdlaWdodD0iNjAwIj5yZXBsYWNlczwvdHNwYW4+IGl0PC90ZXh0Pgo8L3N2Zz4K",NP=""+new URL("l03-lochkarte-beschriftet-BjBFZjzb.svg",import.meta.url).href,FP=""+new URL("l03-lochkarte-BB3rWQOm.svg",import.meta.url).href,JP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgMjkwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CjxyZWN0IHdpZHRoPSI0NjAiIGhlaWdodD0iMjkwIiBmaWxsPSIjZmZmZmZmIi8+Cjx0ZXh0IHg9IjUwIiB5PSI0NCIgZm9udC1zaXplPSI0MCIgZmlsbD0iIzZlNmU3MyIgdGV4dExlbmd0aD0iMjg4IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmdBbmRHbHlwaHMiPnByaWNlPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPlc8L3RzcGFuPml0aDx0c3BhbiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj5UPC90c3Bhbj5heDwvdGV4dD4KPGxpbmUgeDE9IjE4MiIgeTE9IjU0IiB4Mj0iMTgyIiB5Mj0iODIiIHN0cm9rZT0iIzAwN2FmZiIgc3Ryb2tlLXdpZHRoPSIyLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNCIvPgo8bGluZSB4MT0iMjc4IiB5MT0iNTQiIHgyPSIyNzgiIHkyPSI4MiIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSA0Ii8+CjxwYXRoIGQ9Ik0yMCAyNzIgSDQ0MCIgc3Ryb2tlPSIjZTVkM2IwIiBzdHJva2Utd2lkdGg9IjQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTU2IDE3MiBMMTUwIDIyNiIgc3Ryb2tlPSIjYjg4YTUyIiBzdHJva2Utd2lkdGg9IjEzIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTE1MCAyMjYgTDE1NiAyNjIiIHN0cm9rZT0iI2I4OGE1MiIgc3Ryb2tlLXdpZHRoPSI4IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPGNpcmNsZSBjeD0iMTUwIiBjeT0iMjI2IiByPSI2IiBmaWxsPSIjN2E1NTMwIiBvcGFjaXR5PSIwLjU1Ii8+CjxlbGxpcHNlIGN4PSIxNjEiIGN5PSIyNjciIHJ4PSIxMSIgcnk9IjUiIGZpbGw9IiM3YTU1MzAiLz4KPHBhdGggZD0iTTMyOCAxNzIgTDMzMiAyMjYiIHN0cm9rZT0iI2I4OGE1MiIgc3Ryb2tlLXdpZHRoPSIxMyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0zMzIgMjI2IEwzMjggMjYyIiBzdHJva2U9IiNiODhhNTIiIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxjaXJjbGUgY3g9IjMzMiIgY3k9IjIyNiIgcj0iNiIgZmlsbD0iIzdhNTUzMCIgb3BhY2l0eT0iMC41NSIvPgo8ZWxsaXBzZSBjeD0iMzMzIiBjeT0iMjY3IiByeD0iMTEiIHJ5PSI1IiBmaWxsPSIjN2E1NTMwIi8+CjxwYXRoIGQ9Ik0xMjAgMTQwIEMxMDQgMTUwIDEwNCAxNzYgMTEwIDE5NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjYjg4YTUyIiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8ZWxsaXBzZSBjeD0iMTEwIiBjeT0iMjAwIiByeD0iNSIgcnk9IjkiIGZpbGw9IiM3YTU1MzAiLz4KPHBhdGggZD0iTTEyMCAxNzIgQzEwOCAxNTIgMTE0IDEyOCAxMzQgMTIyIEMxNDggMTIwIDE1NCA4NCAxODIgODQgQzIxMCA4NCAyMDggMTI2IDIzMCAxMjQgQzI1MiAxMjYgMjUwIDg0IDI3OCA4NCBDMzA2IDg0IDMwOCAxMjIgMzE4IDEyOCBDMzQwIDEzMiAzNDggMTU4IDM2NCAxNTggQzM3NiAxNTggMzc4IDEyNCAzODIgMTEwIEMzODYgOTggNDAwIDk2IDQxMiA5OSBDNDI0IDEwMiA0MzAgMTA4IDQyOCAxMTYgQzQyNiAxMjMgNDE0IDEyNCA0MDQgMTIyIEMzOTYgMTIyIDM5NCAxMjggMzk0IDEzNiBDMzk0IDE2MiAzODggMTg0IDM2NiAxODYgQzM1MCAxODggMzQwIDE4MiAzMzAgMTc4IEMyNjAgMTg4IDIwMCAxODggMTQwIDE4MiBDMTMwIDE4MCAxMjQgMTc3IDEyMCAxNzIgWiIgZmlsbD0iI2QyYTU2YSIgc3Ryb2tlPSIjN2E1NTMwIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTM0IDE3MiBMMTI4IDIyNiIgc3Ryb2tlPSIjZDJhNTZhIiBzdHJva2Utd2lkdGg9IjEzIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTEyOCAyMjYgTDEzNCAyNjIiIHN0cm9rZT0iI2QyYTU2YSIgc3Ryb2tlLXdpZHRoPSI4IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPGNpcmNsZSBjeD0iMTI4IiBjeT0iMjI2IiByPSI2IiBmaWxsPSIjN2E1NTMwIiBvcGFjaXR5PSIwLjU1Ii8+CjxlbGxpcHNlIGN4PSIxMzkiIGN5PSIyNjciIHJ4PSIxMSIgcnk9IjUiIGZpbGw9IiM3YTU1MzAiLz4KPHBhdGggZD0iTTMwOCAxNzIgTDMxMiAyMjYiIHN0cm9rZT0iI2QyYTU2YSIgc3Ryb2tlLXdpZHRoPSIxMyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0zMTIgMjI2IEwzMDggMjYyIiBzdHJva2U9IiNkMmE1NmEiIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxjaXJjbGUgY3g9IjMxMiIgY3k9IjIyNiIgcj0iNiIgZmlsbD0iIzdhNTUzMCIgb3BhY2l0eT0iMC41NSIvPgo8ZWxsaXBzZSBjeD0iMzEzIiBjeT0iMjY3IiByeD0iMTEiIHJ5PSI1IiBmaWxsPSIjN2E1NTMwIi8+CjxwYXRoIGQ9Ik0zOTAgMTAzIEwzODYgOTIgTDM5OCAxMDAgWiIgZmlsbD0iI2QyYTU2YSIgc3Ryb2tlPSIjN2E1NTMwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPGNpcmNsZSBjeD0iNDA2IiBjeT0iMTA3IiByPSIzLjIiIGZpbGw9IiMxYzFjMWUiLz4KPHBhdGggZD0iTTQwMSAxMDQgUTQwNiAxMDEgNDExIDEwNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjN2E1NTMwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNNDIyIDEwNyBxNCAxIDUgNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjN2E1NTMwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNNDE2IDExOSBRNDIyIDExOCA0MjcgMTE3IiBmaWxsPSJub25lIiBzdHJva2U9IiM3YTU1MzAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=",RP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjEwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIxMCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjE2Ij5pbnQgYWdlID0gMTQ8L3RleHQ+CiAgPHBhdGggZD0iTTEzMCA3MCBMMTcwIDUwIEwzMDAgNTAgTDI2MCA3MCBaIiBmaWxsPSIjYzk4YTNjIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjE4MCIgeT0iMzQiIHdpZHRoPSI0NCIgaGVpZ2h0PSI1MCIgcng9IjMiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KICA8dGV4dCB4PSIyMDIiIHk9IjYwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjIwIiBmb250LXdlaWdodD0iNzAwIj4xNDwvdGV4dD4KICA8cmVjdCB4PSIxMzAiIHk9IjcwIiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iI2U5Yjg3MiIgc3Ryb2tlPSIjOGE1YTFmIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8cGF0aCBkPSJNMjYwIDcwIEwzMDAgNTAgTDMwMCAxNTAgTDI2MCAxNzAgWiIgZmlsbD0iI2Q0OWE0YyIgc3Ryb2tlPSIjOGE1YTFmIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8cmVjdCB4PSIxNTAiIHk9IjEwMCIgd2lkdGg9IjkwIiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjOGE1YTFmIi8+CiAgPHRleHQgeD0iMTk1IiB5PSIxMjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPmFnZTwvdGV4dD4KICA8cmVjdCB4PSIxMzgiIHk9IjE0MiIgd2lkdGg9IjM0IiBoZWlnaHQ9IjIwIiByeD0iMTAiIGZpbGw9IiMwMDdhZmYiLz4KICA8dGV4dCB4PSIxNTUiIHk9IjE1NiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMiIgZmlsbD0iI2ZmZmZmZiIgZm9udC13ZWlnaHQ9IjYwMCI+aW50PC90ZXh0PgogIDxnIHN0cm9rZT0iIzZlNmU3MyI+CiAgICA8bGluZSB4MT0iMzEwIiB5MT0iNDgiIHgyPSIyMjYiIHkyPSI1MiIvPgogICAgPGxpbmUgeDE9IjMxMCIgeTE9IjExNSIgeDI9IjI0MiIgeTI9IjExNSIvPgogICAgPGxpbmUgeDE9IjgwIiB5MT0iMTUyIiB4Mj0iMTM0IiB5Mj0iMTUyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjMxNiIgeT0iNTIiPlZhbHVlPC90ZXh0PgogIDx0ZXh0IHg9IjMxNiIgeT0iMTE5Ij5OYW1lPC90ZXh0PgogIDx0ZXh0IHg9IjgiIHk9IjE1NiI+RGF0YSB0eXBlPC90ZXh0PgogIDx0ZXh0IHg9IjIwMCIgeT0iMTk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5UaGUgbmFtZSBnZXRzIHlvdSB0byB0aGUgdmFsdWUuPC90ZXh0Pgo8L3N2Zz4K",GP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiPgogICAgPHRleHQgeD0iNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+cG9pbnRzPC90ZXh0PgogICAgPHRleHQgeD0iMTI1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPj08L3RleHQ+CiAgICA8dGV4dCB4PSIyNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9pbnRzICsgNTwvdGV4dD4KICA8L2c+CiAgPHJlY3QgeD0iMTgwIiB5PSI4NiIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjYwIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPuKRoCB3b3JrIG91dCB0aGUgcmlnaHQ6IDEwICsgNSA9IDE1PC90ZXh0PgogIDxwYXRoIGQ9Ik0yNTAgODIgQzIzMCAzMCwgOTAgMzAsIDY0IDg0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgPHRleHQgeD0iMTYwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiI+4pGhIHN0b3JlIHRoZSByZXN1bHQgb24gdGhlIGxlZnQ8L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjE2NCIgd2lkdGg9IjM2MCIgaGVpZ2h0PSIyNiIgcng9IjYiIGZpbGw9IiNmMmYyZjciLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE4MiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9pbnRzIGJlZm9yZTogPHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiPjEwPC90c3Bhbj4gICDihpIgICBwb2ludHMgYWZ0ZXI6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xNTwvdHNwYW4+PC90ZXh0Pgo8L3N2Zz4K",HP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjYwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjYwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiPgogICAgPHBhdGggZD0iTTQwIDExMCBMNDggMTgwIEwxMDIgMTgwIEwxMTAgMTEwIi8+CiAgICA8cGF0aCBkPSJNMTY1IDExMCBMMTczIDE4MCBMMjI3IDE4MCBMMjM1IDExMCIvPgogICAgPHBhdGggZD0iTTI5MCAxMTAgTDI5OCAxODAgTDM1MiAxODAgTDM2MCAxMTAiLz4KICA8L2c+CiAgPHBhdGggZD0iTTQ0IDEzNSBMNDggMTgwIEwxMDIgMTgwIEwxMDYgMTM1IFoiIGZpbGw9IiNmZGJhNzQiLz4KICA8cGF0aCBkPSJNMjk0IDEzNSBMMjk4IDE4MCBMMzUyIDE4MCBMMzU2IDEzNSBaIiBmaWxsPSIjOTNjNWZkIi8+CiAgPHRleHQgeD0iNzUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+bGVmdDwvdGV4dD4KICA8dGV4dCB4PSI3NSIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5qdWljZTwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+dGVtcDwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+ZW1wdHk8L3RleHQ+CiAgPHRleHQgeD0iMzI1IiB5PSIyMDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPnJpZ2h0PC90ZXh0PgogIDx0ZXh0IHg9IjMyNSIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj53YXRlcjwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxwYXRoIGQ9Ik04OCAxMDQgQzExMCA3MCwgMTYwIDcwLCAxODYgMTA0Ii8+CiAgICA8cGF0aCBkPSJNMzE4IDEwNCBDMjcwIDE1LCAxMzAgMTUsIDgyIDEwNCIvPgogICAgPHBhdGggZD0iTTIxNCAxMDQgQzI0MCA3MCwgMjkwIDcwLCAzMTIgMTA0Ii8+CiAgPC9nPgogIDxnIGZvbnQtd2VpZ2h0PSI3MDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPGNpcmNsZSBjeD0iMTM3IiBjeT0iODAiIHI9IjExIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz48dGV4dCB4PSIxMzciIHk9Ijg1Ij4xPC90ZXh0PgogICAgPGNpcmNsZSBjeD0iMjAwIiBjeT0iMzgiIHI9IjExIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz48dGV4dCB4PSIyMDAiIHk9IjQzIj4yPC90ZXh0PgogICAgPGNpcmNsZSBjeD0iMjYzIiBjeT0iODAiIHI9IjExIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz48dGV4dCB4PSIyNjMiIHk9Ijg1Ij4zPC90ZXh0PgogIDwvZz4KICA8ZyB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxMiI+CiAgICA8dGV4dCB4PSI3MCIgeT0iMjQ3Ij4xOiB0ZW1wID0gbGVmdDwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMjQ3Ij4yOiBsZWZ0ID0gcmlnaHQ8L3RleHQ+CiAgICA8dGV4dCB4PSIzMzAiIHk9IjI0NyI+MzogcmlnaHQgPSB0ZW1wPC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",VP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDxyZWN0IHg9IjIwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+PHJlY3QgeD0iMzEwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+CiAgPHJlY3QgeD0iOTAiIHk9IjUwIiB3aWR0aD0iMjIwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZGNmY2U3Ii8+CiAgPGxpbmUgeDE9IjIwIiB5MT0iNzQiIHgyPSIzODAiIHkyPSI3NCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8bGluZSB4MT0iNDYiIHkxPSI2OCIgeDI9IjQ2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iNDYiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4wPC90ZXh0PgogIDxsaW5lIHgxPSI5MCIgeTE9IjY4IiB4Mj0iOTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjE8L3RleHQ+CiAgPGxpbmUgeDE9IjEzNCIgeTE9IjY4IiB4Mj0iMTM0IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTM0IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MjwvdGV4dD4KICA8bGluZSB4MT0iMTc4IiB5MT0iNjgiIHgyPSIxNzgiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIxNzgiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4zPC90ZXh0PgogIDxsaW5lIHgxPSIyMjIiIHkxPSI2OCIgeDI9IjIyMiIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjIyMiIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjQ8L3RleHQ+CiAgPGxpbmUgeDE9IjI2NiIgeTE9IjY4IiB4Mj0iMjY2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjY2IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NTwvdGV4dD4KICA8bGluZSB4MT0iMzEwIiB5MT0iNjgiIHgyPSIzMTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIzMTAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj42PC90ZXh0PgogIDxsaW5lIHgxPSIzNTQiIHkxPSI2OCIgeDI9IjM1NCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjM1NCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjc8L3RleHQ+CiAgPGNpcmNsZSBjeD0iOTAiIGN5PSI3NCIgcj0iNiIgZmlsbD0iIzE1ODAzZCIvPjxjaXJjbGUgY3g9IjMxMCIgY3k9Ijc0IiByPSI2IiBmaWxsPSIjMTU4MDNkIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dmFsaWQ8L3RleHQ+CiAgPHRleHQgeD0iNDAiIHk9IjQwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5pbnZhbGlkPC90ZXh0Pjx0ZXh0IHg9IjM2MCIgeT0iNDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPmludmFsaWQ8L3RleHQ+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPHRleHQgeD0iMjAwIiB5PSIxMjQiIGZpbGw9IiMxNTgwM2QiPmdyYWRlICZndDs9IDEgJmFtcDsmYW1wOyBncmFkZSAmbHQ7PSA2PC90ZXh0PgogICAgPHRleHQgeD0iMjAwIiB5PSIxNDIiIGZpbGw9IiNiOTFjMWMiPmdyYWRlICZsdDsgMSB8fCBncmFkZSAmZ3Q7IDY8L3RleHQ+CiAgPC9nPgo8L3N2Zz4K",qP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIj5Ib3cgdGhlIHdoaWxlIGxvb3AgcnVuczwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjQ0IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjQwIiByeD0iMjAiIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI2OSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIGNoZWNrIHRoZSBjb25kaXRpb248L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSIxMjgiIHdpZHRoPSIxNjAiIGhlaWdodD0iNDAiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTUzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgcnVuIHRoZSBpbnNpZGU8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iODQiIHgyPSIyMDAiIHkyPSIxMjYiLz4KICAgIDxwYXRoIGQ9Ik0xMjAgMTQ4IEM4MCAxNDgsIDgwIDY0LCAxMTggNjQiLz4KICAgIDxwYXRoIGQ9Ik0yODAgNjQgTDM0MCA2NCBMMzQwIDIwMCBMMjgyIDIwMCIvPgogIDwvZz4KICA8dGV4dCB4PSIyMDgiIHk9IjExMCIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dHJ1ZTwvdGV4dD4KICA8dGV4dCB4PSIzOCIgeT0iMTEwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5iYWNrPC90ZXh0PgogIDx0ZXh0IHg9IjM4IiB5PSIxMjYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPnRvIHRoZSB0b3A8L3RleHQ+CiAgPHRleHQgeD0iMzQ4IiB5PSIxMzQiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPmZhbHNlPC90ZXh0PgogIDx0ZXh0IHg9IjI3NiIgeT0iMjA1IiB0ZXh0LWFuY2hvcj0iZW5kIj5jb250aW51ZSBiZWxvdyB0aGUgbG9vcDwvdGV4dD4KPC9zdmc+Cg==",QP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+cHJlLXRlc3QgKHdoaWxlKTwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9IjIyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iNjAwIj5wb3N0LXRlc3QgKGRvLXdoaWxlKTwvdGV4dD4KICA8bGluZSB4MT0iMjAwIiB5MT0iMTAiIHgyPSIyMDAiIHkyPSIyMjAiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxyZWN0IHg9IjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iNjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCBjb25kaXRpb248L3RleHQ+CiAgPHJlY3QgeD0iMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIxNDciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoSBpbnNpZGU8L3RleHQ+CiAgPHJlY3QgeD0iMjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIGluc2lkZTwvdGV4dD4KICA8cmVjdCB4PSIyMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjMwMCIgeT0iMTQ3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgY29uZGl0aW9uPC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiPgogICAgPGxpbmUgeDE9IjEwMCIgeTE9IjgwIiB4Mj0iMTAwIiB5Mj0iMTIyIi8+CiAgICA8cGF0aCBkPSJNMzUgMTQyIEM4IDE0MiwgOCA2MiwgMzMgNjIiLz4KICAgIDxsaW5lIHgxPSIzMDAiIHkxPSI4MCIgeDI9IjMwMCIgeTI9IjEyMiIvPgogICAgPHBhdGggZD0iTTM2NSAxNDIgQzM5MiAxNDIsIDM5MiA2MiwgMzY3IDYyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjEwNiIgeT0iMTA2IiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTA2IiB0ZXh0LWFuY2hvcj0iZW5kIiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5JZiB0aGUgY29uZGl0aW9uIGlzIGZhbHNlIGF0IG9uY2UsPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj50aGUgaW5zaWRlIHJ1bnMgPHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPm5ldmVyPC90c3Bhbj4uPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5UaGUgaW5zaWRlIGFsd2F5cyBydW5zPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj48dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+YXQgbGVhc3Qgb25jZTwvdHNwYW4+LjwvdGV4dD4KPC9zdmc+Cg==",UP="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjUwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHJlY3QgeD0iMTIwIiB5PSIxNCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIFN0YXJ0IDx0c3BhbiBmaWxsPSIjNmU2ZTczIj4ob25seSBvbmNlKTwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iNzYiIHdpZHRoPSIxNjAiIGhlaWdodD0iMzQiIHJ4PSIxNyIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjYjQ1MzA5IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgY2hlY2sgdGhlIGNvbmRpdGlvbjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjEzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIxNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoiBydW4gdGhlIGluc2lkZTwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjIwMCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIyMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoyBzdGVwLCBlLmcuIGkrKzwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjIwMCIgeTI9Ijc0Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTEwIiB4Mj0iMjAwIiB5Mj0iMTM2Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTcyIiB4Mj0iMjAwIiB5Mj0iMTk4Ii8+CiAgICA8cGF0aCBkPSJNMTIwIDIxNyBDNjAgMjE3LCA2MCA5MywgMTE4IDkzIi8+CiAgICA8cGF0aCBkPSJNMjgwIDkzIEwzMzAgOTMiLz4KICA8L2c+CiAgPHRleHQgeD0iMjA4IiB5PSIxMjkiIGZpbGw9IiMxNTgwM2QiIGZvbnQtd2VpZ2h0PSI2MDAiPnRydWU8L3RleHQ+CiAgPHRleHQgeD0iNDgiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+YmFjazwvdGV4dD4KICA8dGV4dCB4PSI0OCIgeT0iMTc2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj50byDikaE8L3RleHQ+CiAgPHRleHQgeD0iMzAwIiB5PSI4NCIgZmlsbD0iI2I5MWMxYyIgZm9udC13ZWlnaHQ9IjYwMCI+ZmFsc2U8L3RleHQ+CiAgPHRleHQgeD0iMzM2IiB5PSI5OCI+ZG9uZTwvdGV4dD4KPC9zdmc+Cg==",$P="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMTkwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCI+aW50W10gbnVtYmVycyA9IHsyLCA0LCA2LCA4LCAxMH08L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjU0IiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj5JbmRleDwvdGV4dD4KICA8dGV4dCB4PSI5MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjA8L3RleHQ+PHJlY3QgeD0iNjAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iOTAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj4yPC90ZXh0PgogIDx0ZXh0IHg9IjE1MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjE8L3RleHQ+PHJlY3QgeD0iMTIwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjE1MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjQ8L3RleHQ+CiAgPHRleHQgeD0iMjEwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MjwvdGV4dD48cmVjdCB4PSIxODAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjEwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+NjwvdGV4dD4KICA8dGV4dCB4PSIyNzAiIHk9IjU0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj4zPC90ZXh0PjxyZWN0IHg9IjI0MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyNzAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj44PC90ZXh0PgogIDx0ZXh0IHg9IjMzMCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjQ8L3RleHQ+PHJlY3QgeD0iMzAwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjMzMCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjEwPC90ZXh0PgogIDx0ZXh0IHg9IjIwIiB5PSI5MCIgZmlsbD0iIzZlNmU3MyIgZm9udC1zaXplPSIxMiI+VmFsdWU8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+PGxpbmUgeDE9IjkwIiB5MT0iMTQwIiB4Mj0iOTAiIHkyPSIxMTIiLz48bGluZSB4MT0iMzMwIiB5MT0iMTQwIiB4Mj0iMzMwIiB5Mj0iMTEyIi8+PC9nPgogIDxnIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjEzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dGV4dCB4PSI5MCIgeT0iMTU2Ij5udW1iZXJzWzBdIGlzIDI8L3RleHQ+PHRleHQgeD0iMzMwIiB5PSIxNTYiPm51bWJlcnNbNF0gaXMgMTA8L3RleHQ+PC9nPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTgyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj41IHNsb3RzLCBjb3VudGluZyBzdGFydHMgYXQgMDogdGhlIGxhc3QgaW5kZXggaXMgNC48L3RleHQ+Cjwvc3ZnPgo=",YP=""+new URL("mvc-klick-BIA_bYzu.svg",import.meta.url).href,XP=""+new URL("ss-binaere-suche-D02W1TH_.svg",import.meta.url).href,KP=""+new URL("ss-bubblesort-CmKEoNfO.svg",import.meta.url).href,eD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDQgMTk2IiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KPHJlY3Qgd2lkdGg9IjQwNCIgaGVpZ2h0PSIxOTYiIGZpbGw9IiNmZmZmZmYiLz4KPHRleHQgeD0iMTQiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIiBmb250LXNpemU9IjE1Ij5Mb29raW5nIGZvciB0aGUgOS4gVGhlIGNhcmRzIGFyZSBtaXhlZCB1cC48L3RleHQ+CjxnPjxyZWN0IHg9IjE0IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48dGV4dCB4PSIzNC4wIiB5PSI3NS4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZGMyNjI2Ij43PC90ZXh0Pjx0ZXh0IHg9IjM0LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjZGMyNjI2Ij7imaU8L3RleHQ+PC9nPgo8dGV4dCB4PSIzNC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMzQuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj4xLjwvdGV4dD4KPGc+PHJlY3QgeD0iNjIiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjgyLjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjM8L3RleHQ+PHRleHQgeD0iODIuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiMxYzFjMWUiPuKZoDwvdGV4dD48L2c+Cjx0ZXh0IHg9IjgyLjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSI4Mi4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjIuPC90ZXh0Pgo8Zz48cmVjdCB4PSIxMTAiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjEzMC4wIiB5PSI3NS4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZGMyNjI2Ij4xMDwvdGV4dD48dGV4dCB4PSIxMzAuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNkYzI2MjYiPuKZpjwvdGV4dD48L2c+Cjx0ZXh0IHg9IjEzMC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMTMwLjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+My48L3RleHQ+CjxnPjxyZWN0IHg9IjE1OCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iMTc4LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjU8L3RleHQ+PHRleHQgeD0iMTc4LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxYzFlIj7imaM8L3RleHQ+PC9nPgo8dGV4dCB4PSIxNzguMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZGMyNjI2Ij7inJc8L3RleHQ+Cjx0ZXh0IHg9IjE3OC4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjQuPC90ZXh0Pgo8Zz48cmVjdCB4PSIyMDYiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiMxNTgwM2QiIHN0cm9rZS13aWR0aD0iMyIvPjx0ZXh0IHg9IjIyNi4wIiB5PSI3NS4yIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjMWMxYzFlIj45PC90ZXh0Pjx0ZXh0IHg9IjIyNi4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+4pmgPC90ZXh0PjwvZz4KPHRleHQgeD0iMjI2LjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iIzE1ODAzZCI+4pyTPC90ZXh0Pgo8dGV4dCB4PSIyMjYuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj41LjwvdGV4dD4KPGc+PHJlY3QgeD0iMjU0IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iIzFkNGVkOCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSIyNTgiIHk9IjU0IiB3aWR0aD0iMzIiIGhlaWdodD0iNDgiIHJ4PSIzIiBmaWxsPSJub25lIiBzdHJva2U9IiM5M2M1ZmQiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtZGFzaGFycmF5PSIzIDIiLz48L2c+CjxnPjxyZWN0IHg9IjMwMiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiMxZDRlZDgiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHJlY3QgeD0iMzA2IiB5PSI1NCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjQ4IiByeD0iMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTNjNWZkIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWRhc2hhcnJheT0iMyAyIi8+PC9nPgo8Zz48cmVjdCB4PSIzNTAiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjMWQ0ZWQ4IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjxyZWN0IHg9IjM1NCIgeT0iNTQiIHdpZHRoPSIzMiIgaGVpZ2h0PSI0OCIgcng9IjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzkzYzVmZCIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMiIvPjwvZz4KPHRleHQgeD0iMTQiIHk9IjE2OCIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzZlNmU3MyI+VHVybiB0aGVtIG92ZXIgZnJvbSBsZWZ0IHRvIHJpZ2h0OjwvdGV4dD48dGV4dCB4PSIxNCIgeT0iMTg4IiBmb250LXNpemU9IjE1IiBmaWxsPSIjNmU2ZTczIj5BZnRlciA1IGNvbXBhcmlzb25zIHRoZSA5IGlzIGZvdW5kLjwvdGV4dD4KPC9zdmc+Cg==",tD=""+new URL("ss-vergleiche-UczNldcC.svg",import.meta.url).href,nD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjAgNDUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KPGRlZnM+PG1hcmtlciBpZD0iayIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDEwIDUgTDAgMTAgWiIgZmlsbD0iIzFjMWMxZSIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImIiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjYiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNMCAwIEwxMCA1IEwwIDEwIFoiIGZpbGw9IiMxZDRlZDgiLz48L21hcmtlcj48bWFya2VyIGlkPSJvIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjYjQ1MzA5Ii8+PC9tYXJrZXI+PC9kZWZzPgo8cmVjdCB3aWR0aD0iNDIwIiBoZWlnaHQ9IjQ1MCIgZmlsbD0iI2ZmZmZmZiIvPgo8dGV4dCB4PSIxMCIgeT0iMjIiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI3MDAiPkNhbGwgYnkgdmFsdWU6IGEgY29weTwvdGV4dD4KPHJlY3QgeD0iMTAiIHk9IjM4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9Ijg2IiByeD0iOCIgZmlsbD0iI2VmZjZmZiIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8dGV4dCB4PSIyMCIgeT0iNTgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPk1haW4gcHJvZ3JhbTwvdGV4dD4KPHRleHQgeD0iMTYiIHk9Ijk4IiBmb250LXNpemU9IjEyIj5udW1iZXI8L3RleHQ+CjxyZWN0IHg9IjcwIiB5PSI3OCIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9Ijk4IiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+NTwvdGV4dD4KPHJlY3QgeD0iMjUwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNmZmY3ZWQiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjYwIiB5PSI1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+ZG91YmxlSXQ8L3RleHQ+Cjx0ZXh0IHg9IjI2MCIgeT0iOTgiPng8L3RleHQ+CjxyZWN0IHg9IjI4MCIgeT0iNzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMCIgcng9IjQiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8dGV4dCB4PSIzMjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dHNwYW4gZmlsbD0iIzZlNmU3MyIgdGV4dC1kZWNvcmF0aW9uPSJsaW5lLXRocm91Z2giPjU8L3RzcGFuPiA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCI+MTA8L3RzcGFuPjwvdGV4dD4KPGxpbmUgeDE9IjEyOCIgeTE9IjkzIiB4Mj0iMjQ4IiB5Mj0iOTMiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNCIgbWFya2VyLWVuZD0idXJsKCNrKSIvPgo8dGV4dCB4PSIyMTAiIHk9Ijg0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5jb3B5PC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iMTUwIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj54IGJlY29tZXMgMTAsIGJ1dCBudW1iZXIgc3RheXMgNS48L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxNjgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPkxpa2UgYSBwaG90b2NvcHk6IHdyaXRpbmcgb24gdGhlIGNvcHk8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxODYiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPmRvZXMgbm90IGNoYW5nZSB0aGUgb3JpZ2luYWwuPC90ZXh0Pgo8bGluZSB4MT0iMTAiIHkxPSIyMDgiIHgyPSI0MTAiIHkyPSIyMDgiIHN0cm9rZT0iI2QxZDFkNiIvPgo8dGV4dCB4PSIxMCIgeT0iMjM2IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNzAwIj5DYWxsIGJ5IHJlZmVyZW5jZTogdGhlIHNhbWUgYXJyYXk8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZWZmNmZmIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjIwIiB5PSIyNzIiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPk1haW4gcHJvZ3JhbTwvdGV4dD4KPHRleHQgeD0iMjAiIHk9IjMwMCI+cm93PC90ZXh0Pgo8Y2lyY2xlIGN4PSIxNTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiMxZDRlZDgiLz4KPHJlY3QgeD0iMjUwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZmZmN2VkIiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjI2MCIgeT0iMjcyIiBmb250LXNpemU9IjEzIiBmaWxsPSIjYjQ1MzA5Ij5jbGVhcjwvdGV4dD4KPHRleHQgeD0iMjYwIiB5PSIzMDAiPnNlYXRzPC90ZXh0Pgo8Y2lyY2xlIGN4PSIzOTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiNiNDUzMDkiLz4KPHBhdGggZD0iTTE1MCAzMDAgTDE1MCAzNDAgTDE0MCAzNTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYikiLz4KPHBhdGggZD0iTTM5MCAzMDAgTDM5MCAzNDAgTDMyMiAzNTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjbykiLz4KPHJlY3QgeD0iOTAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHJlY3QgeD0iMTUwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+CjxyZWN0IHg9IjIxMCIgeT0iMzU4IiB3aWR0aD0iNjAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8cmVjdCB4PSIyNzAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHRleHQgeD0iMTIwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxODAiIHk9IjM3OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+ZmFsc2U8L3RleHQ+Cjx0ZXh0IHg9IjI0MCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMzAwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iNDE2IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj5UaGVyZSBpcyBvbmx5IG9uZSBhcnJheS4gV2hhdCBjbGVhciBjaGFuZ2VzIHRocm91Z2ggc2VhdHMsPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iNDM0IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj50aGUgbWFpbiBwcm9ncmFtIHNlZXMgdW5kZXIgcm93LjwvdGV4dD4KPC9zdmc+Cg==",iD=""+new URL("zk-zeichen-CgUEhNoK.svg",import.meta.url).href,aD=""+new URL("ike-nassi-D2w47gvX.jpg",import.meta.url).href,sD=""+new URL("kino-saal-CYMOok4_.svg",import.meta.url).href,rD=""+new URL("kino-schleifen-DrTQV7dq.svg",import.meta.url).href,oD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDkyIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iNDkyIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiPgogICAgPCEtLSBTdGFydCAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMTAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjgiIHJ4PSIxNCIgZmlsbD0iI2QxZjJkOSIvPgogICAgPGxpbmUgeDE9IjE1MCIgeTE9IjM4IiB4Mj0iMTUwIiB5Mj0iNTQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gQW53ZWlzdW5nIC0tPgogICAgPHJlY3QgeD0iNTAiIHk9IjU2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iODYiIHgyPSIxNTAiIHkyPSI5OCIgbWFya2VyLWVuZD0idXJsKCNhKSIvPgogICAgPCEtLSBSYXV0ZSAxIC0tPgogICAgPHBhdGggZD0iTTE1MCAxMDAgTDIzNSAxMjggTDE1MCAxNTYgTDY1IDEyOCBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMTU2IiB4Mj0iMTUwIiB5Mj0iMTcyIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8cmVjdCB4PSI1MCIgeT0iMTc0IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMjA0IiB4Mj0iMTUwIiB5Mj0iMjUwIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIG5laW4tV2VnIHVtIGRlbiBLYXN0ZW4gaGVydW0gLS0+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIyMzUsMTI4IDI4NSwxMjggMjg1LDIyMiAxNTAsMjIyIiBmaWxsPSJub25lIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIFJhdXRlIDIgLS0+CiAgICA8cGF0aCBkPSJNMTUwIDI1MiBMMjM1IDI4MCBMMTUwIDMwOCBMNjUgMjgwIFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxsaW5lIHgxPSIyMzUiIHkxPSIyODAiIHgyPSIyNjgiIHkyPSIyODAiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjI3MCIgeT0iMjY1IiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8IS0tIHp1csO8Y2sgenVyIFByw7xmdW5nIC0tPgogICAgPHBvbHlsaW5lIHBvaW50cz0iMzI3LDI2NSAzMjcsMjM4IDE1MCwyMzgiIGZpbGw9Im5vbmUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzMDgiIHgyPSIxNTAiIHkyPSIzMjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjUwIiB5PSIzMjgiIHdpZHRoPSIyMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNlNWYwZmYiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzNTgiIHgyPSIxNTAiIHkyPSIzNzQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gRW5kZSAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjI4IiByeD0iMTQiIGZpbGw9IiNkMWYyZDkiLz4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSI+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI5Ij5TdGFydDwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iNzYiPlRhc3NlIGF1ZiBkZW4gVGlzY2ggc3RlbGxlbjwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTMzIj5adWNrZXIgZ2V3w7xuc2NodD88L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjE5NCI+WnVja2VyIGhpbmVpbmdlYmVuPC90ZXh0PgogICAgPHRleHQgeD0iMTUwIiB5PSIyODUiPlRlZSBub2NoIHp1IGhlacOfPzwvdGV4dD4KICAgIDx0ZXh0IHg9IjMyNy41IiB5PSIyODUiPjEgTWludXRlIHdhcnRlbjwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzQ4Ij5UZWUgdHJpbmtlbjwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzk1Ij5FbmRlPC90ZXh0PgogIDwvZz4KICA8ZyBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNjAwIj4KICAgIDx0ZXh0IHg9IjE1NiIgeT0iMTY4IiBmaWxsPSIjMjQ4YTNkIj5qYTwvdGV4dD4KICAgIDx0ZXh0IHg9IjI0MiIgeT0iMTIyIiBmaWxsPSIjZDcwMDE1Ij5uZWluPC90ZXh0PgogICAgPHRleHQgeD0iMjQwIiB5PSIyNzQiIGZpbGw9IiMyNDhhM2QiPmphPC90ZXh0PgogICAgPHRleHQgeD0iMTU2IiB5PSIzMjAiIGZpbGw9IiNkNzAwMTUiPm5laW48L3RleHQ+CiAgPC9nPgogIDwhLS0gTGVnZW5kZSAtLT4KICA8bGluZSB4MT0iMTAiIHkxPSI0MTgiIHgyPSIzOTAiIHkyPSI0MTgiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxnIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjUiPgogICAgPHJlY3QgeD0iNDAiIHk9IjQzMCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjE4IiByeD0iOSIgZmlsbD0iI2QxZjJkOSIvPgogICAgPHJlY3QgeD0iMjIwIiB5PSI0MzAiIHdpZHRoPSIzNiIgaGVpZ2h0PSIxOCIgZmlsbD0iI2U1ZjBmZiIvPgogICAgPHBhdGggZD0iTTU4IDQ1OCBMNzYgNDY5IEw1OCA0ODAgTDQwIDQ2OSBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8cGF0aCBkPSJNMjI2IDQ2MCBMMjU2IDQ2MCBMMjUwIDQ3OCBMMjIwIDQ3OCBaIiBmaWxsPSIjZjJlNmZmIi8+CiAgPC9nPgogIDxnIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiMzYTNhM2MiPgogICAgPHRleHQgeD0iODYiIHk9IjQ0MyI+U3RhcnQgb2RlciBFbmRlPC90ZXh0PgogICAgPHRleHQgeD0iMjY2IiB5PSI0NDMiPkFud2Vpc3VuZzwvdGV4dD4KICAgIDx0ZXh0IHg9Ijg2IiB5PSI0NzMiPlZlcnp3ZWlndW5nPC90ZXh0PgogICAgPHRleHQgeD0iMjY2IiB5PSI0NzMiPkVpbi0gb2RlciBBdXNnYWJlPC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",lD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE5MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwIiB5PSIyNCIgZm9udC13ZWlnaHQ9IjYwMCI+V29oaW4gbGFuZGV0IGRhcyBFbGVtZW50PzwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iNDAiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkYmVhZmUiLz4KICA8cmVjdCB4PSIyMCIgeT0iNzUiIHdpZHRoPSIxOTAiIGhlaWdodD0iMzUiIGZpbGw9IiNkY2ZjZTciLz4KICA8bGluZSB4MT0iMjAiIHkxPSI3NSIgeDI9IjIxMCIgeTI9Ijc1IiBzdHJva2U9IiM2ZTZlNzMiIHN0cm9rZS1kYXNoYXJyYXk9IjQgMyIvPgogIDxyZWN0IHg9IjIwIiB5PSI0MCIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI3MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjYyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMWQ0ZWQ4Ij5vYmVyZSBIw6RsZnRlPC90ZXh0PgogIDx0ZXh0IHg9IjExNSIgeT0iOTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPnVudGVyZSBIw6RsZnRlPC90ZXh0PgogIDx0ZXh0IHg9IjIyNCIgeT0iNjIiPuKGkiBrb21tdCA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+ZGF2b3I8L3RzcGFuPjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9Ijk3Ij7ihpIga29tbXQgPHRzcGFuIGZvbnQtd2VpZ2h0PSI2MDAiPmRhaGludGVyPC90c3Bhbj48L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjEzMiIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI0MCIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjE1NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiI+w7g8L3RleHQ+CiAgPHRleHQgeD0iMjI0IiB5PSIxNTciPuKGkiA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+ZXJzZXR6dDwvdHNwYW4+IGRlbiBQbGF0emhhbHRlcjwvdGV4dD4KPC9zdmc+Cg==",uD=""+new URL("l03-lochkarte-beschriftet-7hmU_7ct.svg",import.meta.url).href,cD=""+new URL("l03-lochkarte-gzfFEatc.svg",import.meta.url).href,mD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgMjkwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CjxyZWN0IHdpZHRoPSI0NjAiIGhlaWdodD0iMjkwIiBmaWxsPSIjZmZmZmZmIi8+Cjx0ZXh0IHg9IjUwIiB5PSI0NCIgZm9udC1zaXplPSI0MCIgZmlsbD0iIzZlNmU3MyIgdGV4dExlbmd0aD0iMzM2IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmdBbmRHbHlwaHMiPnByZWlzPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPk08L3RzcGFuPml0PHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPlM8L3RzcGFuPnRldWVyPC90ZXh0Pgo8bGluZSB4MT0iMTgyIiB5MT0iNTQiIHgyPSIxODIiIHkyPSI4MiIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSA0Ii8+CjxsaW5lIHgxPSIyNTQiIHkxPSI1NCIgeDI9IjI1NCIgeTI9IjgyIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtZGFzaGFycmF5PSI1IDQiLz4KPHBhdGggZD0iTTIwIDI3MiBINDQwIiBzdHJva2U9IiNlNWQzYjAiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0xNTYgMTcyIEwxNTAgMjI2IiBzdHJva2U9IiNiODhhNTIiIHN0cm9rZS13aWR0aD0iMTMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTUwIDIyNiBMMTU2IDI2MiIgc3Ryb2tlPSIjYjg4YTUyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8Y2lyY2xlIGN4PSIxNTAiIGN5PSIyMjYiIHI9IjYiIGZpbGw9IiM3YTU1MzAiIG9wYWNpdHk9IjAuNTUiLz4KPGVsbGlwc2UgY3g9IjE2MSIgY3k9IjI2NyIgcng9IjExIiByeT0iNSIgZmlsbD0iIzdhNTUzMCIvPgo8cGF0aCBkPSJNMzA0IDE3MiBMMzA4IDIyNiIgc3Ryb2tlPSIjYjg4YTUyIiBzdHJva2Utd2lkdGg9IjEzIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTMwOCAyMjYgTDMwNCAyNjIiIHN0cm9rZT0iI2I4OGE1MiIgc3Ryb2tlLXdpZHRoPSI4IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPGNpcmNsZSBjeD0iMzA4IiBjeT0iMjI2IiByPSI2IiBmaWxsPSIjN2E1NTMwIiBvcGFjaXR5PSIwLjU1Ii8+CjxlbGxpcHNlIGN4PSIzMDkiIGN5PSIyNjciIHJ4PSIxMSIgcnk9IjUiIGZpbGw9IiM3YTU1MzAiLz4KPHBhdGggZD0iTTEyMCAxNDAgQzEwNCAxNTAgMTA0IDE3NiAxMTAgMTk2IiBmaWxsPSJub25lIiBzdHJva2U9IiNiODhhNTIiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxlbGxpcHNlIGN4PSIxMTAiIGN5PSIyMDAiIHJ4PSI1IiByeT0iOSIgZmlsbD0iIzdhNTUzMCIvPgo8cGF0aCBkPSJNMTIwIDE3MiBDMTA4IDE1MiAxMTQgMTI4IDEzNCAxMjIgQzE0OCAxMjAgMTU0IDg0IDE4MiA4NCBDMjEwIDg0IDIwOCAxMjYgMjE4IDEyNCBDMjI4IDEyNiAyMjYgODQgMjU0IDg0IEMyODIgODQgMjg0IDEyMiAyOTQgMTI4IEMzMTYgMTMyIDMyNCAxNTggMzQwIDE1OCBDMzUyIDE1OCAzNTQgMTI0IDM1OCAxMTAgQzM2MiA5OCAzNzYgOTYgMzg4IDk5IEM0MDAgMTAyIDQwNiAxMDggNDA0IDExNiBDNDAyIDEyMyAzOTAgMTI0IDM4MCAxMjIgQzM3MiAxMjIgMzcwIDEyOCAzNzAgMTM2IEMzNzAgMTYyIDM2NCAxODQgMzQyIDE4NiBDMzI2IDE4OCAzMTYgMTgyIDMwNiAxNzggQzI0OCAxODggMTg4IDE4OCAxNDAgMTgyIEMxMzAgMTgwIDEyNCAxNzcgMTIwIDE3MiBaIiBmaWxsPSIjZDJhNTZhIiBzdHJva2U9IiM3YTU1MzAiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xMzQgMTcyIEwxMjggMjI2IiBzdHJva2U9IiNkMmE1NmEiIHN0cm9rZS13aWR0aD0iMTMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTI4IDIyNiBMMTM0IDI2MiIgc3Ryb2tlPSIjZDJhNTZhIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8Y2lyY2xlIGN4PSIxMjgiIGN5PSIyMjYiIHI9IjYiIGZpbGw9IiM3YTU1MzAiIG9wYWNpdHk9IjAuNTUiLz4KPGVsbGlwc2UgY3g9IjEzOSIgY3k9IjI2NyIgcng9IjExIiByeT0iNSIgZmlsbD0iIzdhNTUzMCIvPgo8cGF0aCBkPSJNMjg0IDE3MiBMMjg4IDIyNiIgc3Ryb2tlPSIjZDJhNTZhIiBzdHJva2Utd2lkdGg9IjEzIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTI4OCAyMjYgTDI4NCAyNjIiIHN0cm9rZT0iI2QyYTU2YSIgc3Ryb2tlLXdpZHRoPSI4IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPGNpcmNsZSBjeD0iMjg4IiBjeT0iMjI2IiByPSI2IiBmaWxsPSIjN2E1NTMwIiBvcGFjaXR5PSIwLjU1Ii8+CjxlbGxpcHNlIGN4PSIyODkiIGN5PSIyNjciIHJ4PSIxMSIgcnk9IjUiIGZpbGw9IiM3YTU1MzAiLz4KPHBhdGggZD0iTTM2NiAxMDMgTDM2MiA5MiBMMzc0IDEwMCBaIiBmaWxsPSIjZDJhNTZhIiBzdHJva2U9IiM3YTU1MzAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8Y2lyY2xlIGN4PSIzODIiIGN5PSIxMDciIHI9IjMuMiIgZmlsbD0iIzFjMWMxZSIvPgo8cGF0aCBkPSJNMzc3IDEwNCBRMzgyIDEwMSAzODcgMTA0IiBmaWxsPSJub25lIiBzdHJva2U9IiM3YTU1MzAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0zOTggMTA3IHE0IDEgNSA0IiBmaWxsPSJub25lIiBzdHJva2U9IiM3YTU1MzAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0zOTIgMTE5IFEzOTggMTE4IDQwMyAxMTciIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzdhNTUzMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPC9zdmc+Cg==",dD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjEwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIxMCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjE2Ij5pbnQgYWx0ZXIgPSAxNDwvdGV4dD4KICA8cGF0aCBkPSJNMTMwIDcwIEwxNzAgNTAgTDMwMCA1MCBMMjYwIDcwIFoiIGZpbGw9IiNjOThhM2MiIHN0cm9rZT0iIzhhNWExZiIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHJlY3QgeD0iMTgwIiB5PSIzNCIgd2lkdGg9IjQ0IiBoZWlnaHQ9IjUwIiByeD0iMyIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjEuNSIvPgogIDx0ZXh0IHg9IjIwMiIgeT0iNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI3MDAiPjE0PC90ZXh0PgogIDxyZWN0IHg9IjEzMCIgeT0iNzAiIHdpZHRoPSIxMzAiIGhlaWdodD0iMTAwIiBmaWxsPSIjZTliODcyIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxwYXRoIGQ9Ik0yNjAgNzAgTDMwMCA1MCBMMzAwIDE1MCBMMjYwIDE3MCBaIiBmaWxsPSIjZDQ5YTRjIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjE1MCIgeT0iMTAwIiB3aWR0aD0iOTAiIGhlaWdodD0iMzAiIHJ4PSI0IiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiM4YTVhMWYiLz4KICA8dGV4dCB4PSIxOTUiIHk9IjEyMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+YWx0ZXI8L3RleHQ+CiAgPHJlY3QgeD0iMTM4IiB5PSIxNDIiIHdpZHRoPSIzNCIgaGVpZ2h0PSIyMCIgcng9IjEwIiBmaWxsPSIjMDA3YWZmIi8+CiAgPHRleHQgeD0iMTU1IiB5PSIxNTYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiNmZmZmZmYiIGZvbnQtd2VpZ2h0PSI2MDAiPmludDwvdGV4dD4KICA8ZyBzdHJva2U9IiM2ZTZlNzMiPgogICAgPGxpbmUgeDE9IjMxMCIgeTE9IjQ4IiB4Mj0iMjI2IiB5Mj0iNTIiLz4KICAgIDxsaW5lIHgxPSIzMTAiIHkxPSIxMTUiIHgyPSIyNDIiIHkyPSIxMTUiLz4KICAgIDxsaW5lIHgxPSI4MCIgeTE9IjE1MiIgeDI9IjEzNCIgeTI9IjE1MiIvPgogIDwvZz4KICA8dGV4dCB4PSIzMTYiIHk9IjUyIj5XZXJ0PC90ZXh0PgogIDx0ZXh0IHg9IjMxNiIgeT0iMTE5Ij5OYW1lPC90ZXh0PgogIDx0ZXh0IHg9IjgiIHk9IjE1NiI+RGF0ZW50eXA8L3RleHQ+CiAgPHRleHQgeD0iMjAwIiB5PSIxOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPsOcYmVyIGRlbiBOYW1lbiBrb21tc3QgZHUgYW4gZGVuIFdlcnQuPC90ZXh0Pgo8L3N2Zz4K",hD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiPgogICAgPHRleHQgeD0iNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+cHVua3RlPC90ZXh0PgogICAgPHRleHQgeD0iMTI1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPj08L3RleHQ+CiAgICA8dGV4dCB4PSIyNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cHVua3RlICsgNTwvdGV4dD4KICA8L2c+CiAgPHJlY3QgeD0iMTgwIiB5PSI4NiIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjYwIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPuKRoCByZWNodHMgYXVzcmVjaG5lbjogMTAgKyA1ID0gMTU8L3RleHQ+CiAgPHBhdGggZD0iTTI1MCA4MiBDMjMwIDMwLCA5MCAzMCwgNjQgODQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwN2FmZiIgc3Ryb2tlLXdpZHRoPSIyLjUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICA8dGV4dCB4PSIxNjAiIHk9IjM2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIj7ikaEgRXJnZWJuaXMgbGlua3Mgc3BlaWNoZXJuPC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSIxNjQiIHdpZHRoPSIzNjAiIGhlaWdodD0iMjYiIHJ4PSI2IiBmaWxsPSIjZjJmMmY3Ii8+CiAgPHRleHQgeD0iMjAwIiB5PSIxODIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPnB1bmt0ZSB2b3JoZXI6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xMDwvdHNwYW4+ICAg4oaSICAgcHVua3RlIG5hY2hoZXI6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xNTwvdHNwYW4+PC90ZXh0Pgo8L3N2Zz4K",gD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjYwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjYwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiPgogICAgPHBhdGggZD0iTTQwIDExMCBMNDggMTgwIEwxMDIgMTgwIEwxMTAgMTEwIi8+CiAgICA8cGF0aCBkPSJNMTY1IDExMCBMMTczIDE4MCBMMjI3IDE4MCBMMjM1IDExMCIvPgogICAgPHBhdGggZD0iTTI5MCAxMTAgTDI5OCAxODAgTDM1MiAxODAgTDM2MCAxMTAiLz4KICA8L2c+CiAgPHBhdGggZD0iTTQ0IDEzNSBMNDggMTgwIEwxMDIgMTgwIEwxMDYgMTM1IFoiIGZpbGw9IiNmZGJhNzQiLz4KICA8cGF0aCBkPSJNMjk0IDEzNSBMMjk4IDE4MCBMMzUyIDE4MCBMMzU2IDEzNSBaIiBmaWxsPSIjOTNjNWZkIi8+CiAgPHRleHQgeD0iNzUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+bGlua3M8L3RleHQ+CiAgPHRleHQgeD0iNzUiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+U2FmdDwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+aGlsZjwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+bGVlcjwvdGV4dD4KICA8dGV4dCB4PSIzMjUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+cmVjaHRzPC90ZXh0PgogIDx0ZXh0IHg9IjMyNSIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5XYXNzZXI8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8cGF0aCBkPSJNODggMTA0IEMxMTAgNzAsIDE2MCA3MCwgMTg2IDEwNCIvPgogICAgPHBhdGggZD0iTTMxOCAxMDQgQzI3MCAxNSwgMTMwIDE1LCA4MiAxMDQiLz4KICAgIDxwYXRoIGQ9Ik0yMTQgMTA0IEMyNDAgNzAsIDI5MCA3MCwgMzEyIDEwNCIvPgogIDwvZz4KICA8ZyBmb250LXdlaWdodD0iNzAwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4KICAgIDxjaXJjbGUgY3g9IjEzNyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMTM3IiB5PSI4NSI+MTwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjIwMCIgY3k9IjM4IiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjAwIiB5PSI0MyI+MjwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjI2MyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjYzIiB5PSI4NSI+MzwvdGV4dD4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTIiPgogICAgPHRleHQgeD0iNzAiIHk9IjI0NyI+MTogaGlsZiA9IGxpbmtzPC90ZXh0PgogICAgPHRleHQgeD0iMjAwIiB5PSIyNDciPjI6IGxpbmtzID0gcmVjaHRzPC90ZXh0PgogICAgPHRleHQgeD0iMzMwIiB5PSIyNDciPjM6IHJlY2h0cyA9IGhpbGY8L3RleHQ+CiAgPC9nPgo8L3N2Zz4K",pD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDxyZWN0IHg9IjIwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+PHJlY3QgeD0iMzEwIiB5PSI1MCIgd2lkdGg9IjcwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+CiAgPHJlY3QgeD0iOTAiIHk9IjUwIiB3aWR0aD0iMjIwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZGNmY2U3Ii8+CiAgPGxpbmUgeDE9IjIwIiB5MT0iNzQiIHgyPSIzODAiIHkyPSI3NCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8bGluZSB4MT0iNDYiIHkxPSI2OCIgeDI9IjQ2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iNDYiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4wPC90ZXh0PgogIDxsaW5lIHgxPSI5MCIgeTE9IjY4IiB4Mj0iOTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjE8L3RleHQ+CiAgPGxpbmUgeDE9IjEzNCIgeTE9IjY4IiB4Mj0iMTM0IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTM0IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MjwvdGV4dD4KICA8bGluZSB4MT0iMTc4IiB5MT0iNjgiIHgyPSIxNzgiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIxNzgiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4zPC90ZXh0PgogIDxsaW5lIHgxPSIyMjIiIHkxPSI2OCIgeDI9IjIyMiIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjIyMiIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjQ8L3RleHQ+CiAgPGxpbmUgeDE9IjI2NiIgeTE9IjY4IiB4Mj0iMjY2IiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjY2IiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NTwvdGV4dD4KICA8bGluZSB4MT0iMzEwIiB5MT0iNjgiIHgyPSIzMTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIzMTAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj42PC90ZXh0PgogIDxsaW5lIHgxPSIzNTQiIHkxPSI2OCIgeDI9IjM1NCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjM1NCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjc8L3RleHQ+CiAgPGNpcmNsZSBjeD0iOTAiIGN5PSI3NCIgcj0iNiIgZmlsbD0iIzE1ODAzZCIvPjxjaXJjbGUgY3g9IjMxMCIgY3k9Ijc0IiByPSI2IiBmaWxsPSIjMTU4MDNkIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+Z8O8bHRpZzwvdGV4dD4KICA8dGV4dCB4PSI0MCIgeT0iNDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPnVuZ8O8bHRpZzwvdGV4dD48dGV4dCB4PSIzNjAiIHk9IjQwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj51bmfDvGx0aWc8L3RleHQ+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPHRleHQgeD0iMjAwIiB5PSIxMjQiIGZpbGw9IiMxNTgwM2QiPm5vdGUgJmd0Oz0gMSAmYW1wOyZhbXA7IG5vdGUgJmx0Oz0gNjwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMTQyIiBmaWxsPSIjYjkxYzFjIj5ub3RlICZsdDsgMSB8fCBub3RlICZndDsgNjwvdGV4dD4KICA8L2c+Cjwvc3ZnPgo=",fD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDAgMTkwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+CiAgPHJlY3Qgd2lkdGg9IjQ0MCIgaGVpZ2h0PSIxOTAiIGZpbGw9IiNmZmZmZmYiLz4KICA8cmVjdCB4PSIyMCIgeT0iMTQiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iNjAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPmE8L3RleHQ+CiAgPHJlY3QgeD0iMTAwIiB5PSIxNCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIxNDAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPmI8L3RleHQ+CiAgPHJlY3QgeD0iMTgwIiB5PSIxNCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIyMjAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPmEgJmFtcDsmYW1wOyBiPC90ZXh0PgogIDxyZWN0IHg9IjI2MCIgeT0iMTQiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzAwLjAiIHk9IjM1IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXdlaWdodD0iNzAwIj5hIHx8IGI8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSIxNCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIzODAuMCIgeT0iMzUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI3MDAiPiFhPC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSI0NiIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSI2MC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIxMDAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjE0MC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIxODAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjIyMC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIyNjAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjMwMC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIzNDAiIHk9IjQ2IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjM4MC4wIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9Ijc4IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjYwLjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMTU4MDNkIj50cnVlPC90ZXh0PgogIDxyZWN0IHg9IjEwMCIgeT0iNzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMTQwLjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIj5mYWxzZTwvdGV4dD4KICA8cmVjdCB4PSIxODAiIHk9Ijc4IiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjIyMC4wIiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMjYwIiB5PSI3OCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIzMDAuMCIgeT0iOTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPnRydWU8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSI3OCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmVlMmUyIiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIzODAuMCIgeT0iOTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiPmZhbHNlPC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSIxMTAiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iNjAuMCIgeT0iMTMxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIj5mYWxzZTwvdGV4dD4KICA8cmVjdCB4PSIxMDAiIHk9IjExMCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZGNmY2U3IiBzdHJva2U9IiM4ZThlOTMiLz48dGV4dCB4PSIxNDAuMCIgeT0iMTMxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMTU4MDNkIj50cnVlPC90ZXh0PgogIDxyZWN0IHg9IjE4MCIgeT0iMTEwIiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjIyMC4wIiB5PSIxMzEiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiPmZhbHNlPC90ZXh0PgogIDxyZWN0IHg9IjI2MCIgeT0iMTEwIiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjMwMC4wIiB5PSIxMzEiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPnRydWU8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSIxMTAiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2RjZmNlNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzgwLjAiIHk9IjEzMSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8cmVjdCB4PSIyMCIgeT0iMTQyIiB3aWR0aD0iODAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZWUyZTIiIHN0cm9rZT0iIzhlOGU5MyIvPjx0ZXh0IHg9IjYwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMTAwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMTQwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMTgwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMjIwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMjYwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZlZTJlMiIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzAwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iI2I5MWMxYyI+ZmFsc2U8L3RleHQ+CiAgPHJlY3QgeD0iMzQwIiB5PSIxNDIiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2RjZmNlNyIgc3Ryb2tlPSIjOGU4ZTkzIi8+PHRleHQgeD0iMzgwLjAiIHk9IjE2MyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCI+dHJ1ZTwvdGV4dD4KICA8bGluZSB4MT0iMTgwIiB5MT0iMTQiIHgyPSIxODAiIHkyPSIxNzQiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIzIi8+Cjwvc3ZnPgo=",bD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIj5BYmxhdWYgZGVyIFdoaWxlLVNjaGxlaWZlPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iNDQiIHdpZHRoPSIxNjAiIGhlaWdodD0iNDAiIHJ4PSIyMCIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjYjQ1MzA5IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjY5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaAgQmVkaW5ndW5nIHByw7xmZW48L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSIxMjgiIHdpZHRoPSIxNjAiIGhlaWdodD0iNDAiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTUzIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgSW5oYWx0IGF1c2bDvGhyZW48L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iODQiIHgyPSIyMDAiIHkyPSIxMjYiLz4KICAgIDxwYXRoIGQ9Ik0xMjAgMTQ4IEM4MCAxNDgsIDgwIDY0LCAxMTggNjQiLz4KICAgIDxwYXRoIGQ9Ik0yODAgNjQgTDM0MCA2NCBMMzQwIDIwMCBMMjgyIDIwMCIvPgogIDwvZz4KICA8dGV4dCB4PSIyMDgiIHk9IjExMCIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dHJ1ZTwvdGV4dD4KICA8dGV4dCB4PSIzOCIgeT0iMTEwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj53aWVkZXI8L3RleHQ+CiAgPHRleHQgeD0iMzgiIHk9IjEyNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+bmFjaCBvYmVuPC90ZXh0PgogIDx0ZXh0IHg9IjM0OCIgeT0iMTM0IiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5mYWxzZTwvdGV4dD4KICA8dGV4dCB4PSIyNzYiIHk9IjIwNSIgdGV4dC1hbmNob3I9ImVuZCI+d2VpdGVyIHVudGVyIGRlciBTY2hsZWlmZTwvdGV4dD4KPC9zdmc+Cg==",xD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+a29wZmdlc3RldWVydCAoV2hpbGUpPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPmZ1w59nZXN0ZXVlcnQgKERvLXdoaWxlKTwvdGV4dD4KICA8bGluZSB4MT0iMjAwIiB5MT0iMTAiIHgyPSIyMDAiIHkyPSIyMjAiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxyZWN0IHg9IjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iNjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCBCZWRpbmd1bmc8L3RleHQ+CiAgPHJlY3QgeD0iMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIxNDciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoSBJbmhhbHQ8L3RleHQ+CiAgPHJlY3QgeD0iMjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIEluaGFsdDwvdGV4dD4KICA8cmVjdCB4PSIyMzUiIHk9IjEyNCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjMwMCIgeT0iMTQ3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgQmVkaW5ndW5nPC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiPgogICAgPGxpbmUgeDE9IjEwMCIgeTE9IjgwIiB4Mj0iMTAwIiB5Mj0iMTIyIi8+CiAgICA8cGF0aCBkPSJNMzUgMTQyIEM4IDE0MiwgOCA2MiwgMzMgNjIiLz4KICAgIDxsaW5lIHgxPSIzMDAiIHkxPSI4MCIgeDI9IjMwMCIgeTI9IjEyMiIvPgogICAgPHBhdGggZD0iTTM2NSAxNDIgQzM5MiAxNDIsIDM5MiA2MiwgMzY3IDYyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjEwNiIgeT0iMTA2IiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTA2IiB0ZXh0LWFuY2hvcj0iZW5kIiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5Jc3QgZGllIEJlZGluZ3VuZyBnbGVpY2ggZmFsc2UsPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5sw6R1ZnQgZGVyIEluaGFsdCA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+bmllPC90c3Bhbj4uPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5EZXIgSW5oYWx0IGzDpHVmdCBpbW1lcjwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9IjIwNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+PHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPm1pbmRlc3RlbnMgZWlubWFsPC90c3Bhbj4uPC90ZXh0Pgo8L3N2Zz4K",vD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjUwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHJlY3QgeD0iMTIwIiB5PSIxNCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIFN0YXJ0IDx0c3BhbiBmaWxsPSIjNmU2ZTczIj4obnVyIGVpbm1hbCk8L3RzcGFuPjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9Ijc2IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iMTciIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGhIEJlZGluZ3VuZyBwcsO8ZmVuPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iMTM4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iNiIgZmlsbD0iI2RiZWFmZSIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGiIEluaGFsdCBhdXNmw7xocmVuPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iMjAwIiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iNiIgZmlsbD0iI2RjZmNlNyIgc3Ryb2tlPSIjMTU4MDNkIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGjIFNjaHJpdHQsIHouIEIuIGkrKzwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjIwMCIgeTI9Ijc0Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTEwIiB4Mj0iMjAwIiB5Mj0iMTM2Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTcyIiB4Mj0iMjAwIiB5Mj0iMTk4Ii8+CiAgICA8cGF0aCBkPSJNMTIwIDIxNyBDNjAgMjE3LCA2MCA5MywgMTE4IDkzIi8+CiAgICA8cGF0aCBkPSJNMjgwIDkzIEwzMzAgOTMiLz4KICA8L2c+CiAgPHRleHQgeD0iMjA4IiB5PSIxMjkiIGZpbGw9IiMxNTgwM2QiIGZvbnQtd2VpZ2h0PSI2MDAiPnRydWU8L3RleHQ+CiAgPHRleHQgeD0iNDgiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+enVyw7xjazwvdGV4dD4KICA8dGV4dCB4PSI0OCIgeT0iMTc2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj56dSDikaE8L3RleHQ+CiAgPHRleHQgeD0iMzAwIiB5PSI4NCIgZmlsbD0iI2I5MWMxYyIgZm9udC13ZWlnaHQ9IjYwMCI+ZmFsc2U8L3RleHQ+CiAgPHRleHQgeD0iMzM2IiB5PSI5OCI+ZmVydGlnPC90ZXh0Pgo8L3N2Zz4K",yD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMTkwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCI+aW50W10gemFobGVuID0gezIsIDQsIDYsIDgsIDEwfTwvdGV4dD4KICA8dGV4dCB4PSIyMCIgeT0iNTQiIGZpbGw9IiM2ZTZlNzMiIGZvbnQtc2l6ZT0iMTIiPkluZGV4PC90ZXh0PgogIDx0ZXh0IHg9IjkwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MDwvdGV4dD48cmVjdCB4PSI2MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjI8L3RleHQ+CiAgPHRleHQgeD0iMTUwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MTwvdGV4dD48cmVjdCB4PSIxMjAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTUwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+NDwvdGV4dD4KICA8dGV4dCB4PSIyMTAiIHk9IjU0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj4yPC90ZXh0PjxyZWN0IHg9IjE4MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyMTAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj42PC90ZXh0PgogIDx0ZXh0IHg9IjI3MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjM8L3RleHQ+PHJlY3QgeD0iMjQwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjI3MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjg8L3RleHQ+CiAgPHRleHQgeD0iMzMwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+NDwvdGV4dD48cmVjdCB4PSIzMDAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzMwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+MTA8L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjkwIiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj5XZXJ0PC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwN2FmZiIgc3Ryb2tlLXdpZHRoPSIxLjgiIG1hcmtlci1lbmQ9InVybCgjYSkiPjxsaW5lIHgxPSI5MCIgeTE9IjE0MCIgeDI9IjkwIiB5Mj0iMTEyIi8+PGxpbmUgeDE9IjMzMCIgeTE9IjE0MCIgeDI9IjMzMCIgeTI9IjExMiIvPjwvZz4KICA8ZyBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxMyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+PHRleHQgeD0iOTAiIHk9IjE1NiI+emFobGVuWzBdIGlzdCAyPC90ZXh0Pjx0ZXh0IHg9IjMzMCIgeT0iMTU2Ij56YWhsZW5bNF0gaXN0IDEwPC90ZXh0PjwvZz4KICA8dGV4dCB4PSIyMDAiIHk9IjE4MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+NSBGw6RjaGVyLCBnZXrDpGhsdCB3aXJkIGFiIDA6IGRlciBsZXR6dGUgSW5kZXggaXN0IDQuPC90ZXh0Pgo8L3N2Zz4K",wD=""+new URL("mvc-klick-KmFKqxH-.svg",import.meta.url).href,zD=""+new URL("aufgabe-mehrwertsteuer-KUkerRBd.svg",import.meta.url).href,ID=""+new URL("kino-saal-BOvcmdzb.svg",import.meta.url).href,kD=""+new URL("kino-schleifen-Ci9yPnbo.svg",import.meta.url).href,SD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgNDkyIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iNDkyIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiPgogICAgPCEtLSBTdGFydCAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMTAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMjgiIHJ4PSIxNCIgZmlsbD0iI2QxZjJkOSIvPgogICAgPGxpbmUgeDE9IjE1MCIgeTE9IjM4IiB4Mj0iMTUwIiB5Mj0iNTQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gQW53ZWlzdW5nIC0tPgogICAgPHJlY3QgeD0iNTAiIHk9IjU2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iODYiIHgyPSIxNTAiIHkyPSI5OCIgbWFya2VyLWVuZD0idXJsKCNhKSIvPgogICAgPCEtLSBSYXV0ZSAxIC0tPgogICAgPHBhdGggZD0iTTE1MCAxMDAgTDIzNSAxMjggTDE1MCAxNTYgTDY1IDEyOCBaIiBmaWxsPSIjZmZmNGQ2Ii8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMTU2IiB4Mj0iMTUwIiB5Mj0iMTcyIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8cmVjdCB4PSI1MCIgeT0iMTc0IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8bGluZSB4MT0iMTUwIiB5MT0iMjA0IiB4Mj0iMTUwIiB5Mj0iMjUwIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIG5laW4tV2VnIHVtIGRlbiBLYXN0ZW4gaGVydW0gLS0+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIyMzUsMTI4IDI4NSwxMjggMjg1LDIyMiAxNTAsMjIyIiBmaWxsPSJub25lIiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgICA8IS0tIFJhdXRlIDIgLS0+CiAgICA8cGF0aCBkPSJNMTUwIDI1MiBMMjM1IDI4MCBMMTUwIDMwOCBMNjUgMjgwIFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxsaW5lIHgxPSIyMzUiIHkxPSIyODAiIHgyPSIyNjgiIHkyPSIyODAiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjI3MCIgeT0iMjY1IiB3aWR0aD0iMTE1IiBoZWlnaHQ9IjMwIiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8IS0tIHp1csO8Y2sgenVyIFByw7xmdW5nIC0tPgogICAgPHBvbHlsaW5lIHBvaW50cz0iMzI3LDI2NSAzMjcsMjM4IDE1MCwyMzgiIGZpbGw9Im5vbmUiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzMDgiIHgyPSIxNTAiIHkyPSIzMjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDxyZWN0IHg9IjUwIiB5PSIzMjgiIHdpZHRoPSIyMDAiIGhlaWdodD0iMzAiIGZpbGw9IiNlNWYwZmYiLz4KICAgIDxsaW5lIHgxPSIxNTAiIHkxPSIzNTgiIHgyPSIxNTAiIHkyPSIzNzQiIG1hcmtlci1lbmQ9InVybCgjYSkiLz4KICAgIDwhLS0gRW5kZSAtLT4KICAgIDxyZWN0IHg9IjEwMCIgeT0iMzc2IiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjI4IiByeD0iMTQiIGZpbGw9IiNkMWYyZDkiLz4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSI+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI5Ij5JbsOtY2lvPC90ZXh0PgogICAgPHRleHQgeD0iMTUwIiB5PSI3NiI+UMO0ciB1bWEgY2jDoXZlbmEgbmEgbWVzYTwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTMzIj5RdWVyIGHDp8O6Y2FyPzwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMTk0Ij5KdW50YXIgYcOnw7pjYXI8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjI4NSI+Q2jDoSBtdWl0byBxdWVudGU/PC90ZXh0PgogICAgPHRleHQgeD0iMzI3LjUiIHk9IjI4NSI+RXNwZXJhciAxIG1pbnV0bzwvdGV4dD4KICAgIDx0ZXh0IHg9IjE1MCIgeT0iMzQ4Ij5CZWJlciBvIGNow6E8L3RleHQ+CiAgICA8dGV4dCB4PSIxNTAiIHk9IjM5NSI+RmltPC90ZXh0PgogIDwvZz4KICA8ZyBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNjAwIj4KICAgIDx0ZXh0IHg9IjE1NiIgeT0iMTY4IiBmaWxsPSIjMjQ4YTNkIj5zaW08L3RleHQ+CiAgICA8dGV4dCB4PSIyNDIiIHk9IjEyMiIgZmlsbD0iI2Q3MDAxNSI+bsOjbzwvdGV4dD4KICAgIDx0ZXh0IHg9IjI0MCIgeT0iMjc0IiBmaWxsPSIjMjQ4YTNkIj5zaW08L3RleHQ+CiAgICA8dGV4dCB4PSIxNTYiIHk9IjMyMCIgZmlsbD0iI2Q3MDAxNSI+bsOjbzwvdGV4dD4KICA8L2c+CiAgPCEtLSBMZWdlbmRlIC0tPgogIDxsaW5lIHgxPSIxMCIgeTE9IjQxOCIgeDI9IjM5MCIgeTI9IjQxOCIgc3Ryb2tlPSIjZDFkMWQ2Ii8+CiAgPGcgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuNSI+CiAgICA8cmVjdCB4PSI0MCIgeT0iNDMwIiB3aWR0aD0iMzYiIGhlaWdodD0iMTgiIHJ4PSI5IiBmaWxsPSIjZDFmMmQ5Ii8+CiAgICA8cmVjdCB4PSIyMjAiIHk9IjQzMCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjE4IiBmaWxsPSIjZTVmMGZmIi8+CiAgICA8cGF0aCBkPSJNNTggNDU4IEw3NiA0NjkgTDU4IDQ4MCBMNDAgNDY5IFoiIGZpbGw9IiNmZmY0ZDYiLz4KICAgIDxwYXRoIGQ9Ik0yMjYgNDYwIEwyNTYgNDYwIEwyNTAgNDc4IEwyMjAgNDc4IFoiIGZpbGw9IiNmMmU2ZmYiLz4KICA8L2c+CiAgPGcgZm9udC1zaXplPSIxMiIgZmlsbD0iIzNhM2EzYyI+CiAgICA8dGV4dCB4PSI4NiIgeT0iNDQzIj5JbsOtY2lvIG91IGZpbTwvdGV4dD4KICAgIDx0ZXh0IHg9IjI2NiIgeT0iNDQzIj5JbnN0cnXDp8OjbzwvdGV4dD4KICAgIDx0ZXh0IHg9Ijg2IiB5PSI0NzMiPkRlY2lzw6NvPC90ZXh0PgogICAgPHRleHQgeD0iMjY2IiB5PSI0NzMiPkVudHJhZGEgb3Ugc2HDrWRhPC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",TD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE5MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwIiB5PSIyNCIgZm9udC13ZWlnaHQ9IjYwMCI+T25kZSBmaWNhIG8gZWxlbWVudG8/PC90ZXh0PgogIDxyZWN0IHg9IjIwIiB5PSI0MCIgd2lkdGg9IjE5MCIgaGVpZ2h0PSIzNSIgZmlsbD0iI2RiZWFmZSIvPgogIDxyZWN0IHg9IjIwIiB5PSI3NSIgd2lkdGg9IjE5MCIgaGVpZ2h0PSIzNSIgZmlsbD0iI2RjZmNlNyIvPgogIDxsaW5lIHgxPSIyMCIgeTE9Ijc1IiB4Mj0iMjEwIiB5Mj0iNzUiIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLWRhc2hhcnJheT0iNCAzIi8+CiAgPHJlY3QgeD0iMjAiIHk9IjQwIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjcwIiBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjExNSIgeT0iNjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxZDRlZDgiPm1ldGFkZSBkZSBjaW1hPC90ZXh0PgogIDx0ZXh0IHg9IjExNSIgeT0iOTciIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPm1ldGFkZSBkZSBiYWl4bzwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9IjYyIj7ihpIgZmljYSA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+YW50ZXM8L3RzcGFuPjwvdGV4dD4KICA8dGV4dCB4PSIyMjQiIHk9Ijk3Ij7ihpIgZmljYSA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+ZGVwb2lzPC90c3Bhbj48L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjEzMiIgd2lkdGg9IjE5MCIgaGVpZ2h0PSI0MCIgZmlsbD0iI2ZlZjNjNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIxMTUiIHk9IjE1NyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiI+w7g8L3RleHQ+CiAgPHRleHQgeD0iMjI0IiB5PSIxNTciPuKGkiA8dHNwYW4gZm9udC13ZWlnaHQ9IjYwMCI+c3Vic3RpdHVpLW88L3RzcGFuPjwvdGV4dD4KPC9zdmc+Cg==",_D=""+new URL("l03-lochkarte-beschriftet-D1QjqGFo.svg",import.meta.url).href,AD=""+new URL("l03-lochkarte-BSn6oWaS.svg",import.meta.url).href,OD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgMjkwIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSI+CjxyZWN0IHdpZHRoPSI0NjAiIGhlaWdodD0iMjkwIiBmaWxsPSIjZmZmZmZmIi8+Cjx0ZXh0IHg9IjUwIiB5PSI0NCIgZm9udC1zaXplPSI0MCIgZmlsbD0iIzZlNmU3MyIgdGV4dExlbmd0aD0iMjY0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmdBbmRHbHlwaHMiPnByZWNvPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPkM8L3RzcGFuPm9tPHRzcGFuIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPkk8L3RzcGFuPnZhPC90ZXh0Pgo8bGluZSB4MT0iMTgyIiB5MT0iNTQiIHgyPSIxODIiIHkyPSI4MiIgc3Ryb2tlPSIjMDA3YWZmIiBzdHJva2Utd2lkdGg9IjIuNSIgc3Ryb2tlLWRhc2hhcnJheT0iNSA0Ii8+CjxsaW5lIHgxPSIyNTQiIHkxPSI1NCIgeDI9IjI1NCIgeTI9IjgyIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtZGFzaGFycmF5PSI1IDQiLz4KPHBhdGggZD0iTTIwIDI3MiBINDQwIiBzdHJva2U9IiNlNWQzYjAiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0xNTYgMTcyIEwxNTAgMjI2IiBzdHJva2U9IiNiODhhNTIiIHN0cm9rZS13aWR0aD0iMTMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTUwIDIyNiBMMTU2IDI2MiIgc3Ryb2tlPSIjYjg4YTUyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8Y2lyY2xlIGN4PSIxNTAiIGN5PSIyMjYiIHI9IjYiIGZpbGw9IiM3YTU1MzAiIG9wYWNpdHk9IjAuNTUiLz4KPGVsbGlwc2UgY3g9IjE2MSIgY3k9IjI2NyIgcng9IjExIiByeT0iNSIgZmlsbD0iIzdhNTUzMCIvPgo8cGF0aCBkPSJNMzA0IDE3MiBMMzA4IDIyNiIgc3Ryb2tlPSIjYjg4YTUyIiBzdHJva2Utd2lkdGg9IjEzIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTMwOCAyMjYgTDMwNCAyNjIiIHN0cm9rZT0iI2I4OGE1MiIgc3Ryb2tlLXdpZHRoPSI4IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPGNpcmNsZSBjeD0iMzA4IiBjeT0iMjI2IiByPSI2IiBmaWxsPSIjN2E1NTMwIiBvcGFjaXR5PSIwLjU1Ii8+CjxlbGxpcHNlIGN4PSIzMDkiIGN5PSIyNjciIHJ4PSIxMSIgcnk9IjUiIGZpbGw9IiM3YTU1MzAiLz4KPHBhdGggZD0iTTEyMCAxNDAgQzEwNCAxNTAgMTA0IDE3NiAxMTAgMTk2IiBmaWxsPSJub25lIiBzdHJva2U9IiNiODhhNTIiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxlbGxpcHNlIGN4PSIxMTAiIGN5PSIyMDAiIHJ4PSI1IiByeT0iOSIgZmlsbD0iIzdhNTUzMCIvPgo8cGF0aCBkPSJNMTIwIDE3MiBDMTA4IDE1MiAxMTQgMTI4IDEzNCAxMjIgQzE0OCAxMjAgMTU0IDg0IDE4MiA4NCBDMjEwIDg0IDIwOCAxMjYgMjE4IDEyNCBDMjI4IDEyNiAyMjYgODQgMjU0IDg0IEMyODIgODQgMjg0IDEyMiAyOTQgMTI4IEMzMTYgMTMyIDMyNCAxNTggMzQwIDE1OCBDMzUyIDE1OCAzNTQgMTI0IDM1OCAxMTAgQzM2MiA5OCAzNzYgOTYgMzg4IDk5IEM0MDAgMTAyIDQwNiAxMDggNDA0IDExNiBDNDAyIDEyMyAzOTAgMTI0IDM4MCAxMjIgQzM3MiAxMjIgMzcwIDEyOCAzNzAgMTM2IEMzNzAgMTYyIDM2NCAxODQgMzQyIDE4NiBDMzI2IDE4OCAzMTYgMTgyIDMwNiAxNzggQzI0OCAxODggMTg4IDE4OCAxNDAgMTgyIEMxMzAgMTgwIDEyNCAxNzcgMTIwIDE3MiBaIiBmaWxsPSIjZDJhNTZhIiBzdHJva2U9IiM3YTU1MzAiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xMzQgMTcyIEwxMjggMjI2IiBzdHJva2U9IiNkMmE1NmEiIHN0cm9rZS13aWR0aD0iMTMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMTI4IDIyNiBMMTM0IDI2MiIgc3Ryb2tlPSIjZDJhNTZhIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8Y2lyY2xlIGN4PSIxMjgiIGN5PSIyMjYiIHI9IjYiIGZpbGw9IiM3YTU1MzAiIG9wYWNpdHk9IjAuNTUiLz4KPGVsbGlwc2UgY3g9IjEzOSIgY3k9IjI2NyIgcng9IjExIiByeT0iNSIgZmlsbD0iIzdhNTUzMCIvPgo8cGF0aCBkPSJNMjg0IDE3MiBMMjg4IDIyNiIgc3Ryb2tlPSIjZDJhNTZhIiBzdHJva2Utd2lkdGg9IjEzIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTI4OCAyMjYgTDI4NCAyNjIiIHN0cm9rZT0iI2QyYTU2YSIgc3Ryb2tlLXdpZHRoPSI4IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPGNpcmNsZSBjeD0iMjg4IiBjeT0iMjI2IiByPSI2IiBmaWxsPSIjN2E1NTMwIiBvcGFjaXR5PSIwLjU1Ii8+CjxlbGxpcHNlIGN4PSIyODkiIGN5PSIyNjciIHJ4PSIxMSIgcnk9IjUiIGZpbGw9IiM3YTU1MzAiLz4KPHBhdGggZD0iTTM2NiAxMDMgTDM2MiA5MiBMMzc0IDEwMCBaIiBmaWxsPSIjZDJhNTZhIiBzdHJva2U9IiM3YTU1MzAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8Y2lyY2xlIGN4PSIzODIiIGN5PSIxMDciIHI9IjMuMiIgZmlsbD0iIzFjMWMxZSIvPgo8cGF0aCBkPSJNMzc3IDEwNCBRMzgyIDEwMSAzODcgMTA0IiBmaWxsPSJub25lIiBzdHJva2U9IiM3YTU1MzAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0zOTggMTA3IHE0IDEgNSA0IiBmaWxsPSJub25lIiBzdHJva2U9IiM3YTU1MzAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjxwYXRoIGQ9Ik0zOTIgMTE5IFEzOTggMTE4IDQwMyAxMTciIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzdhNTUzMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPC9zdmc+Cg==",CD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjEwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIxMCIgZmlsbD0iI2ZmZmZmZiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJ1aS1tb25vc3BhY2UsIE1lbmxvLCBDb25zb2xhcywgbW9ub3NwYWNlIiBmb250LXNpemU9IjE2Ij5pbnQgaWRhZGUgPSAxNDwvdGV4dD4KICA8cGF0aCBkPSJNMTMwIDcwIEwxNzAgNTAgTDMwMCA1MCBMMjYwIDcwIFoiIGZpbGw9IiNjOThhM2MiIHN0cm9rZT0iIzhhNWExZiIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHJlY3QgeD0iMTgwIiB5PSIzNCIgd2lkdGg9IjQ0IiBoZWlnaHQ9IjUwIiByeD0iMyIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjEuNSIvPgogIDx0ZXh0IHg9IjIwMiIgeT0iNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI3MDAiPjE0PC90ZXh0PgogIDxyZWN0IHg9IjEzMCIgeT0iNzAiIHdpZHRoPSIxMzAiIGhlaWdodD0iMTAwIiBmaWxsPSIjZTliODcyIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxwYXRoIGQ9Ik0yNjAgNzAgTDMwMCA1MCBMMzAwIDE1MCBMMjYwIDE3MCBaIiBmaWxsPSIjZDQ5YTRjIiBzdHJva2U9IiM4YTVhMWYiIHN0cm9rZS13aWR0aD0iMiIvPgogIDxyZWN0IHg9IjE1MCIgeT0iMTAwIiB3aWR0aD0iOTAiIGhlaWdodD0iMzAiIHJ4PSI0IiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiM4YTVhMWYiLz4KICA8dGV4dCB4PSIxOTUiIHk9IjEyMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+aWRhZGU8L3RleHQ+CiAgPHJlY3QgeD0iMTM4IiB5PSIxNDIiIHdpZHRoPSIzNCIgaGVpZ2h0PSIyMCIgcng9IjEwIiBmaWxsPSIjMDA3YWZmIi8+CiAgPHRleHQgeD0iMTU1IiB5PSIxNTYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiNmZmZmZmYiIGZvbnQtd2VpZ2h0PSI2MDAiPmludDwvdGV4dD4KICA8ZyBzdHJva2U9IiM2ZTZlNzMiPgogICAgPGxpbmUgeDE9IjMxMCIgeTE9IjQ4IiB4Mj0iMjI2IiB5Mj0iNTIiLz4KICAgIDxsaW5lIHgxPSIzMTAiIHkxPSIxMTUiIHgyPSIyNDIiIHkyPSIxMTUiLz4KICAgIDxsaW5lIHgxPSI4MCIgeTE9IjE1MiIgeDI9IjEzNCIgeTI9IjE1MiIvPgogIDwvZz4KICA8dGV4dCB4PSIzMTYiIHk9IjUyIj5WYWxvcjwvdGV4dD4KICA8dGV4dCB4PSIzMTYiIHk9IjExOSI+Tm9tZTwvdGV4dD4KICA8dGV4dCB4PSI4IiB5PSIxNTYiPlRpcG8gZGUgZGFkb3M8L3RleHQ+CiAgPHRleHQgeD0iMjAwIiB5PSIxOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPlBlbG8gbm9tZSBjaGVnYXMgYW8gdmFsb3IuPC90ZXh0Pgo8L3N2Zz4K",jD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiPgogICAgPHRleHQgeD0iNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+cG9udG9zPC90ZXh0PgogICAgPHRleHQgeD0iMTI1IiB5PSIxMTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPj08L3RleHQ+CiAgICA8dGV4dCB4PSIyNjAiIHk9IjExMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9udG9zICsgNTwvdGV4dD4KICA8L2c+CiAgPHJlY3QgeD0iMTgwIiB5PSI4NiIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjYwIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMxNTgwM2QiPuKRoCBjYWxjdWxhciBhIGRpcmVpdGE6IDEwICsgNSA9IDE1PC90ZXh0PgogIDxwYXRoIGQ9Ik0yNTAgODIgQzIzMCAzMCwgOTAgMzAsIDY0IDg0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMi41IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+CiAgPHRleHQgeD0iMTYwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiI+4pGhIGd1YXJkYXIgbyByZXN1bHRhZG8gw6AgZXNxdWVyZGE8L3RleHQ+CiAgPHJlY3QgeD0iMjAiIHk9IjE2NCIgd2lkdGg9IjM2MCIgaGVpZ2h0PSIyNiIgcng9IjYiIGZpbGw9IiNmMmYyZjciLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE4MiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cG9udG9zIGFudGVzOiA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCI+MTA8L3RzcGFuPiAgIOKGkiAgIHBvbnRvcyBkZXBvaXM6IDx0c3BhbiBmb250LXdlaWdodD0iNzAwIj4xNTwvdHNwYW4+PC90ZXh0Pgo8L3N2Zz4K",PD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMzAwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMzAwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPGcgc3Ryb2tlPSIjNmU2ZTczIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9Im5vbmUiPgogICAgPHBhdGggZD0iTTQwIDExMCBMNDggMTgwIEwxMDIgMTgwIEwxMTAgMTEwIi8+CiAgICA8cGF0aCBkPSJNMTY1IDExMCBMMTczIDE4MCBMMjI3IDE4MCBMMjM1IDExMCIvPgogICAgPHBhdGggZD0iTTI5MCAxMTAgTDI5OCAxODAgTDM1MiAxODAgTDM2MCAxMTAiLz4KICA8L2c+CiAgPHBhdGggZD0iTTQ0IDEzNSBMNDggMTgwIEwxMDIgMTgwIEwxMDYgMTM1IFoiIGZpbGw9IiNmZGJhNzQiLz4KICA8cGF0aCBkPSJNMjk0IDEzNSBMMjk4IDE4MCBMMzUyIDE4MCBMMzU2IDEzNSBaIiBmaWxsPSIjOTNjNWZkIi8+CiAgPHRleHQgeD0iNzUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+ZXNxdWVyZGE8L3RleHQ+CiAgPHRleHQgeD0iNzUiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+c3VtbzwvdGV4dD4KICA8dGV4dCB4PSIyMDAiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+YXV4PC90ZXh0PgogIDx0ZXh0IHg9IjIwMCIgeT0iMjE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj52YXppbzwvdGV4dD4KICA8dGV4dCB4PSIzMjUiIHk9IjIwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+ZGlyZWl0YTwvdGV4dD4KICA8dGV4dCB4PSIzMjUiIHk9IjIxNyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+w6FndWE8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8cGF0aCBkPSJNODggMTA0IEMxMTAgNzAsIDE2MCA3MCwgMTg2IDEwNCIvPgogICAgPHBhdGggZD0iTTMxOCAxMDQgQzI3MCAxNSwgMTMwIDE1LCA4MiAxMDQiLz4KICAgIDxwYXRoIGQ9Ik0yMTQgMTA0IEMyNDAgNzAsIDI5MCA3MCwgMzEyIDEwNCIvPgogIDwvZz4KICA8ZyBmb250LXdlaWdodD0iNzAwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4KICAgIDxjaXJjbGUgY3g9IjEzNyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMTM3IiB5PSI4NSI+MTwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjIwMCIgY3k9IjM4IiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjAwIiB5PSI0MyI+MjwvdGV4dD4KICAgIDxjaXJjbGUgY3g9IjI2MyIgY3k9IjgwIiByPSIxMSIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+PHRleHQgeD0iMjYzIiB5PSI4NSI+MzwvdGV4dD4KICA8L2c+CiAgPGcgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTIiPgogICAgPHRleHQgeD0iMjAwIiB5PSIyNTAiPjE6IGF1eCA9IGVzcXVlcmRhPC90ZXh0PgogICAgPHRleHQgeD0iMjAwIiB5PSIyNjgiPjI6IGVzcXVlcmRhID0gZGlyZWl0YTwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMjg2Ij4zOiBkaXJlaXRhID0gYXV4PC90ZXh0PgogIDwvZz4KPC9zdmc+Cg==",DD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2ZmZmZmZiIvPgogIDxyZWN0IHg9IjIwIiB5PSI1MCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+PHJlY3QgeD0iMzAwIiB5PSI1MCIgd2lkdGg9IjgwIiBoZWlnaHQ9IjI0IiBmaWxsPSIjZmVlMmUyIi8+CiAgPHJlY3QgeD0iMTAwIiB5PSI1MCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyNCIgZmlsbD0iI2RjZmNlNyIvPgogIDxsaW5lIHgxPSIyMCIgeTE9Ijc0IiB4Mj0iMzgwIiB5Mj0iNzQiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPGxpbmUgeDE9IjUwIiB5MT0iNjgiIHgyPSI1MCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjUwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MDwvdGV4dD4KICA8bGluZSB4MT0iMTAwIiB5MT0iNjgiIHgyPSIxMDAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIxMDAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4xPC90ZXh0PgogIDxsaW5lIHgxPSIxNTAiIHkxPSI2OCIgeDI9IjE1MCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjE1MCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjI8L3RleHQ+CiAgPGxpbmUgeDE9IjIwMCIgeTE9IjY4IiB4Mj0iMjAwIiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+MzwvdGV4dD4KICA8bGluZSB4MT0iMjUwIiB5MT0iNjgiIHgyPSIyNTAiIHkyPSI4MCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyNTAiIHk9Ijk4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj40PC90ZXh0PgogIDxsaW5lIHgxPSIzMDAiIHkxPSI2OCIgeDI9IjMwMCIgeTI9IjgwIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjMwMCIgeT0iOTgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjU8L3RleHQ+CiAgPGxpbmUgeDE9IjM1MCIgeTE9IjY4IiB4Mj0iMzUwIiB5Mj0iODAiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzUwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NjwvdGV4dD4KICA8Y2lyY2xlIGN4PSIxMDAiIGN5PSI3NCIgcj0iNiIgZmlsbD0iIzE1ODAzZCIvPjxjaXJjbGUgY3g9IjMwMCIgY3k9Ijc0IiByPSI2IiBmaWxsPSIjMTU4MDNkIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dsOhbGlkYTwvdGV4dD4KICA8dGV4dCB4PSI1MCIgeT0iNDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiNiOTFjMWMiIGZvbnQtd2VpZ2h0PSI2MDAiPmludsOhbGlkYTwvdGV4dD48dGV4dCB4PSIzNTAiIHk9IjQwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5pbnbDoWxpZGE8L3RleHQ+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPgogICAgPHRleHQgeD0iMjAwIiB5PSIxMjQiIGZpbGw9IiMxNTgwM2QiPm5vdGEgJmd0Oz0gMSAmYW1wOyZhbXA7IG5vdGEgJmx0Oz0gNTwvdGV4dD4KICAgIDx0ZXh0IHg9IjIwMCIgeT0iMTQyIiBmaWxsPSIjYjkxYzFjIj5ub3RhICZsdDsgMSB8fCBub3RhICZndDsgNTwvdGV4dD4KICA8L2c+Cjwvc3ZnPgo=",BD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIj5Db21vIGZ1bmNpb25hIG8gY2ljbG8gd2hpbGU8L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSI0NCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI0MCIgcng9IjIwIiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iNjkiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCB2ZXJpZmljYXIgYSBjb25kacOnw6NvPC90ZXh0PgogIDxyZWN0IHg9IjEyMCIgeT0iMTI4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjQwIiByeD0iNiIgZmlsbD0iI2RiZWFmZSIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjIiLz4KICA8dGV4dCB4PSIyMDAiIHk9IjE1MyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGhIGV4ZWN1dGFyIG8gaW50ZXJpb3I8L3RleHQ+CiAgPGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEuOCIgbWFya2VyLWVuZD0idXJsKCNhKSI+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iODQiIHgyPSIyMDAiIHkyPSIxMjYiLz4KICAgIDxwYXRoIGQ9Ik0xMjAgMTQ4IEM4MCAxNDgsIDgwIDY0LCAxMTggNjQiLz4KICAgIDxwYXRoIGQ9Ik0yODAgNjQgTDM0MCA2NCBMMzQwIDIwMCBMMjgyIDIwMCIvPgogIDwvZz4KICA8dGV4dCB4PSIyMDgiIHk9IjExMCIgZmlsbD0iIzE1ODAzZCIgZm9udC13ZWlnaHQ9IjYwMCI+dHJ1ZTwvdGV4dD4KICA8dGV4dCB4PSIzOCIgeT0iMTEwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj52b2x0YXI8L3RleHQ+CiAgPHRleHQgeD0iMzgiIHk9IjEyNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+cGFyYSBjaW1hPC90ZXh0PgogIDx0ZXh0IHg9IjM0OCIgeT0iMTM0IiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5mYWxzZTwvdGV4dD4KICA8dGV4dCB4PSIyNzYiIHk9IjIwNSIgdGV4dC1hbmNob3I9ImVuZCI+Y29udGludWFyIHBvciBiYWl4byBkbyBjaWNsbzwvdGV4dD4KPC9zdmc+Cg==",MD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjMwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjMwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMTAwIiB5PSIyMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjYwMCI+cHLDqS10ZXN0ZSAod2hpbGUpPC90ZXh0PgogIDx0ZXh0IHg9IjMwMCIgeT0iMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSI2MDAiPnDDs3MtdGVzdGUgKGRvLXdoaWxlKTwvdGV4dD4KICA8bGluZSB4MT0iMjAwIiB5MT0iMTAiIHgyPSIyMDAiIHkyPSIyMjAiIHN0cm9rZT0iI2QxZDFkNiIvPgogIDxyZWN0IHg9IjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjE4IiBmaWxsPSIjZmVmM2M3IiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iNjciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoCBjb25kacOnw6NvPC90ZXh0PgogIDxyZWN0IHg9IjM1IiB5PSIxMjQiIHdpZHRoPSIxMzAiIGhlaWdodD0iMzYiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjEwMCIgeT0iMTQ3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaEgaW50ZXJpb3I8L3RleHQ+CiAgPHJlY3QgeD0iMjM1IiB5PSI0NCIgd2lkdGg9IjEzMCIgaGVpZ2h0PSIzNiIgcng9IjYiIGZpbGw9IiNkYmVhZmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSI2NyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIGludGVyaW9yPC90ZXh0PgogIDxyZWN0IHg9IjIzNSIgeT0iMTI0IiB3aWR0aD0iMTMwIiBoZWlnaHQ9IjM2IiByeD0iMTgiIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMzAwIiB5PSIxNDciIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoSBjb25kacOnw6NvPC90ZXh0PgogIDxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiPgogICAgPGxpbmUgeDE9IjEwMCIgeTE9IjgwIiB4Mj0iMTAwIiB5Mj0iMTIyIi8+CiAgICA8cGF0aCBkPSJNMzUgMTQyIEM4IDE0MiwgOCA2MiwgMzMgNjIiLz4KICAgIDxsaW5lIHgxPSIzMDAiIHkxPSI4MCIgeDI9IjMwMCIgeTI9IjEyMiIvPgogICAgPHBhdGggZD0iTTM2NSAxNDIgQzM5MiAxNDIsIDM5MiA2MiwgMzY3IDYyIi8+CiAgPC9nPgogIDx0ZXh0IHg9IjEwNiIgeT0iMTA2IiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjM4MCIgeT0iMTA2IiB0ZXh0LWFuY2hvcj0iZW5kIiBmaWxsPSIjMTU4MDNkIiBmb250LXdlaWdodD0iNjAwIj50cnVlPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5TZSBhIGNvbmRpw6fDo28gZm9yIGxvZ28gZmFsc2EsPC90ZXh0PgogIDx0ZXh0IHg9IjEwMCIgeT0iMjA2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjNmU2ZTczIj5vIGludGVyaW9yIDx0c3BhbiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjMWMxYzFlIj5udW5jYTwvdHNwYW4+IMOpIGV4ZWN1dGFkby48L3RleHQ+CiAgPHRleHQgeD0iMzAwIiB5PSIxOTAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPk8gaW50ZXJpb3Igw6kgc2VtcHJlIGV4ZWN1dGFkbzwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9IjIwNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+PHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPnBlbG8gbWVub3MgdW1hIHZlejwvdHNwYW4+LjwvdGV4dD4KPC9zdmc+Cg==",ZD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMjUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMWMxYzFlIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMjUwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHJlY3QgeD0iMTIwIiB5PSIxNCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzZlNmU3MyIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIzNiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGgIEluw61jaW8gPHRzcGFuIGZpbGw9IiM2ZTZlNzMiPihzw7MgdW1hIHZleik8L3RzcGFuPjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9Ijc2IiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjM0IiByeD0iMTciIGZpbGw9IiNmZWYzYzciIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSI5OCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pGhIHZlcmlmaWNhciBhIGNvbmRpw6fDo288L3RleHQ+CiAgPHJlY3QgeD0iMTIwIiB5PSIxMzgiIHdpZHRoPSIxNjAiIGhlaWdodD0iMzQiIHJ4PSI2IiBmaWxsPSIjZGJlYWZlIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMiIvPgogIDx0ZXh0IHg9IjIwMCIgeT0iMTYwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7ikaIgZXhlY3V0YXIgbyBpbnRlcmlvcjwvdGV4dD4KICA8cmVjdCB4PSIxMjAiIHk9IjIwMCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIzNCIgcng9IjYiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIyIi8+CiAgPHRleHQgeD0iMjAwIiB5PSIyMjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuKRoyBwYXNzbywgcC4gZXguIGkrKzwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj4KICAgIDxsaW5lIHgxPSIyMDAiIHkxPSI0OCIgeDI9IjIwMCIgeTI9Ijc0Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTEwIiB4Mj0iMjAwIiB5Mj0iMTM2Ii8+CiAgICA8bGluZSB4MT0iMjAwIiB5MT0iMTcyIiB4Mj0iMjAwIiB5Mj0iMTk4Ii8+CiAgICA8cGF0aCBkPSJNMTIwIDIxNyBDNjAgMjE3LCA2MCA5MywgMTE4IDkzIi8+CiAgICA8cGF0aCBkPSJNMjgwIDkzIEwzMzAgOTMiLz4KICA8L2c+CiAgPHRleHQgeD0iMjA4IiB5PSIxMjkiIGZpbGw9IiMxNTgwM2QiIGZvbnQtd2VpZ2h0PSI2MDAiPnRydWU8L3RleHQ+CiAgPHRleHQgeD0iNDgiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZlNmU3MyI+dm9sdGFyPC90ZXh0PgogIDx0ZXh0IHg9IjQ4IiB5PSIxNzYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPmFvIOKRoTwvdGV4dD4KICA8dGV4dCB4PSIzMDAiIHk9Ijg0IiBmaWxsPSIjYjkxYzFjIiBmb250LXdlaWdodD0iNjAwIj5mYWxzZTwvdGV4dD4KICA8dGV4dCB4PSIzMzYiIHk9Ijk4Ij5maW08L3RleHQ+Cjwvc3ZnPgo=",LD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDAgMTkwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KICA8ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjMDA3YWZmIi8+PC9tYXJrZXI+PC9kZWZzPgogIDxyZWN0IHdpZHRoPSI0MDAiIGhlaWdodD0iMTkwIiBmaWxsPSIjZmZmZmZmIi8+CiAgPHRleHQgeD0iMjAiIHk9IjI0IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBNZW5sbywgQ29uc29sYXMsIG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCI+aW50W10gbnVtZXJvcyA9IHsyLCA0LCA2LCA4LCAxMH08L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjU0IiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj7DjW5kaWNlPC90ZXh0PgogIDx0ZXh0IHg9IjkwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MDwvdGV4dD48cmVjdCB4PSI2MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSI5MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjI8L3RleHQ+CiAgPHRleHQgeD0iMTUwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+MTwvdGV4dD48cmVjdCB4PSIxMjAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMTUwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+NDwvdGV4dD4KICA8dGV4dCB4PSIyMTAiIHk9IjU0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMDA3YWZmIiBmb250LXdlaWdodD0iNzAwIj4yPC90ZXh0PjxyZWN0IHg9IjE4MCIgeT0iNjIiIHdpZHRoPSI2MCIgaGVpZ2h0PSI0NiIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjIiLz48dGV4dCB4PSIyMTAiIHk9IjkyIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNjAwIj42PC90ZXh0PgogIDx0ZXh0IHg9IjI3MCIgeT0iNTQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiMwMDdhZmYiIGZvbnQtd2VpZ2h0PSI3MDAiPjM8L3RleHQ+PHJlY3QgeD0iMjQwIiB5PSI2MiIgd2lkdGg9IjYwIiBoZWlnaHQ9IjQ2IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMiIvPjx0ZXh0IHg9IjI3MCIgeT0iOTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI2MDAiPjg8L3RleHQ+CiAgPHRleHQgeD0iMzMwIiB5PSI1NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzAwN2FmZiIgZm9udC13ZWlnaHQ9IjcwMCI+NDwvdGV4dD48cmVjdCB4PSIzMDAiIHk9IjYyIiB3aWR0aD0iNjAiIGhlaWdodD0iNDYiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIyIi8+PHRleHQgeD0iMzMwIiB5PSI5MiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjYwMCI+MTA8L3RleHQ+CiAgPHRleHQgeD0iMjAiIHk9IjkwIiBmaWxsPSIjNmU2ZTczIiBmb250LXNpemU9IjEyIj5WYWxvcjwvdGV4dD4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiMwMDdhZmYiIHN0cm9rZS13aWR0aD0iMS44IiBtYXJrZXItZW5kPSJ1cmwoI2EpIj48bGluZSB4MT0iOTAiIHkxPSIxNDAiIHgyPSI5MCIgeTI9IjExMiIvPjxsaW5lIHgxPSIzMzAiIHkxPSIxNDAiIHgyPSIzMzAiIHkyPSIxMTIiLz48L2c+CiAgPGcgZm9udC1mYW1pbHk9InVpLW1vbm9zcGFjZSwgTWVubG8sIENvbnNvbGFzLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTMiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjx0ZXh0IHg9IjkwIiB5PSIxNTYiPm51bWVyb3NbMF0gw6kgMjwvdGV4dD48dGV4dCB4PSIzMzAiIHk9IjE1NiI+bnVtZXJvc1s0XSDDqSAxMDwvdGV4dD48L2c+CiAgPHRleHQgeD0iMjAwIiB5PSIxODIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IiM2ZTZlNzMiPjUgcG9zacOnw7VlcywgY29udGEtc2UgYSBwYXJ0aXIgZGUgMDogbyDDumx0aW1vIMOtbmRpY2Ugw6kgNC48L3RleHQ+Cjwvc3ZnPgo=",ED=""+new URL("mvc-klick-DKonBpbs.svg",import.meta.url).href,WD=""+new URL("schiffe-versenken-iEBDHIxD.svg",import.meta.url).href,ND=""+new URL("ss-binaere-suche-DVVS2SNc.svg",import.meta.url).href,FD=""+new URL("ss-bubblesort-AFDcFDah.svg",import.meta.url).href,JD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDQgMTk2IiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KPHJlY3Qgd2lkdGg9IjQwNCIgaGVpZ2h0PSIxOTYiIGZpbGw9IiNmZmZmZmYiLz4KPHRleHQgeD0iMTQiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIiBmb250LXNpemU9IjE1Ij5Qcm9jdXJhLXNlIG8gOS4gQXMgY2FydGFzIGVzdMOjbyBiYXJhbGhhZGFzLjwvdGV4dD4KPGc+PHJlY3QgeD0iMTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjM0LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjc8L3RleHQ+PHRleHQgeD0iMzQuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNkYzI2MjYiPuKZpTwvdGV4dD48L2c+Cjx0ZXh0IHg9IjM0LjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIzNC4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjEuPC90ZXh0Pgo8Zz48cmVjdCB4PSI2MiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iODIuMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+MzwvdGV4dD48dGV4dCB4PSI4Mi4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+4pmgPC90ZXh0PjwvZz4KPHRleHQgeD0iODIuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZGMyNjI2Ij7inJc8L3RleHQ+Cjx0ZXh0IHg9IjgyLjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+Mi48L3RleHQ+CjxnPjxyZWN0IHg9IjExMCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iMTMwLjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjEwPC90ZXh0Pjx0ZXh0IHg9IjEzMC4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iI2RjMjYyNiI+4pmmPC90ZXh0PjwvZz4KPHRleHQgeD0iMTMwLjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIxMzAuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj4zLjwvdGV4dD4KPGc+PHJlY3QgeD0iMTU4IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48dGV4dCB4PSIxNzguMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+NTwvdGV4dD48dGV4dCB4PSIxNzguMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiMxYzFjMWUiPuKZozwvdGV4dD48L2c+Cjx0ZXh0IHg9IjE3OC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMTc4LjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+NC48L3RleHQ+CjxnPjxyZWN0IHg9IjIwNiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIzIi8+PHRleHQgeD0iMjI2LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjk8L3RleHQ+PHRleHQgeD0iMjI2LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxYzFlIj7imaA8L3RleHQ+PC9nPgo8dGV4dCB4PSIyMjYuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjMTU4MDNkIj7inJM8L3RleHQ+Cjx0ZXh0IHg9IjIyNi4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjUuPC90ZXh0Pgo8Zz48cmVjdCB4PSIyNTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjMWQ0ZWQ4IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjxyZWN0IHg9IjI1OCIgeT0iNTQiIHdpZHRoPSIzMiIgaGVpZ2h0PSI0OCIgcng9IjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzkzYzVmZCIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMiIvPjwvZz4KPGc+PHJlY3QgeD0iMzAyIiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iIzFkNGVkOCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSIzMDYiIHk9IjU0IiB3aWR0aD0iMzIiIGhlaWdodD0iNDgiIHJ4PSIzIiBmaWxsPSJub25lIiBzdHJva2U9IiM5M2M1ZmQiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtZGFzaGFycmF5PSIzIDIiLz48L2c+CjxnPjxyZWN0IHg9IjM1MCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiMxZDRlZDgiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHJlY3QgeD0iMzU0IiB5PSI1NCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjQ4IiByeD0iMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTNjNWZkIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWRhc2hhcnJheT0iMyAyIi8+PC9nPgo8dGV4dCB4PSIxNCIgeT0iMTY4IiBmb250LXNpemU9IjE1IiBmaWxsPSIjNmU2ZTczIj5WaXJhciBkYSBlc3F1ZXJkYSBwYXJhIGEgZGlyZWl0YTo8L3RleHQ+PHRleHQgeD0iMTQiIHk9IjE4OCIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzZlNmU3MyI+QXDDs3MgNSBjb21wYXJhw6fDtWVzLCBvIDkgw6kgZW5jb250cmFkby48L3RleHQ+Cjwvc3ZnPgo=",RD=""+new URL("ss-vergleiche-DWgkIvLr.svg",import.meta.url).href,GD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjAgNDUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KPGRlZnM+PG1hcmtlciBpZD0iayIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDEwIDUgTDAgMTAgWiIgZmlsbD0iIzFjMWMxZSIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImIiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjYiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNMCAwIEwxMCA1IEwwIDEwIFoiIGZpbGw9IiMxZDRlZDgiLz48L21hcmtlcj48bWFya2VyIGlkPSJvIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjYjQ1MzA5Ii8+PC9tYXJrZXI+PC9kZWZzPgo8cmVjdCB3aWR0aD0iNDIwIiBoZWlnaHQ9IjQ1MCIgZmlsbD0iI2ZmZmZmZiIvPgo8dGV4dCB4PSIxMCIgeT0iMjIiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI3MDAiPlBhc3NhZ2VtIHBvciB2YWxvcjogdW1hIGPDs3BpYTwvdGV4dD4KPHJlY3QgeD0iMTAiIHk9IjM4IiB3aWR0aD0iMTYwIiBoZWlnaHQ9Ijg2IiByeD0iOCIgZmlsbD0iI2VmZjZmZiIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8dGV4dCB4PSIyMCIgeT0iNTgiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPlByb2dyYW1hIHByaW5jaXBhbDwvdGV4dD4KPHRleHQgeD0iMTYiIHk9Ijk4IiBmb250LXNpemU9IjEyIj5udW1lcm88L3RleHQ+CjxyZWN0IHg9IjcwIiB5PSI3OCIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9Ijk4IiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+NTwvdGV4dD4KPHJlY3QgeD0iMjUwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNmZmY3ZWQiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjYwIiB5PSI1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+ZHVwbGljYXI8L3RleHQ+Cjx0ZXh0IHg9IjI2MCIgeT0iOTgiPng8L3RleHQ+CjxyZWN0IHg9IjI4MCIgeT0iNzgiIHdpZHRoPSI4MCIgaGVpZ2h0PSIzMCIgcng9IjQiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8dGV4dCB4PSIzMjAiIHk9Ijk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj48dHNwYW4gZmlsbD0iIzZlNmU3MyIgdGV4dC1kZWNvcmF0aW9uPSJsaW5lLXRocm91Z2giPjU8L3RzcGFuPiA8dHNwYW4gZm9udC13ZWlnaHQ9IjcwMCI+MTA8L3RzcGFuPjwvdGV4dD4KPGxpbmUgeDE9IjEyOCIgeTE9IjkzIiB4Mj0iMjQ4IiB5Mj0iOTMiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1kYXNoYXJyYXk9IjUgNCIgbWFya2VyLWVuZD0idXJsKCNrKSIvPgo8dGV4dCB4PSIyMTAiIHk9Ijg0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5jw7NwaWE8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxNTAiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPnggcGFzc2EgYSAxMCwgbWFzIG51bWVybyBmaWNhIDUuPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iMTY4IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj5Db21vIHVtYSBmb3RvY8OzcGlhOiBlc2NyZXZlciBuYSBjw7NwaWE8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxODYiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPm7Do28gYWx0ZXJhIG8gb3JpZ2luYWwuPC90ZXh0Pgo8bGluZSB4MT0iMTAiIHkxPSIyMDgiIHgyPSI0MTAiIHkyPSIyMDgiIHN0cm9rZT0iI2QxZDFkNiIvPgo8dGV4dCB4PSIxMCIgeT0iMjM2IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNzAwIj5QYXNzYWdlbSBwb3IgcmVmZXLDqm5jaWE6IG8gbWVzbW8gYXJyYXk8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZWZmNmZmIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjIwIiB5PSIyNzIiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPlByb2dyYW1hIHByaW5jaXBhbDwvdGV4dD4KPHRleHQgeD0iMjAiIHk9IjMwMCI+ZmlsYTwvdGV4dD4KPGNpcmNsZSBjeD0iMTUwIiBjeT0iMjk1IiByPSI1IiBmaWxsPSIjMWQ0ZWQ4Ii8+CjxyZWN0IHg9IjI1MCIgeT0iMjUyIiB3aWR0aD0iMTYwIiBoZWlnaHQ9IjYyIiByeD0iOCIgZmlsbD0iI2ZmZjdlZCIgc3Ryb2tlPSIjYjQ1MzA5IiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8dGV4dCB4PSIyNjAiIHk9IjI3MiIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+bGltcGFyPC90ZXh0Pgo8dGV4dCB4PSIyNjAiIHk9IjMwMCI+bHVnYXJlczwvdGV4dD4KPGNpcmNsZSBjeD0iMzkwIiBjeT0iMjk1IiByPSI1IiBmaWxsPSIjYjQ1MzA5Ii8+CjxwYXRoIGQ9Ik0xNTAgMzAwIEwxNTAgMzQwIEwxNDAgMzUyIiBmaWxsPSJub25lIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41IiBtYXJrZXItZW5kPSJ1cmwoI2IpIi8+CjxwYXRoIGQ9Ik0zOTAgMzAwIEwzOTAgMzQwIEwzMjIgMzU0IiBmaWxsPSJub25lIiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMS41IiBtYXJrZXItZW5kPSJ1cmwoI28pIi8+CjxyZWN0IHg9IjkwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+CjxyZWN0IHg9IjE1MCIgeT0iMzU4IiB3aWR0aD0iNjAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8cmVjdCB4PSIyMTAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHJlY3QgeD0iMjcwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9IjEyMCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMTgwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIyNDAiIHk9IjM3OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+ZmFsc2U8L3RleHQ+Cjx0ZXh0IHg9IjMwMCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjQxNiIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+U8OzIGjDoSB1bSBhcnJheS4gTyBxdWUgbGltcGFyIGFsdGVyYSBhdHJhdsOpcyBkZSBsdWdhcmVzLDwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjQzNCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+byBwcm9ncmFtYSBwcmluY2lwYWwgdsOqIGVtIGZpbGEuPC90ZXh0Pgo8L3N2Zz4K",HD=""+new URL("zk-zeichen-8efNmpGx.svg",import.meta.url).href,VD=""+new URL("schiffe-versenken-CXt1SF0S.svg",import.meta.url).href,qD=""+new URL("ss-binaere-suche-CPsLGldq.svg",import.meta.url).href,QD=""+new URL("ss-bubblesort-Dic2ZfaT.svg",import.meta.url).href,UD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MDQgMTk2IiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWMxYzFlIj4KPHJlY3Qgd2lkdGg9IjQwNCIgaGVpZ2h0PSIxOTYiIGZpbGw9IiNmZmZmZmYiLz4KPHRleHQgeD0iMTQiIHk9IjI0IiBmb250LXdlaWdodD0iNjAwIiBmb250LXNpemU9IjE1Ij5HZXN1Y2h0OiBkaWUgOS4gRGllIEthcnRlbiBzaW5kIGdlbWlzY2h0LjwvdGV4dD4KPGc+PHJlY3QgeD0iMTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjZjJmMmY3IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjx0ZXh0IHg9IjM0LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjc8L3RleHQ+PHRleHQgeD0iMzQuMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiNkYzI2MjYiPuKZpTwvdGV4dD48L2c+Cjx0ZXh0IHg9IjM0LjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIzNC4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjEuPC90ZXh0Pgo8Zz48cmVjdCB4PSI2MiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iODIuMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+MzwvdGV4dD48dGV4dCB4PSI4Mi4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iIzFjMWMxZSI+4pmgPC90ZXh0PjwvZz4KPHRleHQgeD0iODIuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZGMyNjI2Ij7inJc8L3RleHQ+Cjx0ZXh0IHg9IjgyLjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+Mi48L3RleHQ+CjxnPjxyZWN0IHg9IjExMCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNmMmYyZjciIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHRleHQgeD0iMTMwLjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiNkYzI2MjYiPjEwPC90ZXh0Pjx0ZXh0IHg9IjEzMC4wIiB5PSI5NS45MTk5OTk5OTk5OTk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNSIgZmlsbD0iI2RjMjYyNiI+4pmmPC90ZXh0PjwvZz4KPHRleHQgeD0iMTMwLjAiIHk9IjEzMCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxNiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2RjMjYyNiI+4pyXPC90ZXh0Pgo8dGV4dCB4PSIxMzAuMCIgeT0iMTQ4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj4zLjwvdGV4dD4KPGc+PHJlY3QgeD0iMTU4IiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iI2YyZjJmNyIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48dGV4dCB4PSIxNzguMCIgeT0iNzUuMiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxOCIgZm9udC13ZWlnaHQ9IjcwMCIgZmlsbD0iIzFjMWMxZSI+NTwvdGV4dD48dGV4dCB4PSIxNzguMCIgeT0iOTUuOTE5OTk5OTk5OTk5OTkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiMxYzFjMWUiPuKZozwvdGV4dD48L2c+Cjx0ZXh0IHg9IjE3OC4wIiB5PSIxMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNkYzI2MjYiPuKclzwvdGV4dD4KPHRleHQgeD0iMTc4LjAiIHk9IjE0OCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+NC48L3RleHQ+CjxnPjxyZWN0IHg9IjIwNiIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiNkY2ZjZTciIHN0cm9rZT0iIzE1ODAzZCIgc3Ryb2tlLXdpZHRoPSIzIi8+PHRleHQgeD0iMjI2LjAiIHk9Ijc1LjIiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtd2VpZ2h0PSI3MDAiIGZpbGw9IiMxYzFjMWUiPjk8L3RleHQ+PHRleHQgeD0iMjI2LjAiIHk9Ijk1LjkxOTk5OTk5OTk5OTk5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE1IiBmaWxsPSIjMWMxYzFlIj7imaA8L3RleHQ+PC9nPgo8dGV4dCB4PSIyMjYuMCIgeT0iMTMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjE2IiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjMTU4MDNkIj7inJM8L3RleHQ+Cjx0ZXh0IHg9IjIyNi4wIiB5PSIxNDgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPjUuPC90ZXh0Pgo8Zz48cmVjdCB4PSIyNTQiIHk9IjUwIiB3aWR0aD0iNDAiIGhlaWdodD0iNTYiIHJ4PSI1IiBmaWxsPSIjMWQ0ZWQ4IiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMSIvPjxyZWN0IHg9IjI1OCIgeT0iNTQiIHdpZHRoPSIzMiIgaGVpZ2h0PSI0OCIgcng9IjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzkzYzVmZCIgc3Ryb2tlLXdpZHRoPSIxLjIiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMiIvPjwvZz4KPGc+PHJlY3QgeD0iMzAyIiB5PSI1MCIgd2lkdGg9IjQwIiBoZWlnaHQ9IjU2IiByeD0iNSIgZmlsbD0iIzFkNGVkOCIgc3Ryb2tlPSIjMWMxYzFlIiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSIzMDYiIHk9IjU0IiB3aWR0aD0iMzIiIGhlaWdodD0iNDgiIHJ4PSIzIiBmaWxsPSJub25lIiBzdHJva2U9IiM5M2M1ZmQiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtZGFzaGFycmF5PSIzIDIiLz48L2c+CjxnPjxyZWN0IHg9IjM1MCIgeT0iNTAiIHdpZHRoPSI0MCIgaGVpZ2h0PSI1NiIgcng9IjUiIGZpbGw9IiMxZDRlZDgiIHN0cm9rZT0iIzFjMWMxZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PHJlY3QgeD0iMzU0IiB5PSI1NCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjQ4IiByeD0iMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOTNjNWZkIiBzdHJva2Utd2lkdGg9IjEuMiIgc3Ryb2tlLWRhc2hhcnJheT0iMyAyIi8+PC9nPgo8dGV4dCB4PSIxNCIgeT0iMTY4IiBmb250LXNpemU9IjE1IiBmaWxsPSIjNmU2ZTczIj5Wb24gbGlua3MgbmFjaCByZWNodHMgdW1kcmVoZW46PC90ZXh0Pjx0ZXh0IHg9IjE0IiB5PSIxODgiIGZvbnQtc2l6ZT0iMTUiIGZpbGw9IiM2ZTZlNzMiPk5hY2ggNSBWZXJnbGVpY2hlbiBpc3QgZGllIDkgZ2VmdW5kZW4uPC90ZXh0Pgo8L3N2Zz4K",$D=""+new URL("ss-vergleiche-DRqzU2TZ.svg",import.meta.url).href,YD="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MjAgNDUwIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBTZWdvZSBVSSwgUm9ib3RvLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBmaWxsPSIjMWMxYzFlIj4KPGRlZnM+PG1hcmtlciBpZD0iayIgdmlld0JveD0iMCAwIDEwIDEwIiByZWZYPSI5IiByZWZZPSI1IiBtYXJrZXJXaWR0aD0iNiIgbWFya2VySGVpZ2h0PSI2IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDEwIDUgTDAgMTAgWiIgZmlsbD0iIzFjMWMxZSIvPjwvbWFya2VyPjxtYXJrZXIgaWQ9ImIiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjYiIG1hcmtlckhlaWdodD0iNiIgb3JpZW50PSJhdXRvIj48cGF0aCBkPSJNMCAwIEwxMCA1IEwwIDEwIFoiIGZpbGw9IiMxZDRlZDgiLz48L21hcmtlcj48bWFya2VyIGlkPSJvIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI2IiBtYXJrZXJIZWlnaHQ9IjYiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMMTAgNSBMMCAxMCBaIiBmaWxsPSIjYjQ1MzA5Ii8+PC9tYXJrZXI+PC9kZWZzPgo8cmVjdCB3aWR0aD0iNDIwIiBoZWlnaHQ9IjQ1MCIgZmlsbD0iI2ZmZmZmZiIvPgo8dGV4dCB4PSIxMCIgeT0iMjIiIGZvbnQtc2l6ZT0iMTUiIGZvbnQtd2VpZ2h0PSI3MDAiPldlcnTDvGJlcmdhYmU6IGVpbmUgS29waWU8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNlZmY2ZmYiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjAiIHk9IjU4IiBmb250LXNpemU9IjEzIiBmaWxsPSIjMWQ0ZWQ4Ij5IYXVwdHByb2dyYW1tPC90ZXh0Pgo8dGV4dCB4PSIyMCIgeT0iOTgiPnphaGw8L3RleHQ+CjxyZWN0IHg9IjcwIiB5PSI3OCIgd2lkdGg9IjU2IiBoZWlnaHQ9IjMwIiByeD0iNCIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+Cjx0ZXh0IHg9Ijk4IiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9IjcwMCI+NTwvdGV4dD4KPHJlY3QgeD0iMjUwIiB5PSIzOCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSI4NiIgcng9IjgiIGZpbGw9IiNmZmY3ZWQiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiLz4KPHRleHQgeD0iMjYwIiB5PSI1OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iI2I0NTMwOSI+dmVyZG9wcGxlPC90ZXh0Pgo8dGV4dCB4PSIyNjAiIHk9Ijk4Ij54PC90ZXh0Pgo8cmVjdCB4PSIyODAiIHk9Ijc4IiB3aWR0aD0iODAiIGhlaWdodD0iMzAiIHJ4PSI0IiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHRleHQgeD0iMzIwIiB5PSI5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+PHRzcGFuIGZpbGw9IiM2ZTZlNzMiIHRleHQtZGVjb3JhdGlvbj0ibGluZS10aHJvdWdoIj41PC90c3Bhbj4gPHRzcGFuIGZvbnQtd2VpZ2h0PSI3MDAiPjEwPC90c3Bhbj48L3RleHQ+CjxsaW5lIHgxPSIxMjgiIHkxPSI5MyIgeDI9IjI0OCIgeTI9IjkzIiBzdHJva2U9IiMxYzFjMWUiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtZGFzaGFycmF5PSI1IDQiIG1hcmtlci1lbmQ9InVybCgjaykiLz4KPHRleHQgeD0iMjEwIiB5PSI4NCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+S29waWU8L3RleHQ+Cjx0ZXh0IHg9IjEwIiB5PSIxNTAiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiM2ZTZlNzMiPnggd2lyZCAxMCwgYWJlciB6YWhsIGJsZWlidCA1LjwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjE2OCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+V2llIGJlaSBlaW5lciBGb3Rva29waWU6IFdlciBhdWYgZGVyIEtvcGllIHNjaHJlaWJ0LDwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjE4NiIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+w6RuZGVydCBkYXMgT3JpZ2luYWwgbmljaHQuPC90ZXh0Pgo8bGluZSB4MT0iMTAiIHkxPSIyMDgiIHgyPSI0MTAiIHkyPSIyMDgiIHN0cm9rZT0iI2QxZDFkNiIvPgo8dGV4dCB4PSIxMCIgeT0iMjM2IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNzAwIj5SZWZlcmVuesO8YmVyZ2FiZTogZGFzc2VsYmUgQXJyYXk8L3RleHQ+CjxyZWN0IHg9IjEwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZWZmNmZmIiBzdHJva2U9IiMxZDRlZDgiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjIwIiB5PSIyNzIiIGZvbnQtc2l6ZT0iMTMiIGZpbGw9IiMxZDRlZDgiPkhhdXB0cHJvZ3JhbW08L3RleHQ+Cjx0ZXh0IHg9IjIwIiB5PSIzMDAiPnJlaWhlPC90ZXh0Pgo8Y2lyY2xlIGN4PSIxNTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiMxZDRlZDgiLz4KPHJlY3QgeD0iMjUwIiB5PSIyNTIiIHdpZHRoPSIxNjAiIGhlaWdodD0iNjIiIHJ4PSI4IiBmaWxsPSIjZmZmN2VkIiBzdHJva2U9IiNiNDUzMDkiIHN0cm9rZS13aWR0aD0iMS41Ii8+Cjx0ZXh0IHg9IjI2MCIgeT0iMjcyIiBmb250LXNpemU9IjEzIiBmaWxsPSIjYjQ1MzA5Ij5sZWVyZW48L3RleHQ+Cjx0ZXh0IHg9IjI2MCIgeT0iMzAwIj5wbGFldHplPC90ZXh0Pgo8Y2lyY2xlIGN4PSIzOTAiIGN5PSIyOTUiIHI9IjUiIGZpbGw9IiNiNDUzMDkiLz4KPHBhdGggZD0iTTE1MCAzMDAgTDE1MCAzNDAgTDE0MCAzNTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFkNGVkOCIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjYikiLz4KPHBhdGggZD0iTTM5MCAzMDAgTDM5MCAzNDAgTDMyMiAzNTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2I0NTMwOSIgc3Ryb2tlLXdpZHRoPSIxLjUiIG1hcmtlci1lbmQ9InVybCgjbykiLz4KPHJlY3QgeD0iOTAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHJlY3QgeD0iMTUwIiB5PSIzNTgiIHdpZHRoPSI2MCIgaGVpZ2h0PSIzMiIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjMWMxYzFlIi8+CjxyZWN0IHg9IjIxMCIgeT0iMzU4IiB3aWR0aD0iNjAiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzFjMWMxZSIvPgo8cmVjdCB4PSIyNzAiIHk9IjM1OCIgd2lkdGg9IjYwIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9IiMxYzFjMWUiLz4KPHRleHQgeD0iMTIwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxODAiIHk9IjM3OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMyI+ZmFsc2U8L3RleHQ+Cjx0ZXh0IHg9IjI0MCIgeT0iMzc5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LXNpemU9IjEzIj5mYWxzZTwvdGV4dD4KPHRleHQgeD0iMzAwIiB5PSIzNzkiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTMiPmZhbHNlPC90ZXh0Pgo8dGV4dCB4PSIxMCIgeT0iNDE2IiBmb250LXNpemU9IjEzIiBmaWxsPSIjNmU2ZTczIj5FcyBnaWJ0IG51ciBlaW4gQXJyYXkuIFdhcyBsZWVyZW4gw7xiZXIgcGxhZXR6ZSDDpG5kZXJ0LDwvdGV4dD4KPHRleHQgeD0iMTAiIHk9IjQzNCIgZm9udC1zaXplPSIxMyIgZmlsbD0iIzZlNmU3MyI+c2llaHQgZGFzIEhhdXB0cHJvZ3JhbW0gdW50ZXIgcmVpaGUuPC90ZXh0Pgo8L3N2Zz4K",XD=""+new URL("zk-zeichen-vYvc3iJg.svg",import.meta.url).href;function KD(i){const e=[];for(const t of i.replace(/\r\n/g,` +`).split(` +`)){const n=/^###\s+(.+)$/.exec(t),a=e.at(-1);if(n){const s=n[1].trim();e.push({term:s,forms:[s],text:""})}else a&&/^(auch|also):/i.test(t)?a.forms.push(...t.replace(/^(auch|also):/i,"").split(",").map(s=>s.trim()).filter(Boolean)):a&&t.trim()!==""&&(a.text=(a.text+" "+t.trim()).trim())}return e.filter(t=>t.text!=="")}const eB=i=>i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function Lu(i){const e=i.flatMap(t=>t.forms).sort((t,n)=>n.length-t.length);if(e.length!==0)return new RegExp(`(?t.forms.includes(e))}class Bo extends Error{}function tB(i){return i==="zuhoerer"||i==="vertrag"||i==="layout"||i==="bombe"||i==="frage"||i==="reihenfolge"}function nB(i,e,t){const n=h=>{throw new Bo(`${t}: ${h}`)};let a="",s="",r="",o=[],l,u;const c=[];let m,d=!1;for(const h of e){const g=h.trim();if(m&&d&&(/^ {4}|^\t/.test(h)||g==="")){m.code+=(m.code?` +`:"")+h.replace(/^( {4}|\t)/,"");continue}if(d=!1,!g)continue;const f=/^(titel|intro|antworten|frage|runde|klicks|richtig|zeit|fehler|besser|daten):\s*(.*)$/.exec(g);if(f){const[,v,w]=f;v==="runde"?(m={code:"",question:r,options:[],explanation:"",clicks:[]},c.push(m),d=!0):m?v==="frage"?m.question=w:v==="fehler"?m.wrongLine=Number(w):v==="besser"?m.fix=w:v==="klicks"?m.clicks=w.split(",").map(I=>I.trim()).filter(Boolean):v==="richtig"?m.rightText=w:n(`„${v}:“ gehört vor die erste Runde.`):v==="titel"?a=w:v==="intro"?s=w:v==="antworten"?o=w.split("|").map(I=>I.trim()):v==="frage"?r=w:v==="zeit"?l=Number(w):v==="daten"?u=w==="csv"?w:n("„daten:“ kennt nur „csv“."):n(`„${v}:“ gehört in eine Runde.`);continue}m||n(`Unbekannte Zeile vor der ersten Runde: „${g}“`);const b=m,x=/^-\s+(\[x\]\s+)?(.+)$/.exec(g);x?b.options.push({text:x[2].trim().replaceAll("\\n",` +`),right:!!x[1]}):g.startsWith(">")?b.explanation+=(b.explanation?" ":"")+g.slice(1).trim():n(`Unbekannte Zeile im Spiel: „${g}“`)}return a||n("Das Spiel braucht eine Zeile „titel:“."),c.length||n("Das Spiel braucht mindestens eine „runde:“."),c.forEach((h,g)=>{if(h.code=h.code.replace(/\n+$/,""),i==="bombe"){const f=h.code.split(` +`),b=h.wrongLine;(!b||!Number.isInteger(b)||b<1||b>f.length||!f[b-1].trim())&&n(`Runde ${g+1}: „fehler:“ muss eine Zeile des Codes sein.`),h.fix||n(`Runde ${g+1}: „besser:“ fehlt.`),h.options.length&&n(`Runde ${g+1}: Bei „bombe“ gibt es keine Antworten, man tippt auf die Zeile.`),h.question||n(`Runde ${g+1}: keine Frage.`);return}if(i==="reihenfolge"){h.options.length<3&&n(`Runde ${g+1}: „reihenfolge“ braucht mindestens drei Schritte.`),h.options.some(f=>f.right)&&n(`Runde ${g+1}: Bei „reihenfolge“ gibt es kein [x], die Schritte stehen der Reihe nach da.`),new Set(h.options.map(f=>f.text)).size!==h.options.length&&n(`Runde ${g+1}: zwei Schritte sind gleich.`),h.question||n(`Runde ${g+1}: keine Frage.`);return}if(h.options.length||(o.length||n(`Runde ${g+1}: keine Antworten.`),(!h.rightText||!o.includes(h.rightText))&&n(`Runde ${g+1}: „richtig:“ muss eine der Antworten sein.`),h.options=o.map(f=>({text:f,right:f===h.rightText}))),h.options.filter(f=>f.right).length!==1&&n(`Runde ${g+1}: genau eine Antwort muss richtig sein.`),h.question||n(`Runde ${g+1}: keine Frage.`),i==="layout"&&h.options.forEach(f=>Rh(f.text,`Runde ${g+1}`,n)),i==="zuhoerer")try{const f=Gh(h.code);for(const b of h.clicks)f.buttons.some(x=>x.caption===b)||n(`Runde ${g+1}: Knopf „${b}“ gibt es nicht.`);iB(f,h.clicks)}catch(f){if(f instanceof Bo)throw f;n(`Runde ${g+1}: ${f.message}`)}delete h.rightText}),i==="bombe"&&!(l&&l>0)&&n("„bombe“ braucht „zeit:“ mit den Sekunden je Runde."),{kind:i,title:a,intro:s,...i==="bombe"?{seconds:l,...u?{data:u}:{}}:{},rounds:c}}function Rh(i,e="",t=n=>{throw new Bo(n)}){const n=/^(grid|flow|border):\s*(.+)$/.exec(i);if(!n)return t(`${e}: Antwort „${i}“ ist kein Fensterbild (grid:, flow: oder border:).`);if(n[1]==="border"){const s={};for(const r of n[2].split(/\s+/)){const o=/^([NSWEC])=(.+)$/.exec(r);o||t(`${e}: „${r}“ im BorderLayout-Bild verstehe ich nicht (z. B. N=A).`),s[o[1]]=o[2]}return{kind:"border",areas:s}}const a=n[2].split("/").map(s=>s.trim().split(/\s+/).filter(Boolean));return{kind:n[1],rows:a}}const Ea='"((?:[^"\\\\]|\\\\.)*)"';function Gh(i){const e=i.split(` +`),t={title:"",buttons:[],labels:[],ints:{},listeners:[]},n=new Map,a=(r,o,l)=>{if(o.startsWith("{")){let c=r+1;const m=[];for(;c=e.length)throw new Error(`Dem Zuhörer fehlt „${l}“.`);return{from:r,to:c,statements:Mo(m.join(" "))}}const u=l==="});"?o.replace(/\)\s*;\s*$/,""):o.replace(/;\s*$/,"");return{from:r,to:r,statements:Mo(u)}},s=r=>{if(!t.buttons.some(o=>o.name===r))throw new Error(`Knopf ${r} ist nicht angelegt.`);return r};for(let r=0;r\s*(.*)$/.exec(o)){const u=a(r,l[2],"};");n.set(l[1],u),r=u.to}else if(l=/^(\w+)\.addActionListener\(\s*(\w+)\s*\)\s*;$/.exec(o)){const u=n.get(l[2]);if(!u)throw new Error(`Zuhörer ${l[2]} ist nicht angelegt.`);t.listeners.push({button:s(l[1]),...u})}else if(l=/^(\w+)\.addActionListener\(\s*\w+\s*->\s*(.*)$/.exec(o)){const u=a(r,l[2],"});");t.listeners.push({button:s(l[1]),...u}),r=u.to}}return t}function Mo(i){const e=[];let t=0;const n=()=>{for(;t{let u=0,c=!1;const m=t+1;for(;t{let o=0,l=!1;const u=t;for(;t{if(n(),i[t]==="{")return Mo(a("{","}"));if(/^if\s*\(/.test(i.slice(t))){t=i.indexOf("(",t);const l=a("(",")").trim(),u=r();n();let c=[];return/^else\b/.test(i.slice(t))&&(t+=4,c=r()),[{condition:l,then:u,otherwise:c}]}const o=s();return o?[o]:[]};for(n();ta.caption===t)??i.buttons.find(a=>e.texts[a.name]===t);if(!n)throw new Error(`Knopf „${t}“ gibt es nicht.`);return qh(i,e,n.name)}function qh(i,e,t){const n=i.listeners.find(r=>r.button===t),a=[],s={source:t,command:e.texts[t]};for(const r of(n==null?void 0:n.statements)??[])Qh(r,e,a,s);return{button:t,listener:n,texts:{...e.texts},console:a}}function iB(i,e){const t=Hh(i);return e.map(n=>Vh(i,t,n))}function Qh(i,e,t,n){if(typeof i!="string"){for(const s of aB(i.condition,e,n)?i.then:i.otherwise)Qh(s,e,t,n);return}let a;if(a=/^(\w+)\.setText\((.*)\)$/.exec(i)){if(!(a[1]in e.texts))throw new Error(`${a[1]} ist keine Beschriftung und kein Knopf.`);e.texts[a[1]]=String(Un(a[2],e,n))}else if(a=/^System\.out\.println\((.*)\)$/.exec(i))t.push(String(Un(a[1],e,n)));else if(a=/^(\w+)\s*(\+\+|--)$/.exec(i))e.ints[Wu(a[1],e)]+=a[2]==="++"?1:-1;else if(a=/^(\w+)\s*([+-]?=)\s*(.+)$/.exec(i)){const s=Wu(a[1],e),r=Number(Un(a[3],e,n));e.ints[s]=a[2]==="="?r:a[2]==="+="?e.ints[s]+r:e.ints[s]-r}else throw new Error(`Diese Anweisung kann das Spiel nicht nachspielen: „${i}“`)}function aB(i,e,t){let n;if(n=/^e\.getSource\(\)\s*(==|!=)\s*(\w+)$/.exec(i)){if(!(n[2]in e.texts))throw new Error(`${n[2]} ist kein Knopf.`);return t.source===n[2]==(n[1]==="==")}if(n=/^(!?)(.+)\.equals\((.+)\)$/.exec(i))return String(Un(n[2],e,t))===String(Un(n[3],e,t))!=(n[1]==="!");if(n=/^(.+?)\s*(==|!=|<=|>=|<|>)\s*(.+)$/.exec(i)){const a=Number(Un(n[1],e,t)),s=Number(Un(n[3],e,t));return{"==":a===s,"!=":a!==s,"<=":a<=s,">=":a>=s,"<":a":a>s}[n[2]]}throw new Error(`Diese Bedingung kann das Spiel nicht nachspielen: „${i}“`)}function Wu(i,e){if(!(i in e.ints))throw new Error(`Variable ${i} ist nicht angelegt.`);return i}function Un(i,e,t){const n=i.match(new RegExp(`${Ea}|\\d+|e\\.getActionCommand\\(\\)|\\w+(?:\\.getText\\(\\))?|[-+*/()]`,"g"))??[];let a=0;const s=()=>{const l=n[a++];if(l===void 0)throw new Error(`Unvollständiger Ausdruck „${i}“`);if(l==="("){const u=o();return a++,u}if(l.startsWith('"'))return JSON.parse(l);if(/^\d+$/.test(l))return Number(l);if(l==="e.getActionCommand()"){if(!t)throw new Error("e.getActionCommand() gibt es nur im Zuhörer.");return t.command}if(l.endsWith(".getText()"))return e.texts[l.slice(0,-10)]??"";if(l in e.ints)return e.ints[l];throw new Error(`Unbekannt: „${l}“`)},r=()=>{let l=s();for(;n[a]==="*"||n[a]==="/";){const u=n[a++],c=Number(s());l=u==="*"?Number(l)*c:Math.trunc(Number(l)/c)}return l},o=()=>{let l=r();for(;n[a]==="+"||n[a]==="-";){const u=n[a++],c=r();u==="+"?l=typeof l=="string"||typeof c=="string"?`${l}${c}`:l+c:l=Number(l)-Number(c)}return l};return o()}class sB extends Error{}const gs="___";function rB(i){const e=Array.from({length:i.rows},()=>Array(i.cols).fill(""));for(const t of i.words)[...t.word].forEach((n,a)=>e[t.row+(t.across?0:a)][t.col+(t.across?a:0)]=n);return e}function oB(i,e){const t=A=>{throw new sB(`${e}: ${A}`)},n=(A,D)=>{const P=/^(\d+)\s+(\d+)$/.exec(A.trim());return!P||Number(P[1])<1||Number(P[2])<1?t(`${D}: „${A}“ ist kein Feld (Zeile Spalte, ab 1).`):{row:Number(P[1])-1,col:Number(P[2])-1}};let a="",s="",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",o="",l="",u="",c="";const m=[],d=[];let h=[],g,f="start";for(const A of i){const D=A.trim();if(g&&(/^( {4}|\t)/.test(A)||D==="")){const j=A.replace(/^( {4}|\t)/,"");if(g==="station"){const O=m[m.length-1];O.code+=(O.code?` +`:"")+j}else u+=(u?` +`:"")+j;continue}if(g=void 0,!D)continue;const P=/^(titel|intro|alphabet|station|frage|zahl|feld|tipp|kreuzwort|lösung|loesung|tor|ende):\s*(.*)$/.exec(D);if(P){const[,j,O]=P;if(j==="station")m.push({name:O,code:"",question:"",hint:"",explanation:""}),f="station",g="station";else if(j==="kreuzwort")o=O,f="crossword";else if(j==="tor")l=O,f="gate",g="gate";else if(j==="titel")a=O;else if(j==="intro")s=O;else if(j==="alphabet")r=O;else if(j==="ende")c=O;else if(j==="lösung"||j==="loesung")f!=="crossword"&&t("„lösung:“ gehört zum Kreuzworträtsel."),h=O.split(",").map(Z=>n(Z,"lösung"));else{f!=="station"&&t(`„${j}:“ gehört in eine Station.`);const Z=m[m.length-1];j==="frage"?Z.question=O:j==="tipp"?Z.hint=O:j==="zahl"?Z.answer=/^-?\d+$/.test(O)?Number(O):t(`Station „${Z.name}“: „zahl:“ muss eine ganze Zahl sein.`):Object.assign(Z,n(O,`Station „${Z.name}“`))}continue}if(f==="crossword"){const j=/^-\s+([→↓])\s+(\d+)\s+(\d+)\s+([A-ZÄÖÜ]+):\s*(.+)$/u.exec(D);j||t(`Kreuzworträtsel: „${D}“ verstehe ich nicht (z. B. „- → 1 3 STRING: Hinweis“).`),d.push({across:j[1]==="→",row:Number(j[2])-1,col:Number(j[3])-1,word:j[4],clue:j[5]});continue}if(f==="station"&&D.startsWith(">")){const j=m[m.length-1];j.explanation+=(j.explanation?" ":"")+D.slice(1).trim();continue}t(`Unbekannte Zeile im Spiel: „${D}“`)}a||t("Das Spiel braucht eine Zeile „titel:“."),m.length||t("Das Spiel braucht mindestens eine „station:“."),d.length||t("Das Spiel braucht ein „kreuzwort:“ mit Wörtern."),h.length||t("Das Kreuzworträtsel braucht eine Zeile „lösung:“."),u.includes(gs)||t(`Der Code bei „tor:“ braucht ${gs} für das Eingabefeld.`),new Set(r).size!==r.length&&t("Im Alphabet kommt ein Zeichen doppelt vor.");const b=Math.max(...d.map(A=>A.row+(A.across?1:A.word.length))),x=Math.max(...d.map(A=>A.col+(A.across?A.word.length:1))),v=Array.from({length:b},()=>Array(x).fill(""));for(const A of d)[...A.word].forEach((D,P)=>{const j=A.row+(A.across?0:P),O=A.col+(A.across?P:0);v[j][O]&&v[j][O]!==D&&t(`Kreuzworträtsel: ${A.word} passt in Zeile ${j+1}, Spalte ${O+1} nicht (dort steht ${v[j][O]}).`),v[j][O]=D});const w=[...new Set(d.map(A=>A.row*x+A.col))].sort((A,D)=>A-D),I=d.map(A=>({...A,number:w.indexOf(A.row*x+A.col)+1})),z=(A,D)=>{var P;return((P=v[A])==null?void 0:P[D])??""},k=h.map(({row:A,col:D})=>z(A,D)||t(`lösung: In Zeile ${A+1}, Spalte ${D+1} ist kein Feld.`)).join(""),T=m.map(A=>{A.code||t(`Station „${A.name}“: Code fehlt.`),A.question||t(`Station „${A.name}“: „frage:“ fehlt.`),A.answer===void 0&&t(`Station „${A.name}“: „zahl:“ fehlt.`),A.row===void 0&&t(`Station „${A.name}“: „feld:“ fehlt.`);const D=r.charAt(A.answer);D||t(`Station „${A.name}“: alphabet.charAt(${A.answer}) gibt es nicht.`);const P=z(A.row,A.col);return P!==D&&t(`Station „${A.name}“: alphabet.charAt(${A.answer}) ist ${D}, im Feld ${A.row+1} ${A.col+1} steht aber „${P}“.`),A.code=A.code.replace(/\n+$/,""),A});return{title:a,intro:s,alphabet:r,stations:T,crosswordText:o,rows:b,cols:x,words:I,solution:h,keyword:k,gateText:l,gateCode:u.replace(/\n+$/,""),end:c}}const lB=/\[\[(.+?)\]\]/g;function uB(i,e){const t={title:"",task:"",blocks:[]},n=[];let a=!1;for(const s of i){if(/^\s*```/.test(s)){a||n.push([]),a=!a;continue}if(a){n[n.length-1].push(s.replace(/\s+$/,""));continue}const r=s.trim();if(!r)continue;const o=/^([a-zäöü]+):\s*(.*)$/i.exec(r);if(!o)throw new Error(`${e}: Unbekannte Zeile im Lückentext: „${r}“.`);const l=o[2].trim();switch(o[1].toLowerCase()){case"titel":t.title=l;break;case"auftrag":t.task=l;break;case"erklärung":case"erklaerung":t.explanation=l;break;default:throw new Error(`${e}: Unbekannter Schlüssel „${o[1]}“ im Lückentext.`)}}if(a)throw new Error(`${e}: Der Codeblock im Lückentext wird nicht mit \`\`\` geschlossen.`);if(!t.title)throw new Error(`${e}: Ein Lückentext braucht einen Titel.`);if(!n.some(s=>s.some(r=>r.trim())))throw new Error(`${e}: Lückentext „${t.title}“ braucht einen Codeblock.`);if(t.blocks=n.map(s=>{const r=Math.min(...s.filter(o=>o.trim()).map(o=>/^ */.exec(o)[0].length));return s.map(o=>cB(o.slice(r),e,t.title))}),!mB(t).length)throw new Error(`${e}: Lückentext „${t.title}“ braucht mindestens eine Lücke [[…]].`);return t}function cB(i,e,t){const n=[];let a=0;for(const s of i.matchAll(lB)){s.index>a&&n.push(i.slice(a,s.index));const r=s[1].split(/\s+\|\s+/).map(o=>o.trim()).filter(Boolean);if(!r.length)throw new Error(`${e}: Leere Lücke im Lückentext „${t}“.`);n.push({answers:r}),a=s.index+s[0].length}if(atypeof s=="string"&&(s.includes("[[")||s.includes("]]"))))throw new Error(`${e}: Unvollständige Lücke im Lückentext „${t}“: „${i}“.`);return n}function mB(i){return i.blocks.flat().flatMap(e=>e.flatMap(t=>typeof t=="string"?[]:[t.answers]))}function dB(i,e){const t=n=>n.replace(/\s+/g,"");return t(e)!==""&&i.some(n=>t(n)===t(e))}const Nu={start:"oval",ende:"oval",anweisung:"rechteck",eingabe:"parallelogramm",ausgabe:"parallelogramm",frage:"raute"};function hB(i,e){const t={title:"",task:"",nodes:[]},n=[];for(const a of i){const s=a.trim();if(!s)continue;const r=/^([a-zäöü]+):\s*(.*)$/i.exec(s);if(!r)throw new Error(`${e}: Unbekannte Zeile im PAP: „${s}“.`);const o=r[1].toLowerCase(),l=r[2].trim();if(o==="titel")t.title=l;else if(o==="auftrag")t.task=l;else if(o==="erklärung"||o==="erklaerung")t.explanation=l;else if(o==="legende")t.legend=/^(ja|yes|true|sim)$/i.test(l);else if(o in Nu){const[u,c]=l.split(/\s+\|\s+/);if(!u)throw new Error(`${e}: Leeres Element im PAP: „${s}“.`);const m={shape:Nu[o],text:u.trim()};if(t.nodes.push(m),o!=="frage"){if(c)throw new Error(`${e}: Nur eine Frage hat einen zweiten Ausgang: „${s}“.`);continue}const d=/^(ja|nein)\s*(->|:)\s*(.+)$/i.exec(c??"");if(!d)throw new Error(`${e}: Eine Frage braucht „| nein -> Text“ oder „| nein: Text“: „${s}“.`);m.sideExit=d[1].toLowerCase(),d[2]===":"?(m.side=t.nodes.length,t.nodes.push({shape:"rechteck",text:d[3].trim(),isSide:!0})):n.push({node:t.nodes.length-1,target:d[3].trim(),line:s})}else throw new Error(`${e}: Unbekannter Schlüssel „${r[1]}“ im PAP.`)}for(const a of n){const s=t.nodes.findIndex((r,o)=>o{if(n.isSide)return;const s=vB(n.shape);(i.nodes.some(r=>r.backTo===a)||n.side!==void 0)&&(t+=12),e[a]={x:pB,y:t+s/2,w:n.shape==="raute"?170:n.shape==="oval"?110:fB,h:s},n.side!==void 0&&(e[n.side]={x:bB,y:t+s/2,w:xB,h:40}),t+=s+Fu}),{boxes:e,height:t-Fu+10}}function Uh(i,e){if((r=>r.length*6.6<=e)(i))return[i];const n=i.split(" ");let a=[i],s=1/0;for(let r=1;ru.length));l|→)\s*/);if(t.length!==2)throw new ne(`${e}: Test „${i}“ braucht genau ein „->“.`);const n=(a,s)=>a.trim()===""||a.trim()==="-"?[]:a.split(s).map(r=>r.trim());return{inputs:n(t[0],/\s*,\s*/),expected:n(t[1],/\s*\|\s*/)}}function zB(i){const e=/^(.*?)\s*(?:->|→)\s*(.*)$/.exec(i.trim());if(!e)throw new Error(`„messwerte: ${i}“ braucht ein „->“.`);const t={};for(const n of e[1].split(/\s*,\s*/).filter(Boolean)){const a=/^(\w+)\s*=\s*(.+)$/.exec(n);if(!a||!(a[1]in At))throw new Error(`Unbekannter Sensor in „${n}“.`);t[a[1]]=a[2].split("/").map(s=>{const r=s.trim();if(r==="true"||r==="false")return r==="true";if(/^-?\d+(\.\d+)?$/.test(r))return Number(r);if(typeof At[a[1]].simulated=="string")return r;throw new Error(`Messwert „${r}“ ist keine Zahl und nicht true/false.`)})}return Xh({inputs:[],expected:[],sensors:t},e[2])}function Xh(i,e){const t=[];e=e.replace(/\bscreen\s+("(?:[^"\\]|\\.)*")/u,(n,a)=>(i.screen=JSON.parse(a),""));for(const n of e.split(/\s*,\s*/).filter(Boolean))n==="ledOn"||n==="ledOff"?i.led=n==="ledOn":n==="tone"||n==="noTone"?i.tone=n==="tone":n==="none"?i.drive=[]:n==="drives"?i.drives=!0:t.push(n);return t.length&&(i.drive=is(dh(t.join(", ")))),i}function IB(i,e,t){const n={id:i,title:"",task:"",tests:[],requires:[],hints:[],subprograms:[]};let a;for(const s of e){const r=/^(titel|auftrag|start|test|datei|fahrt|befehle|welt|messwerte|schleifentiefe|braucht|tipp|lösung|loesung|unterprogramm|code|bereich):\s*(.*)$/i.exec(s.trim());if(r){const[,o,l]=r;switch(a=void 0,o.toLowerCase()){case"titel":n.title=l;break;case"auftrag":n.task=l,a="task";break;case"start":n.start=l;break;case"test":n.tests.push(wB(l,t));break;case"datei":{const u=/^([\w.-]+)\s*(?:->|→)\s*(.*)$/.exec(l.trim());if(!u||!n.tests.length)throw new ne(`${t}: Übung „${i}“: „datei:“ braucht vorher einen Test und die Form „name.txt -> Zeile | Zeile“.`);const c=n.tests[n.tests.length-1];c.files=[...c.files??[],{name:u[1],lines:u[2].trim()===""?[]:u[2].split(/\s*\|\s*/).map(m=>m.trim())}];break}case"fahrt":try{n.tests.push({inputs:[],expected:[],drive:is(dh(l))})}catch(u){throw new ne(`${t}: Übung „${i}“: ${u.message}`)}break;case"welt":{const u=/^([\w-]+)\s*(?:->|→)\s*(.+)$/.exec(l.trim());if(u){try{n.tests.push(Xh({inputs:[],expected:[],world:u[1]},u[2]))}catch(c){throw new ne(`${t}: Übung „${i}“: ${c.message}`)}break}for(const c of l.split(/\s*,\s*/).filter(Boolean)){if(!/^[\w-]+$/.test(c))throw new ne(`${t}: Übung „${i}“: Weltname „${c}“ (nur Buchstaben, Ziffern, -).`);n.tests.push({inputs:[],expected:[],world:c})}break}case"befehle":try{n.tests.push({inputs:[],expected:[],actions:w3(l)})}catch(u){throw new ne(`${t}: Übung „${i}“: ${u.message}`)}break;case"messwerte":try{n.tests.push(zB(l))}catch(u){throw new ne(`${t}: Übung „${i}“: ${u.message}`)}break;case"schleifentiefe":if(n.loopDepth=Number(l),!Number.isInteger(n.loopDepth)||n.loopDepth<1)throw new ne(`${t}: Übung „${i}“: „schleifentiefe:“ braucht eine Zahl ab 1.`);break;case"braucht":n.requires.push(...l.split(/\s*,\s*/).filter(Boolean));break;case"tipp":n.hints.push(l),a="hint";break;case"lösung":case"loesung":n.solution=l;break;case"unterprogramm":n.subprograms.push(...l.split(/\s*,\s*/).filter(Boolean));break;case"code":if(l.trim().toLowerCase()!=="java")throw new ne(`${t}: Übung „${i}“: „code:“ kennt nur „java“.`);n.code="java";break;case"bereich":{const u=l.trim().toLowerCase();if(u!=="struktogramm"&&u!=="code"&&u!=="beide")throw new ne(`${t}: Übung „${i}“: „bereich:“ kennt nur „struktogramm“, „code“ oder „beide“.`);n.area=u;break}}}else a&&s.trim()!==""?a==="task"?n.task+=` +`+s.trim():n.hints[n.hints.length-1]+=` +`+s.trim():s.trim()===""&&a==="task"&&(n.task+=` +`)}if(!n.title)throw new ne(`${t}: Übung „${i}“ hat keinen Titel.`);if(!n.task.trim())throw new ne(`${t}: Übung „${i}“ hat keinen Auftrag.`);return n.task=n.task.trim(),n}function kB(i,e){const t=[];for(const n of i){const a=n.trim();if(a.startsWith("?"))t.push({question:a.slice(1).trim(),options:[]});else if(/^- \[[ xX]\]/.test(a)){const s=t.at(-1);if(!s)throw new ne(`${e}: Antwort ohne Frage im Quiz.`);s.options.push({text:a.slice(5).trim(),correct:a[3].toLowerCase()==="x"})}else if(a.startsWith("= ")){const s=t.at(-1),r=/^=\s+(.+?)\s+->\s+(.+)$/.exec(a);if(!s||!r)throw new ne(`${e}: Zuordnung „${a}“ braucht die Form „= links -> rechts“ nach einer Frage.`);(s.pairs??(s.pairs=[])).push({left:r[1].trim(),right:r[2].trim()})}else if(a.startsWith("→")){const s=t.at(-1);if(!s)throw new ne(`${e}: „→ Schritt“ ohne Frage im Quiz.`);s.ref=a.slice(1).trim()}else if(a.startsWith(">")){const s=t.at(-1);s&&(s.explanation=((s.explanation?s.explanation+" ":"")+a.slice(1).trim()).trim())}}for(const n of t){if(n.pairs){const a=new Set(n.pairs.map(s=>s.right));if(n.options.length>0||n.pairs.length<2||a.size!==n.pairs.length)throw new ne(`${e}: Zuordnung „${n.question}“ braucht mindestens zwei Paare mit verschiedenen rechten Seiten und keine Antworten.`);continue}if(n.options.length<2||!n.options.some(a=>a.correct))throw new ne(`${e}: Quizfrage „${n.question}“ braucht mindestens zwei Antworten, davon eine richtige.`)}return t}function Kh(i,e){const t=[],n=i.split(` +`);let a=[];const s=()=>{const r=a.join(` +`).trim();r&&t.push({kind:"markdown",text:r}),a=[]};for(let r=0;r=n.length)throw new ne(`${e}: Block „::: ${o[1]}“ wird nicht mit „:::“ geschlossen.`);const c=o[1].toLowerCase(),m=o[2].trim();switch(c){case"diagramm":if(!m)throw new ne(`${e}: „::: diagramm“ braucht einen Dateinamen.`);t.push({kind:"diagram",file:m,caption:l.join(" ").trim()});break;case"übung":case"uebung":if(!m)throw new ne(`${e}: „::: übung“ braucht eine Kennung.`);t.push({kind:"exercise",exercise:IB(m,l,e)});break;case"checkliste":t.push({kind:"checklist",items:l.map(d=>d.trim()).filter(d=>d.startsWith("- ")).map(d=>SB(d.slice(2).trim()))});break;case"kompetenzen":t.push({kind:"competences",items:l.map(d=>d.trim()).filter(d=>d.startsWith("- ")).map(d=>d.slice(2).trim())});break;case"quiz":t.push({kind:"quiz",questions:kB(l,e)});break;case"bild":if(!m)throw new ne(`${e}: „::: bild“ braucht einen Dateinamen.`);t.push({kind:"images",files:m.split(/\s+/),caption:l.join(" ").trim()});break;case"grafik":if(!m)throw new ne(`${e}: „::: grafik“ braucht einen Dateinamen.`);{const[d,h]=m.split(/\s+/);t.push({kind:"graphic",file:d,...h?{labeled:h}:{},caption:l.join(" ").trim()})}break;case"angeberwissen":t.push({kind:"brag",text:l.join(` +`).trim()});break;case"spiel":try{if(tB(m))t.push({kind:"roundGame",game:nB(m,l,e)});else if(m==="prinzessin")t.push({kind:"rescueGame",game:oB(l,e)});else{if(m)throw new ne(`${e}: Unbekanntes Spiel „${m}“ (zuhoerer, vertrag, layout, bombe, frage, reihenfolge oder prinzessin).`);t.push({kind:"game",game:ox(l,e)})}}catch(d){throw new ne(d.message)}break;case"lückentext":case"lueckentext":try{t.push({kind:"cloze",cloze:uB(l,e)})}catch(d){throw new ne(d.message)}break;case"pap":try{t.push({kind:"pap",pap:hB(l,e)})}catch(d){throw new ne(d.message)}break;case"ludwig":t.push({kind:"brag",text:l.join(` +`).trim(),tip:!0});break;case"caesar":{const d=m?Number(m):3;if(!Number.isInteger(d)||d<0||d>25)throw new ne(`${e}: „::: caesar“ braucht einen Schlüssel von 0 bis 25.`);t.push({kind:"caesar",key:d,text:l.join(" ").trim()});break}case"mbot2":{const d={kind:"robotModel",focus:[]};for(const h of l.filter(g=>g.trim())){const g=/^\s*(fokus|focus|ansicht|view|drehen|spin):\s*(.*)$/i.exec(h);if(!g)throw new ne(`${e}: „::: mbot2“ kennt nur Zeilen „fokus:“, „ansicht:“ und „drehen:“.`);const f=g[1].toLowerCase();f==="fokus"||f==="focus"?d.focus=Ju(g[2],e):f==="ansicht"||f==="view"?d.view=g[2].trim().toLowerCase():d.spin=/^(ja|yes|true|sim)$/i.test(g[2].trim())}t.push(d);break}case"mbot2quiz":{const d={kind:"robotQuiz",tasks:[]};for(const h of l.filter(g=>g.trim())){const g=/^\s*-\s*(\w+)\s*:\s*(.+)$/.exec(h),f=/^\s*(fertig|done):\s*(.+)$/i.exec(h);if(g)d.tasks.push({part:Ju(g[1],e)[0],question:g[2].trim()});else if(f)d.done=f[2].trim();else throw new ne(`${e}: „::: mbot2quiz“ braucht Zeilen „- teil: Frage“ und optional „fertig: Text“.`)}if(!d.tasks.length)throw new ne(`${e}: „::: mbot2quiz“ hat keine Fragen.`);t.push(d);break}case"datei":{if(!/^[\w.-]+\.(txt|csv|json)$/u.test(m))throw new ne(`${e}: „::: datei“ braucht einen Dateinamen wie brief.txt, liste.csv oder daten.json.`);for(;l.length&&l[0].trim()==="";)l.shift();for(;l.length&&l[l.length-1].trim()==="";)l.pop();t.push({kind:"textFile",name:m,content:l.join(` +`)});break}default:throw new ne(`${e}: Unbekannter Block „::: ${o[1]}“.`)}r=u}return s(),t}function SB(i){const e=/^(.*?)\s+→\s+(.+)$/.exec(i);return e?{text:e[1],ref:e[2].trim()}:{text:i}}function TB(i,e){const t=new Map(i.map((a,s)=>[a.title.toLowerCase(),s]));for(const a of i.flatMap(s=>s.blocks))if(a.kind==="checklist"){for(const s of a.items)if(s.ref!==void 0&&(s.step=t.get(s.ref.toLowerCase()),s.step===void 0))throw new ne(`${e}: Checkliste verweist auf unbekannten Schritt „${s.ref}“.`)}const n=new Set(i.flatMap(a=>a.blocks).flatMap(a=>a.kind==="checklist"?a.items.map(s=>s.step):[]));for(const a of i.flatMap(s=>s.blocks))if(a.kind==="quiz"){for(const s of a.questions)if(s.ref!==void 0){if(s.step=t.get(s.ref.toLowerCase()),s.step===void 0)throw new ne(`${e}: Quizfrage „${s.question}“ verweist auf unbekannten Schritt „${s.ref}“.`);if(!n.has(s.step))throw new ne(`${e}: Zu „${s.ref}“ (Quizfrage „${s.question}“) gibt es keinen Checklistenpunkt.`)}}}function _B(i,e){var m;const{meta:t,body:n}=Yh(i,e),a=e.replace(/^.*\//,"").replace(/\.md$/,""),s=Number((m=/^(\d+)/.exec(a))==null?void 0:m[1]);if(!Number.isFinite(s))throw new ne(`${e}: Dateiname muss mit der Nummer beginnen (z. B. 01-…).`);const r=[];let o=[],l;const u=()=>{l&&r.push({title:l.title,blocks:Kh(l.lines.join(` +`),e)})};for(const d of n.split(` +`)){const h=/^##\s+(.*)$/.exec(d);h?(u(),l={title:h[1].trim(),lines:[]}):l?l.lines.push(d):o.push(d)}if(u(),r.length===0)throw new ne(`${e}: Keine Schritte (## Überschrift) gefunden.`);TB(r,e);const c=t.get("titel");if(!c)throw new ne(`${e}: „titel:“ fehlt.`);return{id:a,number:s,title:c,section:t.get("bereich")??"",summary:t.get("kurz")??o.join(" ").trim(),steps:r}}function AB(i,e){const{meta:t,body:n}=Yh(i,e),a=t.get("titel");if(!a)throw new ne(`${e}: „titel:“ fehlt.`);const s=t.get("nach");return{id:e.replace(/^.*\//,"").replace(/\.md$/,""),title:a,after:s?Number(s):void 0,level:Number(t.get("stufe")??"1")||1,blocks:Kh(n,e)}}function Ju(i,e){const t=i.split(/\s*,\s*/).map(n=>n.trim()).filter(Boolean);for(const n of t)if(!k3(n))throw new ne(`${e}: Unbekanntes Teil „${n}“. Bekannt: ${hh.join(", ")}.`);return t}const OB=Object.assign({"../../lessons/de/01-was-ist-ein-struktogramm.md":gx,"../../lessons/de/02-der-editor.md":px,"../../lessons/de/03-speichern-oeffnen-exportieren.md":fx,"../../lessons/de/04-variablen-und-datentypen.md":bx,"../../lessons/de/05-sequenz.md":xx,"../../lessons/de/06-eingabe-und-ausgabe.md":vx,"../../lessons/de/07-simulation-und-schreibtischtest.md":yx,"../../lessons/de/08-verzweigung.md":wx,"../../lessons/de/09-bedingungen-verknuepfen.md":zx,"../../lessons/de/10-fallauswahl.md":Ix,"../../lessons/de/11-while-schleife.md":kx,"../../lessons/de/12-do-while-schleife.md":Sx,"../../lessons/de/13-for-schleife.md":Tx,"../../lessons/de/14-verschachteln.md":_x,"../../lessons/de/15-arrays.md":Ax,"../../lessons/de/16-zweidimensionale-arrays.md":Ox,"../../lessons/de/17-zeichenketten.md":Cx,"../../lessons/de/18-aufruf-und-aussprung.md":jx,"../../lessons/de/19-suchen-und-sortieren.md":Px,"../../lessons/de/20-java.md":Dx,"../../lessons/de/21-python-und-javascript.md":Bx,"../../lessons/de/22-try-und-catch.md":Mx,"../../lessons/de/23-text-einlesen-und-speichern.md":Zx,"../../lessons/de/24-zeile-fuer-zeile.md":Lx,"../../lessons/de/25-tabellen-als-csv.md":Ex,"../../lessons/de/26-json.md":Wx,"../../lessons/de/27-formate-im-vergleich.md":Nx,"../../lessons/de/28-erstes-fenster.md":Fx,"../../lessons/de/29-knopf-im-fenster.md":Jx,"../../lessons/de/30-der-knopf-reagiert.md":Rx,"../../lessons/de/31-zahl-verdoppeln.md":Gx,"../../lessons/de/32-klickzaehler.md":Hx,"../../lessons/de/33-ampel.md":Vx,"../../lessons/de/34-notenrechner.md":qx,"../../lessons/de/35-taschenrechner.md":Qx,"../../lessons/de/36-zahlenraten.md":Ux,"../../lessons/de/37-viele-knoepfe-ein-zuhoerer.md":$x,"../../lessons/de/38-innere-klassen.md":Yx,"../../lessons/de/39-zwei-reiter.md":Xx,"../../lessons/de/40-model-view-controller.md":Kx,"../../lessons/de/begriffe.md":e4,"../../lessons/de/nachschlagen.md":t4,"../../lessons/en/01-was-ist-ein-struktogramm.md":n4,"../../lessons/en/02-der-editor.md":i4,"../../lessons/en/03-speichern-oeffnen-exportieren.md":a4,"../../lessons/en/04-variablen-und-datentypen.md":s4,"../../lessons/en/05-sequenz.md":r4,"../../lessons/en/06-eingabe-und-ausgabe.md":o4,"../../lessons/en/07-simulation-und-schreibtischtest.md":l4,"../../lessons/en/08-verzweigung.md":u4,"../../lessons/en/09-bedingungen-verknuepfen.md":c4,"../../lessons/en/10-fallauswahl.md":m4,"../../lessons/en/11-while-schleife.md":d4,"../../lessons/en/12-do-while-schleife.md":h4,"../../lessons/en/13-for-schleife.md":g4,"../../lessons/en/14-verschachteln.md":p4,"../../lessons/en/15-arrays.md":f4,"../../lessons/en/16-zweidimensionale-arrays.md":b4,"../../lessons/en/17-zeichenketten.md":x4,"../../lessons/en/18-aufruf-und-aussprung.md":v4,"../../lessons/en/19-suchen-und-sortieren.md":y4,"../../lessons/en/20-java.md":w4,"../../lessons/en/21-python-und-javascript.md":z4,"../../lessons/en/22-try-und-catch.md":I4,"../../lessons/en/23-text-einlesen-und-speichern.md":k4,"../../lessons/en/24-zeile-fuer-zeile.md":S4,"../../lessons/en/25-tabellen-als-csv.md":T4,"../../lessons/en/26-json.md":_4,"../../lessons/en/27-formate-im-vergleich.md":A4,"../../lessons/en/28-erstes-fenster.md":O4,"../../lessons/en/29-knopf-im-fenster.md":C4,"../../lessons/en/30-der-knopf-reagiert.md":j4,"../../lessons/en/31-zahl-verdoppeln.md":P4,"../../lessons/en/32-klickzaehler.md":D4,"../../lessons/en/33-ampel.md":B4,"../../lessons/en/34-notenrechner.md":M4,"../../lessons/en/35-taschenrechner.md":Z4,"../../lessons/en/36-zahlenraten.md":L4,"../../lessons/en/37-viele-knoepfe-ein-zuhoerer.md":E4,"../../lessons/en/38-innere-klassen.md":W4,"../../lessons/en/39-zwei-reiter.md":N4,"../../lessons/en/40-model-view-controller.md":F4,"../../lessons/en/begriffe.md":J4,"../../lessons/en/nachschlagen.md":R4,"../../lessons/pt/01-was-ist-ein-struktogramm.md":G4,"../../lessons/pt/02-der-editor.md":H4,"../../lessons/pt/03-speichern-oeffnen-exportieren.md":V4,"../../lessons/pt/04-variablen-und-datentypen.md":q4,"../../lessons/pt/05-sequenz.md":Q4,"../../lessons/pt/06-eingabe-und-ausgabe.md":U4,"../../lessons/pt/07-simulation-und-schreibtischtest.md":$4,"../../lessons/pt/08-verzweigung.md":Y4,"../../lessons/pt/09-bedingungen-verknuepfen.md":X4,"../../lessons/pt/10-fallauswahl.md":K4,"../../lessons/pt/11-while-schleife.md":ev,"../../lessons/pt/12-do-while-schleife.md":tv,"../../lessons/pt/13-for-schleife.md":nv,"../../lessons/pt/14-verschachteln.md":iv,"../../lessons/pt/15-arrays.md":av,"../../lessons/pt/16-zweidimensionale-arrays.md":sv,"../../lessons/pt/17-zeichenketten.md":rv,"../../lessons/pt/18-aufruf-und-aussprung.md":ov,"../../lessons/pt/19-suchen-und-sortieren.md":lv,"../../lessons/pt/20-java.md":uv,"../../lessons/pt/21-python-und-javascript.md":cv,"../../lessons/pt/22-try-und-catch.md":mv,"../../lessons/pt/23-text-einlesen-und-speichern.md":dv,"../../lessons/pt/24-zeile-fuer-zeile.md":hv,"../../lessons/pt/25-tabellen-als-csv.md":gv,"../../lessons/pt/26-json.md":pv,"../../lessons/pt/27-formate-im-vergleich.md":fv,"../../lessons/pt/28-erstes-fenster.md":bv,"../../lessons/pt/29-knopf-im-fenster.md":xv,"../../lessons/pt/30-der-knopf-reagiert.md":vv,"../../lessons/pt/31-zahl-verdoppeln.md":yv,"../../lessons/pt/32-klickzaehler.md":wv,"../../lessons/pt/33-ampel.md":zv,"../../lessons/pt/34-notenrechner.md":Iv,"../../lessons/pt/35-taschenrechner.md":kv,"../../lessons/pt/36-zahlenraten.md":Sv,"../../lessons/pt/37-viele-knoepfe-ein-zuhoerer.md":Tv,"../../lessons/pt/38-innere-klassen.md":_v,"../../lessons/pt/39-zwei-reiter.md":Av,"../../lessons/pt/40-model-view-controller.md":Ov,"../../lessons/pt/begriffe.md":Cv,"../../lessons/pt/nachschlagen.md":jv}),CB=Object.assign({"../../lessons/de/aufgaben/alter-unterprogramm.md":Pv,"../../lessons/de/aufgaben/ballwurf.md":Dv,"../../lessons/de/aufgaben/bestenliste.md":Bv,"../../lessons/de/aufgaben/binaerzahl.md":Mv,"../../lessons/de/aufgaben/caesar.md":Zv,"../../lessons/de/aufgaben/collatz.md":Lv,"../../lessons/de/aufgaben/einheitenrechner.md":Ev,"../../lessons/de/aufgaben/fibonacci.md":Wv,"../../lessons/de/aufgaben/gerade-ungerade.md":Nv,"../../lessons/de/aufgaben/mehrwertsteuer.md":Fv,"../../lessons/de/aufgaben/notendurchschnitt.md":Jv,"../../lessons/de/aufgaben/pin-pruefen.md":Rv,"../../lessons/de/aufgaben/schiffe-versenken.md":Gv,"../../lessons/de/aufgaben/speisekarte.md":Hv,"../../lessons/de/aufgaben/summe-bilden.md":Vv,"../../lessons/de/aufgaben/tafeldienst.md":qv,"../../lessons/de/aufgaben/taschenrechner.md":Qv,"../../lessons/de/aufgaben/verleih-menue.md":Uv,"../../lessons/de/aufgaben/vokabeltrainer.md":$v,"../../lessons/de/aufgaben/volljaehrig.md":Yv,"../../lessons/de/aufgaben/wuerfel-mvc.md":Xv,"../../lessons/de/aufgaben/zahl-verdoppeln.md":Kv,"../../lessons/en/aufgaben/alter-unterprogramm.md":ey,"../../lessons/en/aufgaben/ballwurf.md":ty,"../../lessons/en/aufgaben/bestenliste.md":ny,"../../lessons/en/aufgaben/binaerzahl.md":iy,"../../lessons/en/aufgaben/caesar.md":ay,"../../lessons/en/aufgaben/collatz.md":sy,"../../lessons/en/aufgaben/einheitenrechner.md":ry,"../../lessons/en/aufgaben/fibonacci.md":oy,"../../lessons/en/aufgaben/gerade-ungerade.md":ly,"../../lessons/en/aufgaben/mehrwertsteuer.md":uy,"../../lessons/en/aufgaben/notendurchschnitt.md":cy,"../../lessons/en/aufgaben/pin-pruefen.md":my,"../../lessons/en/aufgaben/schiffe-versenken.md":dy,"../../lessons/en/aufgaben/speisekarte.md":hy,"../../lessons/en/aufgaben/summe-bilden.md":gy,"../../lessons/en/aufgaben/tafeldienst.md":py,"../../lessons/en/aufgaben/taschenrechner.md":fy,"../../lessons/en/aufgaben/verleih-menue.md":by,"../../lessons/en/aufgaben/vokabeltrainer.md":xy,"../../lessons/en/aufgaben/volljaehrig.md":vy,"../../lessons/en/aufgaben/wuerfel-mvc.md":yy,"../../lessons/en/aufgaben/zahl-verdoppeln.md":wy,"../../lessons/pt/aufgaben/alter-unterprogramm.md":zy,"../../lessons/pt/aufgaben/ballwurf.md":Iy,"../../lessons/pt/aufgaben/bestenliste.md":ky,"../../lessons/pt/aufgaben/binaerzahl.md":Sy,"../../lessons/pt/aufgaben/caesar.md":Ty,"../../lessons/pt/aufgaben/collatz.md":_y,"../../lessons/pt/aufgaben/einheitenrechner.md":Ay,"../../lessons/pt/aufgaben/fibonacci.md":Oy,"../../lessons/pt/aufgaben/gerade-ungerade.md":Cy,"../../lessons/pt/aufgaben/mehrwertsteuer.md":jy,"../../lessons/pt/aufgaben/notendurchschnitt.md":Py,"../../lessons/pt/aufgaben/pin-pruefen.md":Dy,"../../lessons/pt/aufgaben/schiffe-versenken.md":By,"../../lessons/pt/aufgaben/speisekarte.md":My,"../../lessons/pt/aufgaben/summe-bilden.md":Zy,"../../lessons/pt/aufgaben/tafeldienst.md":Ly,"../../lessons/pt/aufgaben/taschenrechner.md":Ey,"../../lessons/pt/aufgaben/verleih-menue.md":Wy,"../../lessons/pt/aufgaben/vokabeltrainer.md":Ny,"../../lessons/pt/aufgaben/volljaehrig.md":Fy,"../../lessons/pt/aufgaben/wuerfel-mvc.md":Jy,"../../lessons/pt/aufgaben/zahl-verdoppeln.md":Ry}),Ru=Object.assign({"../../lessons/de/visubot/01-der-mbot2.md":Gy,"../../lessons/de/visubot/02-das-quadrat.md":Hy,"../../lessons/de/visubot/03-variablen-und-ausgabe.md":Vy,"../../lessons/de/visubot/04-sensoren.md":qy,"../../lessons/de/visubot/05-bis-zur-wand.md":Qy,"../../lessons/de/visubot/06-abstand.md":Uy,"../../lessons/de/visubot/07-linie.md":$y,"../../lessons/de/visubot/08-farben.md":Yy,"../../lessons/de/visubot/09-fallauswahl.md":Xy,"../../lessons/de/visubot/10-tasten-joystick.md":Ky,"../../lessons/de/visubot/11-licht.md":ew,"../../lessons/de/visubot/12-lautstaerke.md":tw,"../../lessons/de/visubot/13-neigung.md":nw,"../../lessons/de/visubot/14-leds.md":iw,"../../lessons/de/visubot/15-einzelne-leds.md":aw,"../../lessons/de/visubot/16-lautsprecher.md":sw,"../../lessons/de/visubot/17-arrays-melodie.md":rw,"../../lessons/de/visubot/18-bildschirm.md":ow,"../../lessons/de/visubot/19-zeichenketten.md":lw,"../../lessons/de/visubot/20-motoren.md":uw,"../../lessons/de/visubot/21-stoppuhr-akku.md":cw,"../../lessons/de/visubot/22-eigene-methoden.md":mw,"../../lessons/de/visubot/nachschlagen.md":dw,"../../lessons/en/visubot/01-der-mbot2.md":hw,"../../lessons/en/visubot/02-das-quadrat.md":gw,"../../lessons/en/visubot/03-variablen-und-ausgabe.md":pw,"../../lessons/en/visubot/04-sensoren.md":fw,"../../lessons/en/visubot/05-bis-zur-wand.md":bw,"../../lessons/en/visubot/06-abstand.md":xw,"../../lessons/en/visubot/07-linie.md":vw,"../../lessons/en/visubot/08-farben.md":yw,"../../lessons/en/visubot/09-fallauswahl.md":ww,"../../lessons/en/visubot/10-tasten-joystick.md":zw,"../../lessons/en/visubot/11-licht.md":Iw,"../../lessons/en/visubot/12-lautstaerke.md":kw,"../../lessons/en/visubot/13-neigung.md":Sw,"../../lessons/en/visubot/14-leds.md":Tw,"../../lessons/en/visubot/15-einzelne-leds.md":_w,"../../lessons/en/visubot/16-lautsprecher.md":Aw,"../../lessons/en/visubot/17-arrays-melodie.md":Ow,"../../lessons/en/visubot/18-bildschirm.md":Cw,"../../lessons/en/visubot/19-zeichenketten.md":jw,"../../lessons/en/visubot/20-motoren.md":Pw,"../../lessons/en/visubot/21-stoppuhr-akku.md":Dw,"../../lessons/en/visubot/22-eigene-methoden.md":Bw,"../../lessons/en/visubot/nachschlagen.md":Mw}),jB=Object.assign({"../../lessons/de/visubot/aufgaben/alarmanlage.md":Zw,"../../lessons/de/visubot/aufgaben/ausgang.md":Lw,"../../lessons/de/visubot/aufgaben/binaer-zaehlen.md":Ew,"../../lessons/de/visubot/aufgaben/dreieck.md":Ww,"../../lessons/de/visubot/aufgaben/einparken.md":Nw,"../../lessons/de/visubot/aufgaben/hindernis.md":Fw,"../../lessons/de/visubot/aufgaben/knight-rider.md":Jw,"../../lessons/de/visubot/aufgaben/labyrinth.md":Rw,"../../lessons/de/visubot/aufgaben/linienfolger-stopp.md":Gw,"../../lessons/de/visubot/aufgaben/morsen.md":Hw,"../../lessons/de/visubot/aufgaben/nachtwaechter.md":Vw,"../../lessons/de/visubot/aufgaben/slalom.md":qw,"../../lessons/de/visubot/aufgaben/spirale.md":Qw,"../../lessons/de/visubot/aufgaben/treppe.md":Uw,"../../lessons/de/visubot/aufgaben/tunnel.md":$w,"../../lessons/de/visubot/aufgaben/wald.md":Yw,"../../lessons/en/visubot/aufgaben/alarmanlage.md":Xw,"../../lessons/en/visubot/aufgaben/ausgang.md":Kw,"../../lessons/en/visubot/aufgaben/binaer-zaehlen.md":e9,"../../lessons/en/visubot/aufgaben/dreieck.md":t9,"../../lessons/en/visubot/aufgaben/einparken.md":n9,"../../lessons/en/visubot/aufgaben/hindernis.md":i9,"../../lessons/en/visubot/aufgaben/knight-rider.md":a9,"../../lessons/en/visubot/aufgaben/labyrinth.md":s9,"../../lessons/en/visubot/aufgaben/linienfolger-stopp.md":r9,"../../lessons/en/visubot/aufgaben/morsen.md":o9,"../../lessons/en/visubot/aufgaben/nachtwaechter.md":l9,"../../lessons/en/visubot/aufgaben/slalom.md":u9,"../../lessons/en/visubot/aufgaben/spirale.md":c9,"../../lessons/en/visubot/aufgaben/treppe.md":m9,"../../lessons/en/visubot/aufgaben/tunnel.md":d9,"../../lessons/en/visubot/aufgaben/wald.md":h9}),PB=Object.assign({"../../lessons/diagramme/aufgabe-alter-haupt-loesung.visustruct":g9,"../../lessons/diagramme/aufgabe-alter-unterprogramm-loesung.visustruct":p9,"../../lessons/diagramme/aufgabe-ballwurf-loesung.visustruct":f9,"../../lessons/diagramme/aufgabe-ballwurf-start.visustruct":b9,"../../lessons/diagramme/aufgabe-bestenliste-loesung.visustruct":x9,"../../lessons/diagramme/aufgabe-binaer-loesung.visustruct":v9,"../../lessons/diagramme/aufgabe-caesar-array-loesung.visustruct":y9,"../../lessons/diagramme/aufgabe-caesar-array-start.visustruct":w9,"../../lessons/diagramme/aufgabe-caesar-ascii-loesung.visustruct":z9,"../../lessons/diagramme/aufgabe-caesar-entschluesseln-loesung.visustruct":I9,"../../lessons/diagramme/aufgabe-collatz-loesung.visustruct":k9,"../../lessons/diagramme/aufgabe-durchschnitt-loesung.visustruct":S9,"../../lessons/diagramme/aufgabe-fibonacci-loesung.visustruct":T9,"../../lessons/diagramme/aufgabe-gerade-loesung.visustruct":_9,"../../lessons/diagramme/aufgabe-mehrwertsteuer-loesung.visustruct":A9,"../../lessons/diagramme/aufgabe-pin-java-loesung.visustruct":O9,"../../lessons/diagramme/aufgabe-pin-loesung.visustruct":C9,"../../lessons/diagramme/aufgabe-rechner-loesung.visustruct":j9,"../../lessons/diagramme/aufgabe-schiffe-loesung.visustruct":P9,"../../lessons/diagramme/aufgabe-schiffe-start.visustruct":D9,"../../lessons/diagramme/aufgabe-speisekarte-loesung.visustruct":B9,"../../lessons/diagramme/aufgabe-summe-loesung.visustruct":M9,"../../lessons/diagramme/aufgabe-tafeldienst-loesung.visustruct":Z9,"../../lessons/diagramme/aufgabe-verdoppeln-loesung.visustruct":L9,"../../lessons/diagramme/aufgabe-verleih-java-loesung.visustruct":E9,"../../lessons/diagramme/aufgabe-verleih-loesung.visustruct":W9,"../../lessons/diagramme/aufgabe-vokabeln-loesung.visustruct":N9,"../../lessons/diagramme/aufgabe-vokabeln-start.visustruct":F9,"../../lessons/diagramme/aufgabe-volljaehrig-loesung.visustruct":J9,"../../lessons/diagramme/dt-buffered.visustruct":R9,"../../lessons/diagramme/dt-csv.visustruct":G9,"../../lessons/diagramme/dt-json.visustruct":H9,"../../lessons/diagramme/dt-lesen.visustruct":V9,"../../lessons/diagramme/en/aufgabe-alter-haupt-loesung.visustruct":q9,"../../lessons/diagramme/en/aufgabe-alter-unterprogramm-loesung.visustruct":Q9,"../../lessons/diagramme/en/aufgabe-ballwurf-loesung.visustruct":U9,"../../lessons/diagramme/en/aufgabe-ballwurf-start.visustruct":$9,"../../lessons/diagramme/en/aufgabe-bestenliste-loesung.visustruct":Y9,"../../lessons/diagramme/en/aufgabe-binaer-loesung.visustruct":X9,"../../lessons/diagramme/en/aufgabe-caesar-array-loesung.visustruct":K9,"../../lessons/diagramme/en/aufgabe-caesar-array-start.visustruct":e5,"../../lessons/diagramme/en/aufgabe-caesar-ascii-loesung.visustruct":t5,"../../lessons/diagramme/en/aufgabe-caesar-entschluesseln-loesung.visustruct":n5,"../../lessons/diagramme/en/aufgabe-collatz-loesung.visustruct":i5,"../../lessons/diagramme/en/aufgabe-durchschnitt-loesung.visustruct":a5,"../../lessons/diagramme/en/aufgabe-fibonacci-loesung.visustruct":s5,"../../lessons/diagramme/en/aufgabe-gerade-loesung.visustruct":r5,"../../lessons/diagramme/en/aufgabe-mehrwertsteuer-loesung.visustruct":o5,"../../lessons/diagramme/en/aufgabe-pin-java-loesung.visustruct":l5,"../../lessons/diagramme/en/aufgabe-pin-loesung.visustruct":u5,"../../lessons/diagramme/en/aufgabe-rechner-loesung.visustruct":c5,"../../lessons/diagramme/en/aufgabe-schiffe-loesung.visustruct":m5,"../../lessons/diagramme/en/aufgabe-schiffe-start.visustruct":d5,"../../lessons/diagramme/en/aufgabe-speisekarte-loesung.visustruct":h5,"../../lessons/diagramme/en/aufgabe-summe-loesung.visustruct":g5,"../../lessons/diagramme/en/aufgabe-tafeldienst-loesung.visustruct":p5,"../../lessons/diagramme/en/aufgabe-verdoppeln-loesung.visustruct":f5,"../../lessons/diagramme/en/aufgabe-verleih-java-loesung.visustruct":b5,"../../lessons/diagramme/en/aufgabe-verleih-loesung.visustruct":x5,"../../lessons/diagramme/en/aufgabe-vokabeln-loesung.visustruct":v5,"../../lessons/diagramme/en/aufgabe-vokabeln-start.visustruct":y5,"../../lessons/diagramme/en/aufgabe-volljaehrig-loesung.visustruct":w5,"../../lessons/diagramme/en/dt-buffered.visustruct":z5,"../../lessons/diagramme/en/dt-csv.visustruct":I5,"../../lessons/diagramme/en/dt-json.visustruct":k5,"../../lessons/diagramme/en/dt-lesen.visustruct":S5,"../../lessons/diagramme/en/kino-einmaleins-loesung.visustruct":T5,"../../lessons/diagramme/en/kino-frei-loesung.visustruct":_5,"../../lessons/diagramme/en/kino-frei-start.visustruct":A5,"../../lessons/diagramme/en/kino-karte-loesung.visustruct":O5,"../../lessons/diagramme/en/kino-karte-start.visustruct":C5,"../../lessons/diagramme/en/kino-saalplan.visustruct":j5,"../../lessons/diagramme/en/kino-verkaufen.visustruct":P5,"../../lessons/diagramme/en/l04-java-fehler-loesung.visustruct":D5,"../../lessons/diagramme/en/l04-java-fehler-start.visustruct":B5,"../../lessons/diagramme/en/l04-java-steckbrief-loesung.visustruct":M5,"../../lessons/diagramme/en/l04-rechnen.visustruct":Z5,"../../lessons/diagramme/en/l04-reihenfolge-loesung.visustruct":L5,"../../lessons/diagramme/en/l04-reihenfolge-start.visustruct":E5,"../../lessons/diagramme/en/l04-tauschen-loesung.visustruct":W5,"../../lessons/diagramme/en/l04-tauschen-start.visustruct":N5,"../../lessons/diagramme/en/l04-tauschen.visustruct":F5,"../../lessons/diagramme/en/l05-datentypen.visustruct":J5,"../../lessons/diagramme/en/l05-division.visustruct":R5,"../../lessons/diagramme/en/l05-einkauf-loesung.visustruct":G5,"../../lessons/diagramme/en/l05-java-fehler-loesung.visustruct":H5,"../../lessons/diagramme/en/l05-java-fehler-start.visustruct":V5,"../../lessons/diagramme/en/l05-java-kino-loesung.visustruct":q5,"../../lessons/diagramme/en/l05-rechteck-loesung.visustruct":Q5,"../../lessons/diagramme/en/l05-sekunden-loesung.visustruct":U5,"../../lessons/diagramme/en/l05-sekunden-start.visustruct":$5,"../../lessons/diagramme/en/l05-sequenz.visustruct":Y5,"../../lessons/diagramme/en/l06-begruessung-loesung.visustruct":X5,"../../lessons/diagramme/en/l06-eva.visustruct":K5,"../../lessons/diagramme/en/l06-java-fehler-loesung.visustruct":ez,"../../lessons/diagramme/en/l06-java-fehler-start.visustruct":tz,"../../lessons/diagramme/en/l06-java-tage-loesung.visustruct":nz,"../../lessons/diagramme/en/l06-mittelwert-loesung.visustruct":iz,"../../lessons/diagramme/en/l06-rechner-loesung.visustruct":az,"../../lessons/diagramme/en/l07-alter-pruefen.visustruct":sz,"../../lessons/diagramme/en/l07-betrag-loesung.visustruct":rz,"../../lessons/diagramme/en/l07-gerade-loesung.visustruct":oz,"../../lessons/diagramme/en/l07-java-fehler-loesung.visustruct":lz,"../../lessons/diagramme/en/l07-java-fehler-start.visustruct":uz,"../../lessons/diagramme/en/l07-java-pizza-loesung.visustruct":cz,"../../lessons/diagramme/en/l07-java-pizza-start.visustruct":mz,"../../lessons/diagramme/en/l07-maximum-loesung.visustruct":dz,"../../lessons/diagramme/en/l07-rabatt.visustruct":hz,"../../lessons/diagramme/en/l08-gueltig-loesung.visustruct":gz,"../../lessons/diagramme/en/l08-java-bestanden-loesung.visustruct":pz,"../../lessons/diagramme/en/l08-java-fehler-loesung.visustruct":fz,"../../lessons/diagramme/en/l08-java-fehler-start.visustruct":bz,"../../lessons/diagramme/en/l08-jugendticket.visustruct":xz,"../../lessons/diagramme/en/l08-note.visustruct":vz,"../../lessons/diagramme/en/l08-schaltjahr-loesung.visustruct":yz,"../../lessons/diagramme/en/l08-wochenende-loesung.visustruct":wz,"../../lessons/diagramme/en/l09-ampel.visustruct":zz,"../../lessons/diagramme/en/l09-automat.visustruct":Iz,"../../lessons/diagramme/en/l09-java-fehler-loesung.visustruct":kz,"../../lessons/diagramme/en/l09-java-fehler-start.visustruct":Sz,"../../lessons/diagramme/en/l09-java-schule-loesung.visustruct":Tz,"../../lessons/diagramme/en/l09-note-loesung.visustruct":_z,"../../lessons/diagramme/en/l09-rechner-loesung.visustruct":Az,"../../lessons/diagramme/en/l09-verschachtelt.visustruct":Oz,"../../lessons/diagramme/en/l1-grundbausteine.visustruct":Cz,"../../lessons/diagramme/en/l1-sequenz.visustruct":jz,"../../lessons/diagramme/en/l1-tee.visustruct":Pz,"../../lessons/diagramme/en/l1-verzweigung.visustruct":Dz,"../../lessons/diagramme/en/l1-wiederholung.visustruct":Bz,"../../lessons/diagramme/en/l10-bis-n-loesung.visustruct":Mz,"../../lessons/diagramme/en/l10-countdown.visustruct":Zz,"../../lessons/diagramme/en/l10-endlos.visustruct":Lz,"../../lessons/diagramme/en/l10-fakultaet.visustruct":Ez,"../../lessons/diagramme/en/l10-java-fehler-loesung.visustruct":Wz,"../../lessons/diagramme/en/l10-java-fehler-start.visustruct":Nz,"../../lessons/diagramme/en/l10-java-wuerfel-loesung.visustruct":Fz,"../../lessons/diagramme/en/l10-verdoppeln-loesung.visustruct":Jz,"../../lessons/diagramme/en/l11-eingabe-pruefen.visustruct":Rz,"../../lessons/diagramme/en/l11-einmal.visustruct":Gz,"../../lessons/diagramme/en/l11-java-fehler-loesung.visustruct":Hz,"../../lessons/diagramme/en/l11-java-fehler-start.visustruct":Vz,"../../lessons/diagramme/en/l11-java-gerade-loesung.visustruct":qz,"../../lessons/diagramme/en/l11-note-loesung.visustruct":Qz,"../../lessons/diagramme/en/l11-summe-loesung.visustruct":Uz,"../../lessons/diagramme/en/l12-countdown-loesung.visustruct":$z,"../../lessons/diagramme/en/l12-einmaleins-loesung.visustruct":Yz,"../../lessons/diagramme/en/l12-eins-bis-fuenf.visustruct":Xz,"../../lessons/diagramme/en/l12-java-fehler-loesung.visustruct":Kz,"../../lessons/diagramme/en/l12-java-fehler-start.visustruct":e6,"../../lessons/diagramme/en/l12-java-verdoppeln-loesung.visustruct":t6,"../../lessons/diagramme/en/l12-summe.visustruct":n6,"../../lessons/diagramme/en/l13-dreieck.visustruct":i6,"../../lessons/diagramme/en/l13-gerade-eingaben-loesung.visustruct":a6,"../../lessons/diagramme/en/l13-gerade-zaehlen.visustruct":s6,"../../lessons/diagramme/en/l13-java-fehler-loesung.visustruct":r6,"../../lessons/diagramme/en/l13-java-fehler-start.visustruct":o6,"../../lessons/diagramme/en/l13-java-quadrate-loesung.visustruct":l6,"../../lessons/diagramme/en/l13-rechteck-loesung.visustruct":u6,"../../lessons/diagramme/en/l14-array-durchlaufen.visustruct":c6,"../../lessons/diagramme/en/l14-erster-letzter-loesung.visustruct":m6,"../../lessons/diagramme/en/l14-java-fehler-loesung.visustruct":d6,"../../lessons/diagramme/en/l14-java-fehler-start.visustruct":h6,"../../lessons/diagramme/en/l14-java-treppe-loesung.visustruct":g6,"../../lessons/diagramme/en/l14-namen-eingeben.visustruct":p6,"../../lessons/diagramme/en/l14-rueckwaerts-loesung.visustruct":f6,"../../lessons/diagramme/en/l14-summe-max-loesung.visustruct":b6,"../../lessons/diagramme/en/l14-summe-maximum.visustruct":x6,"../../lessons/diagramme/en/l15-bis-null-loesung.visustruct":v6,"../../lessons/diagramme/en/l15-endlos-aussprung.visustruct":y6,"../../lessons/diagramme/en/l15-flaeche-loesung.visustruct":w6,"../../lessons/diagramme/en/l15-flaeche-unterprogramm-loesung.visustruct":z6,"../../lessons/diagramme/en/l15-hauptprogramm.visustruct":I6,"../../lessons/diagramme/en/l15-java-fehler-loesung.visustruct":k6,"../../lessons/diagramme/en/l15-java-fehler-start.visustruct":S6,"../../lessons/diagramme/en/l15-java-noten-loesung.visustruct":T6,"../../lessons/diagramme/en/l15-quadrat-haupt.visustruct":_6,"../../lessons/diagramme/en/l15-quadrat.visustruct":A6,"../../lessons/diagramme/en/l15-titel-loesung.visustruct":O6,"../../lessons/diagramme/en/l15-unterprogramm.visustruct":C6,"../../lessons/diagramme/en/l15-zeige-summe-haupt.visustruct":j6,"../../lessons/diagramme/en/l15-zeige-summe.visustruct":P6,"../../lessons/diagramme/en/l16-countdown-loesung.visustruct":D6,"../../lessons/diagramme/en/l16-countdown-start.visustruct":B6,"../../lessons/diagramme/en/l16-java-fehler-loesung.visustruct":M6,"../../lessons/diagramme/en/l16-java-fehler-start.visustruct":Z6,"../../lessons/diagramme/en/l16-java-punkte-loesung.visustruct":L6,"../../lessons/diagramme/en/l16-schreibtisch.visustruct":E6,"../../lessons/diagramme/en/l16-summe-loesung.visustruct":W6,"../../lessons/diagramme/en/l16-summe-start.visustruct":N6,"../../lessons/diagramme/en/l17-beispiel.visustruct":F6,"../../lessons/diagramme/en/l17-fakultaet-loesung.visustruct":J6,"../../lessons/diagramme/en/l17-java-brief-loesung.visustruct":R6,"../../lessons/diagramme/en/l17-java-brief-start.visustruct":G6,"../../lessons/diagramme/en/l17-java-fehler-loesung.visustruct":H6,"../../lessons/diagramme/en/l17-java-fehler-start.visustruct":V6,"../../lessons/diagramme/en/l17-java-passwort-loesung.visustruct":q6,"../../lessons/diagramme/en/l17-ticket-loesung.visustruct":Q6,"../../lessons/diagramme/en/l18-beispiel.visustruct":U6,"../../lessons/diagramme/en/l18-java-fehler-loesung.visustruct":$6,"../../lessons/diagramme/en/l18-java-fehler-start.visustruct":Y6,"../../lessons/diagramme/en/l18-java-kasse-loesung.visustruct":X6,"../../lessons/diagramme/en/l18-js-loesung.visustruct":K6,"../../lessons/diagramme/en/l18-python-loesung.visustruct":eI,"../../lessons/diagramme/en/l19-java-fehler-loesung.visustruct":tI,"../../lessons/diagramme/en/l19-java-fehler-start.visustruct":nI,"../../lessons/diagramme/en/l19-java-zaehlen-loesung.visustruct":iI,"../../lessons/diagramme/en/l2-ausgabe.visustruct":aI,"../../lessons/diagramme/en/l2-hallo-loesung.visustruct":sI,"../../lessons/diagramme/en/l2-zwei-zeilen-loesung.visustruct":rI,"../../lessons/diagramme/en/l23-java-ergaenzen-loesung.visustruct":oI,"../../lessons/diagramme/en/l23-java-ergaenzen-start.visustruct":lI,"../../lessons/diagramme/en/l23-java-nummern-loesung.visustruct":uI,"../../lessons/diagramme/en/l23-java-nummern-start.visustruct":cI,"../../lessons/diagramme/en/l24-java-fuchs-loesung.visustruct":mI,"../../lessons/diagramme/en/l24-java-fuchs-start.visustruct":dI,"../../lessons/diagramme/en/l24-java-laengster-loesung.visustruct":hI,"../../lessons/diagramme/en/l24-java-laengster-start.visustruct":gI,"../../lessons/diagramme/en/l25-java-beste-loesung.visustruct":pI,"../../lessons/diagramme/en/l25-java-beste-start.visustruct":fI,"../../lessons/diagramme/en/l25-java-schnitt-loesung.visustruct":bI,"../../lessons/diagramme/en/l25-java-schnitt-start.visustruct":xI,"../../lessons/diagramme/en/l26-java-namen-loesung.visustruct":vI,"../../lessons/diagramme/en/l26-java-namen-start.visustruct":yI,"../../lessons/diagramme/en/l26-java-schreiben-loesung.visustruct":wI,"../../lessons/diagramme/en/l26-java-schreiben-start.visustruct":zI,"../../lessons/diagramme/en/l27-java-json-loesung.visustruct":II,"../../lessons/diagramme/en/l27-java-json-start.visustruct":kI,"../../lessons/diagramme/en/l27-java-saetze-loesung.visustruct":SI,"../../lessons/diagramme/en/l27-java-saetze-start.visustruct":TI,"../../lessons/diagramme/en/sim-kino-loesung.visustruct":_I,"../../lessons/diagramme/en/sim-kino-start.visustruct":AI,"../../lessons/diagramme/en/sim-tausch-loesung.visustruct":OI,"../../lessons/diagramme/en/sim-tausch-start.visustruct":CI,"../../lessons/diagramme/en/sim-tausch.visustruct":jI,"../../lessons/diagramme/en/ss-absteigend-loesung.visustruct":PI,"../../lessons/diagramme/en/ss-absteigend-start.visustruct":DI,"../../lessons/diagramme/en/ss-binaere-suche.visustruct":BI,"../../lessons/diagramme/en/ss-bubblesort.visustruct":MI,"../../lessons/diagramme/en/ss-karte-suchen-loesung.visustruct":ZI,"../../lessons/diagramme/en/ss-lineare-suche.visustruct":LI,"../../lessons/diagramme/en/uebergabe-bonus-loesung.visustruct":EI,"../../lessons/diagramme/en/uebergabe-bonus-start.visustruct":WI,"../../lessons/diagramme/en/uebergabe-bonus-unterprogramm-loesung.visustruct":NI,"../../lessons/diagramme/en/uebergabe-haupt.visustruct":FI,"../../lessons/diagramme/en/uebergabe-leeren.visustruct":JI,"../../lessons/diagramme/en/uebergabe-verdopple.visustruct":RI,"../../lessons/diagramme/en/vb-abstand-anzeigen-loesung.visustruct":GI,"../../lessons/diagramme/en/vb-abstand-halten-loesung.visustruct":HI,"../../lessons/diagramme/en/vb-alarmanlage-loesung.visustruct":VI,"../../lessons/diagramme/en/vb-ampel-loesung.visustruct":qI,"../../lessons/diagramme/en/vb-ausgang-loesung.visustruct":QI,"../../lessons/diagramme/en/vb-begruessung-loesung.visustruct":UI,"../../lessons/diagramme/en/vb-binaer-zaehlen-loesung.visustruct":$I,"../../lessons/diagramme/en/vb-bis-rot-loesung.visustruct":YI,"../../lessons/diagramme/en/vb-bis-wand-loesung.visustruct":XI,"../../lessons/diagramme/en/vb-bis-ziel-loesung.visustruct":KI,"../../lessons/diagramme/en/vb-buchstaben-loesung.visustruct":e7,"../../lessons/diagramme/en/vb-drei-lichter-loesung.visustruct":t7,"../../lessons/diagramme/en/vb-dreieck-loesung.visustruct":n7,"../../lessons/diagramme/en/vb-einparken-loesung.visustruct":i7,"../../lessons/diagramme/en/vb-farben-loesung.visustruct":a7,"../../lessons/diagramme/en/vb-farbweiche-loesung.visustruct":s7,"../../lessons/diagramme/en/vb-gas-bis-wand-loesung.visustruct":r7,"../../lessons/diagramme/en/vb-gerade-loesung.visustruct":o7,"../../lessons/diagramme/en/vb-hindernis-loesung.visustruct":l7,"../../lessons/diagramme/en/vb-java-akku-loesung.visustruct":u7,"../../lessons/diagramme/en/vb-java-blau-gruen-loesung.visustruct":c7,"../../lessons/diagramme/en/vb-java-blinken-loesung.visustruct":m7,"../../lessons/diagramme/en/vb-java-countdown-loesung.visustruct":d7,"../../lessons/diagramme/en/vb-java-hoeher-loesung.visustruct":h7,"../../lessons/diagramme/en/vb-java-joystick-loesung.visustruct":g7,"../../lessons/diagramme/en/vb-java-laermampel-loesung.visustruct":p7,"../../lessons/diagramme/en/vb-java-lauflicht-loesung.visustruct":f7,"../../lessons/diagramme/en/vb-java-linienfolger-loesung.visustruct":b7,"../../lessons/diagramme/en/vb-java-nachtlicht-ton-loesung.visustruct":x7,"../../lessons/diagramme/en/vb-java-rand-loesung.visustruct":v7,"../../lessons/diagramme/en/vb-java-rechteck-loesung.visustruct":y7,"../../lessons/diagramme/en/vb-java-textlaenge-loesung.visustruct":w7,"../../lessons/diagramme/en/vb-java-wand-piep-loesung.visustruct":z7,"../../lessons/diagramme/en/vb-java-wasserwaage-loesung.visustruct":I7,"../../lessons/diagramme/en/vb-klatschen-loesung.visustruct":k7,"../../lessons/diagramme/en/vb-knight-rider-loesung.visustruct":S7,"../../lessons/diagramme/en/vb-labyrinth-loesung.visustruct":T7,"../../lessons/diagramme/en/vb-linienfolger-stopp-loesung.visustruct":_7,"../../lessons/diagramme/en/vb-linienmuster-loesung.visustruct":A7,"../../lessons/diagramme/en/vb-melodie-loesung.visustruct":O7,"../../lessons/diagramme/en/vb-morsen-loesung.visustruct":C7,"../../lessons/diagramme/en/vb-nachtlicht-loesung.visustruct":j7,"../../lessons/diagramme/en/vb-nachtwaechter-loesung.visustruct":P7,"../../lessons/diagramme/en/vb-ohne-noten-loesung.visustruct":D7,"../../lessons/diagramme/en/vb-ohne-quadratzahl-loesung.visustruct":B7,"../../lessons/diagramme/en/vb-ohne-quadratzahl-unterprogramm-loesung.visustruct":M7,"../../lessons/diagramme/en/vb-ohne-rueckwaerts-loesung.visustruct":Z7,"../../lessons/diagramme/en/vb-ohne-strecke-loesung.visustruct":L7,"../../lessons/diagramme/en/vb-ohne-summe-loesung.visustruct":E7,"../../lessons/diagramme/en/vb-quadrat-loesung.visustruct":W7,"../../lessons/diagramme/en/vb-quadrat-methode-loesung.visustruct":N7,"../../lessons/diagramme/en/vb-quadrat-schleife-loesung.visustruct":F7,"../../lessons/diagramme/en/vb-quadrat-unterprogramm-loesung.visustruct":J7,"../../lessons/diagramme/en/vb-quadrat-verschachtelt-loesung.visustruct":R7,"../../lessons/diagramme/en/vb-rand-loesung.visustruct":G7,"../../lessons/diagramme/en/vb-schraeglage-loesung.visustruct":H7,"../../lessons/diagramme/en/vb-slalom-loesung.visustruct":V7,"../../lessons/diagramme/en/vb-spirale-loesung.visustruct":q7,"../../lessons/diagramme/en/vb-start-a-loesung.visustruct":Q7,"../../lessons/diagramme/en/vb-tonleiter-loesung.visustruct":U7,"../../lessons/diagramme/en/vb-treppe-loesung.visustruct":$7,"../../lessons/diagramme/en/vb-tunnel-loesung.visustruct":Y7,"../../lessons/diagramme/en/vb-variable-seite-loesung.visustruct":X7,"../../lessons/diagramme/en/vb-vier-quadrate-loesung.visustruct":K7,"../../lessons/diagramme/en/vb-wald-loesung.visustruct":ek,"../../lessons/diagramme/en/vb-wand-vorn-loesung.visustruct":tk,"../../lessons/diagramme/en/vb-zwei-sekunden-loesung.visustruct":nk,"../../lessons/diagramme/en/zk-initialen-loesung.visustruct":ik,"../../lessons/diagramme/en/zk-mehr.visustruct":ak,"../../lessons/diagramme/en/zk-rueckwaerts-loesung.visustruct":sk,"../../lessons/diagramme/en/zk-split.visustruct":rk,"../../lessons/diagramme/en/zk-woerter-loesung.visustruct":ok,"../../lessons/diagramme/en/zk-zaehlen.visustruct":lk,"../../lessons/diagramme/en/zk-zeichen.visustruct":uk,"../../lessons/diagramme/kino-einmaleins-loesung.visustruct":ck,"../../lessons/diagramme/kino-frei-loesung.visustruct":mk,"../../lessons/diagramme/kino-frei-start.visustruct":dk,"../../lessons/diagramme/kino-karte-loesung.visustruct":hk,"../../lessons/diagramme/kino-karte-start.visustruct":gk,"../../lessons/diagramme/kino-saalplan.visustruct":pk,"../../lessons/diagramme/kino-verkaufen.visustruct":fk,"../../lessons/diagramme/l04-java-fehler-loesung.visustruct":bk,"../../lessons/diagramme/l04-java-fehler-start.visustruct":xk,"../../lessons/diagramme/l04-java-steckbrief-loesung.visustruct":vk,"../../lessons/diagramme/l04-rechnen.visustruct":yk,"../../lessons/diagramme/l04-reihenfolge-loesung.visustruct":wk,"../../lessons/diagramme/l04-reihenfolge-start.visustruct":zk,"../../lessons/diagramme/l04-tauschen-loesung.visustruct":Ik,"../../lessons/diagramme/l04-tauschen-start.visustruct":kk,"../../lessons/diagramme/l04-tauschen.visustruct":Sk,"../../lessons/diagramme/l05-datentypen.visustruct":Tk,"../../lessons/diagramme/l05-division.visustruct":_k,"../../lessons/diagramme/l05-einkauf-loesung.visustruct":Ak,"../../lessons/diagramme/l05-java-fehler-loesung.visustruct":Ok,"../../lessons/diagramme/l05-java-fehler-start.visustruct":Ck,"../../lessons/diagramme/l05-java-kino-loesung.visustruct":jk,"../../lessons/diagramme/l05-rechteck-loesung.visustruct":Pk,"../../lessons/diagramme/l05-sekunden-loesung.visustruct":Dk,"../../lessons/diagramme/l05-sekunden-start.visustruct":Bk,"../../lessons/diagramme/l05-sequenz.visustruct":Mk,"../../lessons/diagramme/l06-begruessung-loesung.visustruct":Zk,"../../lessons/diagramme/l06-eva.visustruct":Lk,"../../lessons/diagramme/l06-java-fehler-loesung.visustruct":Ek,"../../lessons/diagramme/l06-java-fehler-start.visustruct":Wk,"../../lessons/diagramme/l06-java-tage-loesung.visustruct":Nk,"../../lessons/diagramme/l06-mittelwert-loesung.visustruct":Fk,"../../lessons/diagramme/l06-rechner-loesung.visustruct":Jk,"../../lessons/diagramme/l07-alter-pruefen.visustruct":Rk,"../../lessons/diagramme/l07-betrag-loesung.visustruct":Gk,"../../lessons/diagramme/l07-gerade-loesung.visustruct":Hk,"../../lessons/diagramme/l07-java-fehler-loesung.visustruct":Vk,"../../lessons/diagramme/l07-java-fehler-start.visustruct":qk,"../../lessons/diagramme/l07-java-pizza-loesung.visustruct":Qk,"../../lessons/diagramme/l07-java-pizza-start.visustruct":Uk,"../../lessons/diagramme/l07-maximum-loesung.visustruct":$k,"../../lessons/diagramme/l07-rabatt.visustruct":Yk,"../../lessons/diagramme/l08-gueltig-loesung.visustruct":Xk,"../../lessons/diagramme/l08-java-bestanden-loesung.visustruct":Kk,"../../lessons/diagramme/l08-java-fehler-loesung.visustruct":e8,"../../lessons/diagramme/l08-java-fehler-start.visustruct":t8,"../../lessons/diagramme/l08-jugendticket.visustruct":n8,"../../lessons/diagramme/l08-note.visustruct":i8,"../../lessons/diagramme/l08-schaltjahr-loesung.visustruct":a8,"../../lessons/diagramme/l08-wochenende-loesung.visustruct":s8,"../../lessons/diagramme/l09-ampel.visustruct":r8,"../../lessons/diagramme/l09-automat.visustruct":o8,"../../lessons/diagramme/l09-java-fehler-loesung.visustruct":l8,"../../lessons/diagramme/l09-java-fehler-start.visustruct":u8,"../../lessons/diagramme/l09-java-schule-loesung.visustruct":c8,"../../lessons/diagramme/l09-note-loesung.visustruct":m8,"../../lessons/diagramme/l09-rechner-loesung.visustruct":d8,"../../lessons/diagramme/l09-verschachtelt.visustruct":h8,"../../lessons/diagramme/l1-grundbausteine.visustruct":g8,"../../lessons/diagramme/l1-sequenz.visustruct":p8,"../../lessons/diagramme/l1-tee.visustruct":f8,"../../lessons/diagramme/l1-verzweigung.visustruct":b8,"../../lessons/diagramme/l1-wiederholung.visustruct":x8,"../../lessons/diagramme/l10-bis-n-loesung.visustruct":v8,"../../lessons/diagramme/l10-countdown.visustruct":y8,"../../lessons/diagramme/l10-endlos.visustruct":w8,"../../lessons/diagramme/l10-fakultaet.visustruct":z8,"../../lessons/diagramme/l10-java-fehler-loesung.visustruct":I8,"../../lessons/diagramme/l10-java-fehler-start.visustruct":k8,"../../lessons/diagramme/l10-java-wuerfel-loesung.visustruct":S8,"../../lessons/diagramme/l10-verdoppeln-loesung.visustruct":T8,"../../lessons/diagramme/l11-eingabe-pruefen.visustruct":_8,"../../lessons/diagramme/l11-einmal.visustruct":A8,"../../lessons/diagramme/l11-java-fehler-loesung.visustruct":O8,"../../lessons/diagramme/l11-java-fehler-start.visustruct":C8,"../../lessons/diagramme/l11-java-gerade-loesung.visustruct":j8,"../../lessons/diagramme/l11-note-loesung.visustruct":P8,"../../lessons/diagramme/l11-summe-loesung.visustruct":D8,"../../lessons/diagramme/l12-countdown-loesung.visustruct":B8,"../../lessons/diagramme/l12-einmaleins-loesung.visustruct":M8,"../../lessons/diagramme/l12-eins-bis-fuenf.visustruct":Z8,"../../lessons/diagramme/l12-java-fehler-loesung.visustruct":L8,"../../lessons/diagramme/l12-java-fehler-start.visustruct":E8,"../../lessons/diagramme/l12-java-verdoppeln-loesung.visustruct":W8,"../../lessons/diagramme/l12-summe.visustruct":N8,"../../lessons/diagramme/l13-dreieck.visustruct":F8,"../../lessons/diagramme/l13-gerade-eingaben-loesung.visustruct":J8,"../../lessons/diagramme/l13-gerade-zaehlen.visustruct":R8,"../../lessons/diagramme/l13-java-fehler-loesung.visustruct":G8,"../../lessons/diagramme/l13-java-fehler-start.visustruct":H8,"../../lessons/diagramme/l13-java-quadrate-loesung.visustruct":V8,"../../lessons/diagramme/l13-rechteck-loesung.visustruct":q8,"../../lessons/diagramme/l14-array-durchlaufen.visustruct":Q8,"../../lessons/diagramme/l14-erster-letzter-loesung.visustruct":U8,"../../lessons/diagramme/l14-java-fehler-loesung.visustruct":$8,"../../lessons/diagramme/l14-java-fehler-start.visustruct":Y8,"../../lessons/diagramme/l14-java-treppe-loesung.visustruct":X8,"../../lessons/diagramme/l14-namen-eingeben.visustruct":K8,"../../lessons/diagramme/l14-rueckwaerts-loesung.visustruct":eS,"../../lessons/diagramme/l14-summe-max-loesung.visustruct":tS,"../../lessons/diagramme/l14-summe-maximum.visustruct":nS,"../../lessons/diagramme/l15-bis-null-loesung.visustruct":iS,"../../lessons/diagramme/l15-endlos-aussprung.visustruct":aS,"../../lessons/diagramme/l15-flaeche-loesung.visustruct":sS,"../../lessons/diagramme/l15-flaeche-unterprogramm-loesung.visustruct":rS,"../../lessons/diagramme/l15-hauptprogramm.visustruct":oS,"../../lessons/diagramme/l15-java-fehler-loesung.visustruct":lS,"../../lessons/diagramme/l15-java-fehler-start.visustruct":uS,"../../lessons/diagramme/l15-java-noten-loesung.visustruct":cS,"../../lessons/diagramme/l15-quadrat-haupt.visustruct":mS,"../../lessons/diagramme/l15-quadrat.visustruct":dS,"../../lessons/diagramme/l15-titel-loesung.visustruct":hS,"../../lessons/diagramme/l15-unterprogramm.visustruct":gS,"../../lessons/diagramme/l15-zeige-summe-haupt.visustruct":pS,"../../lessons/diagramme/l15-zeige-summe.visustruct":fS,"../../lessons/diagramme/l16-countdown-loesung.visustruct":bS,"../../lessons/diagramme/l16-countdown-start.visustruct":xS,"../../lessons/diagramme/l16-java-fehler-loesung.visustruct":vS,"../../lessons/diagramme/l16-java-fehler-start.visustruct":yS,"../../lessons/diagramme/l16-java-punkte-loesung.visustruct":wS,"../../lessons/diagramme/l16-schreibtisch.visustruct":zS,"../../lessons/diagramme/l16-summe-loesung.visustruct":IS,"../../lessons/diagramme/l16-summe-start.visustruct":kS,"../../lessons/diagramme/l17-beispiel.visustruct":SS,"../../lessons/diagramme/l17-fakultaet-loesung.visustruct":TS,"../../lessons/diagramme/l17-java-brief-loesung.visustruct":_S,"../../lessons/diagramme/l17-java-brief-start.visustruct":AS,"../../lessons/diagramme/l17-java-fehler-loesung.visustruct":OS,"../../lessons/diagramme/l17-java-fehler-start.visustruct":CS,"../../lessons/diagramme/l17-java-passwort-loesung.visustruct":jS,"../../lessons/diagramme/l17-ticket-loesung.visustruct":PS,"../../lessons/diagramme/l18-beispiel.visustruct":DS,"../../lessons/diagramme/l18-java-fehler-loesung.visustruct":BS,"../../lessons/diagramme/l18-java-fehler-start.visustruct":MS,"../../lessons/diagramme/l18-java-kasse-loesung.visustruct":ZS,"../../lessons/diagramme/l18-js-loesung.visustruct":LS,"../../lessons/diagramme/l18-python-loesung.visustruct":ES,"../../lessons/diagramme/l19-java-fehler-loesung.visustruct":WS,"../../lessons/diagramme/l19-java-fehler-start.visustruct":NS,"../../lessons/diagramme/l19-java-zaehlen-loesung.visustruct":FS,"../../lessons/diagramme/l2-ausgabe.visustruct":JS,"../../lessons/diagramme/l2-hallo-loesung.visustruct":RS,"../../lessons/diagramme/l2-zwei-zeilen-loesung.visustruct":GS,"../../lessons/diagramme/l20-countdown-loesung.visustruct":HS,"../../lessons/diagramme/l23-java-ergaenzen-loesung.visustruct":VS,"../../lessons/diagramme/l23-java-ergaenzen-start.visustruct":qS,"../../lessons/diagramme/l23-java-nummern-loesung.visustruct":QS,"../../lessons/diagramme/l23-java-nummern-start.visustruct":US,"../../lessons/diagramme/l24-java-fuchs-loesung.visustruct":$S,"../../lessons/diagramme/l24-java-fuchs-start.visustruct":YS,"../../lessons/diagramme/l24-java-laengster-loesung.visustruct":XS,"../../lessons/diagramme/l24-java-laengster-start.visustruct":KS,"../../lessons/diagramme/l25-java-beste-loesung.visustruct":eT,"../../lessons/diagramme/l25-java-beste-start.visustruct":tT,"../../lessons/diagramme/l25-java-schnitt-loesung.visustruct":nT,"../../lessons/diagramme/l25-java-schnitt-start.visustruct":iT,"../../lessons/diagramme/l26-java-namen-loesung.visustruct":aT,"../../lessons/diagramme/l26-java-namen-start.visustruct":sT,"../../lessons/diagramme/l26-java-schreiben-loesung.visustruct":rT,"../../lessons/diagramme/l26-java-schreiben-start.visustruct":oT,"../../lessons/diagramme/l27-java-json-loesung.visustruct":lT,"../../lessons/diagramme/l27-java-json-start.visustruct":uT,"../../lessons/diagramme/l27-java-saetze-loesung.visustruct":cT,"../../lessons/diagramme/l27-java-saetze-start.visustruct":mT,"../../lessons/diagramme/pt/aufgabe-alter-haupt-loesung.visustruct":dT,"../../lessons/diagramme/pt/aufgabe-alter-unterprogramm-loesung.visustruct":hT,"../../lessons/diagramme/pt/aufgabe-ballwurf-loesung.visustruct":gT,"../../lessons/diagramme/pt/aufgabe-ballwurf-start.visustruct":pT,"../../lessons/diagramme/pt/aufgabe-bestenliste-loesung.visustruct":fT,"../../lessons/diagramme/pt/aufgabe-binaer-loesung.visustruct":bT,"../../lessons/diagramme/pt/aufgabe-caesar-array-loesung.visustruct":xT,"../../lessons/diagramme/pt/aufgabe-caesar-array-start.visustruct":vT,"../../lessons/diagramme/pt/aufgabe-caesar-ascii-loesung.visustruct":yT,"../../lessons/diagramme/pt/aufgabe-caesar-entschluesseln-loesung.visustruct":wT,"../../lessons/diagramme/pt/aufgabe-collatz-loesung.visustruct":zT,"../../lessons/diagramme/pt/aufgabe-durchschnitt-loesung.visustruct":IT,"../../lessons/diagramme/pt/aufgabe-fibonacci-loesung.visustruct":kT,"../../lessons/diagramme/pt/aufgabe-gerade-loesung.visustruct":ST,"../../lessons/diagramme/pt/aufgabe-mehrwertsteuer-loesung.visustruct":TT,"../../lessons/diagramme/pt/aufgabe-pin-java-loesung.visustruct":_T,"../../lessons/diagramme/pt/aufgabe-pin-loesung.visustruct":AT,"../../lessons/diagramme/pt/aufgabe-rechner-loesung.visustruct":OT,"../../lessons/diagramme/pt/aufgabe-schiffe-loesung.visustruct":CT,"../../lessons/diagramme/pt/aufgabe-schiffe-start.visustruct":jT,"../../lessons/diagramme/pt/aufgabe-speisekarte-loesung.visustruct":PT,"../../lessons/diagramme/pt/aufgabe-summe-loesung.visustruct":DT,"../../lessons/diagramme/pt/aufgabe-tafeldienst-loesung.visustruct":BT,"../../lessons/diagramme/pt/aufgabe-verdoppeln-loesung.visustruct":MT,"../../lessons/diagramme/pt/aufgabe-verleih-java-loesung.visustruct":ZT,"../../lessons/diagramme/pt/aufgabe-verleih-loesung.visustruct":LT,"../../lessons/diagramme/pt/aufgabe-vokabeln-loesung.visustruct":ET,"../../lessons/diagramme/pt/aufgabe-vokabeln-start.visustruct":WT,"../../lessons/diagramme/pt/aufgabe-volljaehrig-loesung.visustruct":NT,"../../lessons/diagramme/pt/dt-buffered.visustruct":FT,"../../lessons/diagramme/pt/dt-csv.visustruct":JT,"../../lessons/diagramme/pt/dt-json.visustruct":RT,"../../lessons/diagramme/pt/dt-lesen.visustruct":GT,"../../lessons/diagramme/pt/kino-einmaleins-loesung.visustruct":HT,"../../lessons/diagramme/pt/kino-frei-loesung.visustruct":VT,"../../lessons/diagramme/pt/kino-frei-start.visustruct":qT,"../../lessons/diagramme/pt/kino-karte-loesung.visustruct":QT,"../../lessons/diagramme/pt/kino-karte-start.visustruct":UT,"../../lessons/diagramme/pt/kino-saalplan.visustruct":$T,"../../lessons/diagramme/pt/kino-verkaufen.visustruct":YT,"../../lessons/diagramme/pt/l04-java-fehler-loesung.visustruct":XT,"../../lessons/diagramme/pt/l04-java-fehler-start.visustruct":KT,"../../lessons/diagramme/pt/l04-java-steckbrief-loesung.visustruct":e_,"../../lessons/diagramme/pt/l04-rechnen.visustruct":t_,"../../lessons/diagramme/pt/l04-reihenfolge-loesung.visustruct":n_,"../../lessons/diagramme/pt/l04-reihenfolge-start.visustruct":i_,"../../lessons/diagramme/pt/l04-tauschen-loesung.visustruct":a_,"../../lessons/diagramme/pt/l04-tauschen-start.visustruct":s_,"../../lessons/diagramme/pt/l04-tauschen.visustruct":r_,"../../lessons/diagramme/pt/l05-datentypen.visustruct":o_,"../../lessons/diagramme/pt/l05-division.visustruct":l_,"../../lessons/diagramme/pt/l05-einkauf-loesung.visustruct":u_,"../../lessons/diagramme/pt/l05-java-fehler-loesung.visustruct":c_,"../../lessons/diagramme/pt/l05-java-fehler-start.visustruct":m_,"../../lessons/diagramme/pt/l05-java-kino-loesung.visustruct":d_,"../../lessons/diagramme/pt/l05-rechteck-loesung.visustruct":h_,"../../lessons/diagramme/pt/l05-sekunden-loesung.visustruct":g_,"../../lessons/diagramme/pt/l05-sekunden-start.visustruct":p_,"../../lessons/diagramme/pt/l05-sequenz.visustruct":f_,"../../lessons/diagramme/pt/l06-begruessung-loesung.visustruct":b_,"../../lessons/diagramme/pt/l06-eva.visustruct":x_,"../../lessons/diagramme/pt/l06-java-fehler-loesung.visustruct":v_,"../../lessons/diagramme/pt/l06-java-fehler-start.visustruct":y_,"../../lessons/diagramme/pt/l06-java-tage-loesung.visustruct":w_,"../../lessons/diagramme/pt/l06-mittelwert-loesung.visustruct":z_,"../../lessons/diagramme/pt/l06-rechner-loesung.visustruct":I_,"../../lessons/diagramme/pt/l07-alter-pruefen.visustruct":k_,"../../lessons/diagramme/pt/l07-betrag-loesung.visustruct":S_,"../../lessons/diagramme/pt/l07-gerade-loesung.visustruct":T_,"../../lessons/diagramme/pt/l07-java-fehler-loesung.visustruct":__,"../../lessons/diagramme/pt/l07-java-fehler-start.visustruct":A_,"../../lessons/diagramme/pt/l07-java-pizza-loesung.visustruct":O_,"../../lessons/diagramme/pt/l07-java-pizza-start.visustruct":C_,"../../lessons/diagramme/pt/l07-maximum-loesung.visustruct":j_,"../../lessons/diagramme/pt/l07-rabatt.visustruct":P_,"../../lessons/diagramme/pt/l08-gueltig-loesung.visustruct":D_,"../../lessons/diagramme/pt/l08-java-bestanden-loesung.visustruct":B_,"../../lessons/diagramme/pt/l08-java-fehler-loesung.visustruct":M_,"../../lessons/diagramme/pt/l08-java-fehler-start.visustruct":Z_,"../../lessons/diagramme/pt/l08-jugendticket.visustruct":L_,"../../lessons/diagramme/pt/l08-note.visustruct":E_,"../../lessons/diagramme/pt/l08-schaltjahr-loesung.visustruct":W_,"../../lessons/diagramme/pt/l08-wochenende-loesung.visustruct":N_,"../../lessons/diagramme/pt/l09-ampel.visustruct":F_,"../../lessons/diagramme/pt/l09-automat.visustruct":J_,"../../lessons/diagramme/pt/l09-java-fehler-loesung.visustruct":R_,"../../lessons/diagramme/pt/l09-java-fehler-start.visustruct":G_,"../../lessons/diagramme/pt/l09-java-schule-loesung.visustruct":H_,"../../lessons/diagramme/pt/l09-note-loesung.visustruct":V_,"../../lessons/diagramme/pt/l09-rechner-loesung.visustruct":q_,"../../lessons/diagramme/pt/l09-verschachtelt.visustruct":Q_,"../../lessons/diagramme/pt/l1-grundbausteine.visustruct":U_,"../../lessons/diagramme/pt/l1-sequenz.visustruct":$_,"../../lessons/diagramme/pt/l1-tee.visustruct":Y_,"../../lessons/diagramme/pt/l1-verzweigung.visustruct":X_,"../../lessons/diagramme/pt/l1-wiederholung.visustruct":K_,"../../lessons/diagramme/pt/l10-bis-n-loesung.visustruct":eA,"../../lessons/diagramme/pt/l10-countdown.visustruct":tA,"../../lessons/diagramme/pt/l10-endlos.visustruct":nA,"../../lessons/diagramme/pt/l10-fakultaet.visustruct":iA,"../../lessons/diagramme/pt/l10-java-fehler-loesung.visustruct":aA,"../../lessons/diagramme/pt/l10-java-fehler-start.visustruct":sA,"../../lessons/diagramme/pt/l10-java-wuerfel-loesung.visustruct":rA,"../../lessons/diagramme/pt/l10-verdoppeln-loesung.visustruct":oA,"../../lessons/diagramme/pt/l11-eingabe-pruefen.visustruct":lA,"../../lessons/diagramme/pt/l11-einmal.visustruct":uA,"../../lessons/diagramme/pt/l11-java-fehler-loesung.visustruct":cA,"../../lessons/diagramme/pt/l11-java-fehler-start.visustruct":mA,"../../lessons/diagramme/pt/l11-java-gerade-loesung.visustruct":dA,"../../lessons/diagramme/pt/l11-note-loesung.visustruct":hA,"../../lessons/diagramme/pt/l11-summe-loesung.visustruct":gA,"../../lessons/diagramme/pt/l12-countdown-loesung.visustruct":pA,"../../lessons/diagramme/pt/l12-einmaleins-loesung.visustruct":fA,"../../lessons/diagramme/pt/l12-eins-bis-fuenf.visustruct":bA,"../../lessons/diagramme/pt/l12-java-fehler-loesung.visustruct":xA,"../../lessons/diagramme/pt/l12-java-fehler-start.visustruct":vA,"../../lessons/diagramme/pt/l12-java-verdoppeln-loesung.visustruct":yA,"../../lessons/diagramme/pt/l12-summe.visustruct":wA,"../../lessons/diagramme/pt/l13-dreieck.visustruct":zA,"../../lessons/diagramme/pt/l13-gerade-eingaben-loesung.visustruct":IA,"../../lessons/diagramme/pt/l13-gerade-zaehlen.visustruct":kA,"../../lessons/diagramme/pt/l13-java-fehler-loesung.visustruct":SA,"../../lessons/diagramme/pt/l13-java-fehler-start.visustruct":TA,"../../lessons/diagramme/pt/l13-java-quadrate-loesung.visustruct":_A,"../../lessons/diagramme/pt/l13-rechteck-loesung.visustruct":AA,"../../lessons/diagramme/pt/l14-array-durchlaufen.visustruct":OA,"../../lessons/diagramme/pt/l14-erster-letzter-loesung.visustruct":CA,"../../lessons/diagramme/pt/l14-java-fehler-loesung.visustruct":jA,"../../lessons/diagramme/pt/l14-java-fehler-start.visustruct":PA,"../../lessons/diagramme/pt/l14-java-treppe-loesung.visustruct":DA,"../../lessons/diagramme/pt/l14-namen-eingeben.visustruct":BA,"../../lessons/diagramme/pt/l14-rueckwaerts-loesung.visustruct":MA,"../../lessons/diagramme/pt/l14-summe-max-loesung.visustruct":ZA,"../../lessons/diagramme/pt/l14-summe-maximum.visustruct":LA,"../../lessons/diagramme/pt/l15-bis-null-loesung.visustruct":EA,"../../lessons/diagramme/pt/l15-endlos-aussprung.visustruct":WA,"../../lessons/diagramme/pt/l15-flaeche-loesung.visustruct":NA,"../../lessons/diagramme/pt/l15-hauptprogramm.visustruct":FA,"../../lessons/diagramme/pt/l15-java-fehler-loesung.visustruct":JA,"../../lessons/diagramme/pt/l15-java-fehler-start.visustruct":RA,"../../lessons/diagramme/pt/l15-java-noten-loesung.visustruct":GA,"../../lessons/diagramme/pt/l15-quadrat-haupt.visustruct":HA,"../../lessons/diagramme/pt/l15-quadrat.visustruct":VA,"../../lessons/diagramme/pt/l15-titel-loesung.visustruct":qA,"../../lessons/diagramme/pt/l15-unterprogramm.visustruct":QA,"../../lessons/diagramme/pt/l15-zeige-summe-haupt.visustruct":UA,"../../lessons/diagramme/pt/l15-zeige-summe.visustruct":$A,"../../lessons/diagramme/pt/l16-countdown-loesung.visustruct":YA,"../../lessons/diagramme/pt/l16-countdown-start.visustruct":XA,"../../lessons/diagramme/pt/l16-java-fehler-loesung.visustruct":KA,"../../lessons/diagramme/pt/l16-java-fehler-start.visustruct":eO,"../../lessons/diagramme/pt/l16-java-punkte-loesung.visustruct":tO,"../../lessons/diagramme/pt/l16-schreibtisch.visustruct":nO,"../../lessons/diagramme/pt/l16-summe-loesung.visustruct":iO,"../../lessons/diagramme/pt/l16-summe-start.visustruct":aO,"../../lessons/diagramme/pt/l17-beispiel.visustruct":sO,"../../lessons/diagramme/pt/l17-fakultaet-loesung.visustruct":rO,"../../lessons/diagramme/pt/l17-java-brief-loesung.visustruct":oO,"../../lessons/diagramme/pt/l17-java-brief-start.visustruct":lO,"../../lessons/diagramme/pt/l17-java-fehler-loesung.visustruct":uO,"../../lessons/diagramme/pt/l17-java-fehler-start.visustruct":cO,"../../lessons/diagramme/pt/l17-java-passwort-loesung.visustruct":mO,"../../lessons/diagramme/pt/l17-ticket-loesung.visustruct":dO,"../../lessons/diagramme/pt/l18-beispiel.visustruct":hO,"../../lessons/diagramme/pt/l18-java-fehler-loesung.visustruct":gO,"../../lessons/diagramme/pt/l18-java-fehler-start.visustruct":pO,"../../lessons/diagramme/pt/l18-java-kasse-loesung.visustruct":fO,"../../lessons/diagramme/pt/l18-js-loesung.visustruct":bO,"../../lessons/diagramme/pt/l18-python-loesung.visustruct":xO,"../../lessons/diagramme/pt/l19-java-fehler-loesung.visustruct":vO,"../../lessons/diagramme/pt/l19-java-fehler-start.visustruct":yO,"../../lessons/diagramme/pt/l19-java-zaehlen-loesung.visustruct":wO,"../../lessons/diagramme/pt/l2-ausgabe.visustruct":zO,"../../lessons/diagramme/pt/l2-hallo-loesung.visustruct":IO,"../../lessons/diagramme/pt/l2-zwei-zeilen-loesung.visustruct":kO,"../../lessons/diagramme/pt/l23-java-ergaenzen-loesung.visustruct":SO,"../../lessons/diagramme/pt/l23-java-ergaenzen-start.visustruct":TO,"../../lessons/diagramme/pt/l23-java-nummern-loesung.visustruct":_O,"../../lessons/diagramme/pt/l23-java-nummern-start.visustruct":AO,"../../lessons/diagramme/pt/l24-java-fuchs-loesung.visustruct":OO,"../../lessons/diagramme/pt/l24-java-fuchs-start.visustruct":CO,"../../lessons/diagramme/pt/l24-java-laengster-loesung.visustruct":jO,"../../lessons/diagramme/pt/l24-java-laengster-start.visustruct":PO,"../../lessons/diagramme/pt/l25-java-beste-loesung.visustruct":DO,"../../lessons/diagramme/pt/l25-java-beste-start.visustruct":BO,"../../lessons/diagramme/pt/l25-java-schnitt-loesung.visustruct":MO,"../../lessons/diagramme/pt/l25-java-schnitt-start.visustruct":ZO,"../../lessons/diagramme/pt/l26-java-namen-loesung.visustruct":LO,"../../lessons/diagramme/pt/l26-java-namen-start.visustruct":EO,"../../lessons/diagramme/pt/l26-java-schreiben-loesung.visustruct":WO,"../../lessons/diagramme/pt/l26-java-schreiben-start.visustruct":NO,"../../lessons/diagramme/pt/l27-java-json-loesung.visustruct":FO,"../../lessons/diagramme/pt/l27-java-json-start.visustruct":JO,"../../lessons/diagramme/pt/l27-java-saetze-loesung.visustruct":RO,"../../lessons/diagramme/pt/l27-java-saetze-start.visustruct":GO,"../../lessons/diagramme/pt/sim-kino-loesung.visustruct":HO,"../../lessons/diagramme/pt/sim-kino-start.visustruct":VO,"../../lessons/diagramme/pt/sim-tausch-loesung.visustruct":qO,"../../lessons/diagramme/pt/sim-tausch-start.visustruct":QO,"../../lessons/diagramme/pt/sim-tausch.visustruct":UO,"../../lessons/diagramme/pt/ss-absteigend-loesung.visustruct":$O,"../../lessons/diagramme/pt/ss-absteigend-start.visustruct":YO,"../../lessons/diagramme/pt/ss-binaere-suche.visustruct":XO,"../../lessons/diagramme/pt/ss-bubblesort.visustruct":KO,"../../lessons/diagramme/pt/ss-karte-suchen-loesung.visustruct":eC,"../../lessons/diagramme/pt/ss-lineare-suche.visustruct":tC,"../../lessons/diagramme/pt/uebergabe-bonus-loesung.visustruct":nC,"../../lessons/diagramme/pt/uebergabe-bonus-start.visustruct":iC,"../../lessons/diagramme/pt/uebergabe-bonus-unterprogramm-loesung.visustruct":aC,"../../lessons/diagramme/pt/uebergabe-haupt.visustruct":sC,"../../lessons/diagramme/pt/uebergabe-leeren.visustruct":rC,"../../lessons/diagramme/pt/uebergabe-verdopple.visustruct":oC,"../../lessons/diagramme/pt/zk-initialen-loesung.visustruct":lC,"../../lessons/diagramme/pt/zk-mehr.visustruct":uC,"../../lessons/diagramme/pt/zk-rueckwaerts-loesung.visustruct":cC,"../../lessons/diagramme/pt/zk-split.visustruct":mC,"../../lessons/diagramme/pt/zk-woerter-loesung.visustruct":dC,"../../lessons/diagramme/pt/zk-zaehlen.visustruct":hC,"../../lessons/diagramme/pt/zk-zeichen.visustruct":gC,"../../lessons/diagramme/sim-kino-loesung.visustruct":pC,"../../lessons/diagramme/sim-kino-start.visustruct":fC,"../../lessons/diagramme/sim-tausch-loesung.visustruct":bC,"../../lessons/diagramme/sim-tausch-start.visustruct":xC,"../../lessons/diagramme/sim-tausch.visustruct":vC,"../../lessons/diagramme/ss-absteigend-loesung.visustruct":yC,"../../lessons/diagramme/ss-absteigend-start.visustruct":wC,"../../lessons/diagramme/ss-binaere-suche.visustruct":zC,"../../lessons/diagramme/ss-bubblesort.visustruct":IC,"../../lessons/diagramme/ss-karte-suchen-loesung.visustruct":kC,"../../lessons/diagramme/ss-lineare-suche.visustruct":SC,"../../lessons/diagramme/uebergabe-bonus-loesung.visustruct":TC,"../../lessons/diagramme/uebergabe-bonus-start.visustruct":_C,"../../lessons/diagramme/uebergabe-bonus-unterprogramm-loesung.visustruct":AC,"../../lessons/diagramme/uebergabe-haupt.visustruct":OC,"../../lessons/diagramme/uebergabe-leeren.visustruct":CC,"../../lessons/diagramme/uebergabe-verdopple.visustruct":jC,"../../lessons/diagramme/vb-abstand-anzeigen-loesung.visustruct":PC,"../../lessons/diagramme/vb-abstand-halten-loesung.visustruct":DC,"../../lessons/diagramme/vb-alarmanlage-loesung.visustruct":BC,"../../lessons/diagramme/vb-ampel-loesung.visustruct":MC,"../../lessons/diagramme/vb-ausgang-loesung.visustruct":ZC,"../../lessons/diagramme/vb-begruessung-loesung.visustruct":LC,"../../lessons/diagramme/vb-binaer-zaehlen-loesung.visustruct":EC,"../../lessons/diagramme/vb-bis-rot-loesung.visustruct":WC,"../../lessons/diagramme/vb-bis-wand-loesung.visustruct":NC,"../../lessons/diagramme/vb-bis-ziel-loesung.visustruct":FC,"../../lessons/diagramme/vb-buchstaben-loesung.visustruct":JC,"../../lessons/diagramme/vb-drei-lichter-loesung.visustruct":RC,"../../lessons/diagramme/vb-dreieck-loesung.visustruct":GC,"../../lessons/diagramme/vb-einparken-loesung.visustruct":HC,"../../lessons/diagramme/vb-farben-loesung.visustruct":VC,"../../lessons/diagramme/vb-farbweiche-loesung.visustruct":qC,"../../lessons/diagramme/vb-gas-bis-wand-loesung.visustruct":QC,"../../lessons/diagramme/vb-gerade-loesung.visustruct":UC,"../../lessons/diagramme/vb-hindernis-loesung.visustruct":$C,"../../lessons/diagramme/vb-java-akku-loesung.visustruct":YC,"../../lessons/diagramme/vb-java-blau-gruen-loesung.visustruct":XC,"../../lessons/diagramme/vb-java-blinken-loesung.visustruct":KC,"../../lessons/diagramme/vb-java-countdown-loesung.visustruct":ej,"../../lessons/diagramme/vb-java-hoeher-loesung.visustruct":tj,"../../lessons/diagramme/vb-java-joystick-loesung.visustruct":nj,"../../lessons/diagramme/vb-java-laermampel-loesung.visustruct":ij,"../../lessons/diagramme/vb-java-lauflicht-loesung.visustruct":aj,"../../lessons/diagramme/vb-java-linienfolger-loesung.visustruct":sj,"../../lessons/diagramme/vb-java-nachtlicht-ton-loesung.visustruct":rj,"../../lessons/diagramme/vb-java-rand-loesung.visustruct":oj,"../../lessons/diagramme/vb-java-rechteck-loesung.visustruct":lj,"../../lessons/diagramme/vb-java-textlaenge-loesung.visustruct":uj,"../../lessons/diagramme/vb-java-wand-piep-loesung.visustruct":cj,"../../lessons/diagramme/vb-java-wasserwaage-loesung.visustruct":mj,"../../lessons/diagramme/vb-klatschen-loesung.visustruct":dj,"../../lessons/diagramme/vb-knight-rider-loesung.visustruct":hj,"../../lessons/diagramme/vb-labyrinth-loesung.visustruct":gj,"../../lessons/diagramme/vb-linienfolger-stopp-loesung.visustruct":pj,"../../lessons/diagramme/vb-linienmuster-loesung.visustruct":fj,"../../lessons/diagramme/vb-melodie-loesung.visustruct":bj,"../../lessons/diagramme/vb-morsen-loesung.visustruct":xj,"../../lessons/diagramme/vb-nachtlicht-loesung.visustruct":vj,"../../lessons/diagramme/vb-nachtwaechter-loesung.visustruct":yj,"../../lessons/diagramme/vb-ohne-noten-loesung.visustruct":wj,"../../lessons/diagramme/vb-ohne-quadratzahl-loesung.visustruct":zj,"../../lessons/diagramme/vb-ohne-quadratzahl-unterprogramm-loesung.visustruct":Ij,"../../lessons/diagramme/vb-ohne-rueckwaerts-loesung.visustruct":kj,"../../lessons/diagramme/vb-ohne-strecke-loesung.visustruct":Sj,"../../lessons/diagramme/vb-ohne-summe-loesung.visustruct":Tj,"../../lessons/diagramme/vb-quadrat-loesung.visustruct":_j,"../../lessons/diagramme/vb-quadrat-methode-loesung.visustruct":Aj,"../../lessons/diagramme/vb-quadrat-schleife-loesung.visustruct":Oj,"../../lessons/diagramme/vb-quadrat-unterprogramm-loesung.visustruct":Cj,"../../lessons/diagramme/vb-quadrat-verschachtelt-loesung.visustruct":jj,"../../lessons/diagramme/vb-rand-loesung.visustruct":Pj,"../../lessons/diagramme/vb-schraeglage-loesung.visustruct":Dj,"../../lessons/diagramme/vb-slalom-loesung.visustruct":Bj,"../../lessons/diagramme/vb-spirale-loesung.visustruct":Mj,"../../lessons/diagramme/vb-start-a-loesung.visustruct":Zj,"../../lessons/diagramme/vb-tonleiter-loesung.visustruct":Lj,"../../lessons/diagramme/vb-treppe-loesung.visustruct":Ej,"../../lessons/diagramme/vb-tunnel-loesung.visustruct":Wj,"../../lessons/diagramme/vb-variable-seite-loesung.visustruct":Nj,"../../lessons/diagramme/vb-vier-quadrate-loesung.visustruct":Fj,"../../lessons/diagramme/vb-wald-loesung.visustruct":Jj,"../../lessons/diagramme/vb-wand-vorn-loesung.visustruct":Rj,"../../lessons/diagramme/vb-zwei-sekunden-loesung.visustruct":Gj,"../../lessons/diagramme/zk-initialen-loesung.visustruct":Hj,"../../lessons/diagramme/zk-mehr.visustruct":Vj,"../../lessons/diagramme/zk-rueckwaerts-loesung.visustruct":qj,"../../lessons/diagramme/zk-split.visustruct":Qj,"../../lessons/diagramme/zk-woerter-loesung.visustruct":Uj,"../../lessons/diagramme/zk-zaehlen.visustruct":$j,"../../lessons/diagramme/zk-zeichen.visustruct":Yj}),DB=Object.assign({"../../lessons/welten/ausgang-1.txt":Xj,"../../lessons/welten/ausgang-2.txt":Kj,"../../lessons/welten/ecke.txt":eP,"../../lessons/welten/farbe-1.txt":tP,"../../lessons/welten/farbe-2.txt":nP,"../../lessons/welten/farbe-3.txt":iP,"../../lessons/welten/farbe-4.txt":aP,"../../lessons/welten/hindernis-1.txt":sP,"../../lessons/welten/hindernis-2.txt":rP,"../../lessons/welten/labyrinth-1.txt":oP,"../../lessons/welten/labyrinth-2.txt":lP,"../../lessons/welten/linie-1.txt":uP,"../../lessons/welten/linie-2.txt":cP,"../../lessons/welten/linie-rot-1.txt":mP,"../../lessons/welten/linie-rot-2.txt":dP,"../../lessons/welten/parken-1.txt":hP,"../../lessons/welten/parken-2.txt":gP,"../../lessons/welten/rand-1.txt":pP,"../../lessons/welten/rand-2.txt":fP,"../../lessons/welten/slalom.txt":bP,"../../lessons/welten/tunnel-1.txt":xP,"../../lessons/welten/tunnel-2.txt":vP,"../../lessons/welten/wald-1.txt":yP,"../../lessons/welten/wald-2.txt":wP,"../../lessons/welten/wand-frei.txt":zP,"../../lessons/welten/wand-kurz.txt":IP,"../../lessons/welten/wand-lang.txt":kP,"../../lessons/welten/wand-mittel.txt":SP,"../../lessons/welten/wand-nah.txt":TP,"../../lessons/welten/zeit-1.txt":_P,"../../lessons/welten/ziel-kurz.txt":AP,"../../lessons/welten/ziel-lang.txt":OP}),BB=Object.assign({"../../lessons/bilder/aufgabe-mehrwertsteuer.svg":CP,"../../lessons/bilder/ben-shneiderman.jpg":jP,"../../lessons/bilder/caesar-ascii.svg":PP,"../../lessons/bilder/caesar-scheibe.svg":DP,"../../lessons/bilder/caesar-verschiebung.svg":BP,"../../lessons/bilder/en/aufgabe-mehrwertsteuer.svg":MP,"../../lessons/bilder/en/kino-saal.svg":ZP,"../../lessons/bilder/en/kino-schleifen.svg":LP,"../../lessons/bilder/en/l01-pap.svg":EP,"../../lessons/bilder/en/l02-einfuegen.svg":WP,"../../lessons/bilder/en/l03-lochkarte-beschriftet.svg":NP,"../../lessons/bilder/en/l03-lochkarte.svg":FP,"../../lessons/bilder/en/l04-camelcase.svg":JP,"../../lessons/bilder/en/l04-variable.svg":RP,"../../lessons/bilder/en/l04-zuweisung.svg":GP,"../../lessons/bilder/en/l05-tauschen.svg":HP,"../../lessons/bilder/en/l08-zahlenstrahl.svg":VP,"../../lessons/bilder/en/l10-kopfgesteuert.svg":qP,"../../lessons/bilder/en/l11-vergleich.svg":QP,"../../lessons/bilder/en/l12-for-ablauf.svg":UP,"../../lessons/bilder/en/l14-array.svg":$P,"../../lessons/bilder/en/mvc-klick.svg":YP,"../../lessons/bilder/en/ss-binaere-suche.svg":XP,"../../lessons/bilder/en/ss-bubblesort.svg":KP,"../../lessons/bilder/en/ss-lineare-suche.svg":eD,"../../lessons/bilder/en/ss-vergleiche.svg":tD,"../../lessons/bilder/en/uebergabe.svg":nD,"../../lessons/bilder/en/zk-zeichen.svg":iD,"../../lessons/bilder/ike-nassi.jpg":aD,"../../lessons/bilder/kino-saal.svg":sD,"../../lessons/bilder/kino-schleifen.svg":rD,"../../lessons/bilder/l01-pap.svg":oD,"../../lessons/bilder/l02-einfuegen.svg":lD,"../../lessons/bilder/l03-lochkarte-beschriftet.svg":uD,"../../lessons/bilder/l03-lochkarte.svg":cD,"../../lessons/bilder/l04-camelcase.svg":mD,"../../lessons/bilder/l04-variable.svg":dD,"../../lessons/bilder/l04-zuweisung.svg":hD,"../../lessons/bilder/l05-tauschen.svg":gD,"../../lessons/bilder/l08-zahlenstrahl.svg":pD,"../../lessons/bilder/l09-wahrheitstabelle.svg":fD,"../../lessons/bilder/l10-kopfgesteuert.svg":bD,"../../lessons/bilder/l11-vergleich.svg":xD,"../../lessons/bilder/l12-for-ablauf.svg":vD,"../../lessons/bilder/l14-array.svg":yD,"../../lessons/bilder/mvc-klick.svg":wD,"../../lessons/bilder/pt/aufgabe-mehrwertsteuer.svg":zD,"../../lessons/bilder/pt/kino-saal.svg":ID,"../../lessons/bilder/pt/kino-schleifen.svg":kD,"../../lessons/bilder/pt/l01-pap.svg":SD,"../../lessons/bilder/pt/l02-einfuegen.svg":TD,"../../lessons/bilder/pt/l03-lochkarte-beschriftet.svg":_D,"../../lessons/bilder/pt/l03-lochkarte.svg":AD,"../../lessons/bilder/pt/l04-camelcase.svg":OD,"../../lessons/bilder/pt/l04-variable.svg":CD,"../../lessons/bilder/pt/l04-zuweisung.svg":jD,"../../lessons/bilder/pt/l05-tauschen.svg":PD,"../../lessons/bilder/pt/l08-zahlenstrahl.svg":DD,"../../lessons/bilder/pt/l10-kopfgesteuert.svg":BD,"../../lessons/bilder/pt/l11-vergleich.svg":MD,"../../lessons/bilder/pt/l12-for-ablauf.svg":ZD,"../../lessons/bilder/pt/l14-array.svg":LD,"../../lessons/bilder/pt/mvc-klick.svg":ED,"../../lessons/bilder/pt/schiffe-versenken.svg":WD,"../../lessons/bilder/pt/ss-binaere-suche.svg":ND,"../../lessons/bilder/pt/ss-bubblesort.svg":FD,"../../lessons/bilder/pt/ss-lineare-suche.svg":JD,"../../lessons/bilder/pt/ss-vergleiche.svg":RD,"../../lessons/bilder/pt/uebergabe.svg":GD,"../../lessons/bilder/pt/zk-zeichen.svg":HD,"../../lessons/bilder/schiffe-versenken.svg":VD,"../../lessons/bilder/ss-binaere-suche.svg":qD,"../../lessons/bilder/ss-bubblesort.svg":QD,"../../lessons/bilder/ss-lineare-suche.svg":UD,"../../lessons/bilder/ss-vergleiche.svg":$D,"../../lessons/bilder/uebergabe.svg":YD,"../../lessons/bilder/zk-zeichen.svg":XD}),eg=i=>i.replace(/^.*\//,"");function G1(i,e,t){const n=s=>new Map(Object.entries(i).filter(([r])=>{var o;return((o=e.exec(r))==null?void 0:o[1])===s}).map(([r,o])=>[eg(r),o]));return[...new Map([...n("en"),...t==="en"?[]:n(t)])]}function Gu(i){return i==="de"?"de":i==="pt-PT"?"pt":"en"}let I1="en",jt=[],On=[],Wa="",Na=[],ps="off";function Hu(i){i!==ps&&(ps=i,jt=[],fs(I1))}function fs(i){var s,r,o;if(b3(i),i===I1&&jt.length>0)return;I1=i;const e=G1(OB,/\/lessons\/([^/]+)\/[^/]+\.md$/,i),t=(l,u)=>l.filter(([c])=>/^\d+/.test(c)).map(([c,m])=>_B(Qu(m,u),`${i}/${c}`)).sort((c,m)=>c.number-m.number),n=(l,u,c)=>l.map(([m,d])=>{const h=AB(Qu(d,c),`${i}/${u}${m}`);return c&&h.after!==void 0?{...h,after:c.get(h.after)??h.after}:h}),a=G1(CB,/\/lessons\/([^/]+)\/aufgaben\/[^/]+\.md$/,i);if(ps==="on"){const l=G1(Ru,/\/lessons\/([^/]+)\/visubot\/[^/]+\.md$/,i),u=MB(qu(e),qu(l)),c=t(e,u.normal),m=h=>{var g;return((g=[...c].reverse().find(f=>u.normal.get(f.number)({...h,number:u.normal.get(h.number)})),...t(l,u.robot).map(h=>{const g=u.robot.get(h.number);return{...h,number:g,section:m(g),robot:!0}})].sort((h,g)=>h.number-g.number);const d=G1(jB,/\/lessons\/([^/]+)\/visubot\/aufgaben\/[^/]+\.md$/,i);On=[...n(a,"aufgaben/",u.normal),...n(d,"visubot/aufgaben/",u.robot).map(h=>({...h,robot:!0}))]}else jt=t(e),On=n(a,"aufgaben/");On.sort((l,u)=>(l.after??0)-(u.after??0)||l.level-u.level||l.title.localeCompare(u.title,i));for(const l of[...jt.flatMap(u=>u.steps.flatMap(c=>c.blocks)),...On.flatMap(u=>u.blocks)])l.kind==="textFile"&&_3(l.name,l.content);if(Wa=((s=e.find(([l])=>l==="nachschlagen.md"))==null?void 0:s[1])??"",ps!=="off"){const l=(r=G1(Ru,/\/lessons\/([^/]+)\/visubot\/[^/]+\.md$/,i).find(([u])=>u==="nachschlagen.md"))==null?void 0:r[1];l&&(Wa=`${Wa.trimEnd()} + +${l}`)}Na=KD(((o=e.find(([l])=>l==="begriffe.md"))==null?void 0:o[1])??"")}const Vu={1:3,2:5,3:5,4:8,5:11,6:11,7:11,8:11,9:11,10:11,11:11,12:11,13:11,14:11,15:11,16:14,17:15,18:15,19:17,20:17,21:17,22:18},qu=i=>i.map(([e])=>{var t;return Number((t=/^(\d+)/.exec(e))==null?void 0:t[1])}).filter(Number.isFinite).sort((e,t)=>e-t);function MB(i,e){const t=[...i].reverse().find(o=>o<=19)??i.at(-1)??0,n=o=>i.includes(Vu[o])?Vu[o]:t,a=new Map,s=new Map;let r=1;for(const o of i){a.set(o,r++);for(const l of e.filter(u=>n(u)===o))s.set(l,r++)}return{normal:a,robot:s}}function Qu(i,e){return e?i.replace(/\b(Lektion(?:en)?|Lessons?|Li[cç](?:ão|ões))(\s+\d+(?:\s*(?:,|bis|und|and|to|a|e|–|-)\s*\d+)*)/gi,(t,n,a)=>n+a.replace(/\d+/g,s=>String(e.get(Number(s))??s))):i}fs("en");function tg(i,e){return I1==="de"?i.get(e)??i.get(`en/${e}`):(I1==="en"?void 0:i.get(`${I1}/${e}`))??i.get(`en/${e}`)??i.get(e)}const ng=(i,e)=>i.slice(i.indexOf(e)+e.length),ZB=new Map(Object.entries(PB).map(([i,e])=>[ng(i,"/diagramme/"),e]));function ti(i){const e=tg(ZB,i);return e===void 0?void 0:Nl(e)}const LB=new Map(Object.entries(BB).map(([i,e])=>[ng(i,"/bilder/"),e]));function zr(i){return tg(LB,i)}const EB=new Map(Object.entries(DB).map(([i,e])=>[eg(i).replace(/\.txt$/,""),e])),Uu=new Map;function Fa(i){const e=EB.get(i);if(e===void 0)return;let t=Uu.get(i);return t||Uu.set(i,t=Hb(e)),t}const ig=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,""");function je(i){const e=[];let t=ig(i).replace(/`([^`]+)`/g,(n,a)=>(e.push(a),`\0${e.length-1}\0`));return t=t.replace(/\*\*(.+?)\*\*/g,"$1").replace(/(^|[^*])\*([^*\s][^*]*?)\*/g,"$1$2").replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(n,a,s)=>{const r=/^(https?:|mailto:|#|\.{0,2}\/)/.test(s)?s:"#",o=/^https?:/.test(r)?' target="_blank" rel="noopener noreferrer"':"";return`${a}`}).replace(/\[([^\]]+)\]\{\.(blau|orange|gruen|gelb|rosa)\}/g,'$1').replace(/\[([^\]]+)\]\{(?:teil|part)=([\w,]+)\}/g,'$1'),t.replace(/\u0000(\d+)\u0000/g,(n,a)=>`${e[Number(a)]}`)}function Tn(i){const e=[],t=i.replace(/\r\n/g,` +`).split(` +`);let n=0;for(;n${ig(m.join(` +`))}`);continue}const s=/^(#{2,4})\s+(.*)$/.exec(a);if(s){const o=s[1].length;e.push(`${je(s[2])}`),n++;continue}if(/^\s*([-*]|\d+\.)\s+/.test(a)){const o=/^\s*\d+\./.test(a),l=[];for(;n${je(u)}`)}e.push(o?`
    ${l.join("")}
`:`
    ${l.join("")}
`);continue}if(a.startsWith("|")&&/^\|?[\s:|-]*-{3,}[\s:|-]*$/.test(t[n+1]??"")){const o=c=>c.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(m=>je(m.trim())),l=o(a);n+=2;const u=[];for(;n${l.map(c=>``).join("")}${u.map(c=>`${c.map(m=>``).join("")}`).join("")}
${c}
${m}
`);continue}if(a.startsWith(">")){const o=[];for(;n");)o.push(t[n++].replace(/^>\s?/,""));e.push(``);continue}const r=[];for(;n|\||\s*([-*]|\d+\.)\s+)/.test(t[n]);)r.push(t[n++].trim());e.push(`

${je(r.join(" "))}

`)}return e.join(` +`)}const ra=""+new URL("ludwig-Cus1i402.webp",import.meta.url).href,Zo="f4ecc8e489ae7865308288c7d0fa313333cf2be3ff529b23bc214bee010310e0",r0="visustruct.learn.teacher";let o0=!1;function $u(){if(o0)return!0;try{return localStorage.getItem(r0)===Zo}catch{return!1}}async function WB(i){const e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(i));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}async function NB(i){let e=!1;try{e=await WB(i.trim())===Zo}catch{return!1}if(e){o0=!0;try{localStorage.setItem(r0,Zo)}catch{}}return e}function FB(){o0=!1;try{localStorage.removeItem(r0)}catch{}}function ag(i,e,t=!1){const n=document.createElement("figure");n.className=t?"learn-file written":"learn-file";const a=document.createElement("figcaption"),s=document.createElement("span");s.className="learn-file-icon",s.setAttribute("aria-hidden","true"),s.textContent="📄",a.append(s,t?p("web_sim_written_file_fmt",i):i);const r=document.createElement("pre");return r.className="learn-file-text",r.dir="ltr",e.replace(/\n$/,"").split(` +`).forEach((l,u)=>{const c=document.createElement("span");c.className="ln",c.textContent=String(u+1),r.append(c,l+` +`)}),n.append(a,r),n}function sg(i){return[...i].map(([e,t])=>ag(e,t,!0))}function t1(i){switch(i.kind){case"finished":return p("sim_notice_finished");case"infiniteLoopWithoutBody":return p("sim_notice_infinite_loop_empty");case"unsupportedStatement":return p("sim_notice_unsupported_statement_fmt",i.text);case"invalidExpression":return p("sim_notice_invalid_expression_fmt",i.text);case"unknownVariable":return p("sim_notice_unknown_variable_fmt",i.text);case"divisionByZero":return p("sim_notice_division_by_zero");case"wholeNumberExpected":return p("sim_notice_whole_number_expected");case"numberExpected":return p("sim_notice_number_expected");case"booleanExpected":return p("sim_notice_boolean_expected");case"subprogramNotFound":return p("sim_notice_subprogram_not_found_fmt",i.text);case"callTooDeep":return p("sim_notice_call_too_deep");case"callArguments":return p("web_sim_call_arguments_fmt",i.text);case"missingReturn":return p("web_sim_missing_return_fmt",i.text);case"fileNotFound":return p("web_sim_file_not_found_fmt",i.text);case"endOfFile":return p("web_sim_end_of_file_fmt",i.text);case"nullValue":return p("web_sim_null_value_fmt",i.text);case"other":return i.text}}const Be=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,"""),Yu=["0.2","0.5","1.0","1.5","2.0"],JB=i=>Number(i).toLocaleString(s1()==="java"?"en":s1(),{minimumFractionDigits:1}),Ir="visustruct.simulation.stepDelay",Xu="visustruct.simulation.highlightMode";function kr(i){try{return localStorage.getItem(i)}catch{return null}}function Ku(i,e){try{localStorage.setItem(i,e)}catch{}}class RB{constructor(e,t,n=()=>{},a=()=>{},s=()=>{}){y(this,"element");y(this,"engine");y(this,"isPlaying",!1);y(this,"playTimer");y(this,"wasPlayingBeforeInput",!1);y(this,"delay",Yu.includes(kr(Ir)??"")?kr(Ir):"0.5");y(this,"highlightMode",kr(Xu)==="nextToExecute"?"nextToExecute":"lastExecuted");y(this,"buttons");y(this,"inputSection");y(this,"trace");y(this,"variables");y(this,"output");y(this,"transcript",[]);y(this,"printed",0);y(this,"notice");y(this,"editButton");y(this,"robot");y(this,"liveBusy",!1);this.currentDocument=e,this.onHighlight=t,this.findSubprogram=n,this.onEdit=a,this.onTranscript=s,this.engine=new wi(e(),n),this.element=document.createElement("aside"),this.element.className="simpanel",this.build()}setRobot(e){var t;this.robot!==e&&((t=this.robot)==null||t.element.remove(),this.robot=e,e&&(this.element.querySelector("section").after(e.element),e.onWorldChange=()=>this.restartEngine(),e.reset()))}showRobot(){var e;(e=this.robot)==null||e.show()}begin(){this.pause(),this.restartEngine(),this.showRobot()}end(){this.pause()}step(){var n,a,s;if((n=this.robot)!=null&&n.live){this.stepLive();return}if(!this.engine.canStep){this.pause();return}const e=this.isPlaying,t=this.engine.currentStepPath;(a=this.robot)==null||a.prepare(this.engine),this.engine.step(),(s=this.robot)==null||s.follow(this.engine.state.robotActions,e?Number(this.delay)*850:450),this.afterStep(e,t)}async stepLive(){if(this.liveBusy)return;if(!this.engine.canStep){this.pause();return}this.liveBusy=!0;const e=this.robot,t=this.isPlaying,n=this.engine.currentStepPath;try{await e.prepareLive(this.engine,v3(JSON.stringify(this.currentDocument()))),this.engine.step(),e.follow(this.engine.state.robotActions,450),await e.drive(this.engine.state.robotActions)}catch(a){e.liveFailed(a),this.isPlaying=!1}finally{this.liveBusy=!1}this.afterStep(t,n)}afterStep(e,t){this.collectOutput(),this.highlightMode==="nextToExecute"&&this.engine.canStep?this.onHighlight(this.engine.currentStepPath):this.onHighlight(t??this.engine.currentStepPath),this.engine.state.inputRequest&&e&&(this.wasPlayingBeforeInput=!0),this.engine.canStep||this.pause(),this.update()}reset(){this.pause(),this.restartEngine()}play(){if(this.isPlaying||!this.engine.canStep)return;this.isPlaying=!0;const e=async()=>{var t;this.playTimer=void 0,this.isPlaying&&((t=this.robot)!=null&&t.live?await this.stepLive():this.step(),this.isPlaying&&this.engine.canStep?this.playTimer=window.setTimeout(()=>void e(),Number(this.delay)*1e3):(this.isPlaying=!1,this.update()))};e()}pause(){this.playTimer!==void 0&&window.clearTimeout(this.playTimer),this.playTimer=void 0,this.isPlaying=!1,this.update()}submitInput(e){var s,r;const t=this.isPlaying||this.wasPlayingBeforeInput;this.pause();const n=((s=this.engine.state.inputRequest)==null?void 0:s.prompt)??"",a=(r=this.engine.state.inputRequest)==null?void 0:r.continuesLine;if(this.engine.provideInput(e.value),!this.engine.state.inputRequest){const o=this.transcript[this.transcript.length-1];a&&o&&o.typed===void 0?o.typed=e.value:this.transcript.push({text:n?`${n} `:"",typed:e.value}),e.value=""}this.onHighlight(this.engine.currentStepPath),t&&this.engine.canStep&&(this.wasPlayingBeforeInput=!1,this.play()),this.update()}restartEngine(){var e;this.engine=new wi(this.currentDocument(),this.findSubprogram),this.transcript=[],this.printed=0,this.wasPlayingBeforeInput=!1,(e=this.robot)==null||e.reset(),this.onHighlight(this.engine.currentStepPath),this.update()}build(){this.element.innerHTML=` +
+

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

+
+ + + + +
+ + +
+

+ +

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

+

${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,Ku(Xu,this.highlightMode)});const n=e("[data-sim=delay]");n.value=this.delay,n.addEventListener("change",()=>{this.delay=n.value,Ku(Ir,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),c=l.insertCell();u.kind==="grid"?c.append(rg(u)):c.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}),...sg(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?t1(r):"",o.hidden=!r}}function rg(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 x1=Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),Gn=360/x1.length,GB="http://www.w3.org/2000/svg";function Je(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 xt(i,e={},t){const n=document.createElementNS(GB,i);for(const[a,s]of Object.entries(e))n.setAttribute(a,String(s));return t!==void 0&&(n.textContent=t),n}function HB(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 ec(i,e){const t=xt("g",{class:e}),n=x1.map((a,s)=>{const r=xt("g",{transform:`rotate(${s*Gn})`});return r.append(xt("text",{x:0,y:-i,"text-anchor":"middle","dominant-baseline":"central"},a)),t.append(r),r});return{group:t,cells:n}}function VB(i,e){let t=i,n=!1,a=-t*Gn;const s=Je("section",{class:"learn-game learn-caesar"});s.append(Je("div",{class:"learn-game-head"},Je("strong",{},p("web_learn_caesar_title")))),s.append(Je("p",{class:"learn-game-status"},p("web_learn_caesar_hint")));const r=xt("svg",{viewBox:"-200 -200 400 400",class:"learn-caesar-disc",role:"img"});r.append(xt("circle",{r:196,class:"outer-disc"})),r.append(xt("path",{d:qB(196,92,Gn/2),class:"window"}));const o=ec(168,"outer-letters");r.append(o.group);for(let O=0;O{o.cells.forEach((Z,W)=>Z.classList.toggle("marked",W===O)),u.cells.forEach((Z,W)=>Z.classList.toggle("marked",O!==void 0&&W===(O+t)%26))},T=()=>{c.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),I.textContent=HB(v.value,n?-t:t)||" ";const O=Array.from(v.value.toUpperCase()).reverse().find(W=>x1.includes(W));if(O===void 0)return k();const Z=x1.indexOf(O);k(n?(Z-t+26)%26:Z)},A=O=>{t=(O%26+26)%26,a=-t*Gn,T()};m.addEventListener("click",()=>A(t-1)),d.addEventListener("click",()=>A(t+1)),f.addEventListener("click",()=>{var O;n&&(v.value=((O=I.textContent)==null?void 0:O.trim())??""),n=!1,T()}),b.addEventListener("click",()=>{var O;n||(v.value=((O=I.textContent)==null?void 0:O.trim())??""),n=!0,T()}),v.addEventListener("input",T),o.cells.forEach((O,Z)=>O.addEventListener("click",()=>k(Z)));let D;const P=O=>{const Z=r.getBoundingClientRect();return Math.atan2(O.clientY-(Z.top+Z.height/2),O.clientX-(Z.left+Z.width/2))*180/Math.PI};l.addEventListener("pointerdown",O=>{const Z=O;D=P(Z)-a,l.classList.add("dragging"),r.setPointerCapture(Z.pointerId),Z.preventDefault()}),r.addEventListener("pointermove",O=>{if(D===void 0)return;a=P(O)-D,l.setAttribute("transform",`rotate(${a})`);const Z=Math.round(-a/Gn);if((Z%26+26)%26!==t){t=(Z%26+26)%26;const W=a;T(),a=W,l.setAttribute("transform",`rotate(${a})`)}});const j=()=>{D!==void 0&&(D=void 0,l.classList.remove("dragging"),A(t))};return r.addEventListener("pointerup",j),r.addEventListener("pointercancel",j),T(),s}function qB(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 l0=i=>p(`web_visubot_part_${i}`),og=new WeakMap;function lg(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=(m,d,h)=>{r.hidden=!1,r.textContent=l0(m),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=K(async()=>{const{Robot3D:m}=await import("./robot3d-DZxNwb67.js");return{Robot3D:m}},[],import.meta.url).then(({Robot3D:m})=>{const d=new m(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(m=>{console.error(m),s.textContent=p("web_visubot_no_3d")}),c={box:a,ready:u,focus:i,view:e};return og.set(a,c),c}function QB(i,e,t=!1){return lg(i,e,t).box}function UB(i){const e=i.querySelector(".visubot-model"),t=e&&og.get(e);for(const n of i.querySelectorAll("[data-robot-part]")){const a=(n.dataset.robotPart??"").split(",").filter(Boolean);if(n.title=a.map(l0).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 $B(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=Tn(`**${t+1}/${i.length}** ${i[t].question}`)},r=lg([],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",l0(l));return}t++,a.className="visubot-quiz-feedback right",t{u.forEach(v=>{window.clearTimeout(v),window.clearInterval(v)}),u=[]},m=()=>{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,I=$("div",{class:"learn-bomb-fuse"},$("span",{})),z=$("span",{class:"learn-bomb-time"}),k=$("div",{class:"learn-bomb","aria-live":"polite"},$("span",{class:"learn-bomb-icon","aria-hidden":"true"},"💣"),z,I),T=$("div",{class:"learn-game-feedback",role:"status"}),A=v.code.split(` +`).map((W,U)=>{const ee=$("button",{class:"ln",type:"button"},W||" ");return ee.disabled=!W.trim(),ee.addEventListener("click",()=>O(U+1===v.wrongLine?"right":"wrong",ee)),ee}),D=$("div",{class:"learn-game-code learn-bomb-code mono",dir:"ltr"},...A),P=Date.now(),j=()=>{if(!t.isConnected&&Date.now()-P>1e3)return c();const W=Math.max(0,w-(Date.now()-P)/1e3);z.textContent=p("web_game_time_fmt",Math.ceil(W)),I.firstChild.style.width=`${W/w*100}%`,k.classList.toggle("hurry",W<=5),W<=0&&O("time")},O=(W,U)=>{c(),A.forEach((Ie,fe)=>{Ie.disabled=!0,fe+1===v.wrongLine&&Ie.classList.add("right")}),U&&W==="wrong"&&U.classList.add("wrong");const ee=W==="right";ee&&l++,m(),k.classList.add(ee?"defused":"boom"),k.firstChild.textContent=ee?"✂️":"💥",T.className=`learn-game-feedback ${ee?"right":"wrong"}`;const he=d();T.replaceChildren($("p",{},p(ee?"web_game_defused":W==="time"?"web_game_boom_time":"web_game_boom_wrong")),Jn("div",{class:"learn-game-explain"},v.explanation),$("p",{class:"learn-bomb-fix"},`${p("web_game_fix")} `,$("code",{},v.fix.trim())),he),he.focus({preventScroll:!0})};s.replaceChildren(k,Jn("p",{class:"learn-game-question"},v.question),D,T),j();const Z=window.setInterval(j,200);u.push(Z)},g=()=>{const v=i.rounds[o],w=[];v.code.trim()&&w.push(nc(v.code).element),w.push(Jn("p",{class:"learn-game-question"},v.question),$("p",{class:"learn-order-hint"},p("web_game_order_hint")));const I=$("div",{class:"learn-game-options learn-order"}),z=$("div",{class:"learn-game-feedback",role:"status"});let k=0;const T=XB(v.options.length).map(D=>{const P=$("span",{class:"learn-order-badge","aria-hidden":"true"}),j=$("span",{});j.innerHTML=je(v.options[D].text);const O=$("button",{},P,j);return O.addEventListener("click",()=>{if(D!==k)return O.classList.add("wrong"),A(!1);O.classList.add("right"),P.textContent=String(++k),O.disabled=!0,k===v.options.length&&A(!0)}),I.append(O),{k:D,b:O,badge:P}}),A=D=>{for(const{k:j,b:O,badge:Z}of[...T].sort((W,U)=>W.k-U.k))O.disabled=!0,Z.textContent=String(j+1),I.append(O);D&&l++,m(),z.className=`learn-game-feedback ${D?"right":"wrong"}`;const P=d();z.replaceChildren($("p",{},p(D?"web_game_right":"web_game_wrong_short")),Jn("div",{class:"learn-game-explain"},v.explanation),P),P.focus({preventScroll:!0})};s.replaceChildren(...w,I,z)},f=()=>{if(c(),i.kind==="bombe"||i.kind==="reihenfolge"){m(),i.kind==="bombe"?h():g();return}const v=i.rounds[o];m();const w=nc(v.code),I=[];let z;i.kind==="zuhoerer"?(z=KB(Gh(v.code),w),I.push($("div",{class:"learn-swing-row"},w.element,z.element)),v.clicks.length&&I.push($("p",{class:"learn-swing-clicks"},`${p("web_game_clicks")} `,...v.clicks.flatMap((P,j)=>[...j?[" → "]:[],$("code",{},P)])))):v.code.trim()&&I.push(w.element),I.push(Jn("p",{class:"learn-game-question"},v.question));const k=$("div",{class:`learn-game-options ${i.kind==="layout"?"pictures":""}`}),T=$("div",{class:"learn-game-feedback",role:"status"}),A=v.options.map(P=>{const j=$("button",{});return i.kind==="layout"?j.append(tM(P.text)):P.text.includes(` +`)?j.append(eM(P.text)):j.innerHTML=je(P.text),j.addEventListener("click",()=>D(P.right,j)),k.append(j),j}),D=(P,j)=>{A.forEach((Z,W)=>{Z.disabled=!0,v.options[W].right&&Z.classList.add("right")}),P||j.classList.add("wrong"),P&&l++,m(),T.className=`learn-game-feedback ${P?"right":"wrong"}`;const O=d();T.replaceChildren($("p",{},p(P?"web_game_right":"web_game_wrong_short")),Jn("div",{class:"learn-game-explain"},v.explanation)),T.append(O),z&&(u=z.replay(v.clicks,()=>O.before($("p",{class:"learn-swing-try"},p("web_game_try"))))),O.focus({preventScroll:!0})};s.replaceChildren(...I,k,T)},b=()=>{c(),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(Jn("p",{},i.intro),x),t}function XB(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 nc(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 KB(i,e){const t=Hh(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 m of i.labels){const d=$("div",{class:"learn-swing-label"},t.texts[m.name]);s.set(m.name,d),a.append(d)}const r=i.buttons.map(m=>{const d=$("button",{class:"learn-swing-button",disabled:""},t.texts[m.name]);return s.set(m.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=m=>{var h,g;const d=s.get(m.button);d.classList.add("pressed"),window.setTimeout(()=>d.classList.remove("pressed"),350),e.highlight((h=m.listener)==null?void 0:h.from,(g=m.listener)==null?void 0:g.to),o.textContent=m.listener?p("web_game_event_fmt",d.textContent??""):p("web_game_nobody"),o.className=`learn-swing-event ${m.listener?"heard":"nobody"}`;for(const[f,b]of Object.entries(m.texts)){const x=s.get(f);x&&x.textContent!==b&&(x.textContent=b,x.classList.remove("changed"),x.offsetWidth,x.classList.add("changed"))}m.console.length&&(l.hidden=!1,l.textContent+=m.console.map(f=>`${f} +`).join(""))},c=m=>u(Vh(i,t,m));return{element:n,replay(m,d){const h=m.map((g,f)=>window.setTimeout(()=>c(g),(f+.3)*tc));return h.push(window.setTimeout(()=>{i.buttons.forEach((g,f)=>{r[f].disabled=!1,r[f].addEventListener("click",()=>u(qh(i,t,g.name)))}),d()},(m.length+.3)*tc)),h}}}function eM(i){return $("pre",{class:"learn-game-file mono",dir:"ltr"},i)}function tM(i){const e=Rh(i),t=$("div",{class:"learn-layout-window",dir:"ltr"},$("div",{class:"learn-layout-title"})),n=$("div",{class:`learn-layout-body ${e.kind}`}),a=(s,r)=>$("span",{class:"learn-layout-cell",...r?{style:`grid-area:${r}`}:{}},s);if(e.kind==="border")for(const[s,r]of Object.entries(e.areas))n.append(a(r,s));else if(e.kind==="grid"){const s=Math.max(...e.rows.map(r=>r.length));n.style.gridTemplateColumns=`repeat(${s}, 1fr)`;for(const r of e.rows)for(let o=0;oa(r))));return t.append(n),t}function H(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 zn(i,e,t){const n=H(i,e);return n.innerHTML=je(t),n}function ic(i){return H("pre",{class:"learn-game-code mono",dir:"ltr"},...i.split(` +`).map(e=>H("div",{class:"ln"},e||" ")))}function nM(i,e){const t=H("section",{class:"learn-game learn-rescue"}),n=H("div",{class:"learn-game-head"});n.append(H("img",{src:e,alt:"",width:"40",height:"40"}),H("strong",{},i.title));const a=i.stations.length,s=i.stations.map(()=>H("span",{class:"learn-rescue-dot"})),r=H("img",{class:"learn-rescue-ludwig",src:e,alt:"",width:"32",height:"32"}),o=H("span",{class:"learn-rescue-tower","aria-hidden":"true"},"🏰",H("span",{class:"learn-rescue-zora"},"🐐"),H("span",{class:"learn-rescue-fox"},"🦊")),l=H("span",{class:"learn-rescue-free"},"🐐"),u=H("div",{class:"learn-rescue-path","aria-hidden":"true"},r,...s,o),c=H("p",{class:"learn-game-status"}),m=H("div",{class:"learn-game-stage"}),d=iM(i);t.append(n,u,c,m);let h=0;const g=()=>{s.forEach((z,k)=>z.classList.toggle("done",k{const z=[...i.alphabet].map((k,T)=>H("span",{class:"learn-rescue-letter"},H("b",{},k),H("small",{},String(T))));return{element:H("div",{class:"learn-rescue-alphabet mono",dir:"ltr"},...z),cells:z}},b=z=>{const k=i.stations[z];c.textContent=p("web_learn_rescue_station_fmt",z+1,a,k.name);const T=f(),A=H("input",{type:"text",inputmode:"numeric",autocomplete:"off",class:"learn-rescue-number mono","aria-label":p("web_learn_rescue_number")}),D=H("button",{class:"primary"},p("web_learn_check")),P=H("div",{class:"learn-game-feedback",role:"status"}),j=()=>{const O=A.value.trim();if(!/^-?\d+$/.test(O)){P.className="learn-game-feedback wrong",P.replaceChildren(H("p",{},p("web_learn_rescue_not_number")));return}if(Number(O)!==k.answer){P.className="learn-game-feedback wrong",P.replaceChildren(H("p",{},p("web_learn_rescue_wrong")),...k.hint?[zn("div",{class:"learn-game-explain"},`**${p("web_learn_hint")}:** ${k.hint}`)]:[]),A.select();return}A.disabled=D.disabled=!0;const Z=i.alphabet.charAt(k.answer);T.cells[k.answer].classList.add("hit"),d.give(k.row,k.col,Z),h++,g();const W=z+1===a,U=H("button",{class:"primary"},p(W?"web_learn_rescue_to_crossword":"web_game_next"));U.addEventListener("click",()=>W?x():b(z+1)),P.className="learn-game-feedback right",P.replaceChildren(H("p",{},p("web_game_right")),H("p",{class:"learn-rescue-charat mono",dir:"ltr"},`alphabet.charAt(${k.answer})`,H("span",{"aria-hidden":"true"}," → "),H("code",{},`'${Z}'`)),zn("div",{class:"learn-game-explain"},k.explanation),H("p",{class:"learn-rescue-moved"},p("web_learn_rescue_letter_moved")),U),U.focus({preventScroll:!0})};D.addEventListener("click",j),A.addEventListener("keydown",O=>{O.key==="Enter"&&j()}),m.replaceChildren(ic(k.code),zn("p",{class:"learn-game-question"},k.question),H("div",{class:"learn-rescue-answer"},A,D),P,H("p",{class:"learn-rescue-label"},p("web_learn_rescue_alphabet")),ic(`String alphabet = "${i.alphabet}";`),T.element,d.element),A.focus({preventScroll:!0})},x=()=>{c.textContent=p("web_learn_rescue_crossword");const z=H("div",{class:"learn-game-feedback",role:"status"}),k=H("button",{class:"primary"},p("web_learn_check"));k.addEventListener("click",()=>{if(!d.check()){z.className="learn-game-feedback wrong",z.replaceChildren(H("p",{},p("web_learn_rescue_cw_wrong")));return}k.disabled=!0,d.lock();const T=H("button",{class:"primary"},p("web_learn_rescue_to_gate"));T.addEventListener("click",v),z.className="learn-game-feedback right",z.replaceChildren(H("p",{},p("web_learn_rescue_cw_done")),T),T.focus({preventScroll:!0})}),d.unlock(),m.replaceChildren(zn("p",{},i.crosswordText),d.element,k,z),d.focusFirst()},v=()=>{c.textContent=p("web_learn_rescue_gate");const z=H("input",{type:"text",autocomplete:"off",autocapitalize:"off",spellcheck:"false",class:"learn-rescue-word mono",size:String(i.keyword.length+2),"aria-label":p("web_learn_rescue_word")}),k=i.gateCode.split(` +`).map(P=>{const j=P.indexOf(gs);return j<0?H("div",{class:"ln"},P||" "):H("div",{class:"ln"},P.slice(0,j),z,P.slice(j+gs.length))}),T=H("button",{class:"primary"},p("web_learn_rescue_open")),A=H("div",{class:"learn-game-feedback",role:"status"}),D=()=>{const P=z.value.trim();if(P!==i.keyword){const O=P.toUpperCase()===i.keyword.toUpperCase();A.className="learn-game-feedback wrong",A.replaceChildren(H("p",{},p(O?"web_learn_rescue_gate_case":"web_learn_rescue_gate_wrong"))),z.select();return}z.disabled=T.disabled=!0,t.classList.add("freed"),r.after(l),c.textContent="";const j=H("button",{},p("web_game_again"));j.addEventListener("click",w),A.className="learn-game-feedback right",A.replaceChildren(H("p",{},p("web_learn_rescue_freed")),zn("div",{class:"learn-game-explain"},i.end),j)};T.addEventListener("click",D),z.addEventListener("keydown",P=>{P.key==="Enter"&&D()}),m.replaceChildren(zn("p",{},i.gateText),H("div",{class:"learn-game-code mono learn-rescue-gate",dir:"ltr"},...k),T,A),z.focus({preventScroll:!0})},w=()=>{h=0,t.classList.remove("freed"),l.remove(),d.reset(),g(),b(0)},I=H("button",{class:"primary"},p("web_game_start"));return I.addEventListener("click",w),m.append(zn("p",{},i.intro),I),t}function iM(i){const e=rB(i),t=new Map(i.solution.map((g,f)=>[`${g.row} ${g.col}`,f])),n=new Map;for(const g of i.words)n.set(`${g.row} ${g.col}`,g.number);const a=new Map,s=H("div",{class:"learn-cw-grid",dir:"ltr"});s.style.gridTemplateColumns=`repeat(${i.cols}, var(--cw-cell))`;let r=!0;const o=(g,f)=>i.words.filter(b=>b.across?b.row===g&&f>=b.col&&f=b.row&&g{var v;const x=r?`${g} ${f+b}`:`${g+b} ${f}`;(v=a.get(x))==null||v.focus()};e.forEach((g,f)=>g.forEach((b,x)=>{if(!b)return s.append(H("span",{class:"learn-cw-empty"}));const v=`${f} ${x}`,w=H("input",{type:"text",maxlength:"1",autocomplete:"off",autocapitalize:"characters",spellcheck:"false","aria-label":p("web_learn_rescue_cell_fmt",f+1,x+1)});w.disabled=!0,w.addEventListener("focus",()=>{const T=o(f,x);T.some(A=>A.across===r)||(r=T[0].across),w.select()}),w.addEventListener("input",()=>{w.value=w.value.slice(-1).toUpperCase(),w.classList.remove("wrong"),m(),w.value&&l(f,x,1)}),w.addEventListener("keydown",T=>{if(T.key==="Backspace"&&!w.value)l(f,x,-1);else if(T.key==="ArrowRight"||T.key==="ArrowLeft")r=!0,l(f,x,T.key==="ArrowRight"?1:-1);else if(T.key==="ArrowDown"||T.key==="ArrowUp")r=!1,l(f,x,T.key==="ArrowDown"?1:-1);else return;T.preventDefault()}),a.set(v,w);const I=t.get(v),z=H("span",{class:`learn-cw-cell${I!==void 0?" key":""}`}),k=n.get(v);k&&z.append(H("small",{class:"learn-cw-number"},String(k))),I!==void 0&&z.append(H("small",{class:"learn-cw-keyindex"},String(I+1))),z.append(w),s.append(z)}));const u=g=>{const f=H("ol",{class:"learn-cw-clues"});for(const b of i.words.filter(x=>x.across===g).sort((x,v)=>x.number-v.number)){const x=zn("li",{value:String(b.number)},`${b.clue} (${b.word.length})`);x.addEventListener("click",()=>{var v;r=b.across,(v=a.get(`${b.row} ${b.col}`))==null||v.focus()}),f.append(x)}return H("div",{},H("strong",{},p(g?"web_learn_rescue_across":"web_learn_rescue_down")),f)},c=i.solution.map(()=>H("span",{class:"learn-cw-keybox"})),m=()=>i.solution.forEach((g,f)=>c[f].textContent=a.get(`${g.row} ${g.col}`).value||" "),d=H("div",{class:"learn-cw"},H("div",{class:"learn-cw-board"},s,H("p",{class:"learn-cw-keyword"},`${p("web_learn_rescue_keyword")} `,H("span",{class:"mono",dir:"ltr"},...c))),H("div",{class:"learn-cw-cluebox"},u(!0),u(!1))),h=new Set;return{element:d,give(g,f,b){const x=a.get(`${g} ${f}`);x.value=b,x.parentElement.classList.add("given","arrived"),h.add(`${g} ${f}`),m()},unlock(){for(const[g,f]of a)f.disabled=h.has(g)},lock(){for(const g of a.values())g.disabled=!0},focusFirst(){var g;(g=[...a].find(([f])=>!h.has(f)))==null||g[1].focus({preventScroll:!0})},check(){let g=!0;for(const[f,b]of a){const[x,v]=f.split(" ").map(Number),w=b.value!==e[x][v];b.classList.toggle("wrong",w),w&&(g=!1)}return g},reset(){h.clear();for(const g of a.values())g.value="",g.disabled=!0,g.classList.remove("wrong"),g.parentElement.classList.remove("given","arrived");m()}}}function St(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 ac(i,e,t){const n=St(i,e);return n.innerHTML=je(t),n}function aM(i){const e=St("section",{class:"learn-cloze"});e.append(St("strong",{class:"learn-cloze-title"},i.title)),i.task&&e.append(ac("p",{},i.task)),e.append(St("p",{class:"learn-cloze-hint"},p("web_learn_cloze_hint")));const t=[];for(const c of i.blocks){const m=St("pre",{class:"learn-cloze-code mono",dir:"ltr"});for(const d of c){const h=St("div",{class:"ln"});for(const g of d){if(typeof g=="string"){h.append(g);continue}const f=St("input",{type:"text",class:"learn-cloze-gap mono",autocomplete:"off",autocapitalize:"off",autocorrect:"off",spellcheck:"false",enterkeyhint:"done","aria-label":`${t.length+1}`});f.style.width=`${Math.max(3,...g.answers.map(b=>b.length))+1}ch`,t.push({input:f,answers:g.answers}),h.append(f)}d.length||h.append(` +`),m.append(h)}e.append(m)}const n=St("p",{class:"learn-cloze-status",role:"status"}),a=i.explanation?ac("p",{class:"learn-explanation"},i.explanation):void 0;a&&(a.hidden=!0);const s=St("button",{class:"learn-cloze-check"},p("web_learn_check")),r=St("button",{},p("web_learn_cloze_solution")),o=St("button",{},p("web_learn_cloze_again"));r.hidden=!0,o.hidden=!0;const l=St("div",{class:"learn-cloze-actions"},s,r,o);e.append(l,n),a&&e.append(a);const u=()=>{var d;let c=0;for(const h of t){const g=dB(h.answers,h.input.value);h.input.classList.toggle("right",g),h.input.classList.toggle("wrong",!g),g&&c++}const m=c===t.length;n.textContent=m?p("web_learn_cloze_all_right"):p("web_learn_cloze_score_fmt",c,t.length),n.className=`learn-cloze-status ${m?"right":"wrong"}`,a&&(a.hidden=!m),m?(t.forEach(h=>h.input.disabled=!0),s.hidden=!0,o.hidden=!1):(r.hidden=!1,(d=t.find(h=>h.input.classList.contains("wrong")))==null||d.input.focus())};return s.addEventListener("click",u),r.addEventListener("click",()=>{for(const c of t)c.input.value=c.answers[0],c.input.classList.remove("right","wrong"),c.input.classList.add("shown"),c.input.disabled=!0;n.textContent="",n.className="learn-cloze-status",a&&(a.hidden=!1),s.hidden=!0,r.hidden=!0,o.hidden=!1}),o.addEventListener("click",()=>{var c;for(const m of t)m.input.value="",m.input.classList.remove("right","wrong","shown"),m.input.disabled=!1;n.textContent="",n.className="learn-cloze-status",a&&(a.hidden=!0),s.hidden=!1,r.hidden=!0,o.hidden=!0,(c=t[0])==null||c.input.focus()}),t.forEach((c,m)=>{c.input.addEventListener("input",()=>c.input.classList.remove("right","wrong")),c.input.addEventListener("keydown",d=>{d.key==="Enter"&&(d.preventDefault(),m1?12:13});return n.forEach((s,r)=>{const o=yt("tspan",{x:e.x,y:e.y+4.5+(r-(n.length-1)/2)*14});o.textContent=s,a.append(o)}),a}function oa(i,e){return yt("polyline",{points:i.map(t=>t.join(",")).join(" "),fill:"none","marker-end":`url(#${e})`})}function sc(i,e,t,n){const a=yt("text",{x:e,y:t,"font-size":12,"font-weight":600,fill:n?"#248a3d":"#d70015"});return a.textContent=i,a}function oM(i,e){const t=Uh(e,110),n=Math.max(...t.map(u=>u.length)),a=Math.max(70,n*6.6+(i==="raute"?56:26)),s=i==="raute"?48:t.length>1?40:30,r=yt("svg",{viewBox:`0 0 ${a+4} ${s+4}`,width:a+4,height:s+4,"aria-hidden":"true"}),o={x:(a+4)/2,y:(s+4)/2,w:a,h:s},l=c0(i,o);return l.setAttribute("fill",u0[i]),l.setAttribute("stroke","#1c1c1e"),l.setAttribute("stroke-width","1.5"),r.append(l,ug(e,{...o,w:t.length>1?124:a},i)),r}function lM(i){const e=[...Array(i).keys()];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 i>1&&e.every((t,n)=>t===n)&&e.reverse(),e}function uM(){const i=qe("dl",{class:"learn-pap-legend"}),e=[["oval","web_learn_pap_legend_oval"],["rechteck","web_learn_pap_legend_rect"],["raute","web_learn_pap_legend_diamond"],["parallelogramm","web_learn_pap_legend_para"]];for(const[t,n]of e){const a=t==="raute"?44:40,s=yt("svg",{viewBox:`0 0 ${a+4} 28`,width:a+4,height:28,"aria-hidden":"true"}),r=c0(t,{x:(a+4)/2,y:14,w:a,h:t==="raute"?24:18});r.setAttribute("fill",u0[t]),r.setAttribute("stroke","#1c1c1e"),r.setAttribute("stroke-width","1.5"),s.append(r),i.append(qe("dt",{},s),qe("dd",{},p(n)))}return i}function cM(i){const e=qe("section",{class:"learn-pap"});if(e.append(qe("strong",{class:"learn-pap-title"},i.title)),i.task){const J=qe("p");J.innerHTML=je(i.task),e.append(J)}e.append(qe("p",{class:"learn-pap-hint"},p("web_learn_pap_hint")));const{boxes:t,height:n}=yB(i),a=t.filter(Boolean),s=Math.min(...a.map(J=>J.x-J.w/2))-4,r=i.nodes.some(J=>J.shape==="raute"),o=Math.max(...a.map(J=>J.x+J.w/2),r?Math.max(...a.map(J=>J.x))+85+40:0)+4,l=yt("svg",{viewBox:`${s} 0 ${o-s} ${n}`,class:"learn-pap-plan",role:"group","aria-label":i.title}),u=`pap-arrow-${++rM}`;l.innerHTML=``;const c=yt("g",{stroke:"#1c1c1e","stroke-width":2}),m=yt("g"),d=p("web_learn_pap_yes"),h=p("web_learn_pap_no"),g=J=>t[J].y-t[J].h/2,f=J=>t[J].y+t[J].h/2,b=i.nodes.map((J,C)=>C).filter(J=>!i.nodes[J].isSide);b.forEach((J,C)=>{const N=i.nodes[J],q=t[J],Y=b[C+1];if(Y!==void 0&&(c.append(oa([[q.x,f(J)],[q.x,g(Y)-2]],u)),N.shape==="raute"&&m.append(sc(N.sideExit==="nein"?d:h,q.x+6,f(J)+13,N.sideExit==="nein"))),N.shape!=="raute")return;const ue=q.x+q.w/2;if(m.append(sc(N.sideExit==="ja"?d:h,ue+5,q.y-6,N.sideExit==="ja")),N.backTo!==void 0){const X=g(N.backTo)-14;c.append(oa([[ue,q.y],[ue+22,q.y],[ue+22,X],[q.x,X]],u))}else if(N.side!==void 0){const X=t[N.side],ce=g(J)-14;c.append(oa([[ue,q.y],[X.x-X.w/2-2,q.y]],u)),c.append(oa([[X.x,X.y-X.h/2],[X.x,ce],[q.x,ce]],u))}}),l.append(c,m);const x=i.nodes.map(()=>{}),v=[],w=[];let I;const z=qe("p",{class:"learn-pap-status",role:"status"}),k=i.explanation?qe("p",{class:"learn-explanation"}):void 0;k&&(k.innerHTML=je(i.explanation),k.hidden=!0);let T=!1;const A=()=>{v.forEach(J=>J.classList.remove("right","wrong")),z.textContent="",z.className="learn-pap-status"},D=J=>{const C=v[J];C.replaceChildren();const N=i.nodes[J],q=x[J],Y=c0(N.shape,t[J]);if(Y.setAttribute("class","learn-pap-shape"),q===void 0)Y.setAttribute("fill","#f7f7f9"),Y.setAttribute("stroke-dasharray","6 4"),C.append(Y),C.setAttribute("aria-label",p("web_learn_pap_empty"));else{const ue=i.nodes[q];Y.setAttribute("fill",u0[ue.shape]),C.append(Y,ug(ue.text,t[J],N.shape)),C.setAttribute("aria-label",ue.text)}},P=()=>{i.nodes.forEach((J,C)=>D(C)),w.forEach((J,C)=>{J.hidden=x.includes(C),J.classList.toggle("selected",I===C)})},j=(J,C)=>{if(T)return;const N=x.indexOf(C);N>=0&&(x[N]=void 0),x[J]=C,I=void 0,A(),P()};i.nodes.forEach((J,C)=>{const N=yt("g",{class:"learn-pap-slot","data-slot":C,tabindex:0,role:"button"}),q=()=>{T||(I!==void 0?j(C,I):x[C]!==void 0&&(x[C]=void 0,A(),P()))};N.addEventListener("click",q),N.addEventListener("keydown",Y=>{Y.key!=="Enter"&&Y.key!==" "||(Y.preventDefault(),q())}),v.push(N),l.append(N)});const O=qe("div",{class:"learn-pap-tray"});let Z=!1;for(const J of lM(i.nodes.length)){const C=i.nodes[J],N=qe("button",{class:"learn-pap-card",type:"button","aria-label":C.text},oM(C.shape,C.text));w[J]=N,N.addEventListener("click",()=>{Z||T||(I=I===J?void 0:J,P())}),N.addEventListener("pointerdown",q=>{if(T)return;Z=!1;let Y;const ue=le=>{var Te;!Y&&Math.hypot(le.clientX-q.clientX,le.clientY-q.clientY)<6||(Y||(Z=!0,Y=N.cloneNode(!0),Y.classList.add("learn-pap-ghost"),document.body.append(Y),N.classList.add("dragging")),Y.style.left=`${le.clientX}px`,Y.style.top=`${le.clientY}px`,v.forEach(Fe=>Fe.classList.remove("over")),(Te=X(le))==null||Te.classList.add("over"))},X=le=>{var Fe;Y&&(Y.style.display="none");const Te=(Fe=document.elementFromPoint(le.clientX,le.clientY))==null?void 0:Fe.closest("[data-slot]");return Y&&(Y.style.display=""),Te&&v.includes(Te)?Te:void 0},ce=le=>{if(N.removeEventListener("pointermove",ue),N.removeEventListener("pointerup",ce),N.removeEventListener("pointercancel",ce),v.forEach(Fe=>Fe.classList.remove("over")),N.classList.remove("dragging"),!Y)return;const Te=le.type==="pointerup"?X(le):void 0;Y.remove(),Te&&j(Number(Te.getAttribute("data-slot")),J),setTimeout(()=>Z=!1)};N.setPointerCapture(q.pointerId),N.addEventListener("pointermove",ue),N.addEventListener("pointerup",ce),N.addEventListener("pointercancel",ce)}),O.append(N)}const W=qe("button",{class:"learn-pap-check"},p("web_learn_check")),U=qe("button",{},p("web_learn_cloze_solution")),ee=qe("button",{},p("web_learn_cloze_again"));U.hidden=!0,ee.hidden=!0;const he=()=>{T=!0,W.hidden=!0,U.hidden=!0,ee.hidden=!1,O.hidden=!0,fe.classList.add("done"),k&&(k.hidden=!1)};W.addEventListener("click",()=>{const J=x.filter(q=>q===void 0).length;let C=0;x.forEach((q,Y)=>{const ue=q!==void 0&&gB(i,Y,q);v[Y].classList.toggle("right",ue),v[Y].classList.toggle("wrong",q!==void 0&&!ue),ue&&C++});const N=C===i.nodes.length;z.textContent=N?p("web_learn_pap_all_right"):J?p("web_learn_pap_missing_fmt",J):p("web_learn_pap_score_fmt",C,i.nodes.length),z.className=`learn-pap-status ${N?"right":"wrong"}`,N?he():J||(U.hidden=!1)}),U.addEventListener("click",()=>{i.nodes.forEach((J,C)=>x[C]=C),I=void 0,P(),A(),v.forEach(J=>J.classList.add("shown")),he()}),ee.addEventListener("click",()=>{i.nodes.forEach((J,C)=>x[C]=void 0),T=!1,I=void 0,v.forEach(J=>J.classList.remove("shown")),A(),P(),W.hidden=!1,ee.hidden=!0,O.hidden=!1,fe.classList.remove("done"),k&&(k.hidden=!0)}),P();const Ie=qe("div",{class:"learn-pap-left"});Ie.append(l),i.legend&&Ie.append(uM());const fe=qe("div",{class:"learn-pap-work"},Ie,O);return e.append(fe,qe("div",{class:"learn-pap-actions"},W,U,ee),z),k&&e.append(k),e}const mM="code, pre, a, button, h1, h2, h3, h4, strong, .term, .ui-pointer";function rc(i,e){var s;const t=[...i.querySelectorAll(".learn-text")],n=new Set;for(const r of t.flatMap(o=>[...o.querySelectorAll("strong")])){const o=Lu(e),l=o==null?void 0:o.exec(r.textContent??""),u=l?Eu(e,l[0]):void 0;u&&n.add(u)}let a=e.filter(r=>!n.has(r));for(const r of t){const o=document.createTreeWalker(r,NodeFilter.SHOW_TEXT),l=[];for(;o.nextNode();){const u=o.currentNode;(s=u.parentElement)!=null&&s.closest(mM)||l.push(u)}for(let u of l)for(;;){const c=Lu(a),m=c==null?void 0:c.exec(u.data),d=m?Eu(a,m[0]):void 0;if(!m||!d)break;const h=u.splitText(m.index);u=h.splitText(m[0].length);const g=document.createElement("span");g.className="term",g.tabIndex=0,g.setAttribute("role","button"),g.setAttribute("aria-describedby","term-tip"),g.dataset.term=d.term,g.dataset.text=d.text,h.replaceWith(g),g.append(h),a=a.filter(f=>f!==d)}}}function dM(i){const e=document.createElement("div");e.id="term-tip",e.className="term-tip",e.setAttribute("role","tooltip"),e.hidden=!0,document.body.append(e);let t,n=!1;const a=o=>{t=o,e.replaceChildren();const l=document.createElement("strong");l.textContent=o.dataset.term??"",e.append(l,document.createTextNode(" "+(o.dataset.text??""))),e.hidden=!1;const u=o.getBoundingClientRect(),c=e.offsetWidth,m=e.offsetHeight,d=Math.max(8,Math.min(u.left,window.innerWidth-c-8)),h=u.bottom+6;e.style.left=`${d}px`,e.style.top=`${h+m>window.innerHeight-8?Math.max(8,u.top-m-6):h}px`,o.setAttribute("aria-expanded","true")},s=()=>{t==null||t.setAttribute("aria-expanded","false"),t=void 0,n=!1,e.hidden=!0},r=o=>{var l,u;return((u=(l=o.target)==null?void 0:l.closest)==null?void 0:u.call(l,".term"))??void 0};return i.addEventListener("pointerover",o=>{const l=r(o);l&&o.pointerType==="mouse"&&!n&&a(l)}),i.addEventListener("pointerout",o=>{r(o)&&o.pointerType==="mouse"&&!n&&s()}),i.addEventListener("click",o=>{const l=r(o);if(l){if(n&&t===l)return s();a(l),n=!0}}),i.addEventListener("focusin",o=>{const l=r(o);l&&!n&&a(l)}),i.addEventListener("focusout",o=>{r(o)&&!n&&s()}),i.addEventListener("keydown",o=>{const l=r(o);o.key==="Escape"&&t?s():l&&(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),l.click())}),i.addEventListener("scroll",s,!0),document.addEventListener("pointerdown",o=>{t&&!r(o)&&!e.contains(o.target)&&s()}),{hide:s}}const cg={leiste:".topbar > .toolbar",editor:".editor-rail, .columns > .app",werkzeuge:".diagram-tools",dateien:".files-rail, .files",codelive:".live-rail, .livecode",ausfuehren:"[data-run=play]",konsole:".livecode .console",einzelschritt:"[data-run=step]",elemente:".palette",struktogramm:".canvas",objektinspektor:".inspector",reiter:".tabs",titel:".caption",neu:"[data-action=new]",oeffnen:"[data-action=open]",speichern:"[data-action=save]",exportieren:"[data-action=export]",rueckgaengig:"[data-action=undo]",loeschen:"[data-action=delete]",textgroesse:"[data-action=settings]",einstellungen:"[data-action=settings]",lernen:".learn .learn-hide",code:"[data-action=code]",simulation:"[data-action=simulate]"},mg=new Set(["editor","werkzeuge","elemente","struktogramm","objektinspektor","reiter","titel","rueckgaengig","loeschen","exportieren","code","simulation"]),dg=new Set(["ausfuehren","konsole","einzelschritt"]);function Qs(i,e){return[...i.querySelectorAll(".ui-pointer")].some(t=>e.has(t.dataset.target??""))}function oc(i){return i==="elemente"?["editor","palette"]:mg.has(i)?["editor"]:i==="codelive"||dg.has(i)?["livecode"]:i==="dateien"?["files"]:[]}function hM(i){return Qs(i,new Set(["elemente"]))}function gM(i){return Qs(i,new Set(["dateien"]))}function pM(i){return Qs(i,mg)}function fM(i){return Qs(i,dg)}function lc(i){for(const e of i.querySelectorAll('a[href^="#zeige-"]')){const t=e.getAttribute("href").slice(7);if(!(t in cg))continue;const n=document.createElement("span");n.className="ui-pointer",n.tabIndex=0,n.setAttribute("role","button"),n.dataset.target=t,n.append(...e.childNodes),e.replaceWith(n)}}function bM(i,e=()=>()=>{}){let t,n,a,s,r;const o=()=>{t==null||t.classList.remove("ui-spot"),t=void 0,window.clearTimeout(n)},l=(h,g)=>{o();const f=[...document.querySelectorAll(cg[h.dataset.target??""]??":not(*)")].find(b=>b.getClientRects().length>0);f&&(t=f,f.classList.add("ui-spot"),g&&(n=window.setTimeout(o,2500)))},u=(h,g)=>requestAnimationFrame(()=>{l(h,g),t==null||t.scrollIntoView({block:"nearest",inline:"nearest"})}),c=()=>{window.clearTimeout(s),window.clearTimeout(r),a==null||a(),a=void 0},m=h=>{window.clearTimeout(s),window.clearTimeout(r),a=void 0,e(oc(h.dataset.target??"")),l(h,!0),u(h,!0)},d=h=>{var g,f;return((f=(g=h.target)==null?void 0:g.closest)==null?void 0:f.call(g,".ui-pointer"))??void 0};return i.addEventListener("pointerover",h=>{const g=d(h);!g||h.pointerType!=="mouse"||(window.clearTimeout(r),l(g,!1),window.clearTimeout(s),s=window.setTimeout(()=>{if(a)return;const f=oc(g.dataset.target??"");f.length!==0&&(a=e(f),u(g,!1))},250))}),i.addEventListener("pointerout",h=>{!d(h)||h.pointerType!=="mouse"||(o(),window.clearTimeout(s),window.clearTimeout(r),r=window.setTimeout(c,400))}),i.addEventListener("click",h=>{const g=d(h);g&&m(g)}),i.addEventListener("focusin",h=>{const g=d(h);g&&l(g,!1)}),i.addEventListener("focusout",h=>{d(h)&&o()}),i.addEventListener("keydown",h=>{const g=d(h);g&&(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),m(g))}),{off:()=>{c(),o()}}}const _t='',xM=()=>{const i=[];for(const e of jt){const t=i.at(-1);t&&t.name===e.section?t.lessons.push(e):i.push({name:e.section,lessons:[e]})}return i};function _(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 tt(i,e,t){const n=_(i,e);return n.innerHTML=t,n}const vM=i=>p(`element_${S[i]}`);function yM(i){return{caption:i,elements:[Ae(S.anweisung,{textLines:["ø"]})]}}function uc(i){const e=i.start?ti(i.start):void 0;return e?{...e,caption:e.caption||i.title}:yM(i.title)}class wM{constructor(e){y(this,"element");y(this,"tab","lessons");y(this,"returnTo");y(this,"lessonId");y(this,"taskId");y(this,"body");y(this,"tips");y(this,"pointers");this.host=e,this.element=_("aside",{class:"learn","aria-label":p("web_learn_title")}),this.tips=dM(this.element),this.pointers=bM(this.element,t=>this.host.reveal(t)),fs(Gu(s1())),this.restore()}restore(){const e=be.view();e&&(this.tab=["lessons","tasks","reference"].find(t=>t===e.tab)??"lessons",this.lessonId=jt.some(t=>t.id===e.lesson)?e.lesson:void 0,this.taskId=On.some(t=>t.id===e.task)?e.task:void 0),this.render()}render(){this.tips.hide(),this.pointers.off(),fs(Gu(s1()));const e=_("div",{class:"segmented learn-tabs",role:"tablist"});for(const[a,s]of[["lessons",p("web_learn_lessons")],["tasks",p("web_learn_tasks")],["reference",p("web_learn_reference")]]){const r=_("button",{role:"tab","aria-pressed":String(this.tab===a),"data-learn-tab":a},s);r.addEventListener("click",()=>{this.tab===a&&(a==="lessons"&&(this.lessonId=void 0),a==="tasks"&&(this.taskId=void 0)),this.tab=a,this.persist(),this.render()}),e.append(r)}const t=tt("button",{class:"learn-hide",title:p("web_learn_hide"),"aria-label":p("web_learn_hide")},_t);t.addEventListener("click",()=>this.host.collapse());const n=_("div",{class:"learn-head"},e,t);if(this.body=_("div",{class:"learn-body"}),this.element.replaceChildren(n,this.body),this.tab==="lessons"){const a=jt.find(s=>s.id===this.lessonId);a?this.renderLesson(a):this.renderLessonList()}else if(this.tab==="tasks"){const a=On.find(s=>s.id===this.taskId);a?this.renderTask(a):this.renderTaskList()}else{const a=Na.map(r=>`- **${r.term}:** ${r.text}`).join(` +`),s=tt("div",{class:"learn-text learn-reference"},Tn(`${Wa} + +## ${p("web_learn_terms")} + +${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(){be.setView({tab:this.tab,lesson:this.lessonId,task:this.taskId})}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 xM()){this.body.append(_("h3",{class:"learn-section"},e.name));const t=_("ol",{class:"learn-list"});for(const n of e.lessons){const a=be.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=be.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((c,m)=>{const d=p("web_learn_step_fmt",m+1,c.title),h=mthis.goToStep(e,m)),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 c=_("button",{class:"learn-return"},`↩ ${p("web_learn_back_to_checklist")}`);return c.addEventListener("click",()=>{this.returnTo=void 0,this.goToStep(e,o.step),this.body.scrollTop=o.scroll}),c};o&&this.body.append(l()),a.blocks.forEach((c,m)=>this.body.append(this.renderBlock(c,`${n}-${m}`,e))),lc(this.body),UB(this.body),this.openNeededColumns(a.blocks),rc(this.body,Na),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",()=>{be.updateLesson(e.id,{done:!0});const l=jt.find(u=>u.number===e.number+1);this.openLesson(l==null?void 0:l.id)}),s.append(o)}return s}goToStep(e,t){be.updateLesson(e.id,{step:t}),this.render(),this.body.scrollTop=0}openNeededColumns(e){const t=e.flatMap(n=>n.kind==="exercise"?[n.exercise]:[]);pM(this.body)?(this.host.showEditor(),hM(this.body)&&this.host.reveal(["palette"])):gM(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(),fM(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 On){const n=this.taskExercises(t),a=n.length>0&&n.every(o=>be.exercise(o.id).done),s=jt.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($u()){e.setAttribute("open","");const s=_("button",{},p("web_learn_teacher_off"));return s.addEventListener("click",()=>{FB(),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 NB(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=jt.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}`))),lc(this.body),this.openNeededColumns(e.blocks),rc(this.body,Na)}renderBlock(e,t,n){switch(e.kind){case"markdown":return this.withOpenButtons(tt("div",{class:"learn-text"},Tn(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 this.renderGraphic(e.file,e.caption,e.labeled);case"game":return this.renderGame(e.game);case"roundGame":return YB(e.game,ra);case"rescueGame":return nM(e.game,ra);case"caesar":return VB(e.key,e.text);case"cloze":return aM(e.cloze);case"pap":return cM(e.pap);case"textFile":return ag(e.name,e.content);case"robotModel":return QB(e.focus,e.view,e.spin);case"robotQuiz":return $B(e.tasks,e.done)}}renderBrag(e,t=!1){const n=_("aside",{class:"learn-brag"});n.append(_("img",{src:ra,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(tt("div",{class:"learn-text"},Tn(e))),n.append(a),n}renderGame(e){const n=_("section",{class:"learn-game"}),a=_("div",{class:"learn-game-head"});a.append(_("img",{src:ra,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=dx(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,I]of hx(d))h.append(_("code",{},`${w} = ${I}`));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 I=w===d.answer;I&&l++,s.textContent=`${p("web_game_round_fmt",o+1,10)} · ${p("web_game_score_fmt",l)}`,x.className=`learn-game-feedback ${I?"right":"wrong"}`;const z=_("div",{class:"learn-game-steps mono"});cx(d.condition,d.values).forEach((T,A)=>z.append(_("div",{},`${A?"→ ":""}${T}`)));const k=_("button",{class:"primary"},o+1<10?p("web_game_next"):p("web_game_finish"));k.addEventListener("click",()=>{o++,o<10?u():c()}),x.replaceChildren(_("p",{},p(I?"web_game_right":"web_game_wrong")),z,k),k.focus()};f.addEventListener("click",()=>v(!0)),b.addEventListener("click",()=>v(!1)),r.replaceChildren(h,_("div",{class:"learn-game-condition mono"},d.condition),g,x)},c=()=>{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)},m=_("button",{class:"primary"},p("web_game_start"));return m.addEventListener("click",u),r.append(_("p",{},p("web_game_intro")),m),n}renderImages(e,t){const n=_("figure",{class:"learn-figure"}),a=_("div",{class:"learn-images"});for(const s of e){const r=zr(s);r&&a.append(_("img",{src:r,alt:"",loading:"lazy"}))}return n.append(a),t&&n.append(tt("figcaption",{},je(t))),n}renderGraphic(e,t,n){const a=_("figure",{class:"learn-figure"}),s=zr(e),r=n?zr(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(tt("figcaption",{},je(t))),a}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=ti(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(tt("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=()=>be.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),zM(e),tt("div",{class:"learn-text"},Tn(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 m=n().xml;let d=uc(e);if(m)try{d=Nl(m)}catch{}this.host.openExercise(e,d)});const u=_("button",{},p("web_learn_check"));if(u.addEventListener("click",()=>{const m=this.host.exerciseDocument(e.id);if(!m){s.className="learn-result info",s.textContent=p("web_learn_open_first");return}if(m.elements.every(Zl)){s.className="learn-result info",s.textContent=p("web_learn_empty");return}this.host.stopSimulation();const d=sx(m,e.tests,this.host.subprogramsFor(e.id),Fa),h=rx(m),g=e.requires.map(x=>x==="forZaehlSchleife"?"forSchleife":x).filter(x=>x in S&&!h.has(S[x])),f=e.loopDepth!==void 0&&Do(m.elements)x.passed)&&g.length===0&&!f;this.showResult(s,d,g,b,f),b&&(be.updateExercise(e.id,{done:!0}),a.hidden=!1)}),o.append(l,u),e.hints.length>0){const m=_("button",{},p("web_learn_hint"));m.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(tt("aside",{class:"lesson-note"},Tn(h+e.hints[d]))),m.textContent=p("web_learn_hint_more"),m.toggleAttribute("disabled",d+1>=e.hints.length)}),o.append(m)}const c=_("button",{class:"danger-text"},p("web_learn_reset"));if(c.addEventListener("click",()=>{if(c.dataset.confirm!=="1"){c.dataset.confirm="1",c.textContent=p("web_learn_reset_confirm"),setTimeout(()=>{c.dataset.confirm="",c.textContent=p("web_learn_reset")},4e3);return}be.resetExercise(e.id),this.host.resetExercise(e.id,uc(e)),a.hidden=!0,s.replaceChildren(),s.className="learn-result",c.dataset.confirm="",c.textContent=p("web_learn_reset")}),o.append(c),t.append(o,r,s),$u()&&e.solution){const m=ti(e.solution);if(m){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(m);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(m,e.solution);for(const f of e.subprograms){const b=ti(f);b&&this.host.openDiagram(b,f)}});for(const f of e.subprograms){const b=ti(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,c,m;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",vM(S[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",{},X1(d.test.drive)||"–")),_("span",{},`${p("web_learn_actual")}: `,_("code",{},X1(d.result.drive??[])||"–"))),d.test.actions&&b.append(_("span",{},`${p("web_learn_expected")}: `,_("code",{},X1(d.test.actions)||"–")),_("span",{},`${p("web_learn_actual")}: `,_("code",{},X1(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=Fa(d.test.world))==null?void 0:o.goals)!=null&&l.length||(c=(u=Fa(d.test.world))==null?void 0:u.targets)!=null&&c.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",{},Jh((m=d.result.files)==null?void 0:m.get(x.name)).join(" | ")||"–")));d.result.error&&b.append(_("span",{class:"learn-error"},t1(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(tt("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 c=`${t}-${u}`,m=n?(v=be.lesson(n.id).checks)==null?void 0:v[c]:void 0;let d=m===!0?"sun":m||void 0;const h=tt("span",{class:"learn-check-text"},je(l.text)),g=_("span",{class:"learn-rating",role:"group","aria-label":h.textContent??""}),f=a.map(w=>{const I=_("button",{class:"learn-rating-button",title:w.label,"aria-label":w.label},w.icon);return I.addEventListener("click",()=>{if(d=d===w.value?void 0:w.value,b(),!n)return;const z={...be.lesson(n.id).checks??{}};d?z[c]=d:delete z[c],be.updateLesson(n.id,{checks:Object.keys(z).length?z:void 0})}),I}),b=()=>{f.forEach((w,I)=>w.setAttribute("aria-pressed",String(a[I].value===d))),x.dataset.rating=d??""};g.append(...f);const x=_("li",{},h,g);if(n&&l.step!==void 0){const w=l.step,I=p("web_learn_step_fmt",w+1,n.steps[w].title),z=_("button",{class:"link-button learn-check-link",title:I,"aria-label":`${p("web_learn_review")}: ${I}`},p("web_learn_review"));z.addEventListener("click",()=>{this.returnTo={lesson:n.id,step:be.lesson(n.id).step,scroll:this.body.scrollTop},this.goToStep(n,w)}),x.append(z)}b(),o.append(x)}),s}renderQuiz(e,t,n){const a=_("div",{class:"learn-quiz"}),s=_("p",{class:"learn-score",role:"status"}),r=()=>n?be.lesson(n.id).quiz??{}:{},o=_("div",{class:"learn-review"}),l=()=>{const u=r(),c=(f,b)=>f.pairs?f.pairs.every((x,v)=>u[`${t}-${b}-${v}`]!==void 0):u[`${t}-${b}`]!==void 0,m=(f,b)=>{var x;return!!(f.pairs?f.pairs.every((v,w)=>cc(f)[u[`${t}-${b}-${w}`]]===f.pairs[w].right):(x=f.options[u[`${t}-${b}`]])!=null&&x.correct)},d=e.filter(c).length,h=e.filter(m).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=>m(e[f],f))};return e.forEach((u,c)=>{const m=`${t}-${c}`,d=_("fieldset",{},tt("legend",{},je(u.question))),h=tt("p",{class:"learn-explanation"},je(u.explanation??""));if(u.pairs){d.append(this.renderMatch(u,m,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=tt("button",{class:"learn-option"},je(f.text));x.addEventListener("click",()=>{n&&be.updateLesson(n.id,{quiz:{...r(),[m]:b}}),g(b),l()}),d.append(x)}),d.append(h),g(r()[m]),a.append(d)}),a.append(s,o),l(),a}fillChecklistReview(e,t,n,a){const s={sun:"☀️",cloud:"⛅",umbrella:"☂️"},r=be.lesson(t.id).checks??{},o=[];let l=0;t.steps.forEach((u,c)=>u.blocks.forEach((m,d)=>{m.kind==="checklist"&&m.items.forEach((h,g)=>{const f=r[`${c}-${d}-${g}`],b=f===!0?"sun":f||void 0,x=h.step===void 0?[]:n.map((k,T)=>k.step===h.step?T:-1).filter(k=>k>=0),v=x.filter(k=>!a(k));let w="";b==="sun"&&v.length?w=p("web_learn_review_overrated_fmt",v.map(k=>k+1).join(", ")):b&&b!=="sun"&&x.length&&!v.length&&(w=p("web_learn_review_underrated")),w&&l++;const I=_("li",{class:w?"learn-review-deviation":""}),z=tt("span",{class:"learn-check-text"},je(h.text));if(w&&z.append(_("br",{}),_("em",{},w)),I.append(z,_("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 k=h.step,T=_("button",{class:"link-button learn-check-link"},p("web_learn_review"));T.addEventListener("click",()=>{this.returnTo={lesson:t.id,step:be.lesson(t.id).step,scroll:this.body.scrollTop},this.goToStep(t,k)}),I.append(T)}o.push(I)})})),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=cc(e),u=_("div",{class:"learn-match"});let c={};const m=()=>a?n():c,d=b=>a?be.updateLesson(a.id,{quiz:b}):c=b,h=b=>m()[`${t}-${b}`],g=o.map(b=>{const x=_("select",{class:"learn-match-select"});x.append(_("option",{value:""},"–")),l.forEach((w,I)=>x.append(_("option",{value:String(I)},w)));const v=tt("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={...m()};b.value===""?delete v[`${t}-${x}`]:v[`${t}-${x}`]=Number(b.value),d(v),f(),r()})),f(),u}}function cc(i){return(i.pairs??[]).map(e=>e.right).sort((e,t)=>e.localeCompare(t,"de"))}function zM(i){const e=$h(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 IM=""+new URL("visubot-CyGFOI9V.webp",import.meta.url).href,Us="visustruct.visubot";function $s(){try{return localStorage.getItem(Us)}catch{return null}}function ui(){const i=$s();return i==="1"||i==="kurs"?"on":"off"}const hg=()=>$s()==="2";function gg(){try{localStorage.setItem(Us,"2")}catch{}}const pg=()=>$s()==="3";function fg(){try{localStorage.setItem(Us,"3")}catch{}}const kM=()=>$s()!==null;function Sr(i){try{localStorage.setItem(Us,i==="on"?"1":"0")}catch{}}const SM=`VisuBot`,Hn=()=>ui()!=="off",mc=i=>i.replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]);function Lo(){const i=hg()?"object":pg()?"flow":ui(),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")} +
+ ${mc(p(t))}`}class TM{constructor(e=Ii){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 ds(e),this.element=document.createElement("section"),this.element.className="visubot",this.element.innerHTML=`

${p("web_visubot_world")}

${p("web_visubot_world_in_preview")}

${_M()}${AM()}`,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=ge.listen(()=>this.updateLive()),this.setupControls(),this.check=this.element.querySelector(".visubot-check"),this.setupCheck(),this.updateLive(),this.updateStatus()}show(){this.loading??(this.loading=K(async()=>{const{Robot3D:e}=await import("./robot3d-DZxNwb67.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]??Ii,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 ds(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;ge.run(e.dataset.py).then(()=>t?new Promise(a=>setTimeout(a,Number(n))).then(()=>ge.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&&ge.connected;){for(const e of this.check.querySelectorAll("[data-sensor]")){if(!this.check.open||!ge.connected)break;const t=e.dataset.sensor,n=await ge.ask(At[t].python).catch(()=>{});n!==void 0&&(e.textContent=typeof At[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 ge.connected}async prepareLive(e,t=[]){const n={};for(const a of new Set(["getDistance","getLine",...t])){const s=await ge.ask(At[a].python);typeof At[a].simulated=="boolean"?n[a]=s===!0||typeof s=="number"&&s!==0:typeof At[a].simulated=="string"?n[a]=typeof s=="string"?s:String(At[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){ge.disconnect(e instanceof Error?e.message:String(e))}updateLive(){this.liveStatus.textContent=xg(),this.liveStatus.classList.toggle("connected",ge.connected),this.check.hidden=!ge.connected,ge.connected||(this.check.open=!1),this.updateStatus()}follow(e,t){var a,s,r,o;for(;this.appliedl!==0);this.world.tick(s0),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&&ge.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 H1;function bg(i,e){try{H1??(H1=new AudioContext);const t=H1.createOscillator(),n=H1.createGain();t.type="square",t.frequency.value=Math.max(20,Math.min(2e4,i)),n.gain.value=.05,t.connect(n).connect(H1.destination);const a=H1.currentTime+Math.min(Math.max(e,0),5e3)/1e3;t.start(),t.stop(a)}catch{}}function _M(){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)} + ${i("getPitch","web_visubot_sensor_pitch",-90,90,0)} + ${i("getRoll","web_visubot_sensor_roll",-90,90,0)} +
+ ${e("isButtonA","A","web_visubot_sensor_button_a")}${e("isButtonB","B","web_visubot_sensor_button_b")} + ${e("isJoystickUp","↑","web_visubot_sensor_joy_up")}${e("isJoystickDown","↓","web_visubot_sensor_joy_down")} + ${e("isJoystickLeft","←","web_visubot_sensor_joy_left")}${e("isJoystickRight","→","web_visubot_sensor_joy_right")} + ${e("isShaken",`〰 ${p("web_visubot_shake")}`,"web_visubot_sensor_shake")} +
+
`}function AM(){const i=a=>a.replace(/"/g,"""),e=(a,s,r,o=1e3)=>``,t="mbot2.EM_stop('ALL')",n=vg.map(a=>`${p(a.key)}…`).join("");return``}function xg(){return ge.connecting?p("web_visubot_connecting"):ge.connected?`✓ ${p("web_visubot_connected")}`:ge.error?`⚠︎ ${p("web_visubot_link_error")}: ${ge.error}`:""}async function OM(){if(ge.connected||ge.connecting)return ge.disconnect();try{await ge.connect()}catch(i){await ge.disconnect(i.name==="NotFoundError"?void 0:i.message)}}const ht=i=>()=>Ae(S.anweisung,{textLines:[i]}),CM=[{key:"web_visubot_el_forward",group:"drive",type:S.anweisung,make:ht("mbot.forward()")},{key:"web_visubot_el_backward",group:"drive",type:S.anweisung,make:ht("mbot.backward()")},{key:"web_visubot_el_right",group:"drive",type:S.anweisung,make:ht("mbot.turnRight()")},{key:"web_visubot_el_left",group:"drive",type:S.anweisung,make:ht("mbot.turnLeft()")},{key:"web_visubot_el_drive",group:"wheels",type:S.anweisung,make:ht("mbot.drive(30, 30)")},{key:"web_visubot_el_stop",group:"wheels",type:S.anweisung,make:ht("mbot.stop()")},{key:"web_visubot_el_led",group:"output",type:S.anweisung,make:ht("mbot.setLed(255, 0, 0)")},{key:"web_visubot_el_led_off",group:"output",type:S.anweisung,make:ht("mbot.ledOff()")},{key:"web_visubot_el_led_color",group:"output",type:S.anweisung,make:ht('mbot.led(0).setColor("grün")')},{key:"web_visubot_el_tone",group:"output",type:S.anweisung,make:ht("mbot.playTone(440, 300)")},{key:"web_visubot_el_text",group:"output",type:S.anweisung,make:ht('mbot.showText("Hallo")')},{key:"web_visubot_el_wait",group:"wait",type:S.anweisung,make:ht("mbot.pause(100)")},{key:"web_visubot_el_emotion",group:"emotion",type:S.anweisung,make:ht('mbot.emotion("smile")')},{key:"web_visubot_el_timer",group:"wait",type:S.anweisung,make:ht("mbot.resetTimer()")}],vg=[{key:"web_visubot_sensor_distance",group:"distance",text:"mbot.getDistance()"},{key:"web_visubot_sensor_line",group:"line",text:"mbot.getLine()"},{key:"web_visubot_sensor_line_left",group:"line",text:"mbot.isLineLeft()"},{key:"web_visubot_sensor_line_right",group:"line",text:"mbot.isLineRight()"},{key:"web_visubot_sensor_color",group:"color",get text(){return`mbot.getColor().equals("${ch("red")}")`}},{key:"web_visubot_sensor_button_a",group:"buttons",text:"mbot.isButtonA()"},{key:"web_visubot_sensor_button_b",group:"buttons",text:"mbot.isButtonB()"},{key:"web_visubot_sensor_joy_up",group:"buttons",text:"mbot.isJoystickUp()"},{key:"web_visubot_sensor_joy_down",group:"buttons",text:"mbot.isJoystickDown()"},{key:"web_visubot_sensor_joy_left",group:"buttons",text:"mbot.isJoystickLeft()"},{key:"web_visubot_sensor_joy_right",group:"buttons",text:"mbot.isJoystickRight()"},{key:"web_visubot_sensor_brightness",group:"light",text:"mbot.getBrightness()"},{key:"web_visubot_sensor_loudness",group:"light",text:"mbot.getLoudness()"},{key:"web_visubot_sensor_pitch",group:"tilt",text:"mbot.getPitch()"},{key:"web_visubot_sensor_roll",group:"tilt",text:"mbot.getRoll()"},{key:"web_visubot_sensor_shake",group:"tilt",text:"mbot.isShaken()"},{key:"web_visubot_sensor_timer",group:"timer",text:"mbot.getTimer()"},{key:"web_visubot_sensor_battery",group:"timer",text:"mbot.getBattery()"}],la=()=>typeof window.showDirectoryPicker=="function";class Ys{constructor(e){this.handle=e}get name(){return this.handle.name}async list(){const e=[];for await(const t of this.handle.values())t.name.startsWith(".")||e.push({kind:t.kind,name:t.name});return e}async dir(e,t=!1){return new Ys(await this.handle.getDirectoryHandle(e,{create:t}))}async read(e){return(await(await this.handle.getFileHandle(e)).getFile()).text()}async write(e,t){const a=await(await this.handle.getFileHandle(e,{create:!0})).createWritable();await a.write(t),await a.close()}async has(e){try{return await this.handle.getFileHandle(e),!0}catch{try{return await this.handle.getDirectoryHandle(e),!0}catch{return!1}}}async remove(e){await this.handle.removeEntry(e,{recursive:!0})}}const jM="visustruct-workspace";function PM(){return new Promise((i,e)=>{const t=indexedDB.open(jM,1);t.onupgradeneeded=()=>{t.result.createObjectStore("files"),t.result.createObjectStore("meta")},t.onsuccess=()=>i(t.result),t.onerror=()=>e(t.error)})}async function Tt(i,e,t){const n=await PM();return new Promise((a,s)=>{const r=t(n.transaction(i,e).objectStore(i));r.onsuccess=()=>a(r.result),r.onerror=()=>s(r.error)})}class m0{constructor(e,t){this.name=e,this.path=t}key(e){return this.path+e}async list(){const e=await Tt("files","readonly",n=>n.getAllKeys()),t=new Map;for(const n of e){if(!n.startsWith(this.path)||n===this.path)continue;const a=n.slice(this.path.length),s=a.indexOf("/"),r=s<0?a:a.slice(0,s);t.has(r)||t.set(r,{kind:s<0?"file":"directory",name:r})}return[...t.values()]}async dir(e,t=!1){const n=this.key(e)+"/";if(!(await Tt("files","readonly",s=>s.count(n))>0)){if(!t)throw new DOMException(e,"NotFoundError");await Tt("files","readwrite",s=>s.put("",n))}return new m0(e,n)}async read(e){const t=await Tt("files","readonly",n=>n.get(this.key(e)));if(typeof t!="string")throw new DOMException(e,"NotFoundError");return t}async write(e,t){await Tt("files","readwrite",n=>n.put(t,this.key(e)))}async has(e){const t=await Tt("files","readonly",a=>a.count(this.key(e))),n=await Tt("files","readonly",a=>a.count(this.key(e)+"/"));return t+n>0}async remove(e){const t=this.key(e);await Tt("files","readwrite",n=>n.delete(t)),await Tt("files","readwrite",n=>n.delete(IDBKeyRange.bound(t+"/",t+"/￿")))}}async function DM(i,e="folder"){const t=await window.showDirectoryPicker({id:e==="folder"?"visustruct-workspace":e,mode:"readwrite"}),n=i&&t.name!==i?await t.getDirectoryHandle(i,{create:!0}):t;return await Tt("meta","readwrite",a=>a.put(n,e)),{kind:"folder",root:new Ys(n)}}function dc(){return{kind:"browser",root:new m0("VisuStruct","")}}async function BM(i="folder"){var e;try{const t=await Tt("meta","readonly",a=>a.get(i));if(!t)return;const n=await((e=t.queryPermission)==null?void 0:e.call(t,{mode:"readwrite"}))??"granted";return{handle:t,ready:n==="granted"}}catch{return}}async function hc(i){var t;return(await((t=i.requestPermission)==null?void 0:t.call(i,{mode:"readwrite"}))??"granted")==="granted"?{kind:"folder",root:new Ys(i)}:void 0}async function MM(i="folder"){try{await Tt("meta","readwrite",e=>e.delete(i))}catch{}}const ua="learnProgress.json",ca="lernstand.json",ma="visustruct.files.mode",gc="visustruct.files.expanded";function ZM(i){try{const e=JSON.parse(yg(i)??"[]");return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}catch{return[]}}function yg(i){try{return localStorage.getItem(i)}catch{return null}}function da(i,e){try{e===null?localStorage.removeItem(i):localStorage.setItem(i,e)}catch{}}const te=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,""");function pc(i){return new Promise(e=>{const t=document.createElement("div");t.className="confirm";const n=(i.choices??[]).map(o=>``).join("");t.innerHTML=``;const a=t.querySelector("form"),s=a.querySelector("input"),r=o=>{t.remove(),e(o)};a.addEventListener("submit",o=>{if(o.preventDefault(),!s)return r("");s.value.trim()?r(s.value):s.focus()}),t.addEventListener("click",o=>{var c;const l=o.target,u=(c=l.closest("[data-choice]"))==null?void 0:c.dataset.choice;u!==void 0?r(u):(l===t||l.closest("[data-cancel]"))&&r(void 0)}),t.addEventListener("keydown",o=>o.key==="Escape"&&r(void 0)),document.body.append(t),(s??a.querySelector("[data-cancel]")).focus()})}class LM{constructor(e){y(this,"element");y(this,"body");y(this,"workspace");y(this,"pending");y(this,"expanded",new Set(ZM(gc)));y(this,"rendering",0);y(this,"progressWorkspace");y(this,"hadWorkspace",!1);y(this,"progressTimer");this.host=e,this.element=document.createElement("aside"),this.element.className="files",this.build(),be.onChange(()=>this.progressChanged()),this.restore()}rememberExpanded(){da(gc,JSON.stringify([...this.expanded]))}get ready(){return!!this.workspace}build(){this.element.innerHTML=` +
+

${te(p("web_files_title"))}

+ + + +
+
+ `,this.body=this.element.querySelector(".files-body");const e=(t,n)=>this.element.querySelector(`[data-files=${t}]`).addEventListener("click",n);e("hide",()=>this.host.hide()),e("new-folder",()=>void this.newFolder()),e("switch",()=>void this.switchWorkspace()),this.body.addEventListener("click",t=>void this.onTreeClick(t)),this.render()}async restore(){if(yg(ma)==="browser")this.workspace=dc();else if(la()){const e=await BM();e!=null&&e.ready?this.workspace=await hc(e.handle):this.pending=e==null?void 0:e.handle}await this.render(),this.workspace||this.startDialog()}async startDialog(){var r;const e=p("web_learn_start_folder"),t=(o,l,u=!1,c)=>`${c?`

${te(c)}

`:""}`,n=la()?[this.pending?t("reconnect",`${se.open} ${te(p("web_learn_start_continue_fmt",this.pending.name))}`,!0):"",t("pick",`${se.open} ${te(p("web_learn_start_open"))}`,!this.pending),t("create",`${se.newFolder} ${te(p("web_learn_start_create_fmt",e))}`,!1,p("web_learn_start_create_hint"))]:[t("browser",te(p("web_files_browser")),!0,p("web_files_browser_hint"))],a=document.createElement("div");a.className="confirm",a.innerHTML=``;const s=()=>a.remove();a.addEventListener("click",o=>{var c,m;const l=(c=o.target.closest("[data-world]"))==null?void 0:c.dataset.world;if(l){this.host.chooseWorld(l).then(()=>a.querySelector(".start-world").innerHTML=Lo());return}const u=(m=o.target.closest("[data-start]"))==null?void 0:m.dataset.start;u&&(s(),u==="reconnect"?this.reconnect():u==="pick"?this.connectFolder():u==="create"?this.connectFolder(e):u==="browser"&&this.useBrowser())}),a.addEventListener("keydown",o=>o.key==="Escape"&&s()),document.body.append(a),(r=a.querySelector(".files-start"))==null||r.focus()}async connectFolder(e){try{this.workspace=await DM(e),this.pending=void 0,da(ma,"folder")}catch{}await this.render()}async reconnect(){this.pending&&(this.workspace=await hc(this.pending),this.workspace&&(this.pending=void 0),await this.render())}async useBrowser(){this.workspace=dc(),da(ma,"browser"),await this.render()}async switchWorkspace(){if(la())return this.connectFolder();this.workspace=void 0,da(ma,null),await MM(),await this.render()}async syncProgress(e){if(this.progressWorkspace=e,!e)return;const t=!this.hadWorkspace;this.hadWorkspace=!0;try{const n=await e.root.has(ua)?ua:await e.root.has(ca)?ca:void 0;(!n||!be.loadFile(await e.root.read(n),t))&&(t||be.clear()),this.host.progressLoaded(),await this.writeProgress(e),await e.root.has(ca)&&(await e.root.remove(ca),await this.render())}catch{}}async writeProgress(e){if(e===this.progressWorkspace)try{const t=!await e.root.has(ua);await e.root.write(ua,be.toFile()),t&&await this.render()}catch{}}progressChanged(){const e=this.progressWorkspace;e&&(window.clearTimeout(this.progressTimer),this.progressTimer=window.setTimeout(()=>void this.writeProgress(e),1e3))}async render(){const e=++this.rendering,t=this.workspace;if(t!==this.progressWorkspace&&this.syncProgress(t),this.element.querySelector("[data-files=new-folder]").hidden=!t,this.element.querySelector("[data-files=switch]").hidden=!t,!t){this.body.innerHTML=this.startHTML();return}const n=[],a=async(o,l,u)=>{const c=(await o.list()).sort(Fb);for(const m of c){const d=l?`${l}/${m.name}`:m.name;if(m.kind==="directory"){const h=this.expanded.has(d);n.push(`
+ + +
`),h&&await a(await o.dir(m.name),d,u+1)}else if(/\.(visustruct|java|json)$/i.test(m.name)){if(/\.java$/i.test(m.name)&&c.some(g=>g.name===m.name.replace(/\.java$/i,".visustruct")))continue;const h=/\.(visustruct|java)$/i.test(m.name);n.push(`
+ + ${h?``:""} +
`)}}};try{await a(t.root,"",0)}catch(o){n.push(`

${te(o.message)}

`)}if(e!==this.rendering)return;const s=t.kind==="folder"?`📁 ${te(t.root.name)}`:te(p("web_files_in_browser")),r=p("web_files_save_hint_fmt",_u());this.body.innerHTML=` +

${s}

+
${n.join("")||`

${te(p("web_files_empty"))}

`}
+

${te(r)}

+ `}startHTML(){return this.pending?`

${te(p("web_files_reconnect_hint"))}

+ + `:la()?`

${te(p("web_files_connect_hint"))}

+ `:`

${te(p("web_files_browser_hint"))}

+ `}async onTreeClick(e){var r;const t=e.target,n=(r=t.closest("[data-start]"))==null?void 0:r.dataset.start;if(n==="pick")return this.connectFolder();if(n==="reconnect")return this.reconnect();if(n==="browser")return this.useBrowser();const a=t.closest(".files-row");if(!a||!this.workspace)return;const s=a.dataset.path;if(t.closest(".files-delete"))return this.remove(a);if(a.dataset.kind==="dir")return this.expanded.has(s)?this.expanded.delete(s):this.expanded.add(s),this.rememberExpanded(),this.render();if(a.dataset.kind==="program")return this.openProgram(s)}async locate(e){const t=e.split("/");let n=this.workspace.root;for(const a of t.slice(0,-1))n=await n.dir(a);return{dir:n,name:t.at(-1)}}async openProgram(e){try{const{dir:t,name:n}=await this.locate(e),a=n.replace(/\.(visustruct|java)$/i,""),s=await t.has(`${a}.visustruct`)?await t.read(`${a}.visustruct`):void 0,r=await t.has(`${a}.java`)?await t.read(`${a}.java`):void 0;if(s===void 0&&r===void 0)return;const o={dir:t,base:a,path:e.replace(/\.(visustruct|java)$/i,"")};this.host.open(s??"",o,r)}catch(t){this.host.message(t.message)}}async remove(e){const t=e.dataset.path,n=e.dataset.kind==="program",a=n?t.replace(/\.(visustruct|java)$/i,""):t;if(await pc({title:p("web_files_delete_confirm_fmt",a),ok:p("web_files_delete"),danger:!0})!==void 0){try{const{dir:s,name:r}=await this.locate(t);if(n){const o=r.replace(/\.(visustruct|java)$/i,"");for(const l of[".visustruct",".java"])await s.has(o+l)&&await s.remove(o+l)}else await s.remove(r)}catch(s){this.host.message(s.message)}await this.render()}}async newFolder(){if(!this.workspace)return;const e=Gb(await pc({title:p("web_files_folder_prompt"),input:"",ok:p("web_files_create")})??"");if(e){try{await this.workspace.root.dir(e,!0)}catch(t){this.host.message(t.message)}await this.render()}}async save(e,t,n,a){const s=this.workspace;if(!s)return;let r=a;if(!r){const o=_u(),l=await s.root.dir(o,!0),u=Rb(Jb(e,p("web_files_default_name")),(await l.list()).map(c=>c.name));r={dir:l,base:u,path:`${o}/${u}`},this.expanded.add(o),this.rememberExpanded()}return await r.dir.write(`${r.base}.visustruct`,t),n!==void 0&&await r.dir.write(`${r.base}.java`,n),await this.render(),r}}const wg=["boolean","int","double","String","char","long","float","short","byte"],EM=new Set([...wg,"Boolean","Integer","Double","Character","Long","Float","Short","Byte","var","void"]);function WM(i){if(EM.has(i))return;const e=i.toLowerCase();for(const t of wg)if(NM(e,t.toLowerCase())<=(t.length>=6?2:1))return t}function NM(i,e){const t=Array.from({length:i.length+1},(n,a)=>Array.from({length:e.length+1},(s,r)=>a===0?r:r===0?a:0));for(let n=1;n<=i.length;n++)for(let a=1;a<=e.length;a++){const s=i[n-1]===e[a-1]?0:1;t[n][a]=Math.min(t[n-1][a]+1,t[n][a-1]+1,t[n-1][a-1]+s),n>1&&a>1&&i[n-1]===e[a-2]&&i[n-2]===e[a-1]&&(t[n][a]=Math.min(t[n][a],t[n-2][a-2]+1))}return t[i.length][e.length]}const FM=[">>>=","<<=",">>=",">>>","->","::","++","--","==","!=","<=",">=","&&","||","+=","-=","*=","/=","%=","&=","|=","^=","<<"];function JM(i,e){const t=[];let n=0,a=0;const s=(r,o,l,u)=>t.push({kind:r,text:i.slice(o,l),start:o,end:l,line:u});for(;ni.startsWith(d,n))??r;n+=m.length,s("op",o,n,l)}return t}const Tr=new Set(["if","else","for","while","do","switch","case","default","break","return","try"]),_r=new Set(["public","private","protected","static","final","abstract"]),fc="(?:int|long|short|byte|float|double|boolean|char|String)";let RM=class{constructor(e,t,n){y(this,"toks");y(this,"comments");y(this,"i",0);y(this,"problems",[]);y(this,"placeholders",[]);y(this,"lines",new Map);y(this,"className");y(this,"imports",[]);y(this,"fileScanners",new Set);this.src=e,this.labels=t,this.opts=n;const a=JM(e,this.problems);this.toks=a.filter(s=>s.kind!=="comment"),this.comments=a.filter(s=>s.kind==="comment")}get tok(){return this.toks[this.i]}is(e,t=this.tok){return t!==void 0&&t.text===e&&t.kind!=="str"}next(){return this.toks[this.i++]}eat(e){return this.is(e)?this.next():void 0}prev(){return this.toks[this.i-1]}problem(e,t,n){const a=t??{start:this.src.length,end:this.src.length};this.problems.push({from:a.start,to:Math.max(a.end,a.start+1),key:e,arg:n})}missingAfter(e,t){const n=e?e.end:this.src.length;this.problems.push({from:Math.max(0,n-1),to:n,key:"web_parse_missing",arg:t})}text(e,t){let n="",a=e;for(const s of this.comments)s.end<=e||s.start>=t||(n+=this.src.slice(a,Math.max(a,s.start)),a=Math.max(a,s.end));return n+=this.src.slice(a,Math.max(a,t)),n.replace(/\s*\n\s*/g," ").trim()}slot(e,t,n){const a=this.text(e,t);if(a===n){const s=this.src.indexOf(n,e);return s>=0&&this.placeholders.push({from:s,to:s+n.length}),""}return a}record(e,t,n){return this.lines.set(e,[t,n]),{element:e,from:t,to:n}}lineOf(e){var t;return(e==null?void 0:e.line)??((t=this.toks[this.toks.length-1])==null?void 0:t.line)??0}checkImports(){const e=["File","PrintWriter","FileReader","FileWriter","BufferedReader","IOException","FileNotFoundException"].map(t=>[t,"java.io"]);for(const[t,n]of[["Scanner","java.util"],["Files","java.nio.file"],["Path","java.nio.file"],["Paths","java.nio.file"],...e]){const a=this.imports.some(r=>r===`import${n}.${t};`||r===`import${n}.*;`),s=this.toks.find((r,o)=>{var l;return r.kind==="id"&&r.text===t&&(n!=="java.nio.file"||((l=this.toks[o+1])==null?void 0:l.text)===".")});if(!a&&s){this.problem("web_parse_missing_import",s,n==="java.util"?`import ${n}.${t};`:`import ${n}.*;`);return}}}checkScanners(){var n;const e=new Set(["next","nextInt","nextDouble","nextLine","nextBoolean","nextLong","nextFloat","hasNext","hasNextInt","hasNextLine","hasNextDouble"]),t=a=>this.toks.some((s,r)=>{const o=this.toks[r-1];return s.kind==="id"&&s.text===a&&!!o&&(o.kind==="id"&&!Tr.has(o.text)&&o.text!=="new"||o.text===">"||o.text==="]")});for(let a=0;a{var s;return((s=this.toks[a-1])==null?void 0:s.text)==="class"}).map(n=>n.text));for(let n=0;no.text).join(""));continue}const a=this.classStart();if(a!==void 0){this.className??(this.className=a.name),this.i=a.index;const r=this.parseClassBody();e.push(...r.elements),t??(t=r.caption);continue}const s=this.methodStart();if(s){n&&this.problem("web_parse_more_methods",this.tok);const r=this.parseMethod(s);n||(t=s.caption,e.push(...r)),n=!0;continue}if(this.is("}")){this.problem("web_parse_extra",this.next(),"}");continue}e.push(...this.parseStatement())}return{caption:t,elements:this.finishList(e)}}skipPast(e){for(;this.tok&&!this.is(e);)this.next();this.eat(e)}classStart(){var n,a;let e=this.i;for(;this.toks[e]&&_r.has(this.toks[e].text);)e++;if(((n=this.toks[e])==null?void 0:n.text)!=="class"||((a=this.toks[e+1])==null?void 0:a.kind)!=="id")return;const t=this.toks[e+1].text;for(e+=2;this.toks[e]&&this.toks[e].text!=="{";)e++;return{name:t,index:e+1}}parseClassBody(){let e,t,n=!1;const a=[];for(;this.tok&&!this.is("}");){const s=this.methodStart();if(!s){this.is("{")?a.push(...this.parseBlock().elements):a.push(...this.parseStatement());continue}const r=this.tok,o=this.parseMethod(s);s.name==="main"?e??(e=o):t?n=!0:t={caption:s.caption,body:o},(e&&t||n)&&this.problem("web_parse_more_methods",r)}return this.eat("}"),e?{elements:e}:a.length>0||!t?{elements:a}:{caption:t.caption,elements:t.body}}methodStart(){var g,f,b,x,v,w,I,z,k,T,A;let e=this.i,t=0;for(;this.toks[e]&&_r.has(this.toks[e].text);)e++,t++;const n=this.toks[e];if((n==null?void 0:n.kind)!=="id"||Tr.has(n.text)||n.text==="new")return;for(e++;((g=this.toks[e])==null?void 0:g.text)==="["&&((f=this.toks[e+1])==null?void 0:f.text)==="]";)e+=2;const a=this.toks[e];if((a==null?void 0:a.kind)!=="id"||((b=this.toks[e+1])==null?void 0:b.text)!=="(")return;let s=0,r=e+1;for(;this.toks[r];r++){const D=this.toks[r].text;if(D==="(")s++;else{if(D===")"&&--s===0)break;if(D===";"||D==="{"||D==="}")break}}let o=r+1;if(((x=this.toks[r])==null?void 0:x.text)===")"&&((v=this.toks[o])==null?void 0:v.text)==="throws")for(o++;((w=this.toks[o])==null?void 0:w.kind)==="id"&&(((I=this.toks[o+1])==null?void 0:I.text)===","||((z=this.toks[o+1])==null?void 0:z.text)==="{"||((k=this.toks[o+1])==null?void 0:k.text)===".");)o+=this.toks[o+1].text==="{"?1:2;const l=this.toks[o],u=((T=this.toks[r])==null?void 0:T.text)===")"&&(l==null?void 0:l.text)==="{";if(!u&&!(t>0&&(l===void 0||this.toks[r]===void 0)))return;const c=((A=this.toks[r])==null?void 0:A.text)===")"?this.toks[r].start:this.src.length,m=this.text(this.toks[e+1].end,c),h=`${this.text(n.start,this.toks[e-1].end).replace(/\s+/g,"")} ${a.text}(${m.replace(/\s*,\s*/g,", ")})`;return this.i=Math.min(u?o:r+1,this.toks.length),{name:a.text,caption:a.text==="main"||!zt(h)?void 0:h}}parseMethod(e){return this.is("{")?this.parseBlock().elements:(this.missingAfter(this.prev(),"{"),[])}parseBlock(){const e=this.next(),t=[];for(;this.tok&&!this.is("}")&&!(this.is("case")||this.is("default"));)t.push(...this.parseStatement());const n=this.eat("}");if(n||this.problem("web_parse_missing",e,"}"),t.length===0){const a=(n==null?void 0:n.start)??this.src.length,s=this.comments.find(r=>r.start>e.end&&r.startn.element)}parseStatement(){const e=this.tok;switch(e.kind==="id"?e.text:""){case"if":return[this.parseIf()];case"while":return[this.parseWhile()];case"do":return[this.parseDo()];case"for":return[this.parseFor()];case"switch":return[this.parseSwitch()];case"try":return this.parseTry();case"break":{this.next();const t=this.eat(";");t||this.missingAfter(e,";");const n=this.trailingComment(t??e);return[this.record(Ae(S.aussprung,{textLines:[n]}),e.line,e.line)]}case"else":return this.problem("web_parse_else_without_if",this.next()),[];case"case":case"default":for(this.problem("web_parse_case_outside_switch",this.next());this.tok&&!this.is(":")&&!this.is("->")&&!this.is(";");)this.next();return this.next(),[]}return this.is("{")?this.parseBlock().elements:this.is(";")?(this.next(),[this.record(Ae(S.anweisung),e.line,e.line)]):this.parseSimple()}parseTry(){const e=this.next();let t=e;const n=(r,o)=>{t=this.next();let u=1;for(;this.tok;){const c=this.next();if(t=c,c.kind!=="str"){if(c.text===r)u++;else if(c.text===o&&--u===0)return!0}}return this.missingAfter(t,o),!1};let a=!0;for(this.is("(")&&(a=n("(",")")),a&&this.is("{")?a=n("{","}"):a&&this.missingAfter(t,"{");a&&(this.is("catch")||this.is("finally"));){const r=this.next().text==="catch";t=this.prev(),r&&(this.is("(")?a=n("(",")"):this.missingAfter(t,"(")),a&&this.is("{")?a=n("{","}"):a&&this.missingAfter(t,"{")}const s=this.text(e.start,t.end).replace(/\s+/g," ");return[this.record(Ae(S.anweisung,{textLines:[s]}),e.line,t.line)]}trailingComment(e){const t=this.comments.find(a=>a.start>=e.end&&a.line===e.line),n=this.toks.find(a=>a.start>=e.end);return!t||n&&n.start1;)c.push("");const m=this.parseBody();return this.record(Ae(S.forSchleife,{textLines:c,loopBody:m.elements}),e.line,m.end)}parseSwitch(){const e=this.next(),t=this.parenthesized(e,this.labels.selector),n=[];let a=this.lineOf(this.prev());const s=this.eat("{");if(!s)this.missingAfter(this.prev(),"{");else{for(;this.tok&&!this.is("}");){if(!this.is("case")&&!this.is("default")){this.problem("web_parse_case_outside_switch",this.tok),this.parseStatement();continue}n.push(this.parseCase())}const o=this.eat("}");o||this.problem("web_parse_missing",s,"}"),a=this.lineOf(o??this.prev())}n.some(o=>o.isDefault)||n.push({name:"default",elements:[nn()],isDefault:!0});const r=[...n.filter(o=>!o.isDefault),...n.filter(o=>o.isDefault)].map(({name:o,elements:l})=>({name:o,elements:l}));return this.record(Ae(S.fallauswahl,{textLines:[t.text],cases:r}),e.line,a)}parseCase(){var l;const e=this.next(),t=e.text==="default",n=((l=this.tok)==null?void 0:l.start)??e.end;let a=n;for(;this.tok&&!this.is("->")&&!this.is(":")&&!this.is("{")&&!this.is("}");)a=this.next().end;const s=this.eat("->")??this.eat(":");s||this.missingAfter(this.prev(),"->");let r=t?"default":this.text(n,a),o=[];if((s==null?void 0:s.text)==="->")this.is("{")?(t&&(r=this.trailingComment(this.tok)||r),o=this.parseBlock().elements):this.tok&&!this.is("}")&&(o=this.parseStatement());else{for(t&&s&&(r=this.trailingComment(s)||r);this.tok&&!this.is("case")&&!this.is("default")&&!this.is("}");)o.push(...this.parseStatement());const u=o[o.length-1];(u==null?void 0:u.element.type)===S.aussprung&&u.element.textLines.every(c=>c==="")&&o.pop()}return{name:r,elements:this.finishList(o),isDefault:t}}parseSimple(){const e=this.next();let t=e;const n=e.text==="("||e.text==="["||e.text==="{"?[e.text]:[],a=()=>n.length>0&&n[n.length-1]==="{"&&e.text!=="{";let s;for(;this.tok;){const u=this.tok;if(u.text===";"&&u.kind==="op"&&!a()){s=this.next();break}if(u.line!==t.line&&!a()&&(n.length===0||u.kind==="id"&&Tr.has(u.text)||u.text==="}")||u.text==="}"&&n.length===0)break;(u.text==="("||u.text==="["||u.text==="{")&&n.push(u.text),(u.text===")"||u.text==="]"||u.text==="}")&&n.pop(),t=this.next()}s||this.missingAfter(t,";"),this.checkBrackets(e,t);const r=this.text(e.start,t.end),o=this.simpleElement(r);if(!o)return[];const l=this.record(o.element,e.line,t.line);return l.prompt=o.prompt,[l]}checkBrackets(e,t){const n=[],a={")":"(","]":"[","}":"{"},s={"(":")","[":"]","{":"}"};for(let r=this.toks.indexOf(e);r>=0&&rAe(S.anweisung,{textLines:[u]}),a=/^System\.out\.println\s*\(([\s\S]*?)\)?$/.exec(e);if(a){const u=a[1].trim();if(u==="")return{element:n("output: ")};const c=/^"((?:[^"\\]|\\.)*)"$/.exec(u),m=c?GM(c[1]):void 0;return{element:n(`output: ${u}`),prompt:m!==void 0&&!m.includes('"')?m:void 0}}const s=new RegExp(`^(?:(${fc})\\s+)?([A-Za-z_]\\w*(?:\\s*\\[[^\\]]+\\])*)\\s*=\\s*\\w+\\.(nextInt|nextDouble|nextLine|next|nextBoolean)\\s*\\(\\s*\\)$`).exec(e);if(s&&!this.fileScanners.has(e.replace(/^[\s\S]*=\s*(\w+)\.\w+\s*\(\s*\)$/,"$1"))){const u={nextInt:"int",nextDouble:"double",nextLine:"String",next:"String",nextBoolean:"boolean"}[s[3]],c=s[2].replace(/\s+/g,"");if((s[1]===u||!s[1]&&c.includes("["))&&u)return{element:n(`input: ${u} ${c}`)}}const r=new RegExp(`^final\\s+(${fc}\\s+[\\s\\S]*)$`).exec(e);if(r)return{element:n(`const ${r[1]}`)};const o=/^(?:(?:\w+\s+)?\w+\s*=\s*)?([A-Za-z_]\w*)\s*\(/.exec(e);return o&&((l=this.opts.subprograms)!=null&&l.has(o[1]))?{element:Ae(S.aufruf,{textLines:[e]})}:{element:n(e)}}spansFor(e,t=[],n=[]){return e.forEach((a,s)=>{var l;const r=[...t,s],o=this.lines.get(a);o&&n.push({path:r,from:o[0],to:o[1]}),a.loopBody&&this.spansFor(a.loopBody,[...r,0],n),(l=a.cases)==null||l.forEach((u,c)=>this.spansFor(u.elements,[...r,c],n))}),n}isCodePlaceholder(e){return e.text.startsWith("//")&&e.text.slice(2).trim()===this.labels.code}markPlaceholderComments(){for(const e of this.comments)this.isCodePlaceholder(e)&&this.placeholders.push({from:e.start,to:e.end})}};function GM(i){return i.replace(/\\(.)/g,(e,t)=>({n:` +`,r:"\r",t:" "})[t]??t)}function Eo(i,e,t={}){const n=new RM(i,e,t),{caption:a,elements:s}=n.parseProgram();n.markPlaceholderComments(),n.checkImports(),n.checkScanners(),n.checkTypes();const r=n.spansFor(s),o=n.problems.sort((l,u)=>l.from-u.from);return{caption:a,className:n.className,elements:s,spans:r,placeholders:n.placeholders.sort((l,u)=>l.from-u.from),problems:o}}const d0={asClass:!1,withMain:!1},bc=i=>/^import\s+[\w.]+(?:\.\*)?\s*;$/.test(i.trim()),xc=i=>i.map(e=>e.trim()===""?"":" "+e);function zg(i,e,t=d0){var u;const n=Zh(i,"java",e);let a=n.text.replaceAll(Wi,"").replaceAll(t0,"").split(` +`),s=n.spans;const r=c=>s=s.map(m=>({...m,from:m.from+c,to:m.to+c})),o=zt(i.caption)!==void 0,l=[];if(t.withMain&&!o||t.asClass){for(let c=a.findIndex(bc);c>=0;c=a.findIndex(bc))l.push(a[c].trim()),a.splice(c,1),s=s.map(m=>({...m,from:m.from>c?m.from-1:m.from,to:m.to>c?m.to-1:m.to}));l.length&&((u=a[0])==null?void 0:u.trim())===""&&(a.splice(0,1),s=s.map(c=>({...c,from:c.from>0?c.from-1:c.from,to:c.to>0?c.to-1:c.to}))),l.length&&l.push("")}return t.withMain&&!o&&(a=[`public static void main(String[] args)${bb(i)?" throws Exception":""} {`,...xc(a),"}"],r(1)),t.asClass&&(a=[`public class ${qs(o?"Main":i.caption)} {`,...xc(a),"}"],r(1)),l.length&&(a=[...l,...a],r(l.length)),{text:a.join(` +`),spans:s}}function ci(i,e,t=d0){return zg(i,e,t).text}function Ar(i){const e=Ig(i).code;return(e.trim()===""?i:e).replace(/\s+/g,"")}function Ig(i){let e="";for(let t=0;tnew Array(a+1).fill(0));for(let u=n-1;u>=0;u--)for(let c=a-1;c>=0;c--)s[u][c]=t(i[u],e[c])?s[u+1][c+1]+1:Math.max(s[u+1][c],s[u][c+1]);const r=[];let o=0,l=0;for(;o=s[o][l+1])?r.push({kind:"del",a:o++}):r.push({kind:"ins",b:l++});return r}function yc(i,e,t,n,a={},s=d0){const r=ci(t,n,s),o=ci(e,n,s);if(i===o)return r;const l=o.split(` +`),u=r.split(` +`),c=i.split(` +`),m=new Array(l.length).fill(-1);for(const v of vc(l,c,(w,I)=>Ar(w)!==""&&Ar(w)===Ar(I)))v.kind==="keep"&&(m[v.a]=v.b);const d=[];let h=0,g="";const f=v=>{for(;hw===I))if(v.kind==="keep")m[v.a]>=0&&(f(m[v.a]+1),g="");else if(v.kind==="del"){const w=m[v.a];if(w<0)continue;f(w),g||(g=Ig(c[w]).comment),h=w+1}else{const w=u[v.b];d.push(g&&w.trim()!==""?`${w} ${g}`:w),w.trim()!==""&&(g="")}f(c.length);const b=d.join(` +`),x=Eo(b,n,a);return ci(Wo(t,x),n,s)===r?b:r}function Wo(i,e){let t=e.caption??(zt(i.caption)?"":i.caption);return!e.caption&&e.className&&qs(t)!==e.className&&(t=e.className),{...i,caption:t,elements:No(i.elements,e.elements)}}function No(i,e){return e.map((t,n)=>{const a=i[n];if(!a||a.type!==t.type)return t;const s={...t,zoomX:a.zoomX,zoomY:a.zoomY};return a.textColor&&(s.textColor=a.textColor),a.backgroundColor&&(s.backgroundColor=a.backgroundColor),t.loopBody&&(s.loopBody=No(a.loopBody??[],t.loopBody)),t.cases&&(s.cases=t.cases.map((r,o)=>{var l,u;return{...r,elements:No(((u=(l=a.cases)==null?void 0:l[o])==null?void 0:u.elements)??[],r.elements)}})),s})}let Fo=[],kg=[];(()=>{let i="lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,1n,9,16,o,,x,1i,3,,i,,7,a,2,t,3,1k,,,7,2,2,2,3,9,,a,2,q,,2,3,1k,,,5,4,2,2,3,3,,u,2,3,,b,3,1k,,,8,,3,,3,k,2,m,6,,3,1k,,,7,2,2,2,3,7,3,a,2,u,,1n,5,3,3,,4,9,,14,5,1j,,,7,,3,,4,7,2,b,2,t,3,1k,,,7,,3,,4,7,2,b,2,f,,c,4,1j,2,,7,,3,,4,9,,a,2,t,3,1y,,4,6,,,,8,i,2,1p,,,8,c,8,2q,,,a,b,7,21,2,r,,,,,,4,2,1d,k,,2,5,b,,10,9,,2u,b,,6,n,4,4,3,g,4,d,,,3,6,,f,,jj,3,qa,4,s,3,t,2,u,2,1s,w,9,,19,3,,,39,2,y,,3a,c,4,c,63,5,1l,a,,,,,2,o,2,,1c,1a,2,c,k,5,1b,h,12,9,c,3,u,d,1k,e,1c,k,48,3,,l,4,,6,,2,3,5i,1s,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,n,5,4,,2b,2,1e,i,q,i,d,,12,8,p,d,18,4,1b,e,10,,1v,e,c,,8,2,1a,,1f,,,3,2,2,5,2,,,15,5,5,2,6k,8,,2,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,1t,5,8t,2,25,6,1y,b,1d,4,3e,3,1h,f,15,,2,2,a,4,19,b,7,,1p,3,10,e,g,2,18,,c,3,1c,e,8,4,,2,2k,c,6,,2,,4d,c,l,4,1j,2,,7,2,2,2,3,9,,a,2,2,7,3,5,1v,9,,,2,,,4,,5,,,e,2,2a,i,n,,29,k,6j,7,2,9,r,2,2a,h,2y,d,2t,3,2,a,74,f,6t,6,,2,2,4,,,,2,3x,7,2,7,3,,s,a,14,7,,4,8,,9,b,1a,g,5i,8,5j,8,,8,2a,m,,e,3e,6,3,,,2,,7,,,1u,5,,2,,5,9n,4,9,2,,,1c,7,3,5,n,,44l,,6,f,8ug,i,1xc,5,1n,7,t4,,,1j,7,4,29,,b,2,f57,2,3mp,1a,2,n,f2,5,3,6,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,2s,,4g,7,af,,1p,4,e4,4,72,2,6r,,2,,7,2,5,,d6,7,31,7,240,5".split(",").map(e=>e?parseInt(e,36):1);for(let e=0,t=0;e>1;if(i=kg[n])e=n+1;else return!0;if(e==t)return!1}}function wc(i){return i>=127462&&i<=127487}const zc=8205;function VM(i,e,t=!0,n=!0){return(t?Sg:qM)(i,e,n)}function Sg(i,e,t){if(e==i.length)return e;e&&Tg(i.charCodeAt(e))&&_g(i.charCodeAt(e-1))&&e--;let n=Or(i,e);for(e+=Ic(n);e=0&&wc(Or(i,r));)s++,r-=2;if(s%2==0)break;e+=2}else break}return e}function qM(i,e,t){for(;e>1;){let n=Sg(i,e-2,t);if(n=56320&&i<57344}function _g(i){return i>=55296&&i<56320}function Ic(i){return i<65536?1:2}class oe{lineAt(e){if(e<0||e>this.length)throw new RangeError(`Invalid position ${e} in document of length ${this.length}`);return this.lineInner(e,!1,1,0)}line(e){if(e<1||e>this.lines)throw new RangeError(`Invalid line number ${e} in ${this.lines}-line document`);return this.lineInner(e,!0,1,0)}replace(e,t,n){[e,t]=C1(this,e,t);let a=[];return this.decompose(0,e,a,2),n.length&&n.decompose(0,n.length,a,3),this.decompose(t,this.length,a,1),an.from(a,this.length-(t-e)+n.length)}append(e){return this.replace(this.length,this.length,e)}slice(e,t=this.length){[e,t]=C1(this,e,t);let n=[];return this.decompose(e,t,n,0),an.from(n,t-e)}eq(e){if(e==this)return!0;if(e.length!=this.length||e.lines!=this.lines)return!1;let t=this.scanIdentical(e,1),n=this.length-this.scanIdentical(e,-1),a=new mi(this),s=new mi(e);for(let r=t,o=t;;){if(a.next(r),s.next(r),r=0,a.lineBreak!=s.lineBreak||a.done!=s.done||a.value!=s.value)return!1;if(o+=a.value.length,a.done||o>=n)return!0}}iter(e=1){return new mi(this,e)}iterRange(e,t=this.length){return new Ag(this,e,t)}iterLines(e,t){let n;if(e==null)n=this.iter();else{t==null&&(t=this.lines+1);let a=this.line(e).from;n=this.iterRange(a,Math.max(a,t==this.lines+1?this.length:t<=1?0:this.line(t-1).to))}return new Og(n)}toString(){return this.sliceString(0)}toJSON(){let e=[];return this.flatten(e),e}constructor(){}static of(e){if(e.length==0)throw new RangeError("A document must have at least one line");return e.length==1&&!e[0]?oe.empty:e.length<=32?new Pe(e):an.from(Pe.split(e,[]))}}class Pe extends oe{constructor(e,t=QM(e)){super(),this.text=e,this.length=t}get lines(){return this.text.length}get children(){return null}lineInner(e,t,n,a){for(let s=0;;s++){let r=this.text[s],o=a+r.length;if((t?n:o)>=e)return new UM(a,o,n,r);a=o+1,n++}}decompose(e,t,n,a){let s=e<=0&&t>=this.length?this:new Pe(kc(this.text,e,t),Math.min(t,this.length)-Math.max(0,e));if(a&1){let r=n.pop(),o=Ja(s.text,r.text.slice(),0,s.length);if(o.length<=32)n.push(new Pe(o,r.length+s.length));else{let l=o.length>>1;n.push(new Pe(o.slice(0,l)),new Pe(o.slice(l)))}}else n.push(s)}replace(e,t,n){if(!(n instanceof Pe))return super.replace(e,t,n);[e,t]=C1(this,e,t);let a=Ja(this.text,Ja(n.text,kc(this.text,0,e)),t),s=this.length+n.length-(t-e);return a.length<=32?new Pe(a,s):an.from(Pe.split(a,[]),s)}sliceString(e,t=this.length,n=` +`){[e,t]=C1(this,e,t);let a="";for(let s=0,r=0;s<=t&&re&&r&&(a+=n),es&&(a+=o.slice(Math.max(0,e-s),t-s)),s=l+1}return a}flatten(e){for(let t of this.text)e.push(t)}scanIdentical(){return 0}static split(e,t){let n=[],a=-1;for(let s of e)n.push(s),a+=s.length+1,n.length==32&&(t.push(new Pe(n,a)),n=[],a=-1);return a>-1&&t.push(new Pe(n,a)),t}}class an extends oe{constructor(e,t){super(),this.children=e,this.length=t,this.lines=0;for(let n of e)this.lines+=n.lines}lineInner(e,t,n,a){for(let s=0;;s++){let r=this.children[s],o=a+r.length,l=n+r.lines-1;if((t?l:o)>=e)return r.lineInner(e,t,n,a);a=o+1,n=l+1}}decompose(e,t,n,a){for(let s=0,r=0;r<=t&&s=r){let u=a&((r<=e?1:0)|(l>=t?2:0));r>=e&&l<=t&&!u?n.push(o):o.decompose(e-r,t-r,n,u)}r=l+1}}replace(e,t,n){if([e,t]=C1(this,e,t),n.lines=s&&t<=o){let l=r.replace(e-s,t-s,n),u=this.lines-r.lines+l.lines;if(l.lines>4&&l.lines>u>>6){let c=this.children.slice();return c[a]=l,new an(c,this.length-(t-e)+n.length)}return super.replace(s,o,l)}s=o+1}return super.replace(e,t,n)}sliceString(e,t=this.length,n=` +`){[e,t]=C1(this,e,t);let a="";for(let s=0,r=0;se&&s&&(a+=n),er&&(a+=o.sliceString(e-r,t-r,n)),r=l+1}return a}flatten(e){for(let t of this.children)t.flatten(e)}scanIdentical(e,t){if(!(e instanceof an))return 0;let n=0,[a,s,r,o]=t>0?[0,0,this.children.length,e.children.length]:[this.children.length-1,e.children.length-1,-1,-1];for(;;a+=t,s+=t){if(a==r||s==o)return n;let l=this.children[a],u=e.children[s];if(l!=u)return n+l.scanIdentical(u,t);n+=l.length+1}}static from(e,t=e.reduce((n,a)=>n+a.length+1,-1)){let n=0;for(let h of e)n+=h.lines;if(n<32){let h=[];for(let g of e)g.flatten(h);return new Pe(h,t)}let a=Math.max(32,n>>5),s=a<<1,r=a>>1,o=[],l=0,u=-1,c=[];function m(h){let g;if(h.lines>s&&h instanceof an)for(let f of h.children)m(f);else h.lines>r&&(l>r||!l)?(d(),o.push(h)):h instanceof Pe&&l&&(g=c[c.length-1])instanceof Pe&&h.lines+g.lines<=32?(l+=h.lines,u+=h.length+1,c[c.length-1]=new Pe(g.text.concat(h.text),g.length+1+h.length)):(l+h.lines>a&&d(),l+=h.lines,u+=h.length+1,c.push(h))}function d(){l!=0&&(o.push(c.length==1?c[0]:an.from(c,u)),u=-1,l=c.length=0)}for(let h of e)m(h);return d(),o.length==1?o[0]:new an(o,t)}}oe.empty=new Pe([""],0);function QM(i){let e=-1;for(let t of i)e+=t.length+1;return e}function Ja(i,e,t=0,n=1e9){for(let a=0,s=0,r=!0;s=t&&(l>n&&(o=o.slice(0,n-a)),a0?1:(e instanceof Pe?e.text.length:e.children.length)<<1]}nextInner(e,t){for(this.done=this.lineBreak=!1;;){let n=this.nodes.length-1,a=this.nodes[n],s=this.offsets[n],r=s>>1,o=a instanceof Pe?a.text.length:a.children.length;if(r==(t>0?o:0)){if(n==0)return this.done=!0,this.value="",this;t>0&&this.offsets[n-1]++,this.nodes.pop(),this.offsets.pop()}else if((s&1)==(t>0?0:1)){if(this.offsets[n]+=t,e==0)return this.lineBreak=!0,this.value=` +`,this;e--}else if(a instanceof Pe){let l=a.text[r+(t<0?-1:0)];if(this.offsets[n]+=t,l.length>Math.max(0,e))return this.value=e==0?l:t>0?l.slice(e):l.slice(0,l.length-e),this;e-=l.length}else{let l=a.children[r+(t<0?-1:0)];e>l.length?(e-=l.length,this.offsets[n]+=t):(t<0&&this.offsets[n]--,this.nodes.push(l),this.offsets.push(t>0?1:(l instanceof Pe?l.text.length:l.children.length)<<1))}}}next(e=0){return e<0&&(this.nextInner(-e,-this.dir),e=this.value.length),this.nextInner(e,this.dir)}}class Ag{constructor(e,t,n){this.value="",this.done=!1,this.cursor=new mi(e,t>n?-1:1),this.pos=t>n?e.length:0,this.from=Math.min(t,n),this.to=Math.max(t,n)}nextInner(e,t){if(t<0?this.pos<=this.from:this.pos>=this.to)return this.value="",this.done=!0,this;e+=Math.max(0,t<0?this.pos-this.to:this.from-this.pos);let n=t<0?this.pos-this.from:this.to-this.pos;e>n&&(e=n),n-=e;let{value:a}=this.cursor.next(e);return this.pos+=(a.length+e)*t,this.value=a.length<=n?a:t<0?a.slice(a.length-n):a.slice(0,n),this.done=!this.value,this}next(e=0){return e<0?e=Math.max(e,this.from-this.pos):e>0&&(e=Math.min(e,this.to-this.pos)),this.nextInner(e,this.cursor.dir)}get lineBreak(){return this.cursor.lineBreak&&this.value!=""}}class Og{constructor(e){this.inner=e,this.afterBreak=!0,this.value="",this.done=!1}next(e=0){let{done:t,lineBreak:n,value:a}=this.inner.next(e);return t&&this.afterBreak?(this.value="",this.afterBreak=!1):t?(this.done=!0,this.value=""):n?this.afterBreak?this.value="":(this.afterBreak=!0,this.next()):(this.value=a,this.afterBreak=!1),this}get lineBreak(){return!1}}typeof Symbol<"u"&&(oe.prototype[Symbol.iterator]=function(){return this.iter()},mi.prototype[Symbol.iterator]=Ag.prototype[Symbol.iterator]=Og.prototype[Symbol.iterator]=function(){return this});class UM{constructor(e,t,n,a){this.from=e,this.to=t,this.number=n,this.text=a}get length(){return this.to-this.from}}function C1(i,e,t){return e=Math.max(0,Math.min(i.length,e)),[e,Math.max(e,Math.min(i.length,t))]}function rt(i,e,t=!0,n=!0){return VM(i,e,t,n)}function $M(i){return i>=56320&&i<57344}function YM(i){return i>=55296&&i<56320}function Ot(i,e){let t=i.charCodeAt(e);if(!YM(t)||e+1==i.length)return t;let n=i.charCodeAt(e+1);return $M(n)?(t-55296<<10)+(n-56320)+65536:t}function Cg(i){return i<=65535?String.fromCharCode(i):(i-=65536,String.fromCharCode((i>>10)+55296,(i&1023)+56320))}function mn(i){return i<65536?1:2}const Jo=/\r\n?|\n/;var st=(function(i){return i[i.Simple=0]="Simple",i[i.TrackDel=1]="TrackDel",i[i.TrackBefore=2]="TrackBefore",i[i.TrackAfter=3]="TrackAfter",i})(st||(st={}));class hn{constructor(e){this.sections=e}get length(){let e=0;for(let t=0;te)return s+(e-a);s+=o}else{if(n!=st.Simple&&u>=e&&(n==st.TrackDel&&ae||n==st.TrackBefore&&ae))return null;if(u>e||u==e&&t<0&&!o)return e==a||t<0?s:s+l;s+=l}a=u}if(e>a)throw new RangeError(`Position ${e} is out of range for changeset of length ${a}`);return s}touchesRange(e,t=e){for(let n=0,a=0;n=0&&a<=t&&o>=e)return at?"cover":!0;a=o}return!1}toString(){let e="";for(let t=0;t=0?":"+a:"")}return e}toJSON(){return this.sections}static fromJSON(e){if(!Array.isArray(e)||e.length%2||e.some(t=>typeof t!="number"))throw new RangeError("Invalid JSON representation of ChangeDesc");return new hn(e)}static create(e){return new hn(e)}}class Re extends hn{constructor(e,t){super(e),this.inserted=t}apply(e){if(this.length!=e.length)throw new RangeError("Applying change set to a document with the wrong length");return Ro(this,(t,n,a,s,r)=>e=e.replace(a,a+(n-t),r),!1),e}mapDesc(e,t=!1){return Go(this,e,t,!0)}invert(e){let t=this.sections.slice(),n=[];for(let a=0,s=0;a=0){t[a]=o,t[a+1]=r;let l=a>>1;for(;n.length0&&Cn(n,t,s.text),s.forward(c),o+=c}let u=e[r++];for(;o>1].toJSON()))}return e}static of(e,t,n){let a=[],s=[],r=0,o=null;function l(c=!1){if(!c&&!a.length)return;rd||m<0||d>t)throw new RangeError(`Invalid change range ${m} to ${d} (in doc of length ${t})`);let g=h?typeof h=="string"?oe.of(h.split(n||Jo)):h:oe.empty,f=g.length;if(m==d&&f==0)return;mr&&at(a,m-r,-1),at(a,d-m,f),Cn(s,a,g),r=d}}return u(e),l(!o),o}static empty(e){return new Re(e?[e,-1]:[],[])}static fromJSON(e){if(!Array.isArray(e))throw new RangeError("Invalid JSON representation of ChangeSet");let t=[],n=[];for(let a=0;ao&&typeof r!="string"))throw new RangeError("Invalid JSON representation of ChangeSet");if(s.length==1)t.push(s[0],0);else{for(;n.length=0&&t<=0&&t==i[a+1]?i[a]+=e:a>=0&&e==0&&i[a]==0?i[a+1]+=t:n?(i[a]+=e,i[a+1]+=t):i.push(e,t)}function Cn(i,e,t){if(t.length==0)return;let n=e.length-2>>1;if(n>1])),!(t||r==i.sections.length||i.sections[r+1]<0);)o=i.sections[r++],l=i.sections[r++];e(a,u,s,c,m),a=u,s=c}}}function Go(i,e,t,n=!1){let a=[],s=n?[]:null,r=new Si(i),o=new Si(e);for(let l=-1;;){if(r.done&&o.len||o.done&&r.len)throw new Error("Mismatched change set lengths");if(r.ins==-1&&o.ins==-1){let u=Math.min(r.len,o.len);at(a,u,-1),r.forward(u),o.forward(u)}else if(o.ins>=0&&(r.ins<0||l==r.i||r.off==0&&(o.len=0&&l=0){let u=0,c=r.len;for(;c;)if(o.ins==-1){let m=Math.min(c,o.len);u+=m,c-=m,o.forward(m)}else if(o.ins==0&&o.lenl||r.ins>=0&&r.len>l)&&(o||n.length>u),s.forward2(l),r.forward(l)}}}}class Si{constructor(e){this.set=e,this.i=0,this.next()}next(){let{sections:e}=this.set;this.i>1;return t>=e.length?oe.empty:e[t]}textBit(e){let{inserted:t}=this.set,n=this.i-2>>1;return n>=t.length&&!e?oe.empty:t[n].slice(this.off,e==null?void 0:this.off+e)}forward(e){e==this.len?this.next():(this.len-=e,this.off+=e)}forward2(e){this.ins==-1?this.forward(e):e==this.ins?this.next():(this.ins-=e,this.off+=e)}}class _n{constructor(e,t,n,a){this.from=e,this.to=t,this.flags=n,this.goalColumn=a}get anchor(){return this.flags&32?this.to:this.from}get head(){return this.flags&32?this.from:this.to}get empty(){return this.from==this.to}get assoc(){return this.flags&8?-1:this.flags&16?1:0}get undirectional(){return(this.flags&64)>0}get bidiLevel(){let e=this.flags&7;return e==7?null:e}map(e,t=-1){let n,a;return this.empty?n=a=e.mapPos(this.from,t):(n=e.mapPos(this.from,1),a=e.mapPos(this.to,-1)),n==this.from&&a==this.to?this:new _n(n,a,this.flags,this.goalColumn)}extend(e,t=e,n=0){if(e<=this.anchor&&t>=this.anchor)return B.range(e,t,void 0,void 0,n);let a=Math.abs(e-this.anchor)>Math.abs(t-this.anchor)?e:t;return B.range(this.anchor,a,void 0,void 0,n)}eq(e,t=!1){return this.anchor==e.anchor&&this.head==e.head&&this.goalColumn==e.goalColumn&&(!t||!this.empty||this.assoc==e.assoc)}toJSON(){return{anchor:this.anchor,head:this.head}}static fromJSON(e){if(!e||typeof e.anchor!="number"||typeof e.head!="number")throw new RangeError("Invalid JSON representation for SelectionRange");return B.range(e.anchor,e.head)}static create(e,t,n,a){return new _n(e,t,n,a)}}class B{constructor(e,t){this.ranges=e,this.mainIndex=t}map(e,t=-1){return e.empty?this:B.create(this.ranges.map(n=>n.map(e,t)),this.mainIndex)}eq(e,t=!1){if(this.ranges.length!=e.ranges.length||this.mainIndex!=e.mainIndex)return!1;for(let n=0;ne.toJSON()),main:this.mainIndex}}static fromJSON(e){if(!e||!Array.isArray(e.ranges)||typeof e.main!="number"||e.main>=e.ranges.length)throw new RangeError("Invalid JSON representation for EditorSelection");return new B(e.ranges.map(t=>_n.fromJSON(t)),e.main)}static single(e,t=e){return new B([B.range(e,t)],0)}static create(e,t=0){if(e.length==0)throw new RangeError("A selection needs at least one range");for(let n=0,a=0;aa.from-s.from),t=e.indexOf(n);for(let a=1;as.head?B.range(l,o):B.range(o,l))}}return new B(e,t)}}function Pg(i,e){for(let t of i.ranges)if(t.to>e)throw new RangeError("Selection points outside of document")}let h0=0;class V{constructor(e,t,n,a,s){this.combine=e,this.compareInput=t,this.compare=n,this.isStatic=a,this.id=h0++,this.default=e([]),this.extensions=typeof s=="function"?s(this):s}get reader(){return this}static define(e={}){return new V(e.combine||(t=>t),e.compareInput||((t,n)=>t===n),e.compare||(e.combine?(t,n)=>t===n:g0),!!e.static,e.enables)}of(e){return new Ra([],this,0,e)}compute(e,t){if(this.isStatic)throw new Error("Can't compute a static facet");return new Ra(e,this,1,t)}computeN(e,t){if(this.isStatic)throw new Error("Can't compute a static facet");return new Ra(e,this,2,t)}from(e,t){return t||(t=n=>n),this.compute([e],n=>t(n.field(e)))}}function g0(i,e){return i==e||i.length==e.length&&i.every((t,n)=>t===e[n])}class Ra{constructor(e,t,n,a){this.dependencies=e,this.facet=t,this.type=n,this.value=a,this.id=h0++}dynamicSlot(e){var t;let n=this.value,a=this.facet.compareInput,s=this.id,r=e[s]>>1,o=this.type==2,l=!1,u=!1,c=[];for(let m of this.dependencies)m=="doc"?l=!0:m=="selection"?u=!0:(((t=e[m.id])!==null&&t!==void 0?t:1)&1)==0&&c.push(e[m.id]);return{create(m){return m.values[r]=n(m),1},update(m,d){if(l&&d.docChanged||u&&(d.docChanged||d.selection)||Ho(m,c)){let h=n(m);if(o?!Sc(h,m.values[r],a):!a(h,m.values[r]))return m.values[r]=h,1}return 0},reconfigure:(m,d)=>{let h,g=d.config.address[s];if(g!=null){let f=xs(d,g);if(this.dependencies.every(b=>b instanceof V?d.facet(b)===m.facet(b):b instanceof Et?d.field(b,!1)==m.field(b,!1):!0)||(o?Sc(h=n(m),f,a):a(h=n(m),f)))return m.values[r]=f,0}else h=n(m);return m.values[r]=h,1}}}get extension(){return this}}function Sc(i,e,t){if(i.length!=e.length)return!1;for(let n=0;ni[l.id]),a=t.map(l=>l.type),s=n.filter(l=>!(l&1)),r=i[e.id]>>1;function o(l){let u=[];for(let c=0;cn===a),e);return e.provide&&(t.provides=e.provide(t)),t}create(e){let t=e.facet(ha).find(n=>n.field==this);return((t==null?void 0:t.create)||this.createF)(e)}slot(e){let t=e[this.id]>>1;return{create:n=>(n.values[t]=this.create(n),1),update:(n,a)=>{let s=n.values[t],r=this.updateF(s,a);return this.compareF(s,r)?0:(n.values[t]=r,1)},reconfigure:(n,a)=>{let s=n.facet(ha),r=a.facet(ha),o;return(o=s.find(l=>l.field==this))&&o!=r.find(l=>l.field==this)?(n.values[t]=o.create(n),1):a.config.address[this.id]!=null?(n.values[t]=a.field(this),0):(n.values[t]=this.create(n),1)}}}init(e){return[this,ha.of({field:this,create:e})]}get extension(){return this}}const qn={lowest:4,low:3,default:2,high:1,highest:0};function V1(i){return e=>new Dg(e,i)}const l1={highest:V1(qn.highest),high:V1(qn.high),default:V1(qn.default),low:V1(qn.low),lowest:V1(qn.lowest)};class Dg{constructor(e,t){this.inner=e,this.prec=t}get extension(){return this}}class Ni{of(e){return new Vo(this,e)}reconfigure(e){return Ni.reconfigure.of({compartment:this,extension:e})}get(e){return e.config.compartments.get(this)}}class Vo{constructor(e,t){this.compartment=e,this.inner=t}get extension(){return this}}class bs{constructor(e,t,n,a,s,r){for(this.base=e,this.compartments=t,this.dynamicSlots=n,this.address=a,this.staticValues=s,this.facets=r,this.statusTemplate=[];this.statusTemplate.length>1]}static resolve(e,t,n){let a=[],s=Object.create(null),r=new Map;for(let d of KM(e,t,r))d instanceof Et?a.push(d):(s[d.facet.id]||(s[d.facet.id]=[])).push(d);let o=Object.create(null),l=[],u=[];for(let d of a)o[d.id]=u.length<<1,u.push(h=>d.slot(h));let c=n==null?void 0:n.config.facets;for(let d in s){let h=s[d],g=h[0].facet,f=c&&c[d]||[];if(h.every(b=>b.type==0))if(o[g.id]=l.length<<1|1,g0(f,h))l.push(n.facet(g));else{let b=g.combine(h.map(x=>x.value));l.push(n&&g.compare(b,n.facet(g))?n.facet(g):b)}else{for(let b of h)b.type==0?(o[b.id]=l.length<<1|1,l.push(b.value)):(o[b.id]=u.length<<1,u.push(x=>b.dynamicSlot(x)));o[g.id]=u.length<<1,u.push(b=>XM(b,g,h))}}let m=u.map(d=>d(o));return new bs(e,r,m,o,l,s)}}function KM(i,e,t){let n=[[],[],[],[],[]],a=new Map;function s(r,o){let l=a.get(r);if(l!=null){if(l<=o)return;let u=n[l].indexOf(r);u>-1&&n[l].splice(u,1),r instanceof Vo&&t.delete(r.compartment)}if(a.set(r,o),Array.isArray(r))for(let u of r)s(u,o);else if(r instanceof Vo){if(t.has(r.compartment))throw new RangeError("Duplicate use of compartment in extensions");let u=e.get(r.compartment)||r.inner;t.set(r.compartment,u),s(u,o)}else if(r instanceof Dg)s(r.inner,r.prec);else if(r instanceof Et)n[o].push(r),r.provides&&s(r.provides,o);else if(r instanceof Ra)n[o].push(r),r.facet.extensions&&s(r.facet.extensions,qn.default);else{let u=r.extension;if(!u)throw new Error(`Unrecognized extension value in extension set (${r}).`);if(u==r)throw new Error(`Unrecognized extension value in extension set (${r}). This sometimes happens because multiple instances of @codemirror/state are loaded, breaking instanceof checks.`);s(u,o)}}return s(i,qn.default),n.reduce((r,o)=>r.concat(o))}function di(i,e){if(e&1)return 2;let t=e>>1,n=i.status[t];if(n==4)throw new Error("Cyclic dependency between fields and/or facets");if(n&2)return n;i.status[t]=4;let a=i.computeSlot(i,i.config.dynamicSlots[t]);return i.status[t]=2|a}function xs(i,e){return e&1?i.config.staticValues[e>>1]:i.values[e>>1]}const Bg=V.define(),qo=V.define({combine:i=>i.some(e=>e),static:!0}),Mg=V.define({combine:i=>i.length?i[0]:void 0,static:!0}),Zg=V.define(),Lg=V.define(),Eg=V.define(),Wg=V.define({combine:i=>i.length?i[0]:!1});class Wn{constructor(e,t){this.type=e,this.value=t}static define(){return new eZ}}class eZ{of(e){return new Wn(this,e)}}class tZ{constructor(e){this.map=e}of(e){return new de(this,e)}}class de{constructor(e,t){this.type=e,this.value=t}map(e){let t=this.type.map(this.value,e);return t===void 0?void 0:t==this.value?this:new de(this.type,t)}is(e){return this.type==e}static define(e={}){return new tZ(e.map||(t=>t))}static mapEffects(e,t){if(!e.length)return e;let n=[];for(let a of e){let s=a.map(t);s&&n.push(s)}return n}}de.reconfigure=de.define();de.appendConfig=de.define();class $e{constructor(e,t,n,a,s,r){this.startState=e,this.changes=t,this.selection=n,this.effects=a,this.annotations=s,this.scrollIntoView=r,this._doc=null,this._state=null,n&&Pg(n,t.newLength),s.some(o=>o.type==$e.time)||(this.annotations=s.concat($e.time.of(Date.now())))}static create(e,t,n,a,s,r){return new $e(e,t,n,a,s,r)}get newDoc(){return this._doc||(this._doc=this.changes.apply(this.startState.doc))}get newSelection(){return this.selection||this.startState.selection.map(this.changes)}get state(){return this._state||this.startState.applyTransaction(this),this._state}annotation(e){for(let t of this.annotations)if(t.type==e)return t.value}get docChanged(){return!this.changes.empty}get reconfigured(){return this.startState.config!=this.state.config}isUserEvent(e){let t=this.annotation($e.userEvent);return!!(t&&(t==e||t.length>e.length&&t.slice(0,e.length)==e&&t[e.length]=="."))}}$e.time=Wn.define();$e.userEvent=Wn.define();$e.addToHistory=Wn.define();$e.remote=Wn.define();function nZ(i,e){let t=[];for(let n=0,a=0;;){let s,r;if(n=i[n]))s=i[n++],r=i[n++];else if(a=0;a--){let s=n[a](i);s instanceof $e?i=s:Array.isArray(s)&&s.length==1&&s[0]instanceof $e?i=s[0]:i=Fg(e,k1(s),!1)}return i}function aZ(i){let e=i.startState,t=e.facet(Eg),n=i;for(let a=t.length-1;a>=0;a--){let s=t[a](i);s&&Object.keys(s).length&&(n=Ng(n,Qo(e,s,i.changes.newLength),!0))}return n==i?i:$e.create(e,i.changes,i.selection,n.effects,n.annotations,n.scrollIntoView)}const sZ=[];function k1(i){return i==null?sZ:Array.isArray(i)?i:[i]}var Dt=(function(i){return i[i.Word=0]="Word",i[i.Space=1]="Space",i[i.Other=2]="Other",i})(Dt||(Dt={}));const rZ=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;let Uo;try{Uo=new RegExp("[\\p{Alphabetic}\\p{Number}_]","u")}catch{}function oZ(i){if(Uo)return Uo.test(i);for(let e=0;e"€"&&(t.toUpperCase()!=t.toLowerCase()||rZ.test(t)))return!0}return!1}function lZ(i){return e=>{if(!/\S/.test(e))return Dt.Space;if(oZ(e))return Dt.Word;for(let t=0;t-1)return Dt.Word;return Dt.Other}}class re{constructor(e,t,n,a,s,r){this.config=e,this.doc=t,this.selection=n,this.values=a,this.status=e.statusTemplate.slice(),this.computeSlot=s,r&&(r._state=this);for(let o=0;oa.set(u,l)),t=null),a.set(o.value.compartment,o.value.extension)):o.is(de.reconfigure)?(t=null,n=o.value):o.is(de.appendConfig)&&(t=null,n=k1(n).concat(o.value));let s;t?s=e.startState.values.slice():(t=bs.resolve(n,a,this),s=new re(t,this.doc,this.selection,t.dynamicSlots.map(()=>null),(l,u)=>u.reconfigure(l,this),null).values);let r=e.startState.facet(qo)?e.newSelection:e.newSelection.asSingle();new re(t,e.newDoc,r,s,(o,l)=>l.update(o,e),e)}replaceSelection(e){return typeof e=="string"&&(e=this.toText(e)),this.changeByRange(t=>({changes:{from:t.from,to:t.to,insert:e},range:B.cursor(t.from+e.length,-1)}))}changeByRange(e){let t=this.selection,n=e(t.ranges[0]),a=this.changes(n.changes),s=[n.range],r=k1(n.effects);for(let o=1;or.spec.fromJSON(o,l)))}}return re.create({doc:e.doc,selection:B.fromJSON(e.selection),extensions:t.extensions?a.concat([t.extensions]):a})}static create(e={}){let t=bs.resolve(e.extensions||[],new Map),n=e.doc instanceof oe?e.doc:oe.of((e.doc||"").split(t.staticFacet(re.lineSeparator)||Jo)),a=e.selection?e.selection instanceof B?e.selection:B.single(e.selection.anchor,e.selection.head):B.single(0);return Pg(a,n.length),t.staticFacet(qo)||(a=a.asSingle()),new re(t,n,a,t.dynamicSlots.map(()=>null),(s,r)=>r.create(s),null)}get tabSize(){return this.facet(re.tabSize)}get lineBreak(){return this.facet(re.lineSeparator)||` +`}get readOnly(){return this.facet(Wg)}phrase(e,...t){for(let n of this.facet(re.phrases))if(Object.prototype.hasOwnProperty.call(n,e)){e=n[e];break}return t.length&&(e=e.replace(/\$(\$|\d*)/g,(n,a)=>{if(a=="$")return"$";let s=+(a||1);return!s||s>t.length?n:t[s-1]})),e}languageDataAt(e,t,n=-1){let a=[];for(let s of this.facet(Bg))for(let r of s(this,t,n))Object.prototype.hasOwnProperty.call(r,e)&&a.push(r[e]);return a}charCategorizer(e){let t=this.languageDataAt("wordChars",e);return lZ(t.length?t[0]:"")}wordAt(e){let{text:t,from:n,length:a}=this.doc.lineAt(e),s=this.charCategorizer(e),r=e-n,o=e-n;for(;r>0;){let l=rt(t,r,!1);if(s(t.slice(l,r))!=Dt.Word)break;r=l}for(;oi.length?i[0]:4});re.lineSeparator=Mg;re.readOnly=Wg;re.phrases=V.define({compare(i,e){let t=Object.keys(i),n=Object.keys(e);return t.length==n.length&&t.every(a=>i[a]==e[a])}});re.languageData=Bg;re.changeFilter=Zg;re.transactionFilter=Lg;re.transactionExtender=Eg;Ni.reconfigure=de.define();function p0(i,e,t={}){let n={};for(let a of i)for(let s of Object.keys(a)){let r=a[s],o=n[s];if(o===void 0)n[s]=r;else if(!(o===r||r===void 0))if(Object.hasOwnProperty.call(t,s))n[s]=t[s](o,r);else throw new Error("Config merge conflict for field "+s)}for(let a in e)n[a]===void 0&&(n[a]=e[a]);return n}class Bn{eq(e){return this==e}range(e,t=e){return $o.create(e,t,this)}}Bn.prototype.startSide=Bn.prototype.endSide=0;Bn.prototype.point=!1;Bn.prototype.mapMode=st.TrackDel;function f0(i,e){return i==e||i.constructor==e.constructor&&i.eq(e)}let $o=class Jg{constructor(e,t,n){this.from=e,this.to=t,this.value=n}static create(e,t,n){return new Jg(e,t,n)}};function Yo(i,e){return i.from-e.from||i.value.startSide-e.value.startSide}class b0{constructor(e,t,n,a){this.from=e,this.to=t,this.value=n,this.maxPoint=a}get length(){return p1(this.to)}findIndex(e,t,n,a=0){let s=n?this.to:this.from;for(let r=a,o=s.length;;){if(r==o)return r;let l=r+o>>1,u=s[l]-e||(n?this.value[l].endSide:this.value[l].startSide)-t;if(l==r)return u>=0?r:o;u>=0?o=l:r=l+1}}between(e,t,n,a){for(let s=this.findIndex(t,-1e9,!0),r=this.findIndex(n,1e9,!1,s);sb||f==b&&d.startSide>0&&d.endSide<=0)continue;if(!((b-f||d.endSide-d.startSide)<0))if(u<0&&(u=f),d.point&&(c=Math.max(c,b-f)),(f-n||d.startSide-a)>=0)r.push(d),o.push(f-u),l.push(b-u),n=b,a=d.endSide;else{if(f==b)for(let x=r.length;x>0;x--){if((f-(l[x-1]+u)||d.startSide-r[x-1].endSide)>=0){r.splice(x,0,d),o.splice(x,0,f-u),l.splice(x,0,b-u);continue e}if((f-(o[x-1]+u)||d.endSide-r[x-1].startSide)>0)break}s(f,b,d)}}return{mapped:r.length?new b0(o,l,r,c):null,pos:u}}}class ie{constructor(e,t,n,a){this.chunkPos=e,this.chunk=t,this.nextLayer=n,this.maxPoint=a}static create(e,t,n,a){return new ie(e,t,n,a)}get length(){let e=this.chunk.length-1;return e<0?0:Math.max(this.chunkEnd(e),this.nextLayer.length)}get size(){if(this.isEmpty)return 0;let e=this.nextLayer.size;for(let t of this.chunk)e+=t.value.length;return e}chunkEnd(e){return this.chunkPos[e]+this.chunk[e].length}update(e){let{add:t=[],sort:n=!1,filterFrom:a=0,filterTo:s=this.length}=e,r=e.filter;if(t.length==0&&!r)return this;if(n&&(t=t.slice().sort(Yo)),this.isEmpty)return t.length?ie.of(t):this;let o=new Rg(this,null,-1).goto(0),l=0,u=[],c=new n1;for(;o.value||l=0){let m=t[l++];c.addInner(m.from,m.to,m.value,!1)||u.push(m)}else o.rangeIndex==1&&o.chunkIndexthis.chunkEnd(o.chunkIndex)||so.to||s{s||(s=new n1),s.addRange(l,u,c,!1)};for(let l=0;l=s&&e<=s+r.length&&r.between(s,e-s,t-s,n)===!1)return}this.nextLayer.between(e,t,n)}}iter(e=0){return Ti.from([this]).goto(e)}get isEmpty(){return this.nextLayer==this}static iter(e,t=0){return Ti.from(e).goto(t)}static compare(e,t,n,a,s=-1){let r=e.filter(m=>m.maxPoint>0||!m.isEmpty&&m.maxPoint>=s),o=t.filter(m=>m.maxPoint>0||!m.isEmpty&&m.maxPoint>=s),l=Tc(r,o,n),u=new q1(r,l,s),c=new q1(o,l,s);n.iterGaps((m,d,h)=>_c(u,m,c,d,h,a)),n.empty&&n.length==0&&_c(u,0,c,0,0,a)}static eq(e,t,n=0,a){a==null&&(a=999999999);let s=e.filter(c=>!c.isEmpty&&t.indexOf(c)<0),r=t.filter(c=>!c.isEmpty&&e.indexOf(c)<0);if(s.length!=r.length)return!1;if(!s.length)return!0;let o=Tc(s,r),l=new q1(s,o,0).goto(n),u=new q1(r,o,0).goto(n);for(;;){if(l.to!=u.to||!Xo(l.active,u.active)||l.point&&(!u.point||!f0(l.point,u.point)))return!1;if(l.to>a)return!0;l.next(),u.next()}}static spans(e,t,n,a,s=-1){let r=new q1(e,null,s).goto(t),o=t,l=r.openStart;for(;;){let u=Math.min(r.to,n);if(r.point){let c=r.activeForPoint(r.to),m=r.pointFromo&&(a.span(o,u,r.active,l),l=r.openEnd(u));if(r.to>n)return l+(r.point&&r.to>n?1:0);o=r.to,r.next()}}static of(e,t=!1){let n=new n1;for(let a of e instanceof $o?[e]:t?uZ(e):e)n.add(a.from,a.to,a.value);return n.finish()}static join(e){if(!e.length)return ie.empty;let t=p1(e);for(let n=e.length-2;n>=0;n--)for(let a=e[n];a!=ie.empty;a=a.nextLayer)t=new ie(a.chunkPos,a.chunk,t,Math.max(a.maxPoint,t.maxPoint));return t}}ie.empty=new ie([],[],null,-1);function p1(i){return i[i.length-1]}function uZ(i){if(i.length>1)for(let e=i[0],t=1;t0)return i.slice().sort(Yo);e=n}return i}ie.empty.nextLayer=ie.empty;class n1{finishChunk(e){this.chunks.push(new b0(this.from,this.to,this.value,this.maxPoint)),this.chunkPos.push(this.chunkStart),this.chunkStart=-1,this.setMaxPoint=Math.max(this.setMaxPoint,this.maxPoint),this.maxPoint=-1,e&&(this.from=[],this.to=[],this.value=[])}constructor(){this.chunks=[],this.chunkPos=[],this.chunkStart=-1,this.last=null,this.lastFrom=-1e9,this.lastTo=-1e9,this.from=[],this.to=[],this.value=[],this.maxPoint=-1,this.setMaxPoint=-1,this.nextLayer=null}add(e,t,n){this.addRange(e,t,n,!0)}addRange(e,t,n,a){this.addInner(e,t,n,a)||(this.nextLayer||(this.nextLayer=new n1)).addRange(e,t,n,a)}addInner(e,t,n,a){let s=e-this.lastTo||n.startSide-this.last.endSide;if(a&&s<=0&&(e-this.lastFrom||n.startSide-this.last.startSide)<0)throw new Error("Ranges must be added sorted by `from` position and `startSide`");return s<0?!1:(this.from.length==250&&this.finishChunk(!0),this.chunkStart<0&&(this.chunkStart=e),this.from.push(e-this.chunkStart),this.to.push(t-this.chunkStart),this.last=n,this.lastFrom=e,this.lastTo=t,this.value.push(n),n.point&&(this.maxPoint=Math.max(this.maxPoint,t-e)),!0)}addChunk(e,t){if((e-this.lastTo||t.value[0].startSide-this.last.endSide)<0)return!1;this.from.length&&this.finishChunk(!0),this.setMaxPoint=Math.max(this.setMaxPoint,t.maxPoint),this.chunks.push(t),this.chunkPos.push(e);let n=t.value.length-1;return this.last=t.value[n],this.lastFrom=t.from[n]+e,this.lastTo=t.to[n]+e,!0}finish(){return this.finishInner(ie.empty)}finishInner(e){if(this.from.length&&this.finishChunk(!1),this.chunks.length==0)return e;let t=ie.create(this.chunkPos,this.chunks,this.nextLayer?this.nextLayer.finishInner(e):e,this.setMaxPoint);return this.from=null,t}}function Tc(i,e,t){let n=new Map;for(let s of i)for(let r=0;r=this.minPoint)break}}setRangeIndex(e){if(e==this.layer.chunk[this.chunkIndex].value.length){if(this.chunkIndex++,this.skip)for(;this.chunkIndex=n&&a.push(new Rg(r,t,n,s));return a.length==1?a[0]:new Ti(a)}get startSide(){return this.value?this.value.startSide:0}goto(e,t=-1e9){for(let n of this.heap)n.goto(e,t);for(let n=this.heap.length>>1;n>=0;n--)Cr(this.heap,n);return this.next(),this}forward(e,t){for(let n of this.heap)n.forward(e,t);for(let n=this.heap.length>>1;n>=0;n--)Cr(this.heap,n);(this.to-e||this.value.endSide-t)<0&&this.next()}next(){if(this.heap.length==0)this.from=this.to=1e9,this.value=null,this.rank=-1;else{let e=this.heap[0];this.from=e.from,this.to=e.to,this.value=e.value,this.rank=e.rank,e.value&&e.next(),Cr(this.heap,0)}}}function Cr(i,e){for(let t=i[e];;){let n=(e<<1)+1;if(n>=i.length)break;let a=i[n];if(n+1=0&&(a=i[n+1],n++),t.compare(a)<0)break;i[n]=t,i[e]=a,e=n}}class q1{constructor(e,t,n){this.minPoint=n,this.active=[],this.activeTo=[],this.activeRank=[],this.minActive=-1,this.point=null,this.pointFrom=0,this.pointRank=0,this.to=-1e9,this.endSide=0,this.openStart=-1,this.cursor=Ti.from(e,t,n)}goto(e,t=-1e9){return this.cursor.goto(e,t),this.active.length=this.activeTo.length=this.activeRank.length=0,this.minActive=-1,this.to=e,this.endSide=t,this.openStart=-1,this.next(),this}forward(e,t){for(;this.minActive>-1&&(this.activeTo[this.minActive]-e||this.active[this.minActive].endSide-t)<0;)this.removeActive(this.minActive);this.cursor.forward(e,t)}removeActive(e){ga(this.active,e),ga(this.activeTo,e),ga(this.activeRank,e),this.minActive=Ac(this.active,this.activeTo)}addActive(e){let t=0,{value:n,to:a,rank:s}=this.cursor;for(;t0;)t++;pa(this.active,t,n),pa(this.activeTo,t,a),pa(this.activeRank,t,s),e&&pa(e,t,this.cursor.from),this.minActive=Ac(this.active,this.activeTo)}next(){let e=this.to,t=this.point;this.point=null;let n=this.openStart<0?[]:null;for(;;){let a=this.minActive;if(a>-1&&(this.activeTo[a]-this.cursor.from||this.active[a].endSide-this.cursor.startSide)<0){if(this.activeTo[a]>e){this.to=this.activeTo[a],this.endSide=this.active[a].endSide;break}this.removeActive(a),n&&ga(n,a)}else if(this.cursor.value)if(this.cursor.from>e){this.to=this.cursor.from,this.endSide=this.cursor.startSide;break}else{let s=this.cursor.value;if(!s.point)this.addActive(n),this.cursor.next();else if(t&&this.cursor.to==this.to&&this.cursor.from=0&&n[a]=0&&!(this.activeRank[n]e||this.activeTo[n]==e&&this.active[n].endSide>=this.point.endSide)&&t.push(this.active[n]);return t.reverse()}openEnd(e){let t=0;for(let n=this.activeTo.length-1;n>=0&&this.activeTo[n]>e;n--)t++;return t}}function _c(i,e,t,n,a,s){i.goto(e),t.goto(n);let r=n+a,o=n,l=n-e,u=!!s.boundChange;for(let c=!1;;){let m=i.to+l-t.to,d=m||i.endSide-t.endSide,h=d<0?i.to+l:t.to,g=Math.min(h,r);if(i.point||t.point?(i.point&&t.point&&f0(i.point,t.point)&&Xo(i.activeForPoint(i.to),t.activeForPoint(t.to))||s.comparePoint(o,g,i.point,t.point),c=!1):(c&&(s.boundChange(o),c=!1),g>o&&!Xo(i.active,t.active)&&s.compareRange(o,g,i.active,t.active),u&&gr)break;o=h,d<=0&&i.next(),d>=0&&t.next()}}function Xo(i,e){if(i.length!=e.length)return!1;for(let t=0;t=e;n--)i[n+1]=i[n];i[e]=t}function Ac(i,e){let t=-1,n=1e9;for(let a=0;a=e)return a;if(a==i.length)break;s+=i.charCodeAt(a)==9?t-s%t:1,a=rt(i,a)}return i.length}const Ko="ͼ",Oc=typeof Symbol>"u"?"__"+Ko:Symbol.for(Ko),el=typeof Symbol>"u"?"__styleSet"+Math.floor(Math.random()*1e8):Symbol("styleSet"),Cc=typeof globalThis<"u"?globalThis:typeof window<"u"?window:{};class Mn{constructor(e,t){this.rules=[];let{finish:n}=t||{};function a(r){return/^@/.test(r)?[r]:r.split(/,\s*/)}function s(r,o,l,u){let c=[],m=/^@(\w+)\b/.exec(r[0]),d=m&&m[1]=="keyframes";if(m&&o==null)return l.push(r[0]+";");for(let h in o){let g=o[h];if(/&/.test(h))s(h.split(/,\s*/).map(f=>r.map(b=>f.replace(/&/,b))).reduce((f,b)=>f.concat(b)),g,l);else if(g&&typeof g=="object"){if(!m)throw new RangeError("The value of a property ("+h+") should be a primitive value.");s(a(h),g,c,d)}else g!=null&&c.push(h.replace(/_.*/,"").replace(/[A-Z]/g,f=>"-"+f.toLowerCase())+": "+g+";")}(c.length||d)&&l.push((n&&!m&&!u?r.map(n):r).join(", ")+" {"+c.join(" ")+"}")}for(let r in e)s(a(r),e[r],this.rules)}getRules(){return this.rules.join(` +`)}static newName(){let e=Cc[Oc]||1;return Cc[Oc]=e+1,Ko+e.toString(36)}static mount(e,t,n){let a=e[el],s=n&&n.nonce;a?s&&a.setNonce(s):a=new mZ(e,s),a.mount(Array.isArray(t)?t:[t],e)}}let jc=new Map;class mZ{constructor(e,t){let n=e.ownerDocument||e,a=n.defaultView;if(!e.head&&e.adoptedStyleSheets&&a.CSSStyleSheet){let s=jc.get(n);if(s)return e[el]=s;this.sheet=new a.CSSStyleSheet,jc.set(n,this)}else this.styleTag=n.createElement("style"),t&&this.styleTag.setAttribute("nonce",t);this.modules=[],e[el]=this}mount(e,t){let n=this.sheet,a=0,s=0,r=!1;for(let o=0;o-1&&(this.modules.splice(u,1),r=!0,s--,u=-1),u==-1){if(this.modules.splice(s++,0,l),r=!0,n)for(let c=0;c",191:"?",192:"~",219:"{",220:"|",221:"}",222:'"'},dZ=typeof navigator<"u"&&/Mac/.test(navigator.platform),hZ=typeof navigator<"u"&&/MSIE \d|Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);for(var Ue=0;Ue<10;Ue++)Zn[48+Ue]=Zn[96+Ue]=String(Ue);for(var Ue=1;Ue<=24;Ue++)Zn[Ue+111]="F"+Ue;for(var Ue=65;Ue<=90;Ue++)Zn[Ue]=String.fromCharCode(Ue+32),_i[Ue]=String.fromCharCode(Ue);for(var jr in Zn)_i.hasOwnProperty(jr)||(_i[jr]=Zn[jr]);function gZ(i){var e=dZ&&i.metaKey&&i.shiftKey&&!i.ctrlKey&&!i.altKey||hZ&&i.shiftKey&&i.key&&i.key.length==1||i.key=="Unidentified",t=!e&&i.key||(i.shiftKey?_i:Zn)[i.keyCode]||i.key||"Unidentified";return t=="Esc"&&(t="Escape"),t=="Del"&&(t="Delete"),t=="Left"&&(t="ArrowLeft"),t=="Up"&&(t="ArrowUp"),t=="Right"&&(t="ArrowRight"),t=="Down"&&(t="ArrowDown"),t}let ut=typeof navigator<"u"?navigator:{userAgent:"",vendor:"",platform:""},tl=typeof document<"u"?document:{documentElement:{style:{}}};const nl=/Edge\/(\d+)/.exec(ut.userAgent),Gg=/MSIE \d/.test(ut.userAgent),il=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(ut.userAgent),Xs=!!(Gg||il||nl),Pc=!Xs&&/gecko\/(\d+)/i.test(ut.userAgent),Pr=!Xs&&/Chrome\/(\d+)/.exec(ut.userAgent),Dc="webkitFontSmoothing"in tl.documentElement.style,al=!Xs&&/Apple Computer/.test(ut.vendor),Bc=al&&(/Mobile\/\w+/.test(ut.userAgent)||ut.maxTouchPoints>2);var G={mac:Bc||/Mac/.test(ut.platform),windows:/Win/.test(ut.platform),linux:/Linux|X11/.test(ut.platform),ie:Xs,ie_version:Gg?tl.documentMode||6:il?+il[1]:nl?+nl[1]:0,gecko:Pc,gecko_version:Pc?+(/Firefox\/(\d+)/.exec(ut.userAgent)||[0,0])[1]:0,chrome:!!Pr,chrome_version:Pr?+Pr[1]:0,ios:Bc,android:/Android\b/.test(ut.userAgent),webkit:Dc,webkit_version:Dc?+(/\bAppleWebKit\/(\d+)/.exec(ut.userAgent)||[0,0])[1]:0,safari:al,safari_version:al?+(/\bVersion\/(\d+(\.\d+)?)/.exec(ut.userAgent)||[0,0])[1]:0,tabSize:tl.documentElement.style.tabSize!=null?"tab-size":"-moz-tab-size"};function x0(i,e){for(let t in i)t=="class"&&e.class?e.class+=" "+i.class:t=="style"&&e.style?e.style+=";"+i.style:e[t]=i[t];return e}const vs=Object.create(null);function v0(i,e,t){if(i==e)return!0;i||(i=vs),e||(e=vs);let n=Object.keys(i),a=Object.keys(e);if(n.length-0!=a.length-0)return!1;for(let s of n)if(s!=t&&(a.indexOf(s)==-1||i[s]!==e[s]))return!1;return!0}function pZ(i,e){for(let t=i.attributes.length-1;t>=0;t--){let n=i.attributes[t].name;e[n]==null&&i.removeAttribute(n)}for(let t in e){let n=e[t];t=="style"?i.style.cssText=n:i.getAttribute(t)!=n&&i.setAttribute(t,n)}}function Mc(i,e,t){let n=!1;if(e)for(let a in e)t&&a in t||(n=!0,a=="style"?i.style.cssText="":i.removeAttribute(a));if(t)for(let a in t)e&&e[a]==t[a]||(n=!0,a=="style"?i.style.cssText=t[a]:i.setAttribute(a,t[a]));return n}function fZ(i){let e=Object.create(null);for(let t=0;t0?3e8:-4e8:t>0?1e8:-1e8,new r1(e,t,t,n,e.widget||null,!1)}static replace(e){let t=!!e.block,n,a;if(e.isBlockGap)n=-5e8,a=4e8;else{let{start:s,end:r}=Hg(e,t);n=(s?t?-3e8:-1:5e8)-1,a=(r?t?2e8:1:-6e8)+1}return new r1(e,n,a,t,e.widget||null,!0)}static line(e){return new Gi(e)}static set(e,t=!1){return ie.of(e,t)}hasHeight(){return this.widget?this.widget.estimatedHeight>-1:!1}}pe.none=ie.empty;class Ri extends pe{constructor(e){let{start:t,end:n}=Hg(e);super(t?-1:5e8,n?1:-6e8,null,e),this.tagName=e.tagName||"span",this.attrs=e.class&&e.attributes?x0(e.attributes,{class:e.class}):e.class?{class:e.class}:e.attributes||vs}eq(e){return this==e||e instanceof Ri&&this.tagName==e.tagName&&v0(this.attrs,e.attrs)}range(e,t=e){if(e>=t)throw new RangeError("Mark decorations may not be empty");return super.range(e,t)}}Ri.prototype.point=!1;class Gi extends pe{constructor(e){super(-2e8,-2e8,null,e)}eq(e){return e instanceof Gi&&this.spec.class==e.spec.class&&v0(this.spec.attributes,e.spec.attributes)}range(e,t=e){if(t!=e)throw new RangeError("Line decoration ranges must be zero-length");return super.range(e,t)}}Gi.prototype.mapMode=st.TrackBefore;Gi.prototype.point=!0;class r1 extends pe{constructor(e,t,n,a,s,r){super(t,n,s,e),this.block=a,this.isReplace=r,this.mapMode=a?t<=0?st.TrackBefore:st.TrackAfter:st.TrackDel}get type(){return this.startSide!=this.endSide?Ye.WidgetRange:this.startSide<=0?Ye.WidgetBefore:Ye.WidgetAfter}get heightRelevant(){return this.block||!!this.widget&&(this.widget.estimatedHeight>=5||this.widget.lineBreaks>0)}eq(e){return e instanceof r1&&bZ(this.widget,e.widget)&&this.block==e.block&&this.startSide==e.startSide&&this.endSide==e.endSide}range(e,t=e){if(this.isReplace&&(e>t||e==t&&this.startSide>0&&this.endSide<=0))throw new RangeError("Invalid range for replacement decoration");if(!this.isReplace&&t!=e)throw new RangeError("Widget decorations can only have zero-length ranges");return super.range(e,t)}}r1.prototype.point=!0;function Hg(i,e=!1){let{inclusiveStart:t,inclusiveEnd:n}=i;return t==null&&(t=i.inclusive),n==null&&(n=i.inclusive),{start:t??e,end:n??e}}function bZ(i,e){return i==e||!!(i&&e&&i.compare(e))}function S1(i,e,t,n=0){let a=t.length-1;a>=0&&t[a]+n>=i?t[a]=Math.max(t[a],e):t.push(i,e)}class Ai extends Bn{constructor(e,t,n){super(),this.tagName=e,this.attributes=t,this.rank=n}eq(e){return e==this||e instanceof Ai&&this.tagName==e.tagName&&v0(this.attributes,e.attributes)}static create(e){return new Ai(e.tagName,e.attributes||vs,e.rank==null?50:Math.max(0,Math.min(e.rank,100)))}static set(e,t=!1){return ie.of(e,t)}}Ai.prototype.startSide=Ai.prototype.endSide=-1;const He=i=>i.nodeType==1,j1=i=>i.nodeType==3;function Oi(i){let e;return i.nodeType==11?e=i.getSelection?i:i.ownerDocument:e=i,e.getSelection()}function sl(i,e){return e?i==e||i.contains(e.nodeType!=1?e.parentNode:e):!1}function hi(i,e){if(!e.anchorNode)return!1;try{return sl(i,e.anchorNode)}catch{return!1}}function Ga(i){return j1(i)?Ci(i,0,i.nodeValue.length).getClientRects():He(i)?i.getClientRects():[]}function gi(i,e,t,n){return t?Zc(i,e,t,n,-1)||Zc(i,e,t,n,1):!1}function Ln(i){for(var e=0;;e++)if(i=i.previousSibling,!i)return e}function ys(i){return He(i)&&/^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(i.nodeName)}function Zc(i,e,t,n,a){for(;;){if(i==t&&e==n)return!0;if(e==(a<0?0:bn(i))){if(i.nodeName=="DIV")return!1;let s=i.parentNode;if(!s||!He(s))return!1;e=Ln(i)+(a<0?0:1),i=s}else if(He(i)){if(i=i.childNodes[e+(a<0?-1:0)],He(i)&&(i.nodeName=="IMG"||i.nodeName=="BR"||i.contentEditable=="false"))return!1;e=a<0?bn(i):0}else return!1}}function bn(i){return j1(i)?i.nodeValue.length:i.childNodes.length}function ws(i,e){let{left:t,right:n}=i;if(t==n)return i;let a=e?t:n;return{left:a,right:a,top:i.top,bottom:i.bottom}}function xZ(i){let e=i.visualViewport;return e?{left:0,right:e.width,top:0,bottom:e.height}:{left:0,right:i.innerWidth,top:0,bottom:i.innerHeight}}function Vg(i,e){let t=e.width/i.offsetWidth,n=e.height/i.offsetHeight;return(t>.995&&t<1.005||!isFinite(t)||Math.abs(e.width-i.offsetWidth)<1)&&(t=1),(n>.995&&n<1.005||!isFinite(n)||Math.abs(e.height-i.offsetHeight)<1)&&(n=1),{scaleX:t,scaleY:n}}function vZ(i,e,t,n,a,s,r,o){let l=i.ownerDocument,u=l.defaultView||window;for(let c=i,m=!1;c&&!m;)if(He(c)){let d,h=c==l.body,g=1,f=1,b=!0,x=!0;if(h)d=xZ(u);else{let I=getComputedStyle(c);if(/^(fixed|sticky)$/.test(I.position)&&(m=!0),(c.scrollHeight<=c.clientHeight||!/auto|scroll/.test(I.overflowY))&&(x=!1),(c.scrollWidth<=c.clientWidth||!/auto|scroll/.test(I.overflowX))&&(b=!1),!b&&!x){c=c.assignedSlot||c.parentNode;continue}let z=c.getBoundingClientRect();({scaleX:g,scaleY:f}=Vg(c,z)),d={left:z.left,right:z.left+c.clientWidth*g,top:z.top,bottom:z.top+c.clientHeight*f}}let v=0,w=0;if(x)if(a=="nearest")e.top0&&e.bottom>d.bottom+w&&(w=e.bottom-d.bottom+r)):e.bottom>d.bottom-r&&(w=e.bottom-d.bottom+r,t<0&&e.top-w0&&e.right>d.right+v&&(v=e.right-d.right+s)):e.right>d.right-s&&(v=e.right-d.right+s,t<0&&e.leftd.bottom||e.leftd.right)&&(e={left:Math.max(e.left,d.left),right:Math.min(e.right,d.right),top:Math.max(e.top,d.top),bottom:Math.min(e.bottom,d.bottom)}),c=c.assignedSlot||c.parentNode}else if(c.nodeType==11)c=c.host;else break}function qg(i,e=!0){let t=i.ownerDocument,n=null,a=null;for(let s=i.parentNode;s&&!(s==t.body||(!e||n)&&a);)if(He(s))!a&&s.scrollHeight>s.clientHeight&&/scroll|auto/.test(getComputedStyle(s).overflowY)&&(a=s),e&&!n&&s.scrollWidth>s.clientWidth&&/scroll|auto/.test(getComputedStyle(s).overflowX)&&(n=s),s=s.assignedSlot||s.parentNode;else if(s.nodeType==11)s=s.host;else break;return{x:n,y:a}}class yZ{constructor(){this.anchorNode=null,this.anchorOffset=0,this.focusNode=null,this.focusOffset=0}eq(e){return this.anchorNode==e.anchorNode&&this.anchorOffset==e.anchorOffset&&this.focusNode==e.focusNode&&this.focusOffset==e.focusOffset}setRange(e){let{anchorNode:t,focusNode:n}=e;this.set(t,Math.min(e.anchorOffset,t?bn(t):0),n,Math.min(e.focusOffset,n?bn(n):0))}set(e,t,n,a){this.anchorNode=e,this.anchorOffset=t,this.focusNode=n,this.focusOffset=a}}function Qg(i){let e=[];for(let t=i;t;t=t.nodeType==11?t.host:t.parentNode)He(t)&&e.push({node:t,left:t.scrollLeft,top:t.scrollTop});return e}function Ug(i,e=!0){for(let{node:t,left:n,top:a}of i)e&&t.scrollTop!=a&&(t.scrollTop=a),t.scrollLeft!=n&&(t.scrollLeft=n)}let Vn=null;G.safari&&G.safari_version>=26&&(Vn=!1);function $g(i){if(i.setActive)return i.setActive();if(Vn)return i.focus(Vn);let e=Qg(i);i.focus(Vn==null?{get preventScroll(){return Vn={preventScroll:!0},!0}}:void 0),Vn||(Vn=!1,Ug(e))}let Lc;function Ci(i,e,t=e){let n=Lc||(Lc=document.createRange());return n.setEnd(i,t),n.setStart(i,e),n}function T1(i,e,t,n){let a={key:e,code:e,keyCode:t,which:t,cancelable:!0};n&&({altKey:a.altKey,ctrlKey:a.ctrlKey,shiftKey:a.shiftKey,metaKey:a.metaKey}=n);let s=new KeyboardEvent("keydown",a);s.synthetic=!0,i.dispatchEvent(s);let r=new KeyboardEvent("keyup",a);return r.synthetic=!0,i.dispatchEvent(r),s.defaultPrevented||r.defaultPrevented}function wZ(i){for(;i;){if(i&&(i.nodeType==9||i.nodeType==11&&i.host))return i;i=i.assignedSlot||i.parentNode}return null}function zZ(i,e){let t=e.focusNode,n=e.focusOffset;if(!t||e.anchorNode!=t||e.anchorOffset!=n)return!1;for(n=Math.min(n,bn(t));;)if(n){if(!He(t))return!1;let a=t.childNodes[n-1];a.contentEditable=="false"?n--:(t=a,n=bn(t))}else{if(t==i)return!0;n=Ln(t),t=t.parentNode}}function Yg(i){return i instanceof Window?i.pageYOffset>Math.max(0,i.document.documentElement.scrollHeight-i.innerHeight-4):i.scrollTop>Math.max(1,i.scrollHeight-i.clientHeight-4)}function Xg(i,e){for(let t=i,n=e;;){if(j1(t)&&n>0)return{node:t,offset:n};if(He(t)&&n>0){if(t.contentEditable=="false")return null;t=t.childNodes[n-1],n=bn(t)}else if(t.parentNode&&!ys(t))n=Ln(t),t=t.parentNode;else return null}}function Kg(i,e){for(let t=i,n=e;;){if(j1(t)&&n=t){if(o.level==n)return r;(s<0||(a!=0?a<0?o.fromt:e[s].level>o.level))&&(s=r)}}if(s<0)throw new RangeError("Index out of range");return s}}function np(i,e){if(i.length!=e.length)return!1;for(let t=0;t=0;f-=3)if(Yt[f+1]==-h){let b=Yt[f+2],x=b&2?a:b&4?b&1?s:a:0;x&&(xe[m]=xe[Yt[f]]=x),o=f;break}}else{if(Yt.length==189)break;Yt[o++]=m,Yt[o++]=d,Yt[o++]=l}else if((g=xe[m])==2||g==1){let f=g==a;l=f?0:1;for(let b=o-3;b>=0;b-=3){let x=Yt[b+2];if(x&2)break;if(f)Yt[b+2]|=2;else{if(x&4)break;Yt[b+2]|=4}}}}}function AZ(i,e,t,n){for(let a=0,s=n;a<=t.length;a++){let r=a?t[a-1].to:i,o=al;)g==b&&(g=t[--f].from,b=f?t[f-1].to:i),xe[--g]=h;l=c}else s=u,l++}}}function ol(i,e,t,n,a,s,r){let o=n%2?2:1;if(n%2==a%2)for(let l=e,u=0;ll&&r.push(new rn(l,f.from,h));let b=f.direction==P1!=!(h%2);ll(i,b?n+1:n,a,f.inner,f.from,f.to,r),l=f.to}g=f.to}else{if(g==t||(c?xe[g]!=o:xe[g]==o))break;g++}d?ol(i,l,g,n+1,a,d,r):le;){let c=!0,m=!1;if(!u||l>s[u-1].to){let f=xe[l-1];f!=o&&(c=!1,m=f==16)}let d=!c&&o==1?[]:null,h=c?n:n+1,g=l;e:for(;;)if(u&&g==s[u-1].to){if(m)break e;let f=s[--u];if(!c)for(let b=f.from,x=u;;){if(b==e)break e;if(x&&s[x-1].to==b)b=s[--x].from;else{if(xe[b-1]==o)break e;break}}if(d)d.push(f);else{f.toxe.length;)xe[xe.length]=256;let n=[],a=e==P1?0:1;return ll(i,a,a,t,0,i.length,n),n}function ip(i){return[new rn(0,i,0)]}let ap="";function CZ(i,e,t,n,a){var s;if(!i.length)return null;let r=n.head-i.from,o;if(n.head==i.from&&n.assoc<0){if(!a)return null;r=e[o=0].side(!1,t)}else if(n.head==i.to&&n.assoc>0){if(a)return null;r=e[o=e.length-1].side(!0,t)}else o=rn.find(e,r,(s=n.bidiLevel)!==null&&s!==void 0?s:-1,n.assoc);let l=e[o],u=l.side(a,t);if(r==u){let d=o+=a?1:-1;if(d<0||d>=e.length)return null;l=e[o=d],r=l.side(!a,t),u=l.side(a,t)}let c=rt(i.text,r,l.forward(a,t));(cl.to)&&(c=u),ap=i.text.slice(Math.min(r,c),Math.max(r,c));let m=o==(a?e.length-1:0)?null:e[o+(a?1:-1)];if(c==u){if(!m)return a?B.cursor(i.to,1):B.cursor(i.from,-1);if(m.level+(a?0:1)i.some(e=>e)}),PZ=V.define({combine:i=>i.some(e=>e)}),dp=V.define();class _1{constructor(e,t,n,a,s,r=!1){this.range=e,this.y=t,this.x=n,this.yMargin=a,this.xMargin=s,this.isSnapshot=r}map(e){return e.empty?this:new _1(this.range.map(e),this.y,this.x,this.yMargin,this.xMargin,this.isSnapshot)}clip(e){return this.range.to<=e.doc.length?this:new _1(B.cursor(e.doc.length),this.y,this.x,this.yMargin,this.xMargin,this.isSnapshot)}}const fa=de.define({map:(i,e)=>i.map(e)}),hp=de.define();function wt(i,e,t){let n=i.facet(lp);n.length?n[0](e):window.onerror&&window.onerror(String(e),t,void 0,void 0,e)||(t?console.error(t+":",e):console.error(e))}const dn=V.define({combine:i=>i.length?i[0]:!0});let DZ=0;const v1=V.define({combine(i){return i.filter((e,t)=>{for(let n=0;n{let l=[];return r&&l.push(Ks.of(u=>{let c=u.plugin(o);return c?r(c):pe.none})),s&&l.push(s(o)),l})}static fromClass(e,t){return Lt.define((n,a)=>new e(n,a),t)}}class Dr{constructor(e){this.spec=e,this.mustUpdate=null,this.value=null}get plugin(){return this.spec&&this.spec.plugin}update(e){if(this.value){if(this.mustUpdate){let t=this.mustUpdate;if(this.mustUpdate=null,this.value.update)try{this.value.update(t)}catch(n){if(wt(t.state,n,"CodeMirror plugin crashed"),this.value.destroy)try{this.value.destroy()}catch{}this.deactivate()}}}else if(this.spec)try{this.value=this.spec.plugin.create(e,this.spec.arg)}catch(t){wt(e.state,t,"CodeMirror plugin crashed"),this.deactivate()}return this}destroy(e){var t;if(!((t=this.value)===null||t===void 0)&&t.destroy)try{this.value.destroy()}catch(n){wt(e.state,n,"CodeMirror plugin crashed")}}deactivate(){this.spec=this.value=null}}const gp=V.define(),I0=V.define(),Ks=V.define(),pp=V.define(),k0=V.define(),Hi=V.define(),fp=V.define();function Ec(i,e){let t=i.state.facet(fp);if(!t.length)return t;let n=t.map(s=>s instanceof Function?s(i):s),a=[];return ie.spans(n,e.from,e.to,{point(){},span(s,r,o,l){let u=s-e.from,c=r-e.from,m=a;for(let d=o.length-1;d>=0;d--,l--){let h=o[d].spec.bidiIsolate,g;if(l>0&&m.length&&(g=m[m.length-1]).to==u&&g.direction==h)g.to=c,m=g.inner;else{let f={from:u,to:c,direction:h,inner:[]};m.push(f),m=f.inner}}}}),bp(e.text,a)}function bp(i,e){for(let t of e){if(t.direction==null){for(let n=t.from,a=0;n0;t--){let a=e[t-1];if(!(a.fromA>n.toA)){if(a.toAa.push(new Bt(s,r,o,l))),this.changedRanges=a}static create(e,t,n){return new zs(e,t,n)}get viewportChanged(){return(this.flags&4)>0}get viewportMoved(){return(this.flags&8)>0}get heightChanged(){return(this.flags&2)>0}get geometryChanged(){return this.docChanged||(this.flags&18)>0}get focusChanged(){return(this.flags&1)>0}get docChanged(){return!this.changes.empty}get selectionSet(){return this.transactions.some(e=>e.selection)}get empty(){return this.flags==0&&this.transactions.length==0}}const BZ=[];class Ce{constructor(e,t,n=0){this.dom=e,this.length=t,this.flags=n,this.parent=null,e.cmTile=this}get breakAfter(){return this.flags&1}get children(){return BZ}isWidget(){return!1}get isHidden(){return!1}isComposite(){return!1}isLine(){return!1}isText(){return!1}isBlock(){return!1}get domAttrs(){return null}sync(e){if(this.flags|=2,this.flags&4){this.flags&=-5;let t=this.domAttrs;t&&pZ(this.dom,t)}}toString(){return this.constructor.name+(this.children.length?`(${this.children})`:"")+(this.breakAfter?"#":"")}destroy(){this.parent=null}setDOM(e){this.dom=e,e.cmTile=this}get posAtStart(){return this.parent?this.parent.posBefore(this):0}get posAtEnd(){return this.posAtStart+this.length}posBefore(e,t=this.posAtStart){let n=t;for(let a of this.children){if(a==e)return n;n+=a.length+a.breakAfter}throw new RangeError("Invalid child in posBefore")}posAfter(e){return this.posBefore(e)+e.length}covers(e){return!0}coordsIn(e,t,n){return null}domPosFor(e,t){let n=Ln(this.dom),a=this.length?e>0:t>0;return new Gt(this.parent.dom,n+(a?1:0),e==0||e==this.length)}markDirty(e){this.flags&=-3,e&&(this.flags|=4),this.parent&&this.parent.flags&2&&this.parent.markDirty(!1)}get overrideDOMText(){return null}get root(){for(let e=this;e;e=e.parent)if(e instanceof tr)return e;return null}static get(e){return e.cmTile}}class er extends Ce{constructor(e){super(e,0),this._children=[]}isComposite(){return!0}get children(){return this._children}get lastChild(){return this.children.length?this.children[this.children.length-1]:null}append(e){this.children.push(e),e.parent=this}sync(e){if(this.flags&2)return;super.sync(e);let t=this.dom,n=null,a,s=(e==null?void 0:e.node)==t?e:null,r=0;for(let o of this.children){if(o.sync(e),r+=o.length+o.breakAfter,a=n?n.nextSibling:t.firstChild,s&&a!=o.dom&&(s.written=!0),o.dom.parentNode==t)for(;a&&a!=o.dom;)a=Wc(a);else t.insertBefore(o.dom,a);n=o.dom}for(a=n?n.nextSibling:t.firstChild,s&&a&&(s.written=!0);a;)a=Wc(a);this.length=r}}function Wc(i){let e=i.nextSibling;return i.parentNode.removeChild(i),e}class tr extends er{constructor(e,t){super(t),this.view=e}owns(e){for(;e;e=e.parent)if(e==this)return!0;return!1}isBlock(){return!0}nearest(e){for(;;){if(!e)return null;let t=Ce.get(e);if(t&&this.owns(t))return t;e=e.parentNode}}blockTiles(e){for(let t=[],n=this,a=0,s=0;;)if(a==n.children.length){if(!t.length)return;n=n.parent,n.breakAfter&&s++,a=t.pop()}else{let r=n.children[a++];if(r instanceof gn)t.push(a),n=r,a=0;else{let o=s+r.length,l=e(r,s);if(l!==void 0)return l;s=o+r.breakAfter}}}resolveBlock(e,t){let n,a=-1,s,r=-1;if(this.blockTiles((o,l)=>{let u=l+o.length;if(e>=l&&e<=u){if(o.isWidget()&&t>=-1&&t<=1){if(o.flags&32)return!0;o.flags&16&&(n=void 0)}(le||e==l&&(t>1?o.length:o.covers(-1)))&&(!s||!o.isWidget()&&s.isWidget())&&(s=o,r=e-l)}}),!n&&!s)throw new Error("No tile at position "+e);return n&&t<0||!s?{tile:n,offset:a}:{tile:s,offset:r}}}class gn extends er{constructor(e,t){super(e),this.wrapper=t}isBlock(){return!0}covers(e){return this.children.length?e<0?this.children[0].covers(-1):this.lastChild.covers(1):!1}get domAttrs(){return this.wrapper.attributes}static of(e,t){let n=new gn(t||document.createElement(e.tagName),e);return t||(n.flags|=4),n}}class D1 extends er{constructor(e,t){super(e),this.attrs=t}isLine(){return!0}static start(e,t,n){let a=new D1(t||document.createElement("div"),e);return(!t||!n)&&(a.flags|=4),a}get domAttrs(){return this.attrs}resolveInline(e,t,n=!1){let a=null,s=-1,r=null,o=-1;function l(c,m){for(let d=0,h=0;d=m&&(g.isComposite()?l(g,m-h):(!r||n&&r.isHidden&&(t>0&&!(r.flags&32)||n&&ZZ(r,g)))&&(f>m||g.flags&32&&t<=1)?(r=g,o=m-h):(h=-1)&&(a=g,s=m-h)),h=f}}l(this,e);let u=(t<0?a:r)||a||r;return u?{tile:u,offset:u==a?s:o}:null}coordsIn(e,t,n){let a=this.resolveInline(e,t,!0);return a?a.tile.coordsIn(Math.max(0,a.offset),t,n):MZ(this)}domIn(e,t){let n=this.resolveInline(e,t);if(n){let{tile:a,offset:s}=n;if(this.dom.contains(a.dom))return a.isText()?new Gt(a.dom,Math.min(a.dom.nodeValue.length,s)):a.domPosFor(s,a.flags&16?1:a.flags&32?-1:t);let r=n.tile.parent,o=!1;for(let l of r.children){if(o)return new Gt(l.dom,0);l==n.tile&&(o=!0)}}return new Gt(this.dom,0)}}function MZ(i){let e=i.dom.lastChild;if(!e)return i.dom.getBoundingClientRect();let t=Ga(e);return t[t.length-1]||null}function ZZ(i,e){let t=i.coordsIn(0,1),n=e.coordsIn(0,1);return t&&n&&n.topa&&(e=a);let s=e,r=e,o=0;e==0&&t<0||e==a&&t>=0?G.chrome||G.gecko||(e?(s--,o=1):r=0)?0:l.length-1];return G.safari&&!o&&u.width==0&&(u=Array.prototype.find.call(l,c=>c.width)||u),n==null?u:ws(u,(o?o>0:t<0)==n)}static of(e,t){let n=new $n(t||document.createTextNode(e),e);return t||(n.flags|=2),n}}class o1 extends Ce{constructor(e,t,n,a){super(e,t,a),this.widget=n}isWidget(){return!0}get isHidden(){return this.widget.isHidden}covers(e){return this.flags&48?!1:(this.flags&(e<0?64:128))>0}coordsIn(e,t){return this.coordsInWidget(e,t,!1)}coordsInWidget(e,t,n){let a=this.widget.coordsAt(this.dom,e,t);if(a)return a;if(n)return ws(this.dom.getBoundingClientRect(),this.length?e==0:t<=0);{let s=this.dom.getClientRects(),r=null;if(!s.length)return null;let o=this.flags&16?!0:this.flags&32?!1:e>0;for(let l=o?s.length-1:0;r=s[l],!(e>0?l==0:l==s.length-1||r.top0==n)}}class LZ{constructor(e){this.index=0,this.beforeBreak=!1,this.parents=[],this.tile=e}advance(e,t,n){let{tile:a,index:s,beforeBreak:r,parents:o}=this;for(;e||t>0;)if(a.isComposite())if(r){if(!e)break;n&&n.break(),e--,r=!1}else if(s==a.children.length){if(!e&&!o.length)break;n&&n.leave(a),r=!!a.breakAfter,{tile:a,index:s}=o.pop(),s++}else{let l=a.children[s],u=l.breakAfter;(t>0?l.length<=e:l.length=0;o--){let l=t.marks[o],u=a.lastChild;if(u instanceof pt&&u.mark.eq(l.mark))u.dom!=l.dom&&u.setDOM(Br(l.dom)),a=u;else{let{dom:c}=l;this.cache.reused.get(l)&&Ce.get(l.dom)&&(c=Br(l.dom));let m=pt.of(l.mark,c);a.append(m),a=m}this.cache.reused.set(l,2)}let s=Ce.get(e.text);s&&this.cache.reused.set(s,2);let r=new $n(e.text,e.text.nodeValue);r.flags|=8,this.pos=e.range.toB,a.append(r)}addInlineWidget(e,t,n){let a=this.afterWidget&&e.flags&48&&(this.afterWidget.flags&48)==(e.flags&48);a||this.flushBuffer();let s=this.ensureMarks(t,n);!a&&!(e.flags&16)&&s.append(this.getBuffer(1)),s.append(e),this.pos+=e.length,this.afterWidget=e}addMark(e,t,n){this.flushBuffer(),this.ensureMarks(t,n).append(e),this.pos+=e.length,this.afterWidget=null}addBlockWidget(e){this.getBlockPos().append(e),this.pos+=e.length,this.lastBlock=e,this.endLine()}continueWidget(e){let t=this.afterWidget||this.lastBlock;t.length+=e,this.pos+=e}addLineStart(e,t){var n;e||(e=vp);let a=D1.start(e,t||((n=this.cache.find(D1))===null||n===void 0?void 0:n.dom),!!t);this.getBlockPos().append(this.lastBlock=this.curLine=a)}addLine(e){this.getBlockPos().append(e),this.pos+=e.length,this.lastBlock=e,this.endLine()}addBreak(){this.lastBlock.flags|=1,this.endLine(),this.pos++}addLineStartIfNotCovered(e){this.blockPosCovered()||this.addLineStart(e)}ensureLine(e){this.curLine||this.addLineStart(e)}ensureMarks(e,t){var n;let a=this.curLine;for(let s=e.length-1;s>=0;s--){let r=e[s],o;if(t>0&&(o=a.lastChild)&&o instanceof pt&&o.mark.eq(r))a=o,t--;else{let l=pt.of(r,(n=this.cache.find(pt,u=>u.mark.eq(r)))===null||n===void 0?void 0:n.dom);a.append(l),a=l,t=0}}return a}endLine(){if(this.curLine){this.flushBuffer();let e=this.curLine.lastChild;(!e||!Nc(this.curLine,!1)||e.dom.nodeName!="BR"&&e.isWidget()&&!(G.ios&&Nc(this.curLine,!0)))&&this.curLine.append(this.cache.findWidget(Mr,0,32)||new o1(Mr.toDOM(),0,Mr,32)),this.curLine=this.afterWidget=null}}updateBlockWrappers(){this.wrapperPos>this.pos+1e4&&(this.blockWrappers.goto(this.pos),this.wrappers.length=0);for(let e=this.wrappers.length-1;e>=0;e--)this.wrappers[e].to=this.pos){let t=e.rank*102+e.value.rank,n=new EZ(e.from,e.to,e.value,t),a=this.wrappers.length;for(;a>0&&(this.wrappers[a-1].rank-n.rank||this.wrappers[a-1].to-n.to)<0;)a--;this.wrappers.splice(a,0,n)}this.wrapperPos=this.pos}getBlockPos(){var e;this.updateBlockWrappers();let t=this.root;for(let n of this.wrappers){let a=t.lastChild;if(n.fromr.wrapper.eq(n.wrapper)))===null||e===void 0?void 0:e.dom);t.append(s),t=s}}return t}blockPosCovered(){let e=this.lastBlock;return e!=null&&!e.breakAfter&&(!e.isWidget()||(e.flags&160)>0)}getBuffer(e){let t=2|(e<0?16:32),n=this.cache.find(Is,void 0,1);return n&&(n.flags=t),n||new Is(t)}flushBuffer(){this.afterWidget&&!(this.afterWidget.flags&32)&&(this.afterWidget.parent.append(this.getBuffer(-1)),this.afterWidget=null)}}class NZ{constructor(e){this.skipCount=0,this.text="",this.textOff=0,this.cursor=e.iter()}skip(e){this.textOff+e<=this.text.length?this.textOff+=e:(this.skipCount+=e-(this.text.length-this.textOff),this.text="",this.textOff=0)}next(e){if(this.textOff==this.text.length){let{value:a,lineBreak:s,done:r}=this.cursor.next(this.skipCount);if(this.skipCount=0,r)throw new Error("Ran out of text content when drawing inline views");this.text=a;let o=this.textOff=Math.min(e,a.length);return s?null:a.slice(0,o)}let t=Math.min(this.text.length,this.textOff+e),n=this.text.slice(this.textOff,t);return this.textOff=t,n}}const ks=[o1,D1,$n,pt,Is,gn,tr];for(let i=0;i[]),this.index=ks.map(()=>0),this.reused=new Map}add(e){let t=e.constructor.bucket,n=this.buckets[t];n.length<6?n.push(e):n[this.index[t]=(this.index[t]+1)%6]=e}find(e,t,n=2){let a=e.bucket,s=this.buckets[a],r=this.index[a];for(let o=0;o{if(this.cache.add(r),r.isComposite())return!1},enter:r=>this.cache.add(r),leave:()=>{},break:()=>{}}}run(e,t){let n=t&&this.getCompositionContext(t.text);for(let a=0,s=0,r=0;;){let o=ra){let u=l-a;this.preserve(u,!r,!o),a=l,s+=u}if(!o)break;t&&o.fromA<=t.range.fromA&&o.toA>=t.range.toA?(this.forward(o.fromA,t.range.fromA,t.range.fromA{if(r.isWidget())if(this.openWidget)this.builder.continueWidget(l-o);else{let u=l>0||o{r.isLine()?this.builder.addLineStart(r.attrs,this.cache.maybeReuse(r)):(this.cache.add(r),r instanceof pt&&a.unshift(r.mark)),this.openWidget=!1},leave:r=>{r.isLine()?a.length&&(a.length=s=0):r instanceof pt&&(a.shift(),s=Math.min(s,a.length))},break:()=>{this.builder.addBreak(),this.openWidget=!1}}),this.text.skip(e)}emit(e,t){let n=null,a=this.builder,s=-1,r=ie.spans(this.decorations,e,t,{point:(o,l,u,c,m,d)=>{if(u instanceof r1){if(this.disallowBlockEffectsFor[d]){if(u.block)throw new RangeError("Block decorations may not be specified via plugins");if(l>this.view.state.doc.lineAt(o).to)throw new RangeError("Decorations that replace line breaks may not be specified via plugins")}if(s=c.length,m>c.length)a.continueWidget(l-o);else{let h=u.widget||(u.block?B1.block:B1.inline),g=RZ(u),f=this.cache.findWidget(h,l-o,g)||o1.of(h,this.view,l-o,g);u.block?(u.startSide>0&&a.addLineStartIfNotCovered(n),a.addBlockWidget(f)):(a.ensureLine(n),a.addInlineWidget(f,c,m))}n=null}else n=GZ(n,u);l>o&&this.text.skip(l-o)},span:(o,l,u,c)=>{for(let m=o;m-1&&(this.openWidget=r>s),this.openWidget||a.addLineStartIfNotCovered(n),this.openMarks=r}forward(e,t,n=1){t-e<=10?this.old.advance(t-e,n,this.reuseWalker):(this.old.advance(5,-1,this.reuseWalker),this.old.advance(t-e-10,-1),this.old.advance(5,n,this.reuseWalker))}getCompositionContext(e){let t=[],n=null;for(let a=e.parentNode;;a=a.parentNode){let s=Ce.get(a);if(a==this.view.contentDOM)break;s instanceof pt?t.push(s):s!=null&&s.isLine()?n=s:s instanceof gn||(a.nodeName=="DIV"&&!n?n=new D1(a,vp):n||t.push(pt.of(new Ri({tagName:a.nodeName.toLowerCase(),attributes:fZ(a)}),a)))}return n?{line:n,marks:t}:null}}function Nc(i,e){let t=n=>{for(let a of n.children)if((e?a.isText():a.length)||t(a))return!0;return!1};return t(i)}function RZ(i){let e=i.isReplace?(i.startSide<0?64:0)|(i.endSide>0?128:0):i.startSide>0?32:16;return i.block&&(e|=256),e}const vp={class:"cm-line"};function GZ(i,e){let t=e.spec.attributes,n=e.spec.class;return!t&&!n||(i||(i={class:"cm-line"}),t&&x0(t,i),n&&(i.class+=" "+n)),i}function HZ(i){let e=[];for(let t=i.parents.length;t>1;t--){let n=t==i.parents.length?i.tile:i.parents[t].tile;n instanceof pt&&e.push(n.mark)}return e}function Br(i){let e=Ce.get(i);return e&&e.setDOM(i.cloneNode()),i}class B1 extends Ji{constructor(e){super(),this.tag=e}eq(e){return e.tag==this.tag}toDOM(){return document.createElement(this.tag)}updateDOM(e){return e.nodeName.toLowerCase()==this.tag}get isHidden(){return!0}}B1.inline=new B1("span");B1.block=new B1("div");const Mr=new class extends Ji{toDOM(){return document.createElement("br")}get isHidden(){return!0}get editable(){return!0}};class Fc{constructor(e){this.view=e,this.decorations=[],this.blockWrappers=[],this.dynamicDecorationMap=[!1],this.domChanged=null,this.hasComposition=null,this.editContextFormatting=pe.none,this.lastCompositionAfterCursor=!1,this.minWidth=0,this.minWidthFrom=0,this.minWidthTo=0,this.impreciseAnchor=null,this.impreciseHead=null,this.forceSelection=!1,this.lastUpdate=Date.now(),this.updateDeco(),this.tile=new tr(e,e.contentDOM),this.updateInner([new Bt(0,0,0,e.state.doc.length)],null)}update(e){var t;let n=e.changedRanges;this.minWidth>0&&n.length&&(n.every(({fromA:c,toA:m})=>mthis.minWidthTo)?(this.minWidthFrom=e.changes.mapPos(this.minWidthFrom,1),this.minWidthTo=e.changes.mapPos(this.minWidthTo,1)):this.minWidth=this.minWidthFrom=this.minWidthTo=0),this.updateEditContextFormatting(e);let a=-1;this.view.inputState.composing>=0&&!this.view.observer.editContext&&(!((t=this.domChanged)===null||t===void 0)&&t.newSel?a=this.domChanged.newSel.head:!eL(e.changes,this.hasComposition)&&!e.selectionSet&&(a=e.state.selection.main.head));let s=a>-1?qZ(this.view,e.changes,a):null;if(this.domChanged=null,this.hasComposition){let{from:c,to:m}=this.hasComposition;n=new Bt(c,m,e.changes.mapPos(c,-1),e.changes.mapPos(m,1)).addToSet(n.slice())}this.hasComposition=s?{from:s.range.fromB,to:s.range.toB}:null,(G.ie||G.chrome)&&!s&&e&&e.state.doc.lines!=e.startState.doc.lines&&(this.forceSelection=!0);let r=this.decorations,o=this.blockWrappers;this.updateDeco();let l=$Z(r,this.decorations,e.changes);l.length&&(n=Bt.extendWithRanges(n,l));let u=XZ(o,this.blockWrappers,e.changes);return u.length&&(n=Bt.extendWithRanges(n,u)),s&&!n.some(c=>c.fromA<=s.range.fromA&&c.toA>=s.range.toA)&&(n=s.range.addToSet(n.slice())),this.tile.flags&2&&n.length==0?!1:(this.updateInner(n,s),e.transactions.length&&(this.lastUpdate=Date.now()),!0)}updateInner(e,t){this.view.viewState.mustMeasureContent=!0;let{observer:n}=this.view;n.ignore(()=>{if(t||e.length){let r=this.tile,o=new JZ(this.view,r,this.blockWrappers,this.decorations,this.dynamicDecorationMap);t&&Ce.get(t.text)&&o.cache.reused.set(Ce.get(t.text),2),this.tile=o.run(e,t),cl(r,o.cache.reused)}this.tile.dom.style.height=this.view.viewState.contentHeight/this.view.scaleY+"px",this.tile.dom.style.flexBasis=this.minWidth?this.minWidth+"px":"";let s=G.chrome||G.ios?{node:n.selectionRange.focusNode,written:!1}:void 0;this.tile.sync(s),s&&(s.written||n.selectionRange.focusNode!=s.node||!this.tile.dom.contains(s.node))&&(this.forceSelection=!0),this.tile.dom.style.height=""});let a=[];if(this.view.viewport.from||this.view.viewport.to-1)&&hi(n,this.view.observer.selectionRange)&&!(a&&n.contains(a));if(!(s||t||r))return;let o=this.forceSelection;this.forceSelection=!1;let l=this.view.state.selection.main,u,c;if(l.empty?c=u=this.inlineDOMNearPos(l.anchor,l.assoc||1):(c=this.inlineDOMNearPos(l.head,l.head==l.from?1:-1),u=this.inlineDOMNearPos(l.anchor,l.anchor==l.from?1:-1)),G.gecko&&l.empty&&!this.hasComposition&&VZ(u)){let d=document.createTextNode("");this.view.observer.ignore(()=>u.node.insertBefore(d,u.node.childNodes[u.offset]||null)),u=c=new Gt(d,0),o=!0}let m=this.view.observer.selectionRange;(o||!m.focusNode||(!gi(u.node,u.offset,m.anchorNode,m.anchorOffset)||!gi(c.node,c.offset,m.focusNode,m.focusOffset))&&!this.suppressWidgetCursorChange(m,l))&&(this.view.observer.ignore(()=>{G.android&&G.chrome&&n.contains(m.focusNode)&&KZ(m.focusNode,n)&&(n.blur(),n.focus({preventScroll:!0}));let d=Oi(this.view.root);if(d)if(l.empty){if(G.gecko){let h=QZ(u.node,u.offset);if(h&&h!=3){let g=(h==1?Xg:Kg)(u.node,u.offset);g&&(u=new Gt(g.node,g.offset))}}d.collapse(u.node,u.offset),l.bidiLevel!=null&&d.caretBidiLevel!==void 0&&(d.caretBidiLevel=l.bidiLevel)}else if(d.extend){d.collapse(u.node,u.offset);try{d.extend(c.node,c.offset)}catch{}}else{let h=document.createRange();l.anchor>l.head&&([u,c]=[c,u]),h.setEnd(c.node,c.offset),h.setStart(u.node,u.offset),d.removeAllRanges(),d.addRange(h)}r&&this.view.root.activeElement==n&&(n.blur(),a&&a.focus())}),this.view.observer.setSelectionRange(u,c)),this.impreciseAnchor=u.precise?null:new Gt(m.anchorNode,m.anchorOffset),this.impreciseHead=c.precise?null:new Gt(m.focusNode,m.focusOffset)}suppressWidgetCursorChange(e,t){return this.hasComposition&&t.empty&&gi(e.focusNode,e.focusOffset,e.anchorNode,e.anchorOffset)&&this.posFromDOM(e.focusNode,e.focusOffset)==t.head}enforceCursorAssoc(){if(this.hasComposition)return;let{view:e}=this,t=e.state.selection.main,n=Oi(e.root),{anchorNode:a,anchorOffset:s}=e.observer.selectionRange;if(!n||!t.empty||!t.assoc||!n.modify)return;let r=this.lineAt(t.head,t.assoc);if(!r)return;let o=r.posAtStart;if(t.head==o||t.head==o+r.length)return;let l=this.coordsAt(t.head,-1),u=this.coordsAt(t.head,1);if(!l||!u||l.bottom>u.top)return;let c=this.domAtPos(t.head+t.assoc,t.assoc);n.collapse(c.node,c.offset),n.modify("move",t.assoc<0?"forward":"backward","lineboundary"),e.observer.readSelectionRange();let m=e.observer.selectionRange;e.docView.posFromDOM(m.anchorNode,m.anchorOffset)!=t.from&&n.collapse(a,s)}posFromDOM(e,t){let n=this.tile.nearest(e);if(!n)return this.tile.dom.compareDocumentPosition(e)&2?0:this.view.state.doc.length;let a=n.posAtStart;if(n.isComposite()){let s;if(e==n.dom)s=n.dom.childNodes[t];else{let r=bn(e)==0?0:t==0?-1:1;for(;;){let o=e.parentNode;if(o==n.dom)break;r==0&&o.firstChild!=o.lastChild&&(e==o.firstChild?r=-1:r=1),e=o}r<0?s=e:s=e.nextSibling}if(s==n.dom.firstChild)return a;for(;s&&!Ce.get(s);)s=s.nextSibling;if(!s)return a+n.length;for(let r=0,o=a;;r++){let l=n.children[r];if(l.dom==s)return o;o+=l.length+l.breakAfter}}else return n.isText()?e==n.dom?a+t:a+(t?n.length:0):a}domAtPos(e,t){let{tile:n,offset:a}=this.tile.resolveBlock(e,t);return n.isWidget()?n.domPosFor(a,t):n.domIn(a,t)}inlineDOMNearPos(e,t){let n,a=-1,s=!1,r,o=-1,l=!1;return this.tile.blockTiles((u,c)=>{if(u.isWidget()){if(u.flags&32&&c>=e)return!0;u.flags&16&&(s=!0)}else{let m=c+u.length;if(c<=e&&(n=u,a=e-c,s=m=e&&!r&&(r=u,o=e-c,l=c>e),c>e&&r)return!0}}),!n&&!r?this.domAtPos(e,t):(s&&r?n=null:l&&n&&(r=null),n&&t<0||!r?n.domIn(a,t):r.domIn(o,t))}coordsAt(e,t,n){let{tile:a,offset:s}=this.tile.resolveBlock(e,t);return a.isWidget()?a.widget instanceof Zr?null:a.coordsInWidget(s,t,!0):a.coordsIn(s,t,n)}lineAt(e,t){let{tile:n}=this.tile.resolveBlock(e,t);return n.isLine()?n:null}coordsForChar(e){let{tile:t,offset:n}=this.tile.resolveBlock(e,1);if(!t.isLine())return null;function a(s,r){if(s.isComposite())for(let o of s.children){if(o.length>=r){let l=a(o,r);if(l)return l}if(r-=o.length,r<0)break}else if(s.isText()&&rMath.max(this.view.scrollDOM.clientWidth,this.minWidth)+1,o=-1,l=this.view.textDirection==ye.LTR,u=0,c=(m,d,h)=>{for(let g=0;ga);g++){let f=m.children[g],b=d+f.length,x=f.dom.getBoundingClientRect(),{height:v}=x;if(h&&!g&&(u+=x.top-h.top),f instanceof gn)b>n&&c(f,d,x);else if(d>=n&&(u>0&&t.push(-u),t.push(v+u),u=0,r)){let w=f.dom.lastChild,I=w?Ga(w):[];if(I.length){let z=I[I.length-1],k=l?z.right-x.left:x.right-z.left;k>o&&(o=k,this.minWidth=s,this.minWidthFrom=d,this.minWidthTo=b)}}h&&g==m.children.length-1&&(u+=h.bottom-x.bottom),d=b+f.breakAfter}};return c(this.tile,0,null),t}textDirectionAt(e){let{tile:t}=this.tile.resolveBlock(e,1);return getComputedStyle(t.dom).direction=="rtl"?ye.RTL:ye.LTR}measureTextSize(){let e=this.tile.blockTiles(r=>{if(r.isLine()&&r.children.length&&r.length<=20){let o=0,l;for(let u of r.children){if(!u.isText()||/[^ -~]/.test(u.text))return;let c=Ga(u.dom);if(c.length!=1)return;o+=c[0].width,l=c[0].height}if(o)return{lineHeight:r.dom.getBoundingClientRect().height,charWidth:o/r.length,textHeight:l}}});if(e)return e;let t=document.createElement("div"),n,a,s;return t.className="cm-line",t.style.width="99999px",t.style.position="absolute",t.textContent="abc def ghi jkl mno pqr stu",this.view.observer.ignore(()=>{this.tile.dom.appendChild(t);let r=Ga(t.firstChild)[0];n=t.getBoundingClientRect().height,a=r&&r.width?r.width/27:7,s=r&&r.height?r.height:n,t.remove()}),{lineHeight:n,charWidth:a,textHeight:s}}computeBlockGapDeco(){let e=[],t=this.view.viewState;for(let n=0,a=0;;a++){let s=a==t.viewports.length?null:t.viewports[a],r=s?s.from-1:this.view.state.doc.length;if(r>n){let o=(t.lineBlockAt(r).bottom-t.lineBlockAt(n).top)/this.view.scaleY;e.push(pe.replace({widget:new Zr(o),block:!0,inclusive:!0,isBlockGap:!0}).range(n,r))}if(!s)break;n=s.to+1}return pe.set(e)}updateDeco(){let e=1,t=this.view.state.facet(Ks).map(s=>(this.dynamicDecorationMap[e++]=typeof s=="function")?s(this.view):s),n=!1,a=this.view.state.facet(k0).map((s,r)=>{let o=typeof s=="function";return o&&(n=!0),o?s(this.view):s});for(a.length&&(this.dynamicDecorationMap[e++]=n,t.push(ie.join(a))),this.decorations=[this.editContextFormatting,...t,this.computeBlockGapDeco(),this.view.viewState.lineGapDeco];etypeof s=="function"?s(this.view):s)}scrollIntoView(e){if(e.isSnapshot){let u=this.view.viewState.lineBlockAt(e.range.head);this.view.scrollDOM.scrollTop=u.top-e.yMargin,this.view.scrollDOM.scrollLeft=e.xMargin;return}for(let u of this.view.state.facet(dp))try{if(u(this.view,e.range,e))return!0}catch(c){wt(this.view.state,c,"scroll handler")}let{range:t}=e,n=this.coordsAt(t.head,t.assoc||(t.head>t.anchor?-1:1)),a;if(!n)return;!t.empty&&(a=this.coordsAt(t.anchor,t.anchor>t.head?-1:1))&&(n={left:Math.min(n.left,a.left),top:Math.min(n.top,a.top),right:Math.max(n.right,a.right),bottom:Math.max(n.bottom,a.bottom)});let s=S0(this.view),r={left:n.left-s.left,top:n.top-s.top,right:n.right+s.right,bottom:n.bottom+s.bottom},{offsetWidth:o,offsetHeight:l}=this.view.scrollDOM;if(vZ(this.view.scrollDOM,r,t.head1&&(n.top>window.visualViewport.offsetTop+window.visualViewport.height||n.bottomn.isWidget()||n.children.some(t);return t(this.tile.resolveBlock(e,1).tile)}destroy(){cl(this.tile)}}function cl(i,e){let t=e==null?void 0:e.get(i);if(t!=1){t==null&&i.destroy();for(let n of i.children)cl(n,e)}}function VZ(i){return He(i.node)&&i.node.firstChild&&(i.offset==0||i.node.childNodes[i.offset-1].contentEditable=="false")&&(i.offset==i.node.childNodes.length||i.node.childNodes[i.offset].contentEditable=="false")}function yp(i,e){let t=i.observer.selectionRange;if(!t.focusNode)return null;let n=Xg(t.focusNode,t.focusOffset),a=Kg(t.focusNode,t.focusOffset),s=n||a;if(a&&n&&a.node!=n.node){let o=Ce.get(a.node);if(!o||o.isText()&&o.text!=a.node.nodeValue)s=a;else if(i.docView.lastCompositionAfterCursor){let l=Ce.get(n.node);!l||l.isText()&&l.text!=n.node.nodeValue||(s=a)}}if(i.docView.lastCompositionAfterCursor=s!=n,!s)return null;let r=e-s.offset;return{from:r,to:r+s.node.nodeValue.length,node:s.node}}function qZ(i,e,t){let n=yp(i,t);if(!n)return null;let{node:a,from:s,to:r}=n,o=a.nodeValue;if(/[\n\r]/.test(o)||i.state.doc.sliceString(n.from,n.to)!=o)return null;let l=e.invertedDesc;return{range:new Bt(l.mapPos(s),l.mapPos(r),s,r),text:a}}function QZ(i,e){return He(i)?(e&&i.childNodes[e-1].contentEditable=="false"?1:0)|(e{ne.from&&(t=!0)}),t}class Zr extends Ji{constructor(e){super(),this.height=e}toDOM(){let e=document.createElement("div");return e.className="cm-gap",this.updateDOM(e),e}eq(e){return e.height==this.height}updateDOM(e){return e.style.height=this.height+"px",!0}get editable(){return!0}get estimatedHeight(){return this.height}ignoreEvent(){return!1}}function tL(i,e,t=1){let n=i.charCategorizer(e),a=i.doc.lineAt(e),s=e-a.from;if(a.length==0)return B.cursor(e);s==0?t=1:s==a.length&&(t=-1);let r=s,o=s;t<0?r=rt(a.text,s,!1):o=rt(a.text,s);let l=n(a.text.slice(r,o));for(;r>0;){let u=rt(a.text,r,!1);if(n(a.text.slice(u,r))!=l)break;r=u}for(;oi.defaultLineHeight*1.5){let o=i.viewState.heightOracle.textHeight,l=Math.floor((a-t.top-(i.defaultLineHeight-o)*.5)/o);s+=l*i.viewState.heightOracle.lineLength}let r=i.state.sliceDoc(t.from,t.to);return t.from+cZ(r,s,i.state.tabSize)}function ml(i,e,t){let n=i.lineBlockAt(e);if(Array.isArray(n.type)){let a;for(let s of n.type){if(s.from>e)break;if(!(s.toe)return s;(!a||s.type==Ye.Text&&(a.type!=s.type||(t<0?s.frome)))&&(a=s)}}return a||n}return n}function iL(i,e,t,n){let a=ml(i,e.head,e.assoc||-1),s=!n||a.type!=Ye.Text||!(i.lineWrapping||a.widgetLineBreaks)?null:i.coordsAtPos(e.assoc<0&&e.head>a.from?e.head-1:e.head);if(s){let r=i.dom.getBoundingClientRect(),o=i.textDirectionAt(a.from),l=i.posAndSideAtCoords({x:t==(o==ye.LTR)?r.right-1:r.left+1,y:(s.top+s.bottom)/2});if(l)return B.cursor(l.pos,l.assoc)}return B.cursor(t?a.to:a.from,t?1:-1)}function Jc(i,e,t,n){let a=i.state.doc.lineAt(e.head),s=i.bidiSpans(a),r=i.textDirectionAt(a.from);for(let o=e,l=null;;){let u=CZ(a,s,r,o,t),c=ap;if(!u){if(a.number==(t?i.state.doc.lines:1))return o;c=` +`,a=i.state.doc.line(a.number+(t?1:-1)),s=i.bidiSpans(a),u=t?B.cursor(a.from,-1):B.cursor(a.to,1)}if(l){if(!l(c))return o}else{if(!n)return u;l=n(c)}o=u}}function aL(i,e,t){let n=i.state.charCategorizer(e),a=n(t);return s=>{let r=n(s);return a==Dt.Space&&(a=r),a==r}}function sL(i,e,t,n){let a=e.head,s=t?1:-1;if(a==(t?i.state.doc.length:0))return B.cursor(a,e.assoc);let r=e.goalColumn,o,l=i.contentDOM.getBoundingClientRect(),u=i.coordsAtPos(a,e.assoc||((e.empty?t:e.head==e.from)?1:-1)),c=i.documentTop;if(u)r==null&&(r=u.left-l.left),o=s<0?u.top:u.bottom;else{let g=i.viewState.lineBlockAt(a);r==null&&(r=Math.min(l.right-l.left,i.defaultCharacterWidth*(a-g.from))),o=(s<0?g.top:g.bottom)+c}let m=l.left+r,d=i.viewState.heightOracle.textHeight>>1,h=n??d;for(let g=0;;g+=d){let f=o+(h+g)*s,b=dl(i,{x:m,y:f},!1,s);if(t?f>l.bottom:fo:v{if(e>s&&ea(i)),t.from,e.head>t.from?-1:1);return n==t.from?t:B.cursor(n,ni.viewState.docHeight)return new sn(i.state.doc.length,-1);if(u=i.elementAtHeight(l),n==null)break;if(u.type==Ye.Text){if(n<0?u.toi.viewport.to)break;let d=i.docView.coordsAt(n<0?u.from:u.to,n>0?-1:1);if(d&&(n<0?d.top<=l+s:d.bottom>=l+s))break}let m=i.viewState.heightOracle.textHeight/2;l=n>0?u.bottom+m:u.top-m}if(i.viewport.from>=u.to||i.viewport.to<=u.from){if(t)return null;if(u.type==Ye.Text){let m=nL(i,a,u,r,o);return new sn(m,m==u.from?1:-1)}}if(u.type!=Ye.Text)return l<(u.top+u.bottom)/2?new sn(u.from,1):new sn(u.to,-1);let c=i.docView.lineAt(u.from,2);return(!c||c.length!=u.length)&&(c=i.docView.lineAt(u.from,-2)),new rL(i,r,o,i.textDirectionAt(u.from)).scanTile(c,u.from)}class rL{constructor(e,t,n,a){this.view=e,this.x=t,this.y=n,this.baseDir=a,this.line=null,this.spans=null}bidiSpansAt(e){return(!this.line||this.line.from>e||this.line.to1||n.length&&(n[0].level!=this.baseDir||n[0].to+a.from>1;t:if(r.has(f)){for(let v=1;v=s&&(w-=g),!r.has(w)){f=w;break t}}break e}r.add(f);let b=t(f),x=0;if(b)for(let v=0;v1))if(w.bottomthis.y)(!u||u.top>w.top)&&(u=w),x=-1;else{let I=w.left>this.x?this.x-w.left:w.right(g+g+f)/3)return this.y=l.bottom-1,this.scan(e,t,!0);if(u&&u.top<(g+f+f)/3)return this.y=u.top+1,this.scan(e,t,!0)}let h=(o?this.dirAt(e[c],1):this.baseDir)==ye.LTR;return{i:c,after:this.x>(d.left+d.right)/2==h}}scanText(e,t){let n=[];for(let s=0;s{let r=n[s]-t,o=n[s+1]-t;return Ci(e.dom,r,o).getClientRects()});return a.after?new sn(n[a.i+1],-1):new sn(n[a.i],1)}scanTile(e,t){if(!e.length)return new sn(t,1);if(e.children.length==1){let o=e.children[0];if(o.isText())return this.scanText(o,t);if(o.isComposite())return this.scanTile(o,t)}let n=[t];for(let o=0,l=t;o{let l=e.children[o];return l.flags&48?null:(He(l.dom)?l.dom:Ci(l.dom,0,l.length)).getClientRects()}),s=e.children[a.i],r=n[a.i];return s.isText()?this.scanText(s,r):s.isComposite()?this.scanTile(s,r):a.after?new sn(n[a.i+1],-1):new sn(r,1)}}const f1="￿";class oL{constructor(e,t){this.points=e,this.view=t,this.text="",this.lineSeparator=t.state.facet(re.lineSeparator)}append(e){this.text+=e}lineBreak(){this.text+=f1}readRange(e,t){if(!e)return this;let n=e.parentNode;for(let a=e;;){this.findPointBefore(n,a);let s=this.text.length;this.readNode(a);let r=Ce.get(a),o=a.nextSibling;if(o==t){r!=null&&r.breakAfter&&!o&&n!=this.view.contentDOM&&this.lineBreak();break}let l=Ce.get(o);(r&&l?r.breakAfter:(r?r.breakAfter:ys(a))||ys(o)&&(a.nodeName!="BR"||r!=null&&r.isWidget())&&this.text.length>s)&&!uL(o,t)&&this.lineBreak(),a=o}return this.findPointBefore(n,t),this}readTextNode(e){let t=e.nodeValue;for(let n of this.points)n.node==e&&(n.pos=this.text.length+Math.min(n.offset,t.length));for(let n=0,a=this.lineSeparator?null:/\r\n?|\n/g;;){let s=-1,r=1,o;if(this.lineSeparator?(s=t.indexOf(this.lineSeparator,n),r=this.lineSeparator.length):(o=a.exec(t))&&(s=o.index,r=o[0].length),this.append(t.slice(n,s<0?t.length:s)),s<0)break;if(this.lineBreak(),r>1)for(let l of this.points)l.node==e&&l.pos>this.text.length&&(l.pos-=r-1);n=s+r}}readNode(e){let t=Ce.get(e),n=t&&t.overrideDOMText;if(n!=null){this.findPointInside(e,n.length);for(let a=n.iter();!a.next().done;)a.lineBreak?this.lineBreak():this.append(a.value)}else j1(e)?this.readTextNode(e):e.nodeName=="BR"?e.nextSibling&&this.lineBreak():He(e)&&this.readRange(e.firstChild,null)}findPointBefore(e,t){for(let n of this.points)n.node==e&&e.childNodes[n.offset]==t&&(n.pos=this.text.length)}findPointInside(e,t){for(let n of this.points)(j1(e)?n.node==e:e.contains(n.node))&&(n.pos=this.text.length+(lL(e,n.node,n.offset)?t:0))}}function lL(i,e,t){for(;;){if(!e||t-1;let{impreciseHead:s,impreciseAnchor:r}=e.docView,o=e.state.selection;if(e.state.readOnly&&t>-1)this.newSel=null;else if(t>-1&&(this.bounds=zp(e.docView.tile,t,n,0))){let l=s||r?[]:dL(e),u=new oL(l,e);u.readRange(this.bounds.startDOM,this.bounds.endDOM),this.text=u.text,this.newSel=hL(l,this.bounds.from)}else{let l=e.observer.selectionRange,u=s&&s.node==l.focusNode&&s.offset==l.focusOffset||!sl(e.contentDOM,l.focusNode)?o.main.head:e.docView.posFromDOM(l.focusNode,l.focusOffset),c=r&&r.node==l.anchorNode&&r.offset==l.anchorOffset||!sl(e.contentDOM,l.anchorNode)?o.main.anchor:e.docView.posFromDOM(l.anchorNode,l.anchorOffset),m=e.viewport;if((G.ios||G.chrome)&&u!=c&&Math.min(u,c)<=o.main.from&&Math.max(u,c)>=o.main.to&&(m.from>0||m.to-1&&o.ranges.length>1)this.newSel=o.replaceRange(B.range(c,u));else if(e.lineWrapping&&c==u&&!(o.main.empty&&o.main.head==u)&&e.inputState.lastTouchTime>Date.now()-100){let d=e.coordsAtPos(u,-1),h=0;d&&(h=e.inputState.lastTouchY<=d.bottom?-1:1),this.newSel=B.create([B.cursor(u,h)])}else this.newSel=B.single(c,u)}}}function zp(i,e,t,n){if(i.isComposite()){let a=-1,s=-1,r=-1,o=-1;for(let l=0,u=n,c=n;lt)return zp(m,e,t,u);if(d>=e&&a==-1&&(a=l,s=u),u>t&&m.dom.parentNode==i.dom){r=l,o=c;break}c=d,u=d+m.breakAfter}return{from:s,to:o<0?n+i.length:o,startDOM:(a?i.children[a-1].dom.nextSibling:null)||i.dom.firstChild,endDOM:r=0?i.children[r].dom:null}}else return i.isText()?{from:n,to:n+i.length,startDOM:i.dom,endDOM:i.dom.nextSibling}:null}function Ip(i,e){let t,{newSel:n}=e,{state:a}=i,s=a.selection.main,r=i.inputState.lastKeyTime>Date.now()-100?i.inputState.lastKeyCode:-1;if(e.bounds){let{from:o,to:l}=e.bounds,u=s.from,c=null;(r===8||G.android&&e.text.length=o&&s.to<=l&&(e.typeOver||m!=e.text)&&m.slice(0,s.from-o)==e.text.slice(0,s.from-o)&&m.slice(s.to-o)==e.text.slice(d=e.text.length-(m.length-(s.to-o)))?t={from:s.from,to:s.to,insert:oe.of(e.text.slice(s.from-o,d).split(f1))}:(h=kp(m,e.text,u-o,c))&&(G.chrome&&r==13&&h.toB==h.from+2&&e.text.slice(h.from,h.toB)==f1+f1&&h.toB--,t={from:o+h.from,to:o+h.toA,insert:oe.of(e.text.slice(h.from,h.toB).split(f1))})}else n&&(!i.hasFocus&&a.facet(dn)||hl(n,s))&&(n=null);if(!t&&!n)return!1;if((G.mac||G.android)&&t&&t.from==t.to&&t.from==s.head-1&&/^\. ?$/.test(t.insert.toString())&&i.contentDOM.getAttribute("autocorrect")=="off"?(n&&t.insert.length==2&&(n=B.single(n.main.anchor-1,n.main.head-1)),t={from:t.from,to:t.to,insert:oe.of([t.insert.toString().replace("."," ")])}):a.doc.lineAt(s.from).toDate.now()-50?t={from:s.from,to:s.to,insert:a.toText(i.inputState.insertingText)}:G.chrome&&t&&t.from==t.to&&t.from==s.head&&t.insert.toString()==` + `&&i.lineWrapping&&(n&&(n=B.single(n.main.anchor-1,n.main.head-1)),t={from:s.from,to:s.to,insert:oe.of([" "])}),t)return T0(i,t,n,r);if(n&&!hl(n,s)){let o=!1,l="select";return i.inputState.lastSelectionTime>Date.now()-50&&(i.inputState.lastSelectionOrigin=="select"&&(o=!0),l=i.inputState.lastSelectionOrigin,l=="select.pointer"&&(n=wp(a.facet(Hi).map(u=>u(i)),n))),i.dispatch({selection:n,scrollIntoView:o,userEvent:l}),!0}else return!1}function T0(i,e,t,n=-1){if(G.ios&&i.inputState.flushIOSKey(e))return!0;let a=i.state.selection.main;if(G.android&&(e.to==a.to&&(e.from==a.from||e.from==a.from-1&&i.state.sliceDoc(e.from,a.from)==" ")&&e.insert.length==1&&e.insert.lines==2&&T1(i.contentDOM,"Enter",13)||(e.from==a.from-1&&e.to==a.to&&e.insert.length==0||n==8&&e.insert.lengtha.head)&&T1(i.contentDOM,"Backspace",8)||e.from==a.from&&e.to==a.to+1&&e.insert.length==0&&T1(i.contentDOM,"Delete",46)))return!0;let s=e.insert.toString();i.inputState.composing>=0&&i.inputState.composing++;let r,o=()=>r||(r=mL(i,e,t));return i.state.facet(up).some(l=>l(i,e.from,e.to,s,o))||i.dispatch(o()),!0}function mL(i,e,t){let n,a=i.state,s=a.selection.main,r=-1;if(e.from==e.to&&e.froms.to){let l=e.fromm(i)),u,l);e.from==c&&(r=c)}if(r>-1)n={changes:e,selection:B.cursor(e.from+e.insert.length,-1)};else if(e.from>=s.from&&e.to<=s.to&&e.to-e.from>=(s.to-s.from)/3&&(!t||t.main.empty&&t.main.from==e.from+e.insert.length)&&i.inputState.composing<0){let l=s.frome.to?a.sliceDoc(e.to,s.to):"";n=a.replaceSelection(i.state.toText(l+e.insert.sliceString(0,void 0,i.state.lineBreak)+u))}else{let l=a.changes(e),u=t&&t.main.to<=l.newLength?t.main:void 0;if(a.selection.ranges.length>1&&(i.inputState.composing>=0||i.inputState.compositionPendingChange)&&e.to<=s.to+10&&e.to>=s.to-10){let c=i.state.sliceDoc(e.from,e.to),m,d=t&&yp(i,t.main.head);if(d){let g=e.insert.length-(e.to-e.from);m={from:d.from,to:d.to-g}}else m=i.state.doc.lineAt(s.head);let h=s.to-e.to;n=a.changeByRange(g=>{if(g.from==s.from&&g.to==s.to)return{changes:l,range:u||g.map(l)};let f=g.to-h,b=f-c.length;if(i.state.sliceDoc(b,f)!=c||f>=m.from&&b<=m.to)return{range:g};let x=a.changes({from:b,to:f,insert:e.insert}),v=g.to-s.to;return{changes:x,range:u?B.range(Math.max(0,u.anchor+v),Math.max(0,u.head+v)):g.map(x)}})}else n={changes:l,selection:u&&a.selection.replaceRange(u)}}let o="input.type";return(i.composing||i.inputState.compositionPendingChange&&i.inputState.compositionEndedAt>Date.now()-50)&&(i.inputState.compositionPendingChange=!1,o+=".compose",i.inputState.compositionFirstChange&&(o+=".start",i.inputState.compositionFirstChange=!1)),a.update(n,{userEvent:o,scrollIntoView:!0})}function kp(i,e,t,n){let a=Math.min(i.length,e.length),s=0;for(;s0&&o>0&&i.charCodeAt(r-1)==e.charCodeAt(o-1);)r--,o--;if(n=="end"){let l=Math.max(0,s-Math.min(r,o));t-=r+l-s}if(r=r?s-t:0;s-=l,o=s+(o-r),r=s}else if(o=o?s-t:0;s-=l,r=s+(r-o),o=s}return{from:s,toA:r,toB:o}}function dL(i){let e=[];if(i.root.activeElement!=i.contentDOM)return e;let{anchorNode:t,anchorOffset:n,focusNode:a,focusOffset:s}=i.observer.selectionRange;return t&&(e.push(new Rc(t,n)),(a!=t||s!=n)&&e.push(new Rc(a,s))),e}function hL(i,e){if(i.length==0)return null;let t=i[0].pos,n=i.length==2?i[1].pos:t;return t<0||n<0?null:t==n?B.create([B.cursor(n+e,-1)]):B.single(t+e,n+e)}function hl(i,e){return e.head==i.main.head&&e.anchor==i.main.anchor}class gL{setSelectionOrigin(e){this.lastSelectionOrigin=e,this.lastSelectionTime=Date.now()}constructor(e){this.view=e,this.lastKeyCode=0,this.lastKeyTime=0,this.touchActive=!1,this.lastTouchTime=0,this.lastTouchX=0,this.lastTouchY=0,this.lastFocusTime=0,this.lastScrollTop=0,this.lastScrollLeft=0,this.lastWheelEvent=0,this.pendingIOSKey=void 0,this.lastIOSMomentumScroll=0,this.tabFocusMode=-1,this.lastSelectionOrigin=null,this.lastSelectionTime=0,this.lastContextMenu=0,this.scrollHandlers=[],this.handlers=Object.create(null),this.composing=-1,this.compositionFirstChange=null,this.compositionEndedAt=0,this.compositionPendingKey=!1,this.compositionPendingChange=!1,this.insertingText="",this.insertingTextAt=0,this.mouseSelection=null,this.draggedContent=null,this.handleEvent=this.handleEvent.bind(this),this.notifiedFocused=e.hasFocus,G.safari&&e.contentDOM.addEventListener("input",()=>null),G.gecko&&CL(e.contentDOM.ownerDocument)}handleEvent(e){!IL(this.view,e)||this.ignoreDuringComposition(e)||e.type=="keydown"&&this.keydown(e)||(this.view.updateState!=0?Promise.resolve().then(()=>this.runHandlers(e.type,e)):this.runHandlers(e.type,e))}runHandlers(e,t){let n=this.handlers[e];if(n){for(let a of n.observers)a(this.view,t);for(let a of n.handlers){if(t.defaultPrevented)break;if(a(this.view,t)){t.preventDefault();break}}}}ensureHandlers(e){let t=fL(e),n=this.handlers,a=this.view.contentDOM;for(let s in t)if(s!="scroll"){let r=!t[s].handlers.length,o=n[s];o&&r!=!o.handlers.length&&(a.removeEventListener(s,this.handleEvent),o=null),o||a.addEventListener(s,this.handleEvent,{passive:r})}for(let s in n)s!="scroll"&&!t[s]&&a.removeEventListener(s,this.handleEvent);this.handlers=t}keydown(e){if(this.lastKeyCode=e.keyCode,this.lastKeyTime=Date.now(),e.keyCode==9&&this.tabFocusMode>-1&&(!this.tabFocusMode||Date.now()<=this.tabFocusMode))return!0;if(this.tabFocusMode>0&&e.keyCode!=27&&Tp.indexOf(e.keyCode)<0&&(this.tabFocusMode=-1),G.android&&G.chrome&&!e.synthetic&&(e.keyCode==13||e.keyCode==8))return this.view.observer.delayAndroidKey(e.key,e.keyCode),!0;if(G.ios&&!e.synthetic&&!e.altKey&&!e.metaKey&&(Sp.some(t=>t.keyCode==e.keyCode)&&!e.ctrlKey||bL.indexOf(e.key)>-1&&e.ctrlKey)){let t={ctrlKey:e.ctrlKey,altKey:e.altKey,metaKey:e.metaKey,shiftKey:e.shiftKey};t.shiftKey&&G.ios&&!/^(off|none)$/.test(this.view.contentDOM.autocapitalize)&&pL(this.view.win)&&(t.shiftKey=!1);let n=this.pendingIOSKey={key:e.key,keyCode:e.keyCode,mods:t};return setTimeout(()=>{this.pendingIOSKey==n&&this.flushIOSKey()},50),!0}return e.keyCode!=229&&this.view.observer.forceFlush(),!1}flushIOSKey(e){let t=this.pendingIOSKey;return!t||this.view.observer.pendingRecords().length||t.key=="Enter"&&e&&e.from0?!0:G.safari&&!G.ios&&this.compositionPendingKey&&Date.now()-this.compositionEndedAt<100?(this.compositionPendingKey=!1,!0):!1}startMouseSelection(e){this.mouseSelection&&this.mouseSelection.destroy(),this.mouseSelection=e}update(e){this.view.observer.update(e),this.mouseSelection&&this.mouseSelection.update(e),this.draggedContent&&e.docChanged&&(this.draggedContent=this.draggedContent.map(e.changes)),e.transactions.length&&(this.lastKeyCode=this.lastSelectionTime=0)}destroy(){this.mouseSelection&&this.mouseSelection.destroy()}}function pL(i){return i.visualViewport?i.visualViewport.height*i.visualViewport.scale/i.document.documentElement.clientHeight<.85:!1}function Gc(i,e){return(t,n)=>{try{return e.call(i,n,t)}catch(a){wt(t.state,a)}}}function fL(i){let e=Object.create(null);function t(n){return e[n]||(e[n]={observers:[],handlers:[]})}for(let n of i){let a=n.spec,s=a&&a.plugin.domEventHandlers,r=a&&a.plugin.domEventObservers;if(s)for(let o in s){let l=s[o];l&&t(o).handlers.push(Gc(n.value,l))}if(r)for(let o in r){let l=r[o];l&&t(o).observers.push(Gc(n.value,l))}}for(let n in Vt)t(n).handlers.push(Vt[n]);for(let n in mt)t(n).observers.push(mt[n]);return e}const Sp=[{key:"Backspace",keyCode:8,inputType:"deleteContentBackward"},{key:"Enter",keyCode:13,inputType:"insertParagraph"},{key:"Enter",keyCode:13,inputType:"insertLineBreak"},{key:"Delete",keyCode:46,inputType:"deleteContentForward"}],bL="dthko",Tp=[16,17,18,20,91,92,224,225],ba=6;function xa(i){return Math.max(0,i)*.7+8}function xL(i,e){return Math.max(Math.abs(i.clientX-e.clientX),Math.abs(i.clientY-e.clientY))}class vL{constructor(e,t,n,a){this.view=e,this.startEvent=t,this.style=n,this.mustSelect=a,this.scrollSpeed={x:0,y:0},this.scrolling=-1,this.lastEvent=t,this.scrollParents=qg(e.contentDOM),this.atoms=e.state.facet(Hi).map(r=>r(e));let s=e.contentDOM.ownerDocument;s.addEventListener("mousemove",this.move=this.move.bind(this)),s.addEventListener("mouseup",this.up=this.up.bind(this)),this.extend=t.shiftKey,this.multiple=e.state.facet(re.allowMultipleSelections)&&yL(e,t),this.dragging=zL(e,t)&&Op(t)==1?null:!1}start(e){this.dragging===!1&&this.select(e)}move(e){if(e.buttons==0)return this.destroy();if(this.dragging||this.dragging==null&&xL(this.startEvent,e)<10)return;this.select(this.lastEvent=e);let t=0,n=0,a=0,s=0,r=this.view.win.innerWidth,o=this.view.win.innerHeight;this.scrollParents.x&&({left:a,right:r}=this.scrollParents.x.getBoundingClientRect()),this.scrollParents.y&&({top:s,bottom:o}=this.scrollParents.y.getBoundingClientRect());let l=S0(this.view);e.clientX-l.left<=a+ba?t=-xa(a-e.clientX):e.clientX+l.right>=r-ba&&(t=xa(e.clientX-r)),e.clientY-l.top<=s+ba?n=-xa(s-e.clientY):e.clientY+l.bottom>=o-ba&&(n=xa(e.clientY-o)),this.setScrollSpeed(t,n)}up(e){this.dragging==null&&this.select(this.lastEvent),this.dragging||e.preventDefault(),this.destroy()}destroy(){this.setScrollSpeed(0,0);let e=this.view.contentDOM.ownerDocument;e.removeEventListener("mousemove",this.move),e.removeEventListener("mouseup",this.up),this.view.inputState.mouseSelection=this.view.inputState.draggedContent=null}setScrollSpeed(e,t){this.scrollSpeed={x:e,y:t},e||t?this.scrolling<0&&(this.scrolling=setInterval(()=>this.scroll(),50)):this.scrolling>-1&&(clearInterval(this.scrolling),this.scrolling=-1)}scroll(){let{x:e,y:t}=this.scrollSpeed;e&&this.scrollParents.x&&(this.scrollParents.x.scrollLeft+=e,e=0),t&&this.scrollParents.y&&(this.scrollParents.y.scrollTop+=t,t=0),(e||t)&&this.view.win.scrollBy(e,t),this.dragging===!1&&this.select(this.lastEvent)}select(e){let{view:t}=this,n=wp(this.atoms,this.style.get(e,this.extend,this.multiple));(this.mustSelect||!n.eq(t.state.selection,this.dragging===!1))&&this.view.dispatch({selection:n,userEvent:"select.pointer"}),this.mustSelect=!1}update(e){e.transactions.some(t=>t.isUserEvent("input.type"))?this.destroy():this.style.update(e)&&setTimeout(()=>this.select(this.lastEvent),20)}}function yL(i,e){let t=i.state.facet(sp);return t.length?t[0](e):G.mac?e.metaKey:e.ctrlKey}function wL(i,e){let t=i.state.facet(rp);return t.length?t[0](e):G.mac?!e.altKey:!e.ctrlKey}function zL(i,e){let{main:t}=i.state.selection;if(t.empty)return!1;let n=Oi(i.root);if(!n||n.rangeCount==0)return!0;let a=n.getRangeAt(0).getClientRects();for(let s=0;s=e.clientX&&r.top<=e.clientY&&r.bottom>=e.clientY)return!0}return!1}function IL(i,e){if(!e.bubbles)return!0;if(e.defaultPrevented)return!1;for(let t=e.target,n;t!=i.contentDOM;t=t.parentNode)if(!t||t.nodeType==11||(n=Ce.get(t))&&n.isWidget()&&!n.isHidden&&n.widget.ignoreEvent(e))return!1;return!0}const Vt=Object.create(null),mt=Object.create(null),_p=G.ie&&G.ie_version<15||G.ios&&G.webkit_version<604;function kL(i){let e=i.dom.parentNode;if(!e)return;let t=e.appendChild(document.createElement("textarea"));t.style.cssText="position: fixed; left: -10000px; top: 10px",t.focus(),setTimeout(()=>{i.focus(),t.remove(),Ap(i,t.value)},50)}function nr(i,e,t){for(let n of i.facet(e))t=n(t,i);return t}function Ap(i,e){e=nr(i.state,w0,e);let{state:t}=i,n,a=1,s=t.toText(e),r=s.lines==t.selection.ranges.length;if(gl!=null&&t.selection.ranges.every(l=>l.empty)&&gl==s.toString()){let l=-1;n=t.changeByRange(u=>{let c=t.doc.lineAt(u.from);if(c.from==l)return{range:u};l=c.from;let m=t.toText((r?s.line(a++).text:e)+t.lineBreak);return{changes:{from:c.from,insert:m},range:B.cursor(u.from+m.length,-1)}})}else r?n=t.changeByRange(l=>{let u=s.line(a++);return{changes:{from:l.from,to:l.to,insert:u.text},range:B.cursor(l.from+u.length,-1)}}):n=t.replaceSelection(s);i.dispatch(n,{userEvent:"input.paste",scrollIntoView:!0})}mt.scroll=i=>{let e=i.inputState;e.lastScrollTop=i.scrollDOM.scrollTop,e.lastScrollLeft=i.scrollDOM.scrollLeft,G.ios&&!e.touchActive&&(e.lastIOSMomentumScroll=Date.now())};mt.wheel=mt.mousewheel=i=>{i.inputState.lastWheelEvent=Date.now()};Vt.keydown=(i,e)=>(i.inputState.setSelectionOrigin("select"),e.keyCode==27&&i.inputState.tabFocusMode!=0&&(i.inputState.tabFocusMode=Date.now()+2e3),!1);mt.touchstart=(i,e)=>{let t=i.inputState,n=e.targetTouches[0];t.touchActive=!0,t.lastTouchTime=Date.now(),n&&(t.lastTouchX=n.clientX,t.lastTouchY=n.clientY),t.setSelectionOrigin("select.pointer")};mt.touchmove=i=>{i.inputState.setSelectionOrigin("select.pointer")};mt.touchend=(i,e)=>{i.inputState.touchActive=!1};Vt.mousedown=(i,e)=>{if(i.observer.flush(),i.inputState.lastTouchTime>Date.now()-2e3)return!1;let t=null;for(let n of i.state.facet(op))if(t=n(i,e),t)break;if(!t&&e.button==0&&(t=TL(i,e)),t){let n=!i.hasFocus;i.inputState.startMouseSelection(new vL(i,e,t,n)),n&&i.observer.ignore(()=>{$g(i.contentDOM);let s=i.root.activeElement;s&&!s.contains(i.contentDOM)&&s.blur()});let a=i.inputState.mouseSelection;if(a)return a.start(e),a.dragging===!1}else i.inputState.setSelectionOrigin("select.pointer");return!1};function Hc(i,e,t,n){if(n==1)return B.cursor(e,t);if(n==2)return tL(i.state,e,t);{let a=i.docView.lineAt(e,t),s=i.state.doc.lineAt(a?a.posAtEnd:e),r=a?a.posAtStart:s.from,o=a?a.posAtEnd:s.to;return oDate.now()-400&&Math.abs(e.clientX-i.clientX)<2&&Math.abs(e.clientY-i.clientY)<2?(qc+1)%3:1}function TL(i,e){let t=i.posAndSideAtCoords({x:e.clientX,y:e.clientY},!1),n=Op(e),a=i.state.selection;return{update(s){s.docChanged&&(t.pos=s.changes.mapPos(t.pos),a=a.map(s.changes))},get(s,r,o){let l=i.posAndSideAtCoords({x:s.clientX,y:s.clientY},!1),u,c=Hc(i,l.pos,l.assoc,n);if(t.pos!=l.pos&&!r){let m=Hc(i,t.pos,t.assoc,n),d=Math.min(m.from,c.from),h=Math.max(m.to,c.to);c=d1&&(u=_L(a,l.pos))?u:o?a.addRange(c):B.create([c])}}}function _L(i,e){for(let t=0;t=e)return B.create(i.ranges.slice(0,t).concat(i.ranges.slice(t+1)),i.mainIndex==t?0:i.mainIndex-(i.mainIndex>t?1:0))}return null}Vt.dragstart=(i,e)=>{let{selection:{main:t}}=i.state;if(e.target.draggable){let a=i.docView.tile.nearest(e.target);if(a&&a.isWidget()){let s=a.posAtStart,r=s+a.length;(s>=t.to||r<=t.from)&&(t=B.undirectionalRange(s,r))}}let{inputState:n}=i;return n.mouseSelection&&(n.mouseSelection.dragging=!0),n.draggedContent=t,e.dataTransfer&&(e.dataTransfer.setData("Text",nr(i.state,z0,i.state.sliceDoc(t.from,t.to))),e.dataTransfer.effectAllowed="copyMove"),!1};Vt.dragend=i=>(i.inputState.draggedContent=null,!1);function Uc(i,e,t,n){if(t=nr(i.state,w0,t),!t)return;let a=i.posAtCoords({x:e.clientX,y:e.clientY},!1),{draggedContent:s}=i.inputState,r=n&&s&&wL(i,e)?{from:s.from,to:s.to}:null,o={from:a,insert:t},l=i.state.changes(r?[r,o]:o);i.focus(),i.dispatch({changes:l,selection:{anchor:l.mapPos(a,-1),head:l.mapPos(a,1)},userEvent:r?"move.drop":"input.drop"}),i.inputState.draggedContent=null}Vt.drop=(i,e)=>{if(!e.dataTransfer)return!1;if(i.state.readOnly)return!0;let t=e.dataTransfer.files;if(t&&t.length){let n=Array(t.length),a=0,s=()=>{++a==t.length&&Uc(i,e,n.filter(r=>r!=null).join(i.state.lineBreak),!1)};for(let r=0;r{/[\x00-\x08\x0e-\x1f]{2}/.test(o.result)||(n[r]=o.result),s()},o.readAsText(t[r])}return!0}else{let n=e.dataTransfer.getData("Text");if(n)return Uc(i,e,n,!0),!0}return!1};Vt.paste=(i,e)=>{if(i.state.readOnly)return!0;i.observer.flush();let t=_p?null:e.clipboardData;return t?(Ap(i,t.getData("text/plain")||t.getData("text/uri-list")),!0):(kL(i),!1)};function AL(i,e){let t=i.dom.parentNode;if(!t)return;let n=t.appendChild(document.createElement("textarea"));n.style.cssText="position: fixed; left: -10000px; top: 10px",n.value=e,n.focus(),n.selectionEnd=e.length,n.selectionStart=0,setTimeout(()=>{n.remove(),i.focus()},50)}function OL(i){let e=[],t=[],n=!1;for(let a of i.selection.ranges)a.empty||(e.push(i.sliceDoc(a.from,a.to)),t.push(a));if(!e.length){let a=-1;for(let{from:s}of i.selection.ranges){let r=i.doc.lineAt(s);r.number>a&&(e.push(r.text),t.push({from:r.from,to:Math.min(i.doc.length,r.to+1)})),a=r.number}n=!0}return{text:nr(i,z0,e.join(i.lineBreak)),ranges:t,linewise:n}}let gl=null;Vt.copy=Vt.cut=(i,e)=>{if(!hi(i.contentDOM,i.observer.selectionRange))return!1;let{text:t,ranges:n,linewise:a}=OL(i.state);if(!t&&!a)return!1;gl=a?t:null,e.type=="cut"&&!i.state.readOnly&&i.dispatch({changes:n,scrollIntoView:!0,userEvent:"delete.cut"});let s=_p?null:e.clipboardData;return s?(s.clearData(),s.setData("text/plain",t),!0):(AL(i,t),!1)};const Cp=Wn.define();function jp(i,e){let t=[];for(let n of i.facet(cp)){let a=n(i,e);a&&t.push(a)}return t.length?i.update({effects:t,annotations:Cp.of(!0)}):null}function Pp(i){setTimeout(()=>{let e=i.hasFocus;if(e!=i.inputState.notifiedFocused){let t=jp(i.state,e);t?i.dispatch(t):i.update([])}},10)}mt.focus=i=>{i.inputState.lastFocusTime=Date.now(),!i.scrollDOM.scrollTop&&(i.inputState.lastScrollTop||i.inputState.lastScrollLeft)&&(i.scrollDOM.scrollTop=i.inputState.lastScrollTop,i.scrollDOM.scrollLeft=i.inputState.lastScrollLeft),Pp(i)};mt.blur=i=>{i.observer.clearSelectionRange(),Pp(i)};mt.compositionstart=mt.compositionupdate=(i,e)=>{if(!i.observer.editContext&&(i.inputState.compositionFirstChange==null&&(i.inputState.compositionFirstChange=!0),i.inputState.composing<0)){let{main:t}=i.state.selection;!t.empty&&i.lineBlockAt(t.from).from!=i.lineBlockAt(t.to).from&&!i.state.readOnly&&i.dispatch({changes:i.state.selection.ranges.filter(n=>!n.empty).map(n=>({from:n.from,to:n.to})),userEvent:"input"}),i.inputState.composing=0}};mt.compositionend=i=>{i.observer.editContext||(i.inputState.composing=-1,i.inputState.compositionEndedAt=Date.now(),i.inputState.compositionPendingKey=!0,i.inputState.compositionPendingChange=i.observer.pendingRecords().length>0,i.inputState.compositionFirstChange=null,G.chrome&&G.android?i.observer.flushSoon():i.inputState.compositionPendingChange?Promise.resolve().then(()=>i.observer.flush()):setTimeout(()=>{i.inputState.composing<0&&i.docView.hasComposition&&i.update([])},50))};mt.contextmenu=i=>{i.inputState.lastContextMenu=Date.now()};Vt.beforeinput=(i,e)=>{var t,n;if((e.inputType=="insertText"||e.inputType=="insertCompositionText")&&(i.inputState.insertingText=e.data,i.inputState.insertingTextAt=Date.now()),e.inputType=="insertReplacementText"&&i.observer.editContext){let s=(t=e.dataTransfer)===null||t===void 0?void 0:t.getData("text/plain"),r=e.getTargetRanges();if(s&&r.length){let o=r[0],l=i.posAtDOM(o.startContainer,o.startOffset),u=i.posAtDOM(o.endContainer,o.endOffset);return T0(i,{from:l,to:u,insert:i.state.toText(s)},null),!0}}let a;if(G.chrome&&G.android&&(a=Sp.find(s=>s.inputType==e.inputType))&&(i.observer.delayAndroidKey(a.key,a.keyCode),a.key=="Backspace"||a.key=="Delete")){let s=((n=window.visualViewport)===null||n===void 0?void 0:n.height)||0;setTimeout(()=>{var r;(((r=window.visualViewport)===null||r===void 0?void 0:r.height)||0)>s+10&&i.hasFocus&&(i.contentDOM.blur(),i.focus())},100)}return G.ios&&e.inputType=="deleteContentForward"&&i.observer.flushSoon(),G.safari&&e.inputType=="insertText"&&i.inputState.composing>=0&&setTimeout(()=>mt.compositionend(i,e),20),!1};const $c=new Set;function CL(i){$c.has(i)||($c.add(i),i.addEventListener("copy",()=>{}),i.addEventListener("cut",()=>{}))}const Yc=["pre-wrap","normal","pre-line","break-spaces"];let M1=!1;function Xc(){M1=!1}class jL{constructor(e){this.lineWrapping=e,this.doc=oe.empty,this.heightSamples={},this.lineHeight=14,this.charWidth=7,this.textHeight=14,this.lineLength=30}heightForGap(e,t){let n=this.doc.lineAt(t).number-this.doc.lineAt(e).number+1;return this.lineWrapping&&(n+=Math.max(0,Math.ceil((t-e-n*this.lineLength*.5)/this.lineLength))),this.lineHeight*n}heightForLine(e){return this.lineWrapping?(1+Math.max(0,Math.ceil((e-this.lineLength)/Math.max(1,this.lineLength-5))))*this.lineHeight:this.lineHeight}setDoc(e){return this.doc=e,this}mustRefreshForWrapping(e){return Yc.indexOf(e)>-1!=this.lineWrapping}mustRefreshForHeights(e){let t=!1;for(let n=0;n-1,l=Math.abs(t-this.lineHeight)>.3||this.lineWrapping!=o;if(this.lineWrapping=o,this.lineHeight=t,this.charWidth=n,this.textHeight=a,this.lineLength=s,l){this.heightSamples={};for(let u=0;u0}set outdated(e){this.flags=(e?2:0)|this.flags&-3}setHeight(e){this.height!=e&&(Math.abs(this.height-e)>Ha&&(M1=!0),this.height=e)}replace(e,t,n){return ct.of(n)}decomposeLeft(e,t){t.push(this)}decomposeRight(e,t){t.push(this)}applyChanges(e,t,n,a){let s=this,r=n.doc;for(let o=a.length-1;o>=0;o--){let{fromA:l,toA:u,fromB:c,toB:m}=a[o],d=s.lineAt(l,we.ByPosNoHeight,n.setDoc(t),0,0),h=d.to>=u?d:s.lineAt(u,we.ByPosNoHeight,n,0,0);for(m+=h.to-u,u=h.to;o>0&&d.from<=a[o-1].toA;)l=a[o-1].fromA,c=a[o-1].fromB,o--,ls*2){let o=e[t-1];o.break?e.splice(--t,1,o.left,null,o.right):e.splice(--t,1,o.left,o.right),n+=1+o.break,a-=o.size}else if(s>a*2){let o=e[n];o.break?e.splice(n,1,o.left,null,o.right):e.splice(n,1,o.left,o.right),n+=2+o.break,s-=o.size}else break;else if(a=s&&r(this.lineAt(0,we.ByPos,n,a,s))}setMeasuredHeight(e){let t=e.heights[e.index++];t<0?(this.spaceAbove=-t,t=e.heights[e.index++]):this.spaceAbove=0,this.setHeight(t)}updateHeight(e,t=0,n=!1,a){return a&&a.from<=t&&a.more&&this.setMeasuredHeight(a),this.outdated=!1,this}toString(){return`block(${this.length})`}}class vt extends Dp{constructor(e,t,n){super(e,t,null),this.collapsed=0,this.widgetHeight=0,this.breaks=0,this.spaceAbove=n}mainBlock(e,t){return new Rt(t,this.length,e+this.spaceAbove,this.height-this.spaceAbove,this.breaks)}replace(e,t,n){let a=n[0];return n.length==1&&(a instanceof vt||a instanceof Qe&&a.flags&4)&&Math.abs(this.length-a.length)<10?(a instanceof Qe?a=new vt(a.length,this.height,this.spaceAbove):a.height=this.height,this.outdated||(a.outdated=!1),a):ct.of(n)}updateHeight(e,t=0,n=!1,a){return a&&a.from<=t&&a.more?this.setMeasuredHeight(a):(n||this.outdated)&&(this.spaceAbove=0,this.setHeight(Math.max(this.widgetHeight,e.heightForLine(this.length-this.collapsed))+this.breaks*e.lineHeight)),this.outdated=!1,this}toString(){return`line(${this.length}${this.collapsed?-this.collapsed:""}${this.widgetHeight?":"+this.widgetHeight:""})`}}class Qe extends ct{constructor(e){super(e,0)}heightMetrics(e,t){let n=e.doc.lineAt(t).number,a=e.doc.lineAt(t+this.length).number,s=a-n+1,r,o=0;if(e.lineWrapping){let l=Math.min(this.height,e.lineHeight*s);r=l/s,this.length>s+1&&(o=(this.height-l)/(this.length-s-1))}else r=this.height/s;return{firstLine:n,lastLine:a,perLine:r,perChar:o}}blockAt(e,t,n,a){let{firstLine:s,lastLine:r,perLine:o,perChar:l}=this.heightMetrics(t,a);if(t.lineWrapping){let u=a+(e0){let s=n[n.length-1];s instanceof Qe?n[n.length-1]=new Qe(s.length+a):n.push(null,new Qe(a-1))}if(e>0){let s=n[0];s instanceof Qe?n[0]=new Qe(e+s.length):n.unshift(new Qe(e-1),null)}return ct.of(n)}decomposeLeft(e,t){t.push(new Qe(e-1),null)}decomposeRight(e,t){t.push(null,new Qe(this.length-e-1))}updateHeight(e,t=0,n=!1,a){let s=t+this.length;if(a&&a.from<=t+this.length&&a.more){let r=[],o=Math.max(t,a.from),l=-1;for(a.from>t&&r.push(new Qe(a.from-t-1).updateHeight(e,t));o<=s&&a.more;){let c=e.doc.lineAt(o).length;r.length&&r.push(null);let m=a.heights[a.index++],d=0;m<0&&(d=-m,m=a.heights[a.index++]),l==-1?l=m:Math.abs(m-l)>=Ha&&(l=-2);let h=new vt(c,m,d);h.outdated=!1,r.push(h),o+=c+1}o<=s&&r.push(null,new Qe(s-o).updateHeight(e,o));let u=ct.of(r);return(l<0||Math.abs(u.height-this.height)>=Ha||Math.abs(l-this.heightMetrics(e,t).perLine)>=Ha)&&(M1=!0),Ss(this,u)}else(n||this.outdated)&&(this.setHeight(e.heightForGap(t,t+this.length)),this.outdated=!1);return this}toString(){return`gap(${this.length})`}}class BL extends ct{constructor(e,t,n){super(e.length+(t?1:0)+n.length,e.height+n.height,(t?1:0)|(e.outdated||n.outdated?2:0)),this.left=e,this.right=n,this.size=e.size+n.size}get break(){return this.flags&1}blockAt(e,t,n,a){let s=n+this.left.height;return eo))return u;let c=t==we.ByPosNoHeight?we.ByPosNoHeight:we.ByPos;return l?u.join(this.right.lineAt(o,c,n,r,o)):this.left.lineAt(o,c,n,a,s).join(u)}forEachLine(e,t,n,a,s,r){let o=a+this.left.height,l=s+this.left.length+this.break;if(this.break)e=l&&this.right.forEachLine(e,t,n,o,l,r);else{let u=this.lineAt(l,we.ByPos,n,a,s);e=e&&u.from<=t&&r(u),t>u.to&&this.right.forEachLine(Math.max(e,u.to+1),t,n,o,l,r)}}replace(e,t,n){let a=this.left.length+this.break;if(tthis.left.length)return this.balanced(this.left,this.right.replace(e-a,t-a,n));let s=[];e>0&&this.decomposeLeft(e,s);let r=s.length;for(let o of n)s.push(o);if(e>0&&Kc(s,r-1),t=n&&t.push(null)),e>n&&this.right.decomposeLeft(e-n,t)}decomposeRight(e,t){let n=this.left.length,a=n+this.break;if(e>=a)return this.right.decomposeRight(e-a,t);e2*t.size||t.size>2*e.size?ct.of(this.break?[e,null,t]:[e,t]):(this.left=Ss(this.left,e),this.right=Ss(this.right,t),this.setHeight(e.height+t.height),this.outdated=e.outdated||t.outdated,this.size=e.size+t.size,this.length=e.length+this.break+t.length,this)}updateHeight(e,t=0,n=!1,a){let{left:s,right:r}=this,o=t+s.length+this.break,l=null;return a&&a.from<=t+s.length&&a.more?l=s=s.updateHeight(e,t,n,a):s.updateHeight(e,t,n),a&&a.from<=o+r.length&&a.more?l=r=r.updateHeight(e,o,n,a):r.updateHeight(e,o,n),l?this.balanced(s,r):(this.height=this.left.height+this.right.height,this.outdated=!1,this)}toString(){return this.left+(this.break?" ":"-")+this.right}}function Kc(i,e){let t,n;i[e]==null&&(t=i[e-1])instanceof Qe&&(n=i[e+1])instanceof Qe&&i.splice(e-1,3,new Qe(t.length+1+n.length))}const ML=5;class _0{constructor(e,t){this.pos=e,this.oracle=t,this.nodes=[],this.lineStart=-1,this.lineEnd=-1,this.covering=null,this.writtenTo=e}get isCovered(){return this.covering&&this.nodes[this.nodes.length-1]==this.covering}span(e,t){if(this.lineStart>-1){let n=Math.min(t,this.lineEnd),a=this.nodes[this.nodes.length-1];a instanceof vt?a.length+=n-this.pos:(n>this.pos||!this.isCovered)&&this.nodes.push(new vt(n-this.pos,-1,0)),this.writtenTo=n,t>n&&(this.nodes.push(null),this.writtenTo++,this.lineStart=-1)}this.pos=t}point(e,t,n){if(e=ML)&&this.addLineDeco(a,s,r)}else t>e&&this.span(e,t);this.lineEnd>-1&&this.lineEnd-1)return;let{from:e,to:t}=this.oracle.doc.lineAt(this.pos);this.lineStart=e,this.lineEnd=t,this.writtenToe&&this.nodes.push(new vt(this.pos-e,-1,0)),this.writtenTo=this.pos}blankContent(e,t){let n=new Qe(t-e);return this.oracle.doc.lineAt(e).to==t&&(n.flags|=4),n}ensureLine(){this.enterLine();let e=this.nodes.length?this.nodes[this.nodes.length-1]:null;if(e instanceof vt)return e;let t=new vt(0,-1,0);return this.nodes.push(t),t}addBlock(e){this.enterLine();let t=e.deco;t&&t.startSide>0&&!this.isCovered&&this.ensureLine(),this.nodes.push(e),this.writtenTo=this.pos=this.pos+e.length,t&&t.endSide>0&&(this.covering=e)}addLineDeco(e,t,n){let a=this.ensureLine();a.length+=n,a.collapsed+=n,a.widgetHeight=Math.max(a.widgetHeight,e),a.breaks+=t,this.writtenTo=this.pos=this.pos+n}finish(e){let t=this.nodes.length==0?null:this.nodes[this.nodes.length-1];this.lineStart>-1&&!(t instanceof vt)&&!this.isCovered?this.nodes.push(new vt(0,-1,0)):(this.writtenTou.clientHeight||u.scrollWidth>u.clientWidth)&&c.overflow!="visible"){let m=u.getBoundingClientRect();s=Math.max(s,m.left),r=Math.min(r,m.right),o=Math.max(o,m.top),l=Math.min(u==i.parentNode?a.innerHeight:l,m.bottom)}u=c.position=="absolute"||c.position=="fixed"?u.offsetParent:u.parentNode}else if(u.nodeType==11)u=u.host;else break;return{left:s-t.left,right:Math.max(s,r)-t.left,top:o-(t.top+e),bottom:Math.max(o,l)-(t.top+e)}}function WL(i){let e=i.getBoundingClientRect(),t=i.ownerDocument.defaultView||window;return e.left0&&e.top0}function NL(i,e){let t=i.getBoundingClientRect();return{left:0,right:t.right-t.left,top:e,bottom:t.bottom-(t.top+e)}}class Er{constructor(e,t,n,a){this.from=e,this.to=t,this.size=n,this.displaySize=a}static same(e,t){if(e.length!=t.length)return!1;for(let n=0;ntypeof a!="function"&&a.class=="cm-lineWrapping");this.heightOracle=new jL(n),this.stateDeco=tm(t),this.heightMap=ct.empty().applyChanges(this.stateDeco,oe.empty,this.heightOracle.setDoc(t.doc),[new Bt(0,0,0,t.doc.length)]);for(let a=0;a<2&&(this.viewport=this.getViewport(0,null),!!this.updateForViewport());a++);this.updateViewportLines(),this.lineGaps=this.ensureLineGaps([]),this.lineGapDeco=pe.set(this.lineGaps.map(a=>a.draw(this,!1))),this.scrollParent=e.scrollDOM,this.computeVisibleRanges()}updateForViewport(){let e=[this.viewport],{main:t}=this.state.selection;for(let n=0;n<=1;n++){let a=n?t.head:t.anchor;if(!e.some(({from:s,to:r})=>a>=s&&a<=r)){let{from:s,to:r}=this.lineBlockAt(a);e.push(new va(s,r))}}return this.viewports=e.sort((n,a)=>n.from-a.from),this.updateScaler()}updateScaler(){let e=this.scaler;return this.scaler=this.heightMap.height<=7e6?pl:Ts.get(this.heightOracle,this.heightMap,this.viewports),e.eq(this.scaler)?0:2}updateViewportLines(){this.viewportLines=[],this.heightMap.forEachLine(this.viewport.from,this.viewport.to,this.heightOracle.setDoc(this.state.doc),0,0,e=>{this.viewportLines.push(ii(e,this.scaler))})}update(e,t=null){this.state=e.state;let n=this.stateDeco;this.stateDeco=tm(this.state);let a=e.changedRanges,s=Bt.extendWithRanges(a,ZL(n,this.stateDeco,e?e.changes:Re.empty(this.state.doc.length))),r=this.heightMap.height,o=this.scrolledToBottom?null:this.scrollAnchorAt(this.scrollOffset);Xc(),this.heightMap=this.heightMap.applyChanges(this.stateDeco,e.startState.doc,this.heightOracle.setDoc(this.state.doc),s),(this.heightMap.height!=r||M1)&&(e.flags|=2),o?(this.scrollAnchorPos=e.changes.mapPos(o.from,-1),this.scrollAnchorHeight=o.top):(this.scrollAnchorPos=-1,this.scrollAnchorHeight=r);let l=s.length?this.mapViewport(this.viewport,e.changes):this.viewport;(t&&(t.range.headl.to)||!this.viewportIsAppropriate(l))&&(l=this.getViewport(0,t));let u=l.from!=this.viewport.from||l.to!=this.viewport.to;this.viewport=l,e.flags|=this.updateForViewport(),(u||!e.changes.empty||e.flags&2)&&this.updateViewportLines(),(this.lineGaps.length||this.viewport.to-this.viewport.from>4e3)&&this.updateLineGaps(this.ensureLineGaps(this.mapLineGaps(this.lineGaps,e.changes))),e.flags|=this.computeVisibleRanges(e.changes),t&&(this.scrollTarget=t),!this.mustEnforceCursorAssoc&&(e.selectionSet||e.focusChanged)&&e.view.lineWrapping&&e.state.selection.main.empty&&e.state.selection.main.assoc&&!e.state.facet(PZ)&&(this.mustEnforceCursorAssoc=!0)}measure(){let{view:e}=this,t=e.contentDOM,n=window.getComputedStyle(t),a=this.heightOracle,s=n.whiteSpace;this.defaultTextDirection=n.direction=="rtl"?ye.RTL:ye.LTR;let r=this.heightOracle.mustRefreshForWrapping(s)||this.mustMeasureContent==="refresh",o=t.getBoundingClientRect(),l=r||this.mustMeasureContent||this.contentDOMHeight!=o.height;this.contentDOMHeight=o.height,this.mustMeasureContent=!1;let u=0,c=0;if(o.width&&o.height){let{scaleX:z,scaleY:k}=Vg(t,o);(z>.005&&Math.abs(this.scaleX-z)>.005||k>.005&&Math.abs(this.scaleY-k)>.005)&&(this.scaleX=z,this.scaleY=k,u|=16,r=l=!0)}let m=(parseInt(n.paddingTop)||0)*this.scaleY,d=(parseInt(n.paddingBottom)||0)*this.scaleY;(this.paddingTop!=m||this.paddingBottom!=d)&&(this.paddingTop=m,this.paddingBottom=d,u|=18),this.editorWidth!=e.scrollDOM.clientWidth&&(a.lineWrapping&&(l=!0),this.editorWidth=e.scrollDOM.clientWidth,u|=16);let h=qg(this.view.contentDOM,!1).y;h!=this.scrollParent&&(this.scrollParent=h,this.scrollAnchorHeight=-1,this.scrollOffset=0);let g=this.getScrollOffset();this.scrollOffset!=g&&(this.scrollAnchorHeight=-1,this.scrollOffset=g),this.scrolledToBottom=Yg(this.scrollParent||e.win);let f=(this.printing?NL:EL)(t,this.paddingTop),b=f.top-this.pixelViewport.top,x=f.bottom-this.pixelViewport.bottom;this.pixelViewport=f;let v=this.pixelViewport.bottom>this.pixelViewport.top&&this.pixelViewport.right>this.pixelViewport.left;if(v!=this.inView&&(this.inView=v,v&&(l=!0)),!this.inView&&!this.scrollTarget&&!WL(e.dom))return 0;let w=o.width;if((this.contentDOMWidth!=w||this.editorHeight!=e.scrollDOM.clientHeight)&&(this.contentDOMWidth=o.width,this.editorHeight=e.scrollDOM.clientHeight,u|=16),l){let z=e.docView.measureVisibleLineHeights(this.viewport);if(a.mustRefreshForHeights(z)&&(r=!0),r||a.lineWrapping&&Math.abs(w-this.contentDOMWidth)>a.charWidth){let{lineHeight:k,charWidth:T,textHeight:A}=e.docView.measureTextSize();r=k>0&&a.refresh(s,k,T,A,Math.max(5,w/T),z),r&&(e.docView.minWidth=0,u|=16)}b>0&&x>0?c=Math.max(b,x):b<0&&x<0&&(c=Math.min(b,x)),Xc();for(let k of this.viewports){let T=k.from==this.viewport.from?z:e.docView.measureVisibleLineHeights(k);this.heightMap=(r?ct.empty().applyChanges(this.stateDeco,oe.empty,this.heightOracle,[new Bt(0,0,0,e.state.doc.length)]):this.heightMap).updateHeight(a,0,r,new PL(k.from,T))}M1&&(u|=2)}let I=!this.viewportIsAppropriate(this.viewport,c)||this.scrollTarget&&(this.scrollTarget.range.headthis.viewport.to);return I&&(u&2&&(u|=this.updateScaler()),this.viewport=this.getViewport(c,this.scrollTarget),u|=this.updateForViewport()),(u&2||I)&&this.updateViewportLines(),(this.lineGaps.length||this.viewport.to-this.viewport.from>4e3)&&this.updateLineGaps(this.ensureLineGaps(r?[]:this.lineGaps,e)),u|=this.computeVisibleRanges(),this.mustEnforceCursorAssoc&&(this.mustEnforceCursorAssoc=!1,e.docView.enforceCursorAssoc()),u}get visibleTop(){return this.scaler.fromDOM(this.pixelViewport.top)}get visibleBottom(){return this.scaler.fromDOM(this.pixelViewport.bottom)}getViewport(e,t){let n=.5-Math.max(-.5,Math.min(.5,e/1e3/2)),a=this.heightMap,s=this.heightOracle,{visibleTop:r,visibleBottom:o}=this,l=new va(a.lineAt(r-n*1e3,we.ByHeight,s,0,0).from,a.lineAt(o+(1-n)*1e3,we.ByHeight,s,0,0).to);if(t){let{head:u}=t.range;if(ul.to){let c=Math.min(this.editorHeight,this.pixelViewport.bottom-this.pixelViewport.top),m=a.lineAt(u,we.ByPos,s,0,0),d;t.y=="center"?d=(m.top+m.bottom)/2-c/2:t.y=="start"||t.y=="nearest"&&u=o+Math.max(10,Math.min(n,250)))&&a>r-2*1e3&&s>1,r=a<<1;if(this.defaultTextDirection!=ye.LTR&&!n)return[];let o=[],l=(c,m,d,h)=>{if(m-cc&&xx.from>=d.from&&x.to<=d.to&&Math.abs(x.from-c)x.fromv));if(!b){if(mw.from<=m&&w.to>=m)){let w=t.moveToLineBoundary(B.cursor(m),!1,!0).head;w>c&&(m=w)}let x=this.gapSize(d,c,m,h),v=n||x<2e6?x:2e6;b=new Er(c,m,x,v)}o.push(b)},u=c=>{if(c.length2e6)for(let k of e)k.from>=c.from&&k.fromc.from&&l(c.from,h,c,m),gt.draw(this,this.heightOracle.lineWrapping))))}computeVisibleRanges(e){let t=this.stateDeco;this.lineGaps.length&&(t=t.concat(this.lineGapDeco));let n=[];ie.spans(t,this.viewport.from,this.viewport.to,{span(s,r){n.push({from:s,to:r})},point(){}},20);let a=0;if(n.length!=this.visibleRanges.length)a=12;else for(let s=0;s=this.viewport.from&&e<=this.viewport.to&&this.viewportLines.find(t=>t.from<=e&&t.to>=e)||ii(this.heightMap.lineAt(e,we.ByPos,this.heightOracle,0,0),this.scaler)}lineBlockAtHeight(e){return e>=this.viewportLines[0].top&&e<=this.viewportLines[this.viewportLines.length-1].bottom&&this.viewportLines.find(t=>t.top<=e&&t.bottom>=e)||ii(this.heightMap.lineAt(this.scaler.fromDOM(e),we.ByHeight,this.heightOracle,0,0),this.scaler)}getScrollOffset(){return this.scrollParent==this.view.scrollDOM?this.scrollParent.scrollTop*this.scaleY:(this.scrollParent?this.scrollParent.getBoundingClientRect().top:0)-this.view.contentDOM.getBoundingClientRect().top}scrollAnchorAt(e){let t=this.lineBlockAtHeight(e+12-this.paddingTop);return t.from>=this.viewport.from||this.viewportLines[0].top-e>200?t:this.viewportLines[0]}elementAtHeight(e){return ii(this.heightMap.blockAt(this.scaler.fromDOM(e),this.heightOracle,0,0),this.scaler)}get docHeight(){return this.scaler.toDOM(this.heightMap.height)}get contentHeight(){return this.docHeight+this.paddingTop+this.paddingBottom}}class va{constructor(e,t){this.from=e,this.to=t}}function JL(i,e,t){let n=[],a=i,s=0;return ie.spans(t,i,e,{span(){},point(r,o){r>a&&(n.push({from:a,to:r}),s+=r-a),a=o}},20),a=1)return e[e.length-1].to;let n=Math.floor(i*t);for(let a=0;;a++){let{from:s,to:r}=e[a],o=r-s;if(n<=o)return s+n;n-=o}}function wa(i,e){let t=0;for(let{from:n,to:a}of i.ranges){if(e<=a){t+=e-n;break}t+=a-n}return t/i.total}function RL(i,e){for(let t of i)if(e(t))return t}const pl={toDOM(i){return i},fromDOM(i){return i},scale:1,eq(i){return i==this}};function tm(i){let e=i.facet(Ks).filter(n=>typeof n!="function"),t=i.facet(k0).filter(n=>typeof n!="function");return t.length&&e.push(ie.join(t)),e}class Ts{constructor(e,t){this.scale=e,this.viewports=t}static get(e,t,n){let a=0,s=0,r=0,o=n.map(({from:u,to:c})=>{let m=t.lineAt(u,we.ByPos,e,0,0).top,d=t.lineAt(c,we.ByPos,e,0,0).bottom;return a+=d-m,{from:u,to:c,top:m,bottom:d,domTop:0,domBottom:0}});if(t.height-a<10)return pl;let l=(7e6-a)/(t.height-a);for(let u of o)u.domTop=r+(u.top-s)*l,r=u.domBottom=u.domTop+(u.bottom-u.top),s=u.bottom;return new Ts(l,o)}toDOM(e){for(let t=0,n=0,a=0;;t++){let s=tt.from==e.viewports[n].from&&t.to==e.viewports[n].to):!1}}function ii(i,e){if(e.scale==1)return i;let t=e.toDOM(i.top),n=e.toDOM(i.bottom);return new Rt(i.from,i.length,t,n-t,Array.isArray(i._content)?i._content.map(a=>ii(a,e)):i._content)}const za=V.define({combine:i=>i.join(" ")}),fl=V.define({combine:i=>i.indexOf(!0)>-1}),bl=Mn.newName(),Bp=Mn.newName(),Mp=Mn.newName(),Zp={"&light":"."+Bp,"&dark":"."+Mp};function xl(i,e,t){return new Mn(e,{finish(n){return/&/.test(n)?n.replace(/&\w*/,a=>{if(a=="&")return i;if(!t||!t[a])throw new RangeError(`Unsupported selector: ${a}`);return t[a]}):i+" "+n}})}const GL=xl("."+bl,{"&":{position:"relative !important",boxSizing:"border-box","&.cm-focused":{outline:"1px dotted #212121"},display:"flex !important",flexDirection:"column"},".cm-scroller":{display:"flex !important",alignItems:"flex-start !important",fontFamily:"monospace",lineHeight:1.4,height:"100%",overflowX:"auto",position:"relative",zIndex:0,overflowAnchor:"none"},".cm-content":{margin:0,flexGrow:2,flexShrink:0,display:"block",whiteSpace:"pre",wordWrap:"normal",boxSizing:"border-box",minHeight:"100%",padding:"4px 0",outline:"none","&[contenteditable=true]":{WebkitUserModify:"read-write-plaintext-only"}},".cm-lineWrapping":{whiteSpace_fallback:"pre-wrap",whiteSpace:"break-spaces",wordBreak:"break-word",overflowWrap:"anywhere",flexShrink:1},"&light .cm-content":{caretColor:"black"},"&dark .cm-content":{caretColor:"white"},".cm-line":{display:"block",padding:"0 2px 0 6px"},".cm-layer":{userSelect:"none",position:"absolute",left:0,top:0,contain:"size style","& > *":{position:"absolute"}},"&light .cm-selectionBackground":{background:"#d9d9d9"},"&dark .cm-selectionBackground":{background:"#222"},"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground":{background:"#d7d4f0"},"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground":{background:"#233"},".cm-cursorLayer":{pointerEvents:"none"},"&.cm-focused > .cm-scroller > .cm-cursorLayer":{animation:"steps(1) cm-blink 1.2s infinite"},"@keyframes cm-blink":{"0%":{},"50%":{opacity:0},"100%":{}},"@keyframes cm-blink2":{"0%":{},"50%":{opacity:0},"100%":{}},".cm-cursor, .cm-dropCursor":{borderLeft:"1.2px solid black",marginLeft:"-0.6px",pointerEvents:"none"},".cm-cursor":{display:"none"},"&dark .cm-cursor":{borderLeftColor:"#ddd"},".cm-selectionHandle":{backgroundColor:"currentColor",width:"1.5px"},".cm-selectionHandle-start::before, .cm-selectionHandle-end::before":{content:'""',backgroundColor:"inherit",borderRadius:"50%",width:"8px",height:"8px",position:"absolute",left:"-3.25px"},".cm-selectionHandle-start::before":{top:"-8px"},".cm-selectionHandle-end::before":{bottom:"-8px"},".cm-dropCursor":{position:"absolute"},"&.cm-focused > .cm-scroller > .cm-cursorLayer .cm-cursor":{display:"block"},".cm-iso":{unicodeBidi:"isolate"},".cm-announced":{position:"fixed",top:"-10000px"},"@media print":{".cm-announced":{display:"none"}},"&light .cm-activeLine":{backgroundColor:"#cceeff44"},"&dark .cm-activeLine":{backgroundColor:"#99eeff33"},"&light .cm-specialChar":{color:"red"},"&dark .cm-specialChar":{color:"#f78"},".cm-gutters":{flexShrink:0,display:"flex",height:"100%",boxSizing:"border-box",zIndex:200},".cm-gutters-before":{insetInlineStart:0},".cm-gutters-after":{insetInlineEnd:0},"&light .cm-gutters":{backgroundColor:"#f5f5f5",color:"#6c6c6c",border:"0px solid #ddd","&.cm-gutters-before":{borderRightWidth:"1px"},"&.cm-gutters-after":{borderLeftWidth:"1px"}},"&dark .cm-gutters":{backgroundColor:"#333338",color:"#ccc"},".cm-gutter":{display:"flex !important",flexDirection:"column",flexShrink:0,boxSizing:"border-box",minHeight:"100%",overflow:"hidden"},".cm-gutterElement":{boxSizing:"border-box"},".cm-lineNumbers .cm-gutterElement":{padding:"0 3px 0 5px",minWidth:"20px",textAlign:"right",whiteSpace:"nowrap"},"&light .cm-activeLineGutter":{backgroundColor:"#e2f2ff"},"&dark .cm-activeLineGutter":{backgroundColor:"#222227"},".cm-panels":{boxSizing:"border-box",position:"sticky",left:0,right:0,zIndex:300},"&light .cm-panels":{backgroundColor:"#f5f5f5",color:"black"},".cm-panels-top":{top:"0"},".cm-panels-bottom":{bottom:"0"},"&light .cm-panels-top":{borderBottom:"1px solid #ddd"},"&light .cm-panels-bottom":{borderTop:"1px solid #ddd"},"&dark .cm-panels":{backgroundColor:"#333338",color:"white"},".cm-dialog":{padding:"2px 19px 4px 6px",position:"relative","& label":{fontSize:"80%"}},".cm-dialog-close":{position:"absolute",top:"3px",right:"4px",backgroundColor:"inherit",border:"none",font:"inherit",fontSize:"14px",padding:"0"},".cm-tab":{display:"inline-block",overflow:"hidden",verticalAlign:"bottom"},".cm-widgetBuffer":{verticalAlign:"baseline",height:"1em",width:0,display:"inline"},".cm-placeholder":{color:"#888",display:"inline-block",verticalAlign:"top",userSelect:"none"},".cm-highlightSpace":{background:"radial-gradient(circle at 50% 55%, #aaa 20%, transparent 0) no-repeat",backgroundSize:".4em",backgroundPosition:"calc(min(50%, 0px)) center"},".cm-highlightTab":{backgroundImage:`url('data:image/svg+xml,')`,backgroundSize:"auto 100%",backgroundPosition:"right 90%",backgroundRepeat:"no-repeat"},".cm-trailingSpace":{backgroundColor:"#ff332255"},".cm-button":{verticalAlign:"middle",color:"inherit",fontSize:"70%",padding:".2em 1em",borderRadius:"1px"},"&light .cm-button":{backgroundImage:"linear-gradient(#eff1f5, #d9d9df)",border:"1px solid #888","&:active":{backgroundImage:"linear-gradient(#b4b4b4, #d0d3d6)"}},"&dark .cm-button":{backgroundImage:"linear-gradient(#393939, #111)",border:"1px solid #888","&:active":{backgroundImage:"linear-gradient(#111, #333)"}},".cm-textfield":{verticalAlign:"middle",color:"inherit",fontSize:"70%",border:"1px solid silver",padding:".2em .5em"},"&light .cm-textfield":{backgroundColor:"white"},"&dark .cm-textfield":{border:"1px solid #555",backgroundColor:"inherit"}},Zp),HL={childList:!0,characterData:!0,subtree:!0,attributes:!0,characterDataOldValue:!0},Wr=G.ie&&G.ie_version<=11;class VL{constructor(e){this.view=e,this.active=!1,this.editContext=null,this.selectionRange=new yZ,this.selectionChanged=!1,this.delayedFlush=-1,this.resizeTimeout=-1,this.queue=[],this.delayedAndroidKey=null,this.flushingAndroidKey=-1,this.lastChange=0,this.scrollTargets=[],this.intersection=null,this.resizeScroll=null,this.intersecting=!1,this.gapIntersection=null,this.gaps=[],this.printQuery=null,this.parentCheck=-1,this.dom=e.contentDOM,this.observer=new MutationObserver(t=>{for(let n of t)this.queue.push(n);(G.ie&&G.ie_version<=11||G.ios&&e.composing)&&t.some(n=>n.type=="childList"&&n.removedNodes.length||n.type=="characterData"&&n.oldValue.length>n.target.nodeValue.length)?this.flushSoon():this.flush()}),window.EditContext&&G.android&&e.constructor.EDIT_CONTEXT!==!1&&!(G.chrome&&G.chrome_version<126)&&(this.editContext=new QL(e),e.state.facet(dn)&&(e.contentDOM.editContext=this.editContext.editContext)),Wr&&(this.onCharData=t=>{this.queue.push({target:t.target,type:"characterData",oldValue:t.prevValue}),this.flushSoon()}),this.onSelectionChange=this.onSelectionChange.bind(this),this.onResize=this.onResize.bind(this),this.onPrint=this.onPrint.bind(this),this.onScroll=this.onScroll.bind(this),window.matchMedia&&(this.printQuery=window.matchMedia("print")),typeof ResizeObserver=="function"&&(this.resizeScroll=new ResizeObserver(()=>{var t;((t=this.view.docView)===null||t===void 0?void 0:t.lastUpdate){this.parentCheck<0&&(this.parentCheck=setTimeout(this.listenForScroll.bind(this),1e3)),t.length>0&&t[t.length-1].intersectionRatio>0!=this.intersecting&&(this.intersecting=!this.intersecting,this.intersecting!=this.view.inView&&this.onScrollChanged(document.createEvent("Event")))},{threshold:[0,.001]}),this.intersection.observe(this.dom),this.gapIntersection=new IntersectionObserver(t=>{t.length>0&&t[t.length-1].intersectionRatio>0&&this.onScrollChanged(document.createEvent("Event"))},{})),this.listenForScroll(),this.readSelectionRange()}onScrollChanged(e){this.view.inputState.runHandlers("scroll",e),this.intersecting&&this.view.measure()}onScroll(e){this.intersecting&&this.flush(this.pendingRecords().length>0),this.editContext&&this.view.requestMeasure(this.editContext.measureReq),this.onScrollChanged(e)}onResize(){this.resizeTimeout<0&&(this.resizeTimeout=setTimeout(()=>{this.resizeTimeout=-1,this.view.requestMeasure()},50))}onPrint(e){(e.type=="change"||!e.type)&&!e.matches||(this.view.viewState.printing=!0,this.view.measure(),setTimeout(()=>{this.view.viewState.printing=!1,this.view.requestMeasure()},500))}updateGaps(e){if(this.gapIntersection&&(e.length!=this.gaps.length||this.gaps.some((t,n)=>t!=e[n]))){this.gapIntersection.disconnect();for(let t of e)this.gapIntersection.observe(t);this.gaps=e}}onSelectionChange(e){let t=this.selectionChanged;if(!this.readSelectionRange()||this.delayedAndroidKey)return;let{view:n}=this,a=this.selectionRange;if(n.state.facet(dn)?n.root.activeElement!=this.dom:!hi(this.dom,a))return;let s=a.anchorNode&&n.docView.tile.nearest(a.anchorNode);if(s&&s.isWidget()&&s.widget.ignoreEvent(e)){t||(this.selectionChanged=!1);return}(G.ie&&G.ie_version<=11||G.android&&G.chrome)&&!n.state.selection.main.empty&&a.focusNode&&gi(a.focusNode,a.focusOffset,a.anchorNode,a.anchorOffset)?this.flushSoon():this.flush(!1)}readSelectionRange(){let{view:e}=this,t=Oi(e.root);if(!t)return!1;let n=G.safari&&e.root.nodeType==11&&e.root.activeElement==this.dom&&qL(this.view,t)||t;if(!n||this.selectionRange.eq(n))return!1;let a=hi(this.dom,n);return a&&!this.selectionChanged&&e.inputState.lastFocusTime>Date.now()-200&&e.inputState.lastTouchTime{let s=this.delayedAndroidKey;s&&(this.clearDelayedAndroidKey(),this.view.inputState.lastKeyCode=s.keyCode,this.view.inputState.lastKeyTime=Date.now(),!this.flush()&&s.force&&T1(this.dom,s.key,s.keyCode))};this.flushingAndroidKey=this.view.win.requestAnimationFrame(a)}(!this.delayedAndroidKey||e=="Enter")&&(this.delayedAndroidKey={key:e,keyCode:t,force:this.lastChange{this.delayedFlush=-1,this.flush()}))}forceFlush(){this.delayedFlush>=0&&(this.view.win.cancelAnimationFrame(this.delayedFlush),this.delayedFlush=-1),this.flush()}pendingRecords(){for(let e of this.observer.takeRecords())this.queue.push(e);return this.queue}processRecords(){let e=this.pendingRecords();e.length&&(this.queue=[]);let t=-1,n=-1,a=!1;for(let s of e){let r=this.readMutation(s);r&&(r.typeOver&&(a=!0),t==-1?{from:t,to:n}=r:(t=Math.min(r.from,t),n=Math.max(r.to,n)))}return{from:t,to:n,typeOver:a}}readChange(){let{from:e,to:t,typeOver:n}=this.processRecords(),a=this.selectionChanged&&hi(this.dom,this.selectionRange);if(e<0&&!a)return null;e>-1&&(this.lastChange=Date.now()),this.view.inputState.lastFocusTime=0,this.selectionChanged=!1;let s=new cL(this.view,e,t,n);return this.view.docView.domChanged={newSel:s.newSel?s.newSel.main:null},s}flush(e=!0){if(this.delayedFlush>=0||this.delayedAndroidKey)return!1;e&&this.readSelectionRange();let t=this.selectionChanged,n=this.readChange();if(!n)return this.view.requestMeasure(),!1;let a=this.view.state,s=Ip(this.view,n);return this.view.state==a&&(n.domChanged||t)&&this.view.update([]),s}readMutation(e){let t=this.view.docView.tile.nearest(e.target);if(!t||t.isWidget())return null;if(t.markDirty(e.type=="attributes"),e.type=="childList"){let n=nm(t,e.previousSibling||e.target.previousSibling,-1),a=nm(t,e.nextSibling||e.target.nextSibling,1);return{from:n?t.posAfter(n):t.posAtStart,to:a?t.posBefore(a):t.posAtEnd,typeOver:!1}}else return e.type=="characterData"?{from:t.posAtStart,to:t.posAtEnd,typeOver:e.target.nodeValue==e.oldValue}:null}setWindow(e){e!=this.win&&(this.removeWindowListeners(this.win),this.win=e,this.addWindowListeners(this.win))}addWindowListeners(e){e.addEventListener("resize",this.onResize),this.printQuery?this.printQuery.addEventListener?this.printQuery.addEventListener("change",this.onPrint):this.printQuery.addListener(this.onPrint):e.addEventListener("beforeprint",this.onPrint),e.addEventListener("scroll",this.onScroll),e.document.addEventListener("selectionchange",this.onSelectionChange)}removeWindowListeners(e){e.removeEventListener("scroll",this.onScroll),e.removeEventListener("resize",this.onResize),this.printQuery?this.printQuery.removeEventListener?this.printQuery.removeEventListener("change",this.onPrint):this.printQuery.removeListener(this.onPrint):e.removeEventListener("beforeprint",this.onPrint),e.document.removeEventListener("selectionchange",this.onSelectionChange)}update(e){this.editContext&&(this.editContext.update(e),e.startState.facet(dn)!=e.state.facet(dn)&&(e.view.contentDOM.editContext=e.state.facet(dn)?this.editContext.editContext:null))}destroy(){var e,t,n;this.stop(),(e=this.intersection)===null||e===void 0||e.disconnect(),(t=this.gapIntersection)===null||t===void 0||t.disconnect(),(n=this.resizeScroll)===null||n===void 0||n.disconnect();for(let a of this.scrollTargets)a.removeEventListener("scroll",this.onScroll);this.removeWindowListeners(this.win),clearTimeout(this.parentCheck),clearTimeout(this.resizeTimeout),this.win.cancelAnimationFrame(this.delayedFlush),this.win.cancelAnimationFrame(this.flushingAndroidKey),this.editContext&&(this.view.contentDOM.editContext=null,this.editContext.destroy())}}function nm(i,e,t){for(;e;){let n=Ce.get(e);if(n&&n.parent==i)return n;let a=e.parentNode;e=a!=i.dom?a:t>0?e.nextSibling:e.previousSibling}return null}function im(i,e){let t=e.startContainer,n=e.startOffset,a=e.endContainer,s=e.endOffset,r=i.docView.domAtPos(i.state.selection.main.anchor,1);return gi(r.node,r.offset,a,s)&&([t,n,a,s]=[a,s,t,n]),{anchorNode:t,anchorOffset:n,focusNode:a,focusOffset:s}}function qL(i,e){if(e.getComposedRanges){let a=e.getComposedRanges(i.root)[0];if(a)return im(i,a)}let t=null;function n(a){a.preventDefault(),a.stopImmediatePropagation(),t=a.getTargetRanges()[0]}return i.contentDOM.addEventListener("beforeinput",n,!0),i.dom.ownerDocument.execCommand("indent"),i.contentDOM.removeEventListener("beforeinput",n,!0),t?im(i,t):null}class QL{constructor(e){this.from=0,this.to=0,this.pendingContextChange=null,this.handlers=Object.create(null),this.composing=null,this.resetRange(e.state);let t=this.editContext=new window.EditContext({text:e.state.doc.sliceString(this.from,this.to),selectionStart:this.toContextPos(Math.max(this.from,Math.min(this.to,e.state.selection.main.anchor))),selectionEnd:this.toContextPos(e.state.selection.main.head)});this.handlers.textupdate=n=>{let a=e.state.selection.main,{anchor:s,head:r}=a,o=this.toEditorPos(n.updateRangeStart),l=this.toEditorPos(n.updateRangeEnd);e.inputState.composing>=0&&!this.composing&&(this.composing={contextBase:n.updateRangeStart,editorBase:o,drifted:!1});let u=l-o>n.text.length;o==this.from&&sthis.to&&(l=s);let c=kp(e.state.sliceDoc(o,l),n.text,(u?a.from:a.to)-o,u?"end":null);if(!c){let d=B.single(this.toEditorPos(n.selectionStart),this.toEditorPos(n.selectionEnd));hl(d,a)||e.dispatch({selection:d,userEvent:"select"});return}let m={from:c.from+o,to:c.toA+o,insert:oe.of(n.text.slice(c.from,c.toB).split(` +`))};if((G.mac||G.android)&&m.from==r-1&&/^\. ?$/.test(n.text)&&e.contentDOM.getAttribute("autocorrect")=="off"&&(m={from:o,to:l,insert:oe.of([n.text.replace("."," ")])}),this.pendingContextChange=m,!e.state.readOnly){let d=this.to-this.from+(m.to-m.from+m.insert.length);T0(e,m,B.single(this.toEditorPos(n.selectionStart,d),this.toEditorPos(n.selectionEnd,d)))}this.pendingContextChange&&(this.revertPending(e.state),this.setSelection(e.state)),m.from=0&&!/[\\p{Alphabetic}\\p{Number}_]/.test(t.text.slice(Math.max(0,n.updateRangeStart-1),Math.min(t.text.length,n.updateRangeStart+1)))&&this.handlers.compositionend(n)},this.handlers.characterboundsupdate=n=>{let a=[],s=null;for(let r=this.toEditorPos(n.rangeStart),o=this.toEditorPos(n.rangeEnd);r{let a=[];for(let s of n.getTextFormats()){let r=s.underlineStyle,o=s.underlineThickness;if(!/none/i.test(r)&&!/none/i.test(o)){let l=this.toEditorPos(s.rangeStart),u=this.toEditorPos(s.rangeEnd);if(l{e.inputState.composing<0&&(e.inputState.composing=0,e.inputState.compositionFirstChange=!0)},this.handlers.compositionend=()=>{if(e.inputState.composing=-1,e.inputState.compositionFirstChange=null,this.composing){let{drifted:n}=this.composing;this.composing=null,n&&this.reset(e.state)}};for(let n in this.handlers)t.addEventListener(n,this.handlers[n]);this.measureReq={read:n=>{let a=Oi(n.root);a&&a.rangeCount&&this.editContext.updateSelectionBounds(a.getRangeAt(0).getBoundingClientRect())}}}applyEdits(e){let t=0,n=!1,a=this.pendingContextChange;return e.changes.iterChanges((s,r,o,l,u)=>{if(n)return;let c=u.length-(r-s);if(a&&r>=a.to)if(a.from==s&&a.to==r&&a.insert.eq(u)){a=this.pendingContextChange=null,t+=c,this.to+=c;return}else a=null,this.revertPending(e.state);if(s+=t,r+=t,r<=this.from)this.from+=c,this.to+=c;else if(sthis.to||this.to-this.from+u.length>3e4){n=!0;return}this.editContext.updateText(this.toContextPos(s),this.toContextPos(r),u.toString()),this.to+=c}t+=c}),a&&!n&&this.revertPending(e.state),!n}update(e){let t=this.pendingContextChange,n=e.startState.selection.main;this.composing&&(this.composing.drifted||!e.changes.touchesRange(n.from,n.to)&&e.transactions.some(a=>!a.isUserEvent("input.type")&&a.changes.touchesRange(this.from,this.to)))?(this.composing.drifted=!0,this.composing.editorBase=e.changes.mapPos(this.composing.editorBase)):!this.applyEdits(e)||!this.rangeIsValid(e.state)?(this.pendingContextChange=null,this.reset(e.state)):(e.docChanged||e.selectionSet||t)&&this.setSelection(e.state),(e.geometryChanged||e.docChanged||e.selectionSet)&&e.view.requestMeasure(this.measureReq)}resetRange(e){let{head:t}=e.selection.main;this.from=Math.max(0,t-1e4),this.to=Math.min(e.doc.length,t+1e4)}reset(e){this.resetRange(e),this.editContext.updateText(0,this.editContext.text.length,e.doc.sliceString(this.from,this.to)),this.setSelection(e)}revertPending(e){let t=this.pendingContextChange;this.pendingContextChange=null,this.editContext.updateText(this.toContextPos(t.from),this.toContextPos(t.from+t.insert.length),e.doc.sliceString(t.from,t.to))}setSelection(e){let{main:t}=e.selection,n=this.toContextPos(Math.max(this.from,Math.min(this.to,t.anchor))),a=this.toContextPos(t.head);(this.editContext.selectionStart!=n||this.editContext.selectionEnd!=a)&&this.editContext.updateSelection(n,a)}rangeIsValid(e){let{head:t}=e.selection.main;return!(this.from>0&&t-this.from<500||this.to1e4*3)}toEditorPos(e,t=this.to-this.from){e=Math.min(e,t);let n=this.composing;return n&&n.drifted?n.editorBase+(e-n.contextBase):e+this.from}toContextPos(e){let t=this.composing;return t&&t.drifted?t.contextBase+(e-t.editorBase):e-this.from}destroy(){for(let e in this.handlers)this.editContext.removeEventListener(e,this.handlers[e])}}class Q{get state(){return this.viewState.state}get viewport(){return this.viewState.viewport}get visibleRanges(){return this.viewState.visibleRanges}get inView(){return this.viewState.inView}get composing(){return!!this.inputState&&this.inputState.composing>0}get compositionStarted(){return!!this.inputState&&this.inputState.composing>=0}get root(){return this._root}get win(){return this.dom.ownerDocument.defaultView||window}constructor(e={}){var t;this.plugins=[],this.pluginMap=new Map,this.editorAttrs={},this.contentAttrs={},this.bidiCache=[],this.destroyed=!1,this.updateState=2,this.measureScheduled=-1,this.measureRequests=[],this.clearAnnouncement=-1,this.contentDOM=document.createElement("div"),this.scrollDOM=document.createElement("div"),this.scrollDOM.tabIndex=-1,this.scrollDOM.className="cm-scroller",this.scrollDOM.appendChild(this.contentDOM),this.announceDOM=document.createElement("div"),this.announceDOM.className="cm-announced",this.announceDOM.setAttribute("aria-live","polite"),this.dom=document.createElement("div"),this.dom.appendChild(this.announceDOM),this.dom.appendChild(this.scrollDOM),e.parent&&e.parent.appendChild(this.dom);let{dispatch:n}=e;this.dispatchTransactions=e.dispatchTransactions||n&&(a=>a.forEach(s=>n(s,this)))||(a=>this.update(a)),this.dispatch=this.dispatch.bind(this),this._root=e.root||wZ(e.parent)||document,this.viewState=new em(this,e.state||re.create(e)),e.scrollTo&&e.scrollTo.is(fa)&&(this.viewState.scrollTarget=e.scrollTo.value.clip(this.viewState.state)),this.plugins=this.state.facet(v1).map(a=>new Dr(a));for(let a of this.plugins)a.update(this);this.observer=new VL(this),this.inputState=new gL(this),this.inputState.ensureHandlers(this.plugins),this.docView=new Fc(this),this.mountStyles(),this.updateAttrs(),this.updateState=0,this.requestMeasure(),!((t=document.fonts)===null||t===void 0)&&t.ready&&document.fonts.ready.then(()=>{this.viewState.mustMeasureContent="refresh",this.requestMeasure()})}dispatch(...e){let t=e.length==1&&e[0]instanceof $e?e:e.length==1&&Array.isArray(e[0])?e[0]:[this.state.update(...e)];this.dispatchTransactions(t,this)}update(e){if(this.updateState!=0)throw new Error("Calls to EditorView.update are not allowed while an update is in progress");let t=!1,n=!1,a,s=this.state;for(let d of e){if(d.startState!=s)throw new RangeError("Trying to update state with a transaction that doesn't start from the previous state.");s=d.state}if(this.destroyed){this.viewState.state=s;return}let r=this.hasFocus,o=0,l=null;e.some(d=>d.annotation(Cp))?(this.inputState.notifiedFocused=r,o=1):r!=this.inputState.notifiedFocused&&(this.inputState.notifiedFocused=r,l=jp(s,r),l||(o=1));let u=this.observer.delayedAndroidKey,c=null;if(u?(this.observer.clearDelayedAndroidKey(),c=this.observer.readChange(),(c&&!this.state.doc.eq(s.doc)||!this.state.selection.eq(s.selection))&&(c=null)):this.observer.clear(),s.facet(re.phrases)!=this.state.facet(re.phrases))return this.setState(s);a=zs.create(this,s,e),a.flags|=o;let m=this.viewState.scrollTarget;try{this.updateState=2;for(let d of e){if(m&&(m=m.map(d.changes)),d.scrollIntoView){let{main:h}=d.state.selection,{x:g,y:f}=this.state.facet(Q.cursorScrollMargin);m=new _1(h.empty?h:B.cursor(h.head,h.head>h.anchor?-1:1),"nearest","nearest",f,g)}for(let h of d.effects)h.is(fa)&&(m=h.value.clip(this.state))}this.viewState.update(a,m),this.bidiCache=_s.update(this.bidiCache,a.changes),a.empty||(this.updatePlugins(a),this.inputState.update(a)),t=this.docView.update(a),this.state.facet(ni)!=this.styleModules&&this.mountStyles(),n=this.updateAttrs(),this.showAnnouncements(e),this.docView.updateSelection(t,e.some(d=>d.isUserEvent("select.pointer")))}finally{this.updateState=0}if(a.startState.facet(za)!=a.state.facet(za)&&(this.viewState.mustMeasureContent=!0),(t||n||m||this.viewState.mustEnforceCursorAssoc||this.viewState.mustMeasureContent)&&this.requestMeasure(),t&&this.docViewUpdate(),!a.empty)for(let d of this.state.facet(ul))try{d(a)}catch(h){wt(this.state,h,"update listener")}(l||c)&&Promise.resolve().then(()=>{l&&this.state==l.startState&&this.dispatch(l),c&&!Ip(this,c)&&u.force&&T1(this.contentDOM,u.key,u.keyCode)})}setState(e){if(this.updateState!=0)throw new Error("Calls to EditorView.setState are not allowed while an update is in progress");if(this.destroyed){this.viewState.state=e;return}this.updateState=2;let t=this.hasFocus;try{for(let n of this.plugins)n.destroy(this);this.viewState=new em(this,e),this.plugins=e.facet(v1).map(n=>new Dr(n)),this.pluginMap.clear();for(let n of this.plugins)n.update(this);this.docView.destroy(),this.docView=new Fc(this),this.inputState.ensureHandlers(this.plugins),this.mountStyles(),this.updateAttrs(),this.bidiCache=[]}finally{this.updateState=0}t&&this.focus(),this.requestMeasure()}updatePlugins(e){let t=e.startState.facet(v1),n=e.state.facet(v1);if(t!=n){let a=[];for(let s of n){let r=t.indexOf(s);if(r<0)a.push(new Dr(s));else{let o=this.plugins[r];o.mustUpdate=e,a.push(o)}}for(let s of this.plugins)s.mustUpdate!=e&&s.destroy(this);this.plugins=a,this.pluginMap.clear()}else for(let a of this.plugins)a.mustUpdate=e;for(let a=0;a-1&&this.win.cancelAnimationFrame(this.measureScheduled),this.observer.delayedAndroidKey){this.measureScheduled=-1,this.requestMeasure();return}this.measureScheduled=0,e&&this.observer.forceFlush();let t=null,n=this.viewState.scrollParent,a=this.viewState.getScrollOffset(),{scrollAnchorPos:s,scrollAnchorHeight:r,scaleY:o}=this.viewState;Math.abs(a-this.viewState.scrollOffset)>1&&(r=-1),this.viewState.scrollAnchorHeight=-1;try{for(let l=0;;l++){if(r<0){if(Yg(n||this.win))s=-1,r=this.viewState.heightMap.height/this.viewState.scaleY;else{let g=this.viewState.scrollAnchorAt(a);s=g.from,r=g.top}o=this.viewState.scaleY}this.updateState=1;let u=this.viewState.measure();if(!u&&!this.measureRequests.length&&this.viewState.scrollTarget==null)break;if(l>5){console.warn(this.measureRequests.length?"Measure loop restarted more than 5 times":"Viewport failed to stabilize");break}let c=[];u&4||([this.measureRequests,c]=[c,this.measureRequests]);let m=c.map(g=>{try{return g.read(this)}catch(f){return wt(this.state,f),am}}),d=zs.create(this,this.state,[]),h=!1;d.flags|=u,t?t.flags|=u:t=d,this.updateState=2,d.empty||(this.updatePlugins(d),this.inputState.update(d),this.updateAttrs(),h=this.docView.update(d),h&&this.docViewUpdate());for(let g=0;g1||f<-1)&&!(G.ios&&this.inputState.lastIOSMomentumScroll>Date.now()-100)&&(n==this.scrollDOM||this.hasFocus||Math.max(this.inputState.lastWheelEvent,this.inputState.lastTouchTime)>Date.now()-100)){a=a+f,n?s<0?n.scrollTop=n.scrollHeight:n.scrollTop+=f:this.win.scrollBy(0,f),r=-1;continue}}break}}}finally{this.updateState=0,this.measureScheduled=-1}if(t&&!t.empty)for(let l of this.state.facet(ul))l(t)}get themeClasses(){return bl+" "+(this.state.facet(fl)?Mp:Bp)+" "+this.state.facet(za)}updateAttrs(){let e=sm(this,gp,{class:"cm-editor"+(this.hasFocus?" cm-focused ":" ")+this.themeClasses}),t={spellcheck:"false",autocorrect:"off",autocapitalize:"off",writingsuggestions:"false",translate:"no",contenteditable:this.state.facet(dn)?"true":"false",class:"cm-content",style:`${G.tabSize}: ${this.state.tabSize}`,role:"textbox","aria-multiline":"true"};this.state.readOnly&&(t["aria-readonly"]="true"),sm(this,I0,t);let n=this.observer.ignore(()=>{let a=Mc(this.contentDOM,this.contentAttrs,t),s=Mc(this.dom,this.editorAttrs,e);return a||s});return this.editorAttrs=e,this.contentAttrs=t,n}showAnnouncements(e){let t=!0;for(let n of e)for(let a of n.effects)if(a.is(Q.announce)){t&&(this.announceDOM.textContent="",this.win.clearTimeout(this.clearAnnouncement),this.clearAnnouncement=this.win.setTimeout(()=>{this.announceDOM.textContent=" "},200),t=!1);let s=this.announceDOM.appendChild(document.createElement("div"));s.textContent=a.value}}mountStyles(){this.styleModules=this.state.facet(ni);let e=this.state.facet(Q.cspNonce);Mn.mount(this.root,this.styleModules.concat(GL).reverse(),e?{nonce:e}:void 0)}readMeasured(){if(this.updateState==2)throw new Error("Reading the editor layout isn't allowed during an update");this.updateState==0&&this.measureScheduled>-1&&this.measure(!1)}requestMeasure(e){if(this.measureScheduled<0&&(this.measureScheduled=this.win.requestAnimationFrame(()=>this.measure())),e){if(this.measureRequests.indexOf(e)>-1)return;if(e.key!=null){for(let t=0;tn.plugin==e)||null),t&&t.update(this).value}get documentTop(){return this.contentDOM.getBoundingClientRect().top+this.viewState.paddingTop}get documentPadding(){return{top:this.viewState.paddingTop,bottom:this.viewState.paddingBottom}}get scaleX(){return this.viewState.scaleX}get scaleY(){return this.viewState.scaleY}elementAtHeight(e){return this.readMeasured(),this.viewState.elementAtHeight(e)}lineBlockAtHeight(e){return this.readMeasured(),this.viewState.lineBlockAtHeight(e)}get viewportLineBlocks(){return this.viewState.viewportLines}lineBlockAt(e){return this.viewState.lineBlockAt(e)}get contentHeight(){return this.viewState.contentHeight}moveByChar(e,t,n){return Lr(this,e,Jc(this,e,t,n))}moveByGroup(e,t){return Lr(this,e,Jc(this,e,t,n=>aL(this,e.head,n)))}visualLineSide(e,t){return t?B.cursor(e.to,1):B.cursor(e.from,-1)}moveToLineBoundary(e,t,n=!0){return iL(this,e,t,n)}moveVertically(e,t,n){return Lr(this,e,sL(this,e,t,n))}domAtPos(e,t=1){return this.docView.domAtPos(e,t)}posAtDOM(e,t=0){return this.docView.posFromDOM(e,t)}posAtCoords(e,t=!0){this.readMeasured();let n=dl(this,e,t);return n&&n.pos}posAndSideAtCoords(e,t=!0){return this.readMeasured(),dl(this,e,t)}coordsAtPos(e,t=1){this.readMeasured();let n=this.state.doc.lineAt(e),a=this.bidiSpans(n),s=a[rn.find(a,e-n.from,-1,t)];return n.length&&(e==n.from&&t<0||e==n.to&&t>0)&&s.dir!=this.textDirectionAt(n.from)&&(e==n.to?(e=n.from+s.from,t=1):(e=n.from+s.to,t=-1)),this.docView.coordsAt(e,t,s.dir==ye.RTL)}coordsForChar(e){return this.readMeasured(),this.docView.coordsForChar(e)}get defaultCharacterWidth(){return this.viewState.heightOracle.charWidth}get defaultLineHeight(){return this.viewState.heightOracle.lineHeight}get textDirection(){return this.viewState.defaultTextDirection}textDirectionAt(e){return!this.state.facet(mp)||ethis.viewport.to?this.textDirection:(this.readMeasured(),this.docView.textDirectionAt(e))}get lineWrapping(){return this.viewState.heightOracle.lineWrapping}bidiSpans(e){if(e.length>UL)return ip(e.length);let t=this.textDirectionAt(e.from),n;for(let s of this.bidiCache)if(s.from==e.from&&s.dir==t&&(s.fresh||np(s.isolates,n=Ec(this,e))))return s.order;n||(n=Ec(this,e));let a=OZ(e.text,t,n);return this.bidiCache.push(new _s(e.from,e.to,t,n,!0,a)),a}get hasFocus(){var e;return(this.dom.ownerDocument.hasFocus()||G.safari&&((e=this.inputState)===null||e===void 0?void 0:e.lastContextMenu)>Date.now()-3e4)&&this.root.activeElement==this.contentDOM}focus(){this.observer.ignore(()=>{$g(this.contentDOM),this.docView.updateSelection()})}setRoot(e){this._root!=e&&(this._root=e,this.observer.setWindow((e.nodeType==9?e:e.ownerDocument).defaultView||window),this.mountStyles())}destroy(){this.root.activeElement==this.contentDOM&&this.contentDOM.blur();for(let e of this.plugins)e.destroy(this);this.plugins=[],this.inputState.destroy(),this.docView.destroy(),this.dom.remove(),this.observer.destroy(),this.win.clearTimeout(this.clearAnnouncement),this.measureScheduled>-1&&this.win.cancelAnimationFrame(this.measureScheduled),this.destroyed=!0}static scrollIntoView(e,t={}){var n,a,s,r;return fa.of(new _1(typeof e=="number"?B.cursor(e):e,(n=t.y)!==null&&n!==void 0?n:"nearest",(a=t.x)!==null&&a!==void 0?a:"nearest",(s=t.yMargin)!==null&&s!==void 0?s:5,(r=t.xMargin)!==null&&r!==void 0?r:5))}scrollSnapshot(){let{scrollTop:e,scrollLeft:t}=this.scrollDOM,n=this.viewState.scrollAnchorAt(e);return fa.of(new _1(B.cursor(n.from),"start","start",n.top-e,t,!0))}setTabFocusMode(e){e==null?this.inputState.tabFocusMode=this.inputState.tabFocusMode<0?0:-1:typeof e=="boolean"?this.inputState.tabFocusMode=e?0:-1:this.inputState.tabFocusMode!=0&&(this.inputState.tabFocusMode=Date.now()+e)}static domEventHandlers(e){return Lt.define(()=>({}),{eventHandlers:e})}static domEventObservers(e){return Lt.define(()=>({}),{eventObservers:e})}static theme(e,t){let n=Mn.newName(),a=[za.of(n),ni.of(xl(`.${n}`,e))];return t&&t.dark&&a.push(fl.of(!0)),a}static baseTheme(e){return l1.lowest(ni.of(xl("."+bl,e,Zp)))}static findFromDOM(e){var t;let n=e.querySelector(".cm-content"),a=n&&Ce.get(n)||Ce.get(e);return((t=a==null?void 0:a.root)===null||t===void 0?void 0:t.view)||null}}Q.styleModule=ni;Q.inputHandler=up;Q.clipboardInputFilter=w0;Q.clipboardOutputFilter=z0;Q.scrollHandler=dp;Q.focusChangeEffect=cp;Q.perLineTextDirection=mp;Q.exceptionSink=lp;Q.updateListener=ul;Q.editable=dn;Q.mouseSelectionStyle=op;Q.dragMovesSelection=rp;Q.clickAddsSelectionRange=sp;Q.decorations=Ks;Q.blockWrappers=pp;Q.outerDecorations=k0;Q.atomicRanges=Hi;Q.bidiIsolatedRanges=fp;Q.cursorScrollMargin=V.define({combine:i=>{let e=5,t=5;for(let n of i)typeof n=="number"?e=t=n:{x:e,y:t}=n;return{x:e,y:t}}});Q.scrollMargins=xp;Q.darkTheme=fl;Q.cspNonce=V.define({combine:i=>i.length?i[0]:""});Q.contentAttributes=I0;Q.editorAttributes=gp;Q.lineWrapping=Q.contentAttributes.of({class:"cm-lineWrapping"});Q.announce=de.define();const UL=4096,am={};class _s{constructor(e,t,n,a,s,r){this.from=e,this.to=t,this.dir=n,this.isolates=a,this.fresh=s,this.order=r}static update(e,t){if(t.empty&&!e.some(s=>s.fresh))return e;let n=[],a=e.length?e[e.length-1].dir:ye.LTR;for(let s=Math.max(0,e.length-10);s=0;a--){let s=n[a],r=typeof s=="function"?s(i):s;r&&x0(r,t)}return t}const $L=G.mac?"mac":G.windows?"win":G.linux?"linux":"key";function YL(i,e){const t=i.split(/-(?!$)/);let n=t[t.length-1];n=="Space"&&(n=" ");let a,s,r,o;for(let l=0;ln.concat(a),[]))),t}let An=null;const eE=4e3;function tE(i,e=$L){let t=Object.create(null),n=Object.create(null),a=(r,o)=>{let l=n[r];if(l==null)n[r]=o;else if(l!=o)throw new Error("Key binding "+r+" is used both as a regular binding and as a multi-stroke prefix")},s=(r,o,l,u,c)=>{var m,d;let h=t[r]||(t[r]=Object.create(null)),g=o.split(/ (?!$)/).map(x=>YL(x,e));for(let x=1;x{let I=An={view:w,prefix:v,scope:r};return setTimeout(()=>{An==I&&(An=null)},eE),!0}]})}let f=g.join(" ");a(f,!1);let b=h[f]||(h[f]={preventDefault:!1,stopPropagation:!1,run:((d=(m=h._any)===null||m===void 0?void 0:m.run)===null||d===void 0?void 0:d.slice())||[]});l&&b.run.push(l),u&&(b.preventDefault=!0),c&&(b.stopPropagation=!0)};for(let r of i){let o=r.scope?r.scope.split(" "):["editor"];if(r.any)for(let u of o){let c=t[u]||(t[u]=Object.create(null));c._any||(c._any={preventDefault:!1,stopPropagation:!1,run:[]});let{any:m}=r;for(let d in c)c[d].run.push(h=>m(h,vl))}let l=r[e]||r.key;if(l)for(let u of o)s(u,l,r.run,r.preventDefault,r.stopPropagation),r.shift&&s(u,"Shift-"+l,r.shift,r.preventDefault,r.stopPropagation)}return t}let vl=null;function nE(i,e,t,n){vl=e;let a=gZ(e),s=Ot(a,0),r=mn(s)==a.length&&a!=" ",o="",l=!1,u=!1,c=!1;An&&An.view==t&&An.scope==n&&(o=An.prefix+" ",Tp.indexOf(e.keyCode)<0&&(u=!0,An=null));let m=new Set,d=b=>{if(b){for(let x of b.run)if(!m.has(x)&&(m.add(x),x(t)))return b.stopPropagation&&(c=!0),!0;b.preventDefault&&(b.stopPropagation&&(c=!0),u=!0)}return!1},h=i[n],g,f;return h&&(d(h[o+Ia(a,e,!r)])?l=!0:r&&(e.altKey||e.metaKey||e.ctrlKey)&&!(G.windows&&e.ctrlKey&&e.altKey)&&!(G.mac&&e.altKey&&!(e.ctrlKey||e.metaKey))&&(g=Zn[e.keyCode])&&g!=a?(d(h[o+Ia(g,e,!0)])||e.shiftKey&&(f=_i[e.keyCode])!=a&&f!=g&&d(h[o+Ia(f,e,!1)]))&&(l=!0):r&&e.shiftKey&&d(h[o+Ia(a,e,!0)])&&(l=!0),!l&&d(h._any)&&(l=!0)),u&&(l=!0),l&&c&&e.stopPropagation(),vl=null,l}class ir{constructor(e,t,n,a,s){this.className=e,this.left=t,this.top=n,this.width=a,this.height=s}draw(){let e=document.createElement("div");return e.className=this.className,this.adjust(e),e}update(e,t){return t.className!=this.className?!1:(this.adjust(e),!0)}adjust(e){e.style.left=this.left+"px",e.style.top=this.top+"px",this.width!=null&&(e.style.width=this.width+"px"),e.style.height=this.height+"px"}eq(e){return this.left==e.left&&this.top==e.top&&this.width==e.width&&this.height==e.height&&this.className==e.className}static forRange(e,t,n){if(n.empty){let a=e.coordsAtPos(n.head,n.assoc||1);if(!a)return[];let s=Lp(e);return[new ir(t,a.left-s.left,a.top-s.top,null,a.bottom-a.top)]}else return iE(e,t,n)}}function Lp(i){let e=i.scrollDOM.getBoundingClientRect();return{left:(i.textDirection==ye.LTR?e.left:e.right-i.scrollDOM.clientWidth*i.scaleX)-i.scrollDOM.scrollLeft*i.scaleX,top:e.top-i.scrollDOM.scrollTop*i.scaleY}}function om(i,e,t,n){let a=i.coordsAtPos(e,t*2);if(!a)return n;let s=i.dom.getBoundingClientRect(),r=(a.top+a.bottom)/2,o=i.posAtCoords({x:s.left+1,y:r}),l=i.posAtCoords({x:s.right-1,y:r});return o==null||l==null?n:{from:Math.max(n.from,Math.min(o,l)),to:Math.min(n.to,Math.max(o,l))}}function iE(i,e,t){if(t.to<=i.viewport.from||t.from>=i.viewport.to)return[];let n=Math.max(t.from,i.viewport.from),a=Math.min(t.to,i.viewport.to),s=i.textDirection==ye.LTR,r=i.contentDOM,o=r.getBoundingClientRect(),l=Lp(i),u=r.querySelector(".cm-line"),c=u&&window.getComputedStyle(u),m=o.left+(c?parseInt(c.paddingLeft)+Math.min(0,parseInt(c.textIndent)):0),d=o.right-(c?parseInt(c.paddingRight):0),h=ml(i,n,1),g=ml(i,a,-1),f=h.type==Ye.Text?h:null,b=g.type==Ye.Text?g:null;if(f&&(i.lineWrapping||h.widgetLineBreaks)&&(f=om(i,n,1,f)),b&&(i.lineWrapping||g.widgetLineBreaks)&&(b=om(i,a,-1,b)),f&&b&&f.from==b.from&&f.to==b.to)return v(w(t.from,t.to,f));{let z=f?w(t.from,null,f):I(h,!1),k=b?w(null,t.to,b):I(g,!0),T=[];return(f||h).to<(b||g).from-(f&&b?1:0)||h.widgetLineBreaks>1&&z.bottom+i.defaultLineHeight/2O&&W.from=ee)break;J>U&&j(Math.max(fe,U),z==null&&fe<=O,Math.min(J,ee),k==null&&J>=Z,Ie.dir)}if(U=he.to+1,U>=ee)break}return P.length==0&&j(O,z==null,Z,k==null,i.textDirection),{top:A,bottom:D,horizontal:P}}function I(z,k){let T=o.top+(k?z.top:z.bottom);return{top:T,bottom:T,horizontal:[]}}}function aE(i,e){return i.constructor==e.constructor&&i.eq(e)}class sE{constructor(e,t){this.view=e,this.layer=t,this.drawn=[],this.scaleX=1,this.scaleY=1,this.measureReq={read:this.measure.bind(this),write:this.draw.bind(this)},this.dom=e.scrollDOM.appendChild(document.createElement("div")),this.dom.classList.add("cm-layer"),t.above&&this.dom.classList.add("cm-layer-above"),t.class&&this.dom.classList.add(t.class),this.scale(),this.dom.setAttribute("aria-hidden","true"),this.setOrder(e.state),e.requestMeasure(this.measureReq),t.mount&&t.mount(this.dom,e)}update(e){e.startState.facet(Va)!=e.state.facet(Va)&&this.setOrder(e.state),(this.layer.update(e,this.dom)||e.geometryChanged)&&(this.scale(),e.view.requestMeasure(this.measureReq))}docViewUpdate(e){this.layer.updateOnDocViewUpdate!==!1&&e.requestMeasure(this.measureReq)}setOrder(e){let t=0,n=e.facet(Va);for(;t!aE(t,this.drawn[n]))){let t=this.dom.firstChild,n=0;for(let a of e)a.update&&t&&a.constructor&&this.drawn[n].constructor&&a.update(t,this.drawn[n])?(t=t.nextSibling,n++):this.dom.insertBefore(a.draw(),t);for(;t;){let a=t.nextSibling;t.remove(),t=a}this.drawn=e,G.webkit&&(this.dom.style.display=this.dom.firstChild?"":"none")}}destroy(){this.layer.destroy&&this.layer.destroy(this.dom,this.view),this.dom.remove()}}const Va=V.define();function rE(i){return[Lt.define(e=>new sE(e,i)),Va.of(i)]}const ka="-10000px";class oE{constructor(e,t,n,a){this.facet=t,this.createTooltipView=n,this.removeTooltipView=a,this.input=e.state.facet(t),this.tooltips=this.input.filter(r=>r);let s=null;this.tooltipViews=this.tooltips.map(r=>s=n(r,s))}update(e,t){var n;let a=e.state.facet(this.facet),s=a.filter(l=>l);if(a===this.input){for(let l of this.tooltipViews)l.update&&l.update(e);return!1}let r=[],o=t?[]:null;for(let l=0;lt[u]=l),t.length=o.length),this.input=a,this.tooltips=s,this.tooltipViews=r,!0}}function Ep(i){let e=i.dom.ownerDocument.documentElement,t=e.clientWidth,n=getComputedStyle(e);if(!/stable/.test(n.scrollbarGutter||""))return{left:0,right:t};let a=e.getBoundingClientRect(),s=i.win.scrollX;return{left:Math.max(0,a.left+s-parseFloat(n.marginLeft)),right:Math.min(t,a.right+s+parseFloat(n.marginRight))}}function lE(i){let{left:e,right:t}=Ep(i);return{top:0,left:e,right:t,bottom:i.dom.ownerDocument.documentElement.clientHeight}}const Nr=V.define({combine:i=>{var e,t,n;return{position:G.ios?"absolute":((e=i.find(a=>a.position))===null||e===void 0?void 0:e.position)||"fixed",parent:((t=i.find(a=>a.parent))===null||t===void 0?void 0:t.parent)||null,tooltipSpace:((n=i.find(a=>a.tooltipSpace))===null||n===void 0?void 0:n.tooltipSpace)||lE}}}),lm=new WeakMap,Wp=Lt.fromClass(class{constructor(i){this.view=i,this.above=[],this.inView=!0,this.madeAbsolute=!1,this.lastTransaction=0,this.measureTimeout=-1;let e=i.state.facet(Nr);this.position=e.position,this.parent=e.parent,this.classes=i.themeClasses,this.createContainer(),this.measureReq={read:this.readMeasure.bind(this),write:this.writeMeasure.bind(this),key:this},this.resizeObserver=typeof ResizeObserver=="function"?new ResizeObserver(()=>this.measureSoon()):null,this.manager=new oE(i,Np,(t,n)=>this.createTooltip(t,n),t=>{this.resizeObserver&&this.resizeObserver.unobserve(t.dom),t.dom.remove()}),this.above=this.manager.tooltips.map(t=>!!t.above),this.intersectionObserver=typeof IntersectionObserver=="function"?new IntersectionObserver(t=>{Date.now()>this.lastTransaction-50&&t.length>0&&t[t.length-1].intersectionRatio<1&&this.measureSoon()},{threshold:[1]}):null,this.observeIntersection(),i.win.addEventListener("resize",this.measureSoon=this.measureSoon.bind(this)),this.maybeMeasure()}createContainer(){this.parent?(this.container=document.createElement("div"),this.container.style.position="relative",this.container.className=this.view.themeClasses,this.parent.appendChild(this.container)):this.container=this.view.dom}observeIntersection(){if(this.intersectionObserver){this.intersectionObserver.disconnect();for(let i of this.manager.tooltipViews)this.intersectionObserver.observe(i.dom)}}measureSoon(){this.measureTimeout<0&&(this.measureTimeout=setTimeout(()=>{this.measureTimeout=-1,this.maybeMeasure()},50))}update(i){i.transactions.length&&(this.lastTransaction=Date.now());let e=this.manager.update(i,this.above);e&&this.observeIntersection();let t=e||i.geometryChanged,n=i.state.facet(Nr);if(n.position!=this.position&&!this.madeAbsolute){this.position=n.position;for(let a of this.manager.tooltipViews)a.dom.style.position=this.position;t=!0}if(n.parent!=this.parent){this.parent&&this.container.remove(),this.parent=n.parent,this.createContainer();for(let a of this.manager.tooltipViews)this.container.appendChild(a.dom);t=!0}else this.parent&&this.view.themeClasses!=this.classes&&(this.classes=this.container.className=this.view.themeClasses);t&&this.maybeMeasure()}createTooltip(i,e){let t=i.create(this.view),n=e?e.dom:null;if(t.dom.classList.add("cm-tooltip"),i.arrow&&!t.dom.querySelector(".cm-tooltip > .cm-tooltip-arrow")){let a=document.createElement("div");a.className="cm-tooltip-arrow",t.dom.appendChild(a)}return t.dom.style.position=this.position,t.dom.style.top=ka,t.dom.style.left="0px",this.container.insertBefore(t.dom,n),t.mount&&t.mount(this.view),this.resizeObserver&&this.resizeObserver.observe(t.dom),t}destroy(){var i,e,t;this.view.win.removeEventListener("resize",this.measureSoon);for(let n of this.manager.tooltipViews)n.dom.remove(),(i=n.destroy)===null||i===void 0||i.call(n);this.parent&&this.container.remove(),(e=this.resizeObserver)===null||e===void 0||e.disconnect(),(t=this.intersectionObserver)===null||t===void 0||t.disconnect(),clearTimeout(this.measureTimeout)}readMeasure(){let i=1,e=1,t=!1,n=0;if(this.position=="fixed"&&this.manager.tooltipViews.length){let{dom:r}=this.manager.tooltipViews[0];if(G.safari){let o=r.getBoundingClientRect();t=Math.abs(o.top+1e4)>1||Math.abs(o.left)>1}else t=!!r.offsetParent&&r.offsetParent!=this.container.ownerDocument.body}if(t||this.position=="absolute")if(this.parent){let r=this.parent.getBoundingClientRect();r.width&&r.height&&(i=r.width/this.parent.offsetWidth,e=r.height/this.parent.offsetHeight)}else({scaleX:i,scaleY:e}=this.view.viewState);else n=Ep(this.view).left;let a=this.view.scrollDOM.getBoundingClientRect(),s=S0(this.view);return{visible:{left:a.left+s.left,top:a.top+s.top,right:a.right-s.right,bottom:a.bottom-s.bottom},parent:this.parent?this.container.getBoundingClientRect():this.view.dom.getBoundingClientRect(),pos:this.manager.tooltips.map((r,o)=>{let l=this.manager.tooltipViews[o];return l.getCoords?l.getCoords(r.pos):this.view.coordsAtPos(r.pos)}),size:this.manager.tooltipViews.map(({dom:r})=>r.getBoundingClientRect()),space:this.view.state.facet(Nr).tooltipSpace(this.view),scaleX:i,scaleY:e,makeAbsolute:t,fixedLeft:n}}writeMeasure(i){var e;if(i.makeAbsolute){this.madeAbsolute=!0,this.position="absolute";for(let o of this.manager.tooltipViews)o.dom.style.position="absolute"}let{visible:t,space:n,scaleX:a,scaleY:s}=i,r=[];for(let o=0;o=Math.min(t.bottom,n.bottom)||m.rightMath.min(t.right,n.right)+.1)){c.style.top=ka;continue}let h=l.arrow?u.dom.querySelector(".cm-tooltip-arrow"):null,g=h?7:0,f=d.right-d.left,b=(e=lm.get(u))!==null&&e!==void 0?e:d.bottom-d.top,x=u.offset||cE,v=this.view.textDirection==ye.LTR,w=d.width>n.right-n.left?v?n.left:n.right-d.width:v?Math.max(n.left,Math.min(m.left-(h?14:0)+x.x,n.right-f)):Math.min(Math.max(n.left,m.left-f+(h?14:0)-x.x),n.right-f),I=this.above[o];!l.strictSide&&(I?m.top-b-g-x.yn.bottom)&&I==n.bottom-m.bottom>m.top-n.top&&(I=this.above[o]=!I);let z=(I?m.top-n.top:n.bottom-m.bottom)-g;if(zw&&A.topk&&(k=I?A.top-b-2-g:A.bottom+g+2);if(this.position=="absolute"?(c.style.top=(k-i.parent.top)/s+"px",um(c,(w-i.parent.left)/a)):(c.style.top=k/s+"px",um(c,(w-i.fixedLeft)/a)),h){let A=m.left+(v?x.x:-x.x)-(w+14-7);h.style.left=A/a+"px"}u.overlap!==!0&&r.push({left:w,top:k,right:T,bottom:k+b}),c.classList.toggle("cm-tooltip-above",I),c.classList.toggle("cm-tooltip-below",!I),u.positioned&&u.positioned(i.space)}}maybeMeasure(){if(this.manager.tooltips.length&&(this.view.inView&&this.view.requestMeasure(this.measureReq),this.inView!=this.view.inView&&(this.inView=this.view.inView,!this.inView)))for(let i of this.manager.tooltipViews)i.dom.style.top=ka}},{eventObservers:{scroll(){this.maybeMeasure()}}});function um(i,e){let t=parseInt(i.style.left,10);(isNaN(t)||Math.abs(e-t)>1)&&(i.style.left=e+"px")}const uE=Q.baseTheme({".cm-tooltip":{zIndex:500,boxSizing:"border-box"},"&light .cm-tooltip":{border:"1px solid #bbb",backgroundColor:"#f5f5f5"},"&light .cm-tooltip-section:not(:first-child)":{borderTop:"1px solid #bbb"},"&dark .cm-tooltip":{backgroundColor:"#333338",color:"white"},".cm-tooltip-arrow":{height:"7px",width:"14px",position:"absolute",zIndex:-1,overflow:"hidden","&:before, &:after":{content:"''",position:"absolute",width:0,height:0,borderLeft:"7px solid transparent",borderRight:"7px solid transparent"},".cm-tooltip-above &":{bottom:"-7px","&:before":{borderTop:"7px solid #bbb"},"&:after":{borderTop:"7px solid #f5f5f5",bottom:"1px"}},".cm-tooltip-below &":{top:"-7px","&:before":{borderBottom:"7px solid #bbb"},"&:after":{borderBottom:"7px solid #f5f5f5",top:"1px"}}},"&dark .cm-tooltip .cm-tooltip-arrow":{"&:before":{borderTopColor:"#333338",borderBottomColor:"#333338"},"&:after":{borderTopColor:"transparent",borderBottomColor:"transparent"}}}),cE={x:0,y:0},Np=V.define({enables:[Wp,uE]});function Fp(i,e){let t=i.plugin(Wp);if(!t)return null;let n=t.manager.tooltips.indexOf(e);return n<0?null:t.manager.tooltipViews[n]}class xn extends Bn{compare(e){return this==e||this.constructor==e.constructor&&this.eq(e)}eq(e){return!1}destroy(e){}}xn.prototype.elementClass="";xn.prototype.toDOM=void 0;xn.prototype.mapMode=st.TrackBefore;xn.prototype.startSide=xn.prototype.endSide=-1;xn.prototype.point=!0;const qa=V.define(),mE=V.define(),dE={class:"",renderEmptyElements:!1,elementStyle:"",markers:()=>ie.empty,lineMarker:()=>null,widgetMarker:()=>null,lineMarkerChange:null,initialSpacer:null,updateSpacer:null,domEventHandlers:{},side:"before"},fi=V.define();function hE(i){return[Jp(),fi.of({...dE,...i})]}const cm=V.define({combine:i=>i.some(e=>e)});function Jp(i){return[gE]}const gE=Lt.fromClass(class{constructor(i){this.view=i,this.domAfter=null,this.prevViewport=i.viewport,this.dom=document.createElement("div"),this.dom.className="cm-gutters cm-gutters-before",this.dom.setAttribute("aria-hidden","true"),this.dom.style.minHeight=this.view.contentHeight/this.view.scaleY+"px",this.gutters=i.state.facet(fi).map(e=>new dm(i,e)),this.fixed=!i.state.facet(cm);for(let e of this.gutters)e.config.side=="after"?this.getDOMAfter().appendChild(e.dom):this.dom.appendChild(e.dom);this.fixed&&(this.dom.style.position="sticky"),this.syncGutters(!1),i.scrollDOM.insertBefore(this.dom,i.contentDOM)}getDOMAfter(){return this.domAfter||(this.domAfter=document.createElement("div"),this.domAfter.className="cm-gutters cm-gutters-after",this.domAfter.setAttribute("aria-hidden","true"),this.domAfter.style.minHeight=this.view.contentHeight/this.view.scaleY+"px",this.domAfter.style.position=this.fixed?"sticky":"",this.view.scrollDOM.appendChild(this.domAfter)),this.domAfter}update(i){if(this.updateGutters(i)){let e=this.prevViewport,t=i.view.viewport,n=Math.min(e.to,t.to)-Math.max(e.from,t.from);this.syncGutters(n<(t.to-t.from)*.8)}if(i.geometryChanged){let e=this.view.contentHeight/this.view.scaleY+"px";this.dom.style.minHeight=e,this.domAfter&&(this.domAfter.style.minHeight=e)}this.view.state.facet(cm)!=!this.fixed&&(this.fixed=!this.fixed,this.dom.style.position=this.fixed?"sticky":"",this.domAfter&&(this.domAfter.style.position=this.fixed?"sticky":"")),this.prevViewport=i.view.viewport}syncGutters(i){let e=this.dom.nextSibling;i&&(this.dom.remove(),this.domAfter&&this.domAfter.remove());let t=ie.iter(this.view.state.facet(qa),this.view.viewport.from),n=[],a=this.gutters.map(s=>new pE(s,this.view.viewport,-this.view.documentPadding.top));for(let s of this.view.viewportLineBlocks)if(n.length&&(n=[]),Array.isArray(s.type)){let r=!0;for(let o of s.type)if(o.type==Ye.Text&&r){yl(t,n,o.from);for(let l of a)l.line(this.view,o,n);r=!1}else if(o.widget)for(let l of a)l.widget(this.view,o)}else if(s.type==Ye.Text){yl(t,n,s.from);for(let r of a)r.line(this.view,s,n)}else if(s.widget)for(let r of a)r.widget(this.view,s);for(let s of a)s.finish();i&&(this.view.scrollDOM.insertBefore(this.dom,e),this.domAfter&&this.view.scrollDOM.appendChild(this.domAfter))}updateGutters(i){let e=i.startState.facet(fi),t=i.state.facet(fi),n=i.docChanged||i.heightChanged||i.viewportChanged||!ie.eq(i.startState.facet(qa),i.state.facet(qa),i.view.viewport.from,i.view.viewport.to);if(e==t)for(let a of this.gutters)a.update(i)&&(n=!0);else{n=!0;let a=[];for(let s of t){let r=e.indexOf(s);r<0?a.push(new dm(this.view,s)):(this.gutters[r].update(i),a.push(this.gutters[r]))}for(let s of this.gutters)s.dom.remove(),a.indexOf(s)<0&&s.destroy();for(let s of a)s.config.side=="after"?this.getDOMAfter().appendChild(s.dom):this.dom.appendChild(s.dom);this.gutters=a}return n}destroy(){for(let i of this.gutters)i.destroy();this.dom.remove(),this.domAfter&&this.domAfter.remove()}},{provide:i=>Q.scrollMargins.of(e=>{let t=e.plugin(i);if(!t||t.gutters.length==0||!t.fixed)return null;let n=t.dom.offsetWidth*e.scaleX,a=t.domAfter?t.domAfter.offsetWidth*e.scaleX:0;return e.textDirection==ye.LTR?{left:n,right:a}:{right:n,left:a}})});function mm(i){return Array.isArray(i)?i:[i]}function yl(i,e,t){for(;i.value&&i.from<=t;)i.from==t&&e.push(i.value),i.next()}class pE{constructor(e,t,n){this.gutter=e,this.height=n,this.i=0,this.cursor=ie.iter(e.markers,t.from)}addElement(e,t,n){let{gutter:a}=this,s=(t.top-this.height)/e.scaleY,r=t.height/e.scaleY;if(this.i==a.elements.length){let o=new Rp(e,r,s,n);a.elements.push(o),a.dom.appendChild(o.dom)}else a.elements[this.i].update(e,r,s,n);this.height=t.bottom,this.i++}line(e,t,n){let a=[];yl(this.cursor,a,t.from),n.length&&(a=a.concat(n));let s=this.gutter.config.lineMarker(e,t,a);s&&a.unshift(s);let r=this.gutter;a.length==0&&!r.config.renderEmptyElements||this.addElement(e,t,a)}widget(e,t){let n=this.gutter.config.widgetMarker(e,t.widget,t),a=n?[n]:null;for(let s of e.state.facet(mE)){let r=s(e,t.widget,t);r&&(a||(a=[])).push(r)}a&&this.addElement(e,t,a)}finish(){let e=this.gutter;for(;e.elements.length>this.i;){let t=e.elements.pop();e.dom.removeChild(t.dom),t.destroy()}}}class dm{constructor(e,t){this.view=e,this.config=t,this.elements=[],this.spacer=null,this.dom=document.createElement("div"),this.dom.className="cm-gutter"+(this.config.class?" "+this.config.class:"");for(let n in t.domEventHandlers)this.dom.addEventListener(n,a=>{let s=a.target,r;if(s!=this.dom&&this.dom.contains(s)){for(;s.parentNode!=this.dom;)s=s.parentNode;let l=s.getBoundingClientRect();r=(l.top+l.bottom)/2}else r=a.clientY;let o=e.lineBlockAtHeight(r-e.documentTop);t.domEventHandlers[n](e,o,a)&&a.preventDefault()});this.markers=mm(t.markers(e)),t.initialSpacer&&(this.spacer=new Rp(e,0,0,[t.initialSpacer(e)]),this.dom.appendChild(this.spacer.dom),this.spacer.dom.style.cssText+="visibility: hidden; pointer-events: none")}update(e){let t=this.markers;if(this.markers=mm(this.config.markers(e.view)),this.spacer&&this.config.updateSpacer){let a=this.config.updateSpacer(this.spacer.markers[0],e);a!=this.spacer.markers[0]&&this.spacer.update(e.view,0,0,[a])}let n=e.view.viewport;return!ie.eq(this.markers,t,n.from,n.to)||(this.config.lineMarkerChange?this.config.lineMarkerChange(e):!1)}destroy(){for(let e of this.elements)e.destroy()}}class Rp{constructor(e,t,n,a){this.height=-1,this.above=0,this.markers=[],this.dom=document.createElement("div"),this.dom.className="cm-gutterElement",this.update(e,t,n,a)}update(e,t,n,a){this.height!=t&&(this.height=t,this.dom.style.height=t+"px"),this.above!=n&&(this.dom.style.marginTop=(this.above=n)?n+"px":""),fE(this.markers,a)||this.setMarkers(e,a)}setMarkers(e,t){let n="cm-gutterElement",a=this.dom.firstChild;for(let s=0,r=0;;){let o=r,l=ss(o,l,u)||r(o,l,u):r}return n}})}});class Fr extends xn{constructor(e){super(),this.number=e}eq(e){return this.number==e.number}toDOM(){return document.createTextNode(this.number)}}function Jr(i,e){return i.state.facet(y1).formatNumber(e,i.state)}const vE=fi.compute([y1],i=>({class:"cm-lineNumbers",renderEmptyElements:!1,markers(e){return e.state.facet(bE)},lineMarker(e,t,n){return n.some(a=>a.toDOM)?null:new Fr(Jr(e,e.state.doc.lineAt(t.from).number))},widgetMarker:(e,t,n)=>{for(let a of e.state.facet(xE)){let s=a(e,t,n);if(s)return s}return null},lineMarkerChange:e=>e.startState.facet(y1)!=e.state.facet(y1),initialSpacer(e){return new Fr(Jr(e,hm(e.state.doc.lines)))},updateSpacer(e,t){let n=Jr(t.view,hm(t.view.state.doc.lines));return n==e.number?e:new Fr(n)},domEventHandlers:i.facet(y1).domEventHandlers,side:"before"}));function yE(i={}){return[y1.of(i),Jp(),vE]}function hm(i){let e=9;for(;e{let e=[],t=-1;for(let n of i.selection.ranges){let a=i.doc.lineAt(n.head).from;a>t&&(t=a,e.push(wE.range(a)))}return ie.of(e)});function IE(){return zE}const Gp=1024;let kE=0;class Rr{constructor(e,t){this.from=e,this.to=t}}class ae{constructor(e={}){this.id=kE++,this.perNode=!!e.perNode,this.deserialize=e.deserialize||(()=>{throw new Error("This node type doesn't define a deserialize function")}),this.combine=e.combine||null}add(e){if(this.perNode)throw new RangeError("Can't add per-node props to node types");return typeof e!="function"&&(e=ft.match(e)),t=>{let n=e(t);return n===void 0?null:[this,n]}}}ae.closedBy=new ae({deserialize:i=>i.split(" ")});ae.openedBy=new ae({deserialize:i=>i.split(" ")});ae.group=new ae({deserialize:i=>i.split(" ")});ae.isolate=new ae({deserialize:i=>{if(i&&i!="rtl"&&i!="ltr"&&i!="auto")throw new RangeError("Invalid value for isolate: "+i);return i||"auto"}});ae.contextHash=new ae({perNode:!0});ae.lookAhead=new ae({perNode:!0});ae.mounted=new ae({perNode:!0});class bi{constructor(e,t,n,a=!1){this.tree=e,this.overlay=t,this.parser=n,this.bracketed=a}static get(e){return e&&e.props&&e.props[ae.mounted.id]}}const SE=Object.create(null);class ft{constructor(e,t,n,a=0){this.name=e,this.props=t,this.id=n,this.flags=a}static define(e){let t=e.props&&e.props.length?Object.create(null):SE,n=(e.top?1:0)|(e.skipped?2:0)|(e.error?4:0)|(e.name==null?8:0),a=new ft(e.name||"",t,e.id,n);if(e.props){for(let s of e.props)if(Array.isArray(s)||(s=s(a)),s){if(s[0].perNode)throw new RangeError("Can't store a per-node prop on a node type");t[s[0].id]=s[1]}}return a}prop(e){return this.props[e.id]}get isTop(){return(this.flags&1)>0}get isSkipped(){return(this.flags&2)>0}get isError(){return(this.flags&4)>0}get isAnonymous(){return(this.flags&8)>0}is(e){if(typeof e=="string"){if(this.name==e)return!0;let t=this.prop(ae.group);return t?t.indexOf(e)>-1:!1}return this.id==e}static match(e){let t=Object.create(null);for(let n in e)for(let a of n.split(" "))t[a]=e[n];return n=>{for(let a=n.prop(ae.group),s=-1;s<(a?a.length:0);s++){let r=t[s<0?n.name:a[s]];if(r)return r}}}}ft.none=new ft("",Object.create(null),0,8);class A0{constructor(e){this.types=e;for(let t=0;t0;for(let l=this.cursor(r|Oe.IncludeAnonymous);;){let u=!1;if(l.from<=s&&l.to>=a&&(!o&&l.type.isAnonymous||t(l)!==!1)){if(l.firstChild())continue;u=!0}for(;u&&n&&(o||!l.type.isAnonymous)&&n(l),!l.nextSibling();){if(!l.parent())return;u=!0}}}prop(e){return e.perNode?this.props?this.props[e.id]:void 0:this.type.prop(e)}get propValues(){let e=[];if(this.props)for(let t in this.props)e.push([+t,this.props[t]]);return e}balance(e={}){return this.children.length<=8?this:j0(ft.none,this.children,this.positions,0,this.children.length,0,this.length,(t,n,a)=>new Ze(this.type,t,n,a,this.propValues),e.makeTree||((t,n,a)=>new Ze(ft.none,t,n,a)))}static build(e){return OE(e)}}Ze.empty=new Ze(ft.none,[],[],0);class O0{constructor(e,t){this.buffer=e,this.index=t}get id(){return this.buffer[this.index-4]}get start(){return this.buffer[this.index-3]}get end(){return this.buffer[this.index-2]}get size(){return this.buffer[this.index-1]}get pos(){return this.index}next(){this.index-=4}fork(){return new O0(this.buffer,this.index)}}class En{constructor(e,t,n){this.buffer=e,this.length=t,this.set=n}get type(){return ft.none}toString(){let e=[];for(let t=0;t0));l=r[l+3]);return o}slice(e,t,n){let a=this.buffer,s=new Uint16Array(t-e),r=0;for(let o=e,l=0;o=e&&te;case 1:return t<=e&&n>e;case 2:return n>e;case 4:return!0}}function Pi(i,e,t,n){for(var a;i.from==i.to||(t<1?i.from>=e:i.from>e)||(t>-1?i.to<=e:i.to0?o.length:-1;e!=u;e+=t){let c=o[e],m=l[e]+r.from,d;if(!(!(s&Oe.EnterBracketed&&c instanceof Ze&&(d=bi.get(c))&&!d.overlay&&d.bracketed&&n>=m&&n<=m+c.length)&&!Hp(a,n,m,m+c.length))){if(c instanceof En){if(s&Oe.ExcludeBuffers)continue;let h=c.findChild(0,c.buffer.length,t,n-m,a);if(h>-1)return new jn(new TE(r,c,e,m),null,h)}else if(s&Oe.IncludeAnonymous||!c.type.isAnonymous||C0(c)){let h;if(!(s&Oe.IgnoreMounts)&&(h=bi.get(c))&&!h.overlay)return new Zt(h.tree,m,e,r);let g=new Zt(c,m,e,r);return s&Oe.IncludeAnonymous||!g.type.isAnonymous?g:g.nextChild(t<0?c.children.length-1:0,t,n,a,s)}}}if(s&Oe.IncludeAnonymous||!r.type.isAnonymous||(r.index>=0?e=r.index+t:e=t<0?-1:r._parent._tree.children.length,r=r._parent,!r))return null}}get firstChild(){return this.nextChild(0,1,0,4)}get lastChild(){return this.nextChild(this._tree.children.length-1,-1,0,4)}childAfter(e){return this.nextChild(0,1,e,2)}childBefore(e){return this.nextChild(this._tree.children.length-1,-1,e,-2)}prop(e){return this._tree.prop(e)}enter(e,t,n=0){let a;if(!(n&Oe.IgnoreOverlays)&&(a=bi.get(this._tree))&&a.overlay){let s=e-this.from,r=n&Oe.EnterBracketed&&a.bracketed;for(let{from:o,to:l}of a.overlay)if((t>0||r?o<=s:o=s:l>s))return new Zt(a.tree,a.overlay[0].from+this.from,-1,this)}return this.nextChild(0,1,e,t,n)}nextSignificantParent(){let e=this;for(;e.type.isAnonymous&&e._parent;)e=e._parent;return e}get parent(){return this._parent?this._parent.nextSignificantParent():null}get nextSibling(){return this._parent&&this.index>=0?this._parent.nextChild(this.index+1,1,0,4):null}get prevSibling(){return this._parent&&this.index>=0?this._parent.nextChild(this.index-1,-1,0,4):null}get tree(){return this._tree}toTree(){return this._tree}toString(){return this._tree.toString()}}function pm(i,e,t,n){let a=i.cursor(),s=[];if(!a.firstChild())return s;if(t!=null){for(let r=!1;!r;)if(r=a.type.is(t),!a.nextSibling())return s}for(;;){if(n!=null&&a.type.is(n))return s;if(a.type.is(e)&&s.push(a.node),!a.nextSibling())return n==null?s:[]}}function wl(i,e,t=e.length-1){for(let n=i;t>=0;n=n.parent){if(!n)return!1;if(!n.type.isAnonymous){if(e[t]&&e[t]!=n.name)return!1;t--}}return!0}class TE{constructor(e,t,n,a){this.parent=e,this.buffer=t,this.index=n,this.start=a}}class jn extends Vp{get name(){return this.type.name}get from(){return this.context.start+this.context.buffer.buffer[this.index+1]}get to(){return this.context.start+this.context.buffer.buffer[this.index+2]}constructor(e,t,n){super(),this.context=e,this._parent=t,this.index=n,this.type=e.buffer.set.types[e.buffer.buffer[n]]}child(e,t,n){let{buffer:a}=this.context,s=a.findChild(this.index+4,a.buffer[this.index+3],e,t-this.context.start,n);return s<0?null:new jn(this.context,this,s)}get firstChild(){return this.child(1,0,4)}get lastChild(){return this.child(-1,0,4)}childAfter(e){return this.child(1,e,2)}childBefore(e){return this.child(-1,e,-2)}prop(e){return this.type.prop(e)}enter(e,t,n=0){if(n&Oe.ExcludeBuffers)return null;let{buffer:a}=this.context,s=a.findChild(this.index+4,a.buffer[this.index+3],t>0?1:-1,e-this.context.start,t);return s<0?null:new jn(this.context,this,s)}get parent(){return this._parent||this.context.parent.nextSignificantParent()}externalSibling(e){return this._parent?null:this.context.parent.nextChild(this.context.index+e,e,0,4)}get nextSibling(){let{buffer:e}=this.context,t=e.buffer[this.index+3];return t<(this._parent?e.buffer[this._parent.index+3]:e.buffer.length)?new jn(this.context,this._parent,t):this.externalSibling(1)}get prevSibling(){let{buffer:e}=this.context,t=this._parent?this._parent.index+4:0;return this.index==t?this.externalSibling(-1):new jn(this.context,this._parent,e.findChild(t,this.index,-1,0,4))}get tree(){return null}toTree(){let e=[],t=[],{buffer:n}=this.context,a=this.index+4,s=n.buffer[this.index+3];if(s>a){let r=n.buffer[this.index+1];e.push(n.slice(a,s,r)),t.push(0)}return new Ze(this.type,e,t,this.to-this.from)}toString(){return this.context.buffer.childString(this.index)}}function qp(i){if(!i.length)return null;let e=0,t=i[0];for(let s=1;st.from||r.to=e){let o=new Zt(r.tree,r.overlay[0].from+s.from,-1,s);(a||(a=[n])).push(Pi(o,e,t,!1))}}return a?qp(a):n}class zl{get name(){return this.type.name}constructor(e,t=0){if(this.buffer=null,this.stack=[],this.index=0,this.bufferNode=null,this.mode=t&~Oe.EnterBracketed,e instanceof Zt)this.yieldNode(e);else{this._tree=e.context.parent,this.buffer=e.context;for(let n=e._parent;n;n=n._parent)this.stack.unshift(n.index);this.bufferNode=e,this.yieldBuf(e.index)}}yieldNode(e){return e?(this._tree=e,this.type=e.type,this.from=e.from,this.to=e.to,!0):!1}yieldBuf(e,t){this.index=e;let{start:n,buffer:a}=this.buffer;return this.type=t||a.set.types[a.buffer[e]],this.from=n+a.buffer[e+1],this.to=n+a.buffer[e+2],!0}yield(e){return e?e instanceof Zt?(this.buffer=null,this.yieldNode(e)):(this.buffer=e.context,this.yieldBuf(e.index,e.type)):!1}toString(){return this.buffer?this.buffer.buffer.childString(this.index):this._tree.toString()}enterChild(e,t,n){if(!this.buffer)return this.yield(this._tree.nextChild(e<0?this._tree._tree.children.length-1:0,e,t,n,this.mode));let{buffer:a}=this.buffer,s=a.findChild(this.index+4,a.buffer[this.index+3],e,t-this.buffer.start,n);return s<0?!1:(this.stack.push(this.index),this.yieldBuf(s))}firstChild(){return this.enterChild(1,0,4)}lastChild(){return this.enterChild(-1,0,4)}childAfter(e){return this.enterChild(1,e,2)}childBefore(e){return this.enterChild(-1,e,-2)}enter(e,t,n=this.mode){return this.buffer?n&Oe.ExcludeBuffers?!1:this.enterChild(1,e,t):this.yield(this._tree.enter(e,t,n))}parent(){if(!this.buffer)return this.yieldNode(this.mode&Oe.IncludeAnonymous?this._tree._parent:this._tree.parent);if(this.stack.length)return this.yieldBuf(this.stack.pop());let e=this.mode&Oe.IncludeAnonymous?this.buffer.parent:this.buffer.parent.nextSignificantParent();return this.buffer=null,this.yieldNode(e)}sibling(e){if(!this.buffer)return this._tree._parent?this.yield(this._tree.index<0?null:this._tree._parent.nextChild(this._tree.index+e,e,0,4,this.mode)):!1;let{buffer:t}=this.buffer,n=this.stack.length-1;if(e<0){let a=n<0?0:this.stack[n]+4;if(this.index!=a)return this.yieldBuf(t.findChild(a,this.index,-1,0,4))}else{let a=t.buffer[this.index+3];if(a<(n<0?t.buffer.length:t.buffer[this.stack[n]+3]))return this.yieldBuf(a)}return n<0?this.yield(this.buffer.parent.nextChild(this.buffer.index+e,e,0,4,this.mode)):!1}nextSibling(){return this.sibling(1)}prevSibling(){return this.sibling(-1)}atLastNode(e){let t,n,{buffer:a}=this;if(a){if(e>0){if(this.index-1)for(let s=t+e,r=e<0?-1:n._tree.children.length;s!=r;s+=e){let o=n._tree.children[s];if(this.mode&Oe.IncludeAnonymous||o instanceof En||!o.type.isAnonymous||C0(o))return!1}return!0}move(e,t){if(t&&this.enterChild(e,0,4))return!0;for(;;){if(this.sibling(e))return!0;if(this.atLastNode(e)||!this.parent())return!1}}next(e=!0){return this.move(1,e)}prev(e=!0){return this.move(-1,e)}moveTo(e,t=0){for(;(this.from==this.to||(t<1?this.from>=e:this.from>e)||(t>-1?this.to<=e:this.to=0;){for(let r=e;r;r=r._parent)if(r.index==a){if(a==this.index)return r;t=r,n=s+1;break e}a=this.stack[--s]}for(let a=n;a=0;s--){if(s<0)return wl(this._tree,e,a);let r=n[t.buffer[this.stack[s]]];if(!r.isAnonymous){if(e[a]&&e[a]!=r.name)return!1;a--}}return!0}}function C0(i){return i.children.some(e=>e instanceof En||!e.type.isAnonymous||C0(e))}function OE(i){var e;let{buffer:t,nodeSet:n,maxBufferLength:a=Gp,reused:s=[],minRepeatType:r=n.types.length}=i,o=Array.isArray(t)?new O0(t,t.length):t,l=n.types,u=0,c=0;function m(z,k,T,A,D,P){let{id:j,start:O,end:Z,size:W}=o,U=c,ee=u;if(W<0)if(o.next(),W==-1){let C=s[j];T.push(C),A.push(O-z);return}else if(W==-3){u=j;return}else if(W==-4){c=j;return}else throw new RangeError(`Unrecognized record size: ${W}`);let he=l[j],Ie,fe,J=O-z;if(Z-O<=a&&(fe=b(o.pos-k,D))){let C=new Uint16Array(fe.size-fe.skip),N=o.pos-fe.size,q=C.length;for(;o.pos>N;)q=x(fe.start,C,q);Ie=new En(C,Z-fe.start,n),J=fe.start-z}else{let C=o.pos-W;o.next();let N=[],q=[],Y=j>=r?j:-1,ue=0,X=Z,ce=U;for(;o.pos>C;)Y>=0&&o.id==Y&&o.size>=0?(o.end<=X-a&&(g(N,q,O,ue,o.end,X,Y,ce,ee),ue=N.length,X=o.end,ce=c),o.next()):P>2500?d(O,C,N,q):m(O,C,N,q,Y,P+1);if(Y>=0&&ue>0&&ue-1&&ue>0){let le=h(he,ee);Ie=j0(he,N,q,0,N.length,0,Z-O,le,le)}else Ie=f(he,N,q,Z-O,U-Z,ee)}T.push(Ie),A.push(J)}function d(z,k,T,A){let D=[],P=0,j=-1;for(;o.pos>k;){let{id:O,start:Z,end:W,size:U}=o;if(U>4)o.next();else{if(j>-1&&Z=0;W-=3)O[U++]=D[W],O[U++]=D[W+1]-Z,O[U++]=D[W+2]-Z,O[U++]=U;T.push(new En(O,D[2]-Z,n)),A.push(Z-z)}}function h(z,k){return(T,A,D)=>{let P=0,j=T.length-1,O,Z;if(j>=0&&(O=T[j])instanceof Ze){if(!j&&O.type==z&&O.length==D)return O;(Z=O.prop(ae.lookAhead))&&(P=A[j]+O.length+Z-D)}return f(z,T,A,D,P,k)}}function g(z,k,T,A,D,P,j,O,Z){let W=[],U=[];for(;z.length>A;)W.push(z.pop()),U.push(k.pop()+T-D);z.push(f(n.types[j],W,U,P-D,O-P,Z)),k.push(D-T)}function f(z,k,T,A,D,P,j){if(P){let O=[ae.contextHash,P];j=j?[O].concat(j):[O]}if(D>25){let O=[ae.lookAhead,D];j=j?[O].concat(j):[O]}return new Ze(z,k,T,A,j)}function b(z,k){let T=o.fork(),A=0,D=0,P=0,j=T.end-a,O={size:0,start:0,skip:0};e:for(let Z=T.pos-z;T.pos>Z;){let W=T.size;if(T.id==k&&W>=0){O.size=A,O.start=D,O.skip=P,P+=4,A+=4,T.next();continue}let U=T.pos-W;if(W<0||U=r?4:0,he=T.start;for(T.next();T.pos>U;){if(T.size<0)if(T.size==-3||T.size==-4)ee+=4;else break e;else T.id>=r&&(ee+=4);T.next()}D=he,A+=W,P+=ee}return(k<0||A==z)&&(O.size=A,O.start=D,O.skip=P),O.size>4?O:void 0}function x(z,k,T){let{id:A,start:D,end:P,size:j}=o;if(o.next(),j>=0&&A4){let Z=o.pos-(j-4);for(;o.pos>Z;)T=x(z,k,T)}k[--T]=O,k[--T]=P-z,k[--T]=D-z,k[--T]=A}else j==-3?u=A:j==-4&&(c=A);return T}let v=[],w=[];for(;o.pos>0;)m(i.start||0,i.bufferStart||0,v,w,-1,0);let I=(e=i.length)!==null&&e!==void 0?e:v.length?w[0]+v[0].length:0;return new Ze(l[i.topID],v.reverse(),w.reverse(),I)}const fm=new WeakMap;function Qa(i,e){if(!i.isAnonymous||e instanceof En||e.type!=i)return 1;let t=fm.get(e);if(t==null){t=1;for(let n of e.children){if(n.type!=i||!(n instanceof Ze)){t=1;break}t+=Qa(i,n)}fm.set(e,t)}return t}function j0(i,e,t,n,a,s,r,o,l){let u=0;for(let g=n;g=c)break;k+=T}if(w==I+1){if(k>c){let T=g[I];h(T.children,T.positions,0,T.children.length,f[I]+v);continue}m.push(g[I])}else{let T=f[w-1]+g[w-1].length-z;m.push(j0(i,g,f,I,w,z,T,null,l))}d.push(z+v-s)}}return h(e,t,n,a,0),(o||l)(m,d,r)}class i1{constructor(e,t,n,a,s=!1,r=!1){this.from=e,this.to=t,this.tree=n,this.offset=a,this.open=(s?1:0)|(r?2:0)}get openStart(){return(this.open&1)>0}get openEnd(){return(this.open&2)>0}static addTree(e,t=[],n=!1){let a=[new i1(0,e.length,e,0,!1,n)];for(let s of t)s.to>e.length&&a.push(s);return a}static applyChanges(e,t,n=128){if(!t.length)return e;let a=[],s=1,r=e.length?e[0]:null;for(let o=0,l=0,u=0;;o++){let c=o=n)for(;r&&r.from=d.from||m<=d.to||u){let h=Math.max(d.from,l)-u,g=Math.min(d.to,m)-u;d=h>=g?null:new i1(h,g,d.tree,d.offset+u,o>0,!!c)}if(d&&a.push(d),r.to>m)break;r=snew Rr(a.from,a.to)):[new Rr(0,0)]:[new Rr(0,e.length)],this.createParse(e,t||[],n)}parse(e,t,n){let a=this.startParse(e,t,n);for(;;){let s=a.advance();if(s)return s}}}class CE{constructor(e){this.string=e}get length(){return this.string.length}chunk(e){return this.string.slice(e)}get lineChunks(){return!1}read(e,t){return this.string.slice(e,t)}}new ae({perNode:!0});let jE=0;class Ct{constructor(e,t,n,a){this.name=e,this.set=t,this.base=n,this.modified=a,this.id=jE++}toString(){let{name:e}=this;for(let t of this.modified)t.name&&(e=`${t.name}(${e})`);return e}static define(e,t){let n=typeof e=="string"?e:"?";if(e instanceof Ct&&(t=e),t!=null&&t.base)throw new Error("Can not derive from a modified tag");let a=new Ct(n,[],null,[]);if(a.set.push(a),t)for(let s of t.set)a.set.push(s);return a}static defineModifier(e){let t=new As(e);return n=>n.modified.indexOf(t)>-1?n:As.get(n.base||n,n.modified.concat(t).sort((a,s)=>a.id-s.id))}}let PE=0;class As{constructor(e){this.name=e,this.instances=[],this.id=PE++}static get(e,t){if(!t.length)return e;let n=t[0].instances.find(o=>o.base==e&&DE(t,o.modified));if(n)return n;let a=[],s=new Ct(e.name,a,e,t);for(let o of t)o.instances.push(s);let r=BE(t);for(let o of e.set)if(!o.modified.length)for(let l of r)a.push(As.get(o,l));return s}}function DE(i,e){return i.length==e.length&&i.every((t,n)=>t==e[n])}function BE(i){let e=[[]];for(let t=0;tn.length-t.length)}function Up(i){let e=Object.create(null);for(let t in i){let n=i[t];Array.isArray(n)||(n=[n]);for(let a of t.split(" "))if(a){let s=[],r=2,o=a;for(let m=0;;){if(o=="..."&&m>0&&m+3==a.length){r=1;break}let d=/^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(o);if(!d)throw new RangeError("Invalid path: "+a);if(s.push(d[0]=="*"?"":d[0][0]=='"'?JSON.parse(d[0]):d[0]),m+=d[0].length,m==a.length)break;let h=a[m++];if(m==a.length&&h=="!"){r=0;break}if(h!="/")throw new RangeError("Invalid path: "+a);o=a.slice(m)}let l=s.length-1,u=s[l];if(!u)throw new RangeError("Invalid path: "+a);let c=new Di(n,r,l>0?s.slice(0,l):null);e[u]=c.sort(e[u])}}return $p.add(e)}const $p=new ae({combine(i,e){let t,n,a;for(;i||e;){if(!i||e&&i.depth<=e.depth?(a=e,e=e.next):(a=i,i=i.next),t&&t.mode==a.mode&&!a.context&&!t.context)continue;let s=new Di(a.tags,a.mode,a.context);t?t.next=s:n=s,t=s}return n}});class Di{constructor(e,t,n,a){this.tags=e,this.mode=t,this.context=n,this.next=a}get opaque(){return this.mode==0}get inherit(){return this.mode==1}sort(e){return!e||e.depth{let r=a;for(let o of s)for(let l of o.set){let u=t[l.id];if(u){r=r?r+" "+u:u;break}}return r},scope:n}}function ME(i,e){let t=null;for(let n of i){let a=n.style(e);a&&(t=t?t+" "+a:a)}return t}function ZE(i,e,t,n=0,a=i.length){let s=new LE(n,Array.isArray(e)?e:[e],t);s.highlightRange(i.cursor(),n,a,"",s.highlighters),s.flush(a)}class LE{constructor(e,t,n){this.at=e,this.highlighters=t,this.span=n,this.class=""}startSpan(e,t){t!=this.class&&(this.flush(e),e>this.at&&(this.at=e),this.class=t)}flush(e){e>this.at&&this.class&&this.span(this.at,e,this.class)}highlightRange(e,t,n,a,s){let{type:r,from:o,to:l}=e;if(o>=n||l<=t)return;r.isTop&&(s=this.highlighters.filter(h=>!h.scope||h.scope(r)));let u=a,c=EE(e)||Di.empty,m=ME(s,c.tags);if(m&&(u&&(u+=" "),u+=m,c.mode==1&&(a+=(a?" ":"")+m)),this.startSpan(Math.max(t,o),u),c.opaque)return;let d=e.tree&&e.tree.prop(ae.mounted);if(d&&d.overlay){let h=e.node.enter(d.overlay[0].from+o,1),g=this.highlighters.filter(b=>!b.scope||b.scope(d.tree.type)),f=e.firstChild();for(let b=0,x=o;;b++){let v=b=w||!e.nextSibling())););if(!v||w>n)break;x=v.to+o,x>t&&(this.highlightRange(h.cursor(),Math.max(t,v.from+o),Math.min(n,x),"",g),this.startSpan(Math.min(n,x),u))}f&&e.parent()}else if(e.firstChild()){d&&(a="");do if(!(e.to<=t)){if(e.from>=n)break;this.highlightRange(e,t,n,a,s),this.startSpan(Math.min(n,e.to),u)}while(e.nextSibling());e.parent()}}}function EE(i){let e=i.type.prop($p);for(;e&&e.context&&!i.matchContext(e.context);)e=e.next;return e||null}const F=Ct.define,Ta=F(),kn=F(),bm=F(kn),xm=F(kn),Sn=F(),_a=F(Sn),Gr=F(Sn),en=F(),Rn=F(en),Xt=F(),Kt=F(),Il=F(),Q1=F(Il),Aa=F(),L={comment:Ta,lineComment:F(Ta),blockComment:F(Ta),docComment:F(Ta),name:kn,variableName:F(kn),typeName:bm,tagName:F(bm),propertyName:xm,attributeName:F(xm),className:F(kn),labelName:F(kn),namespace:F(kn),macroName:F(kn),literal:Sn,string:_a,docString:F(_a),character:F(_a),attributeValue:F(_a),number:Gr,integer:F(Gr),float:F(Gr),bool:F(Sn),regexp:F(Sn),escape:F(Sn),color:F(Sn),url:F(Sn),keyword:Xt,self:F(Xt),null:F(Xt),atom:F(Xt),unit:F(Xt),modifier:F(Xt),operatorKeyword:F(Xt),controlKeyword:F(Xt),definitionKeyword:F(Xt),moduleKeyword:F(Xt),operator:Kt,derefOperator:F(Kt),arithmeticOperator:F(Kt),logicOperator:F(Kt),bitwiseOperator:F(Kt),compareOperator:F(Kt),updateOperator:F(Kt),definitionOperator:F(Kt),typeOperator:F(Kt),controlOperator:F(Kt),punctuation:Il,separator:F(Il),bracket:Q1,angleBracket:F(Q1),squareBracket:F(Q1),paren:F(Q1),brace:F(Q1),content:en,heading:Rn,heading1:F(Rn),heading2:F(Rn),heading3:F(Rn),heading4:F(Rn),heading5:F(Rn),heading6:F(Rn),contentSeparator:F(en),list:F(en),quote:F(en),emphasis:F(en),strong:F(en),link:F(en),monospace:F(en),strikethrough:F(en),inserted:F(),deleted:F(),changed:F(),invalid:F(),meta:Aa,documentMeta:F(Aa),annotation:F(Aa),processingInstruction:F(Aa),definition:Ct.defineModifier("definition"),constant:Ct.defineModifier("constant"),function:Ct.defineModifier("function"),standard:Ct.defineModifier("standard"),local:Ct.defineModifier("local"),special:Ct.defineModifier("special")};for(let i in L){let e=L[i];e instanceof Ct&&(e.name=i)}Yp([{tag:L.link,class:"tok-link"},{tag:L.heading,class:"tok-heading"},{tag:L.emphasis,class:"tok-emphasis"},{tag:L.strong,class:"tok-strong"},{tag:L.keyword,class:"tok-keyword"},{tag:L.atom,class:"tok-atom"},{tag:L.bool,class:"tok-bool"},{tag:L.url,class:"tok-url"},{tag:L.labelName,class:"tok-labelName"},{tag:L.inserted,class:"tok-inserted"},{tag:L.deleted,class:"tok-deleted"},{tag:L.literal,class:"tok-literal"},{tag:L.string,class:"tok-string"},{tag:L.number,class:"tok-number"},{tag:[L.regexp,L.escape,L.special(L.string)],class:"tok-string2"},{tag:L.variableName,class:"tok-variableName"},{tag:L.local(L.variableName),class:"tok-variableName tok-local"},{tag:L.definition(L.variableName),class:"tok-variableName tok-definition"},{tag:L.special(L.variableName),class:"tok-variableName2"},{tag:L.definition(L.propertyName),class:"tok-propertyName tok-definition"},{tag:L.typeName,class:"tok-typeName"},{tag:L.namespace,class:"tok-namespace"},{tag:L.className,class:"tok-className"},{tag:L.macroName,class:"tok-macroName"},{tag:L.propertyName,class:"tok-propertyName"},{tag:L.operator,class:"tok-operator"},{tag:L.comment,class:"tok-comment"},{tag:L.meta,class:"tok-meta"},{tag:L.invalid,class:"tok-invalid"},{tag:L.punctuation,class:"tok-punctuation"}]);var Hr;const w1=new ae;function WE(i){return V.define({combine:i?e=>e.concat(i):void 0})}const NE=new ae;class Ht{constructor(e,t,n=[],a=""){this.data=e,this.name=a,re.prototype.hasOwnProperty("tree")||Object.defineProperty(re.prototype,"tree",{get(){return Xe(this)}}),this.parser=t,this.extension=[L1.of(this),re.languageData.of((s,r,o)=>{let l=vm(s,r,o),u=l.type.prop(w1);if(!u)return[];let c=s.facet(u),m=l.type.prop(NE);if(m){let d=l.resolve(r-l.from,o);for(let h of m)if(h.test(d,s)){let g=s.facet(h.facet);return h.type=="replace"?g:g.concat(c)}}return c})].concat(n)}isActiveAt(e,t,n=-1){return vm(e,t,n).type.prop(w1)==this.data}findRegions(e){let t=e.facet(L1);if((t==null?void 0:t.data)==this.data)return[{from:0,to:e.doc.length}];if(!t||!t.allowsNesting)return[];let n=[],a=(s,r)=>{if(s.prop(w1)==this.data){n.push({from:r,to:r+s.length});return}let o=s.prop(ae.mounted);if(o){if(o.tree.prop(w1)==this.data){if(o.overlay)for(let l of o.overlay)n.push({from:l.from+r,to:l.to+r});else n.push({from:r,to:r+s.length});return}else if(o.overlay){let l=n.length;if(a(o.tree,o.overlay[0].from+r),n.length>l)return}}for(let l=0;ln.isTop?t:void 0)]}),e.name)}configure(e,t){return new Os(this.data,this.parser.configure(e),t||this.name)}get allowsNesting(){return this.parser.hasWrappers()}}function Xe(i){let e=i.field(Ht.state,!1);return e?e.tree:Ze.empty}class FE{constructor(e){this.doc=e,this.cursorPos=0,this.string="",this.cursor=e.iter()}get length(){return this.doc.length}syncTo(e){return this.string=this.cursor.next(e-this.cursorPos).value,this.cursorPos=e+this.string.length,this.cursorPos-this.string.length}chunk(e){return this.syncTo(e),this.string}get lineChunks(){return!0}read(e,t){let n=this.cursorPos-this.string.length;return e=this.cursorPos?this.doc.sliceString(e,t):this.string.slice(e-n,t-n)}}let U1=null;class Cs{constructor(e,t,n=[],a,s,r,o,l){this.parser=e,this.state=t,this.fragments=n,this.tree=a,this.treeLen=s,this.viewport=r,this.skipped=o,this.scheduleOn=l,this.parse=null,this.tempSkipped=[]}static create(e,t,n){return new Cs(e,t,[],Ze.empty,0,n,[],null)}startParse(){return this.parser.startParse(new FE(this.state.doc),this.fragments)}work(e,t){return t!=null&&t>=this.state.doc.length&&(t=void 0),this.tree!=Ze.empty&&this.isDone(t??this.state.doc.length)?(this.takeTree(),!0):this.withContext(()=>{var n;if(typeof e=="number"){let a=Date.now()+e;e=()=>Date.now()>a}for(this.parse||(this.parse=this.startParse()),t!=null&&(this.parse.stoppedAt==null||this.parse.stoppedAt>t)&&t=this.treeLen&&((this.parse.stoppedAt==null||this.parse.stoppedAt>e)&&this.parse.stopAt(e),this.withContext(()=>{for(;!(t=this.parse.advance()););}),this.treeLen=e,this.tree=t,this.fragments=this.withoutTempSkipped(i1.addTree(this.tree,this.fragments,!0)),this.parse=null)}withContext(e){let t=U1;U1=this;try{return e()}finally{U1=t}}withoutTempSkipped(e){for(let t;t=this.tempSkipped.pop();)e=ym(e,t.from,t.to);return e}changes(e,t){let{fragments:n,tree:a,treeLen:s,viewport:r,skipped:o}=this;if(this.takeTree(),!e.empty){let l=[];if(e.iterChangedRanges((u,c,m,d)=>l.push({fromA:u,toA:c,fromB:m,toB:d})),n=i1.applyChanges(n,l),a=Ze.empty,s=0,r={from:e.mapPos(r.from,-1),to:e.mapPos(r.to,1)},this.skipped.length){o=[];for(let u of this.skipped){let c=e.mapPos(u.from,1),m=e.mapPos(u.to,-1);ce.from&&(this.fragments=ym(this.fragments,a,s),this.skipped.splice(n--,1))}return this.skipped.length>=t?!1:(this.reset(),!0)}reset(){this.parse&&(this.takeTree(),this.parse=null)}skipUntilInView(e,t){this.skipped.push({from:e,to:t})}static getSkippingParser(e){return new class extends Qp{createParse(t,n,a){let s=a[0].from,r=a[a.length-1].to;return{parsedPos:s,advance(){let l=U1;if(l){for(let u of a)l.tempSkipped.push(u);e&&(l.scheduleOn=l.scheduleOn?Promise.all([l.scheduleOn,e]):e)}return this.parsedPos=r,new Ze(ft.none,[],[],r-s)},stoppedAt:null,stopAt(){}}}}}isDone(e){e=Math.min(e,this.state.doc.length);let t=this.fragments;return this.treeLen>=e&&t.length&&t[0].from==0&&t[0].to>=e}static get(){return U1}}function ym(i,e,t){return i1.applyChanges(i,[{fromA:e,toA:t,fromB:e,toB:t}])}class Z1{constructor(e){this.context=e,this.tree=e.tree}apply(e){if(!e.docChanged&&this.tree==this.context.tree)return this;let t=this.context.changes(e.changes,e.state),n=this.context.treeLen==e.startState.doc.length?void 0:Math.max(e.changes.mapPos(this.context.treeLen),t.viewport.to);return t.work(20,n)||t.takeTree(),new Z1(t)}static init(e){let t=Math.min(3e3,e.doc.length),n=Cs.create(e.facet(L1).parser,e,{from:0,to:t});return n.work(20,t)||n.takeTree(),new Z1(n)}}Ht.state=Et.define({create:Z1.init,update(i,e){for(let t of e.effects)if(t.is(Ht.setState))return t.value;return e.startState.facet(L1)!=e.state.facet(L1)?Z1.init(e.state):i.apply(e)}});let Xp=i=>{let e=setTimeout(()=>i(),500);return()=>clearTimeout(e)};typeof requestIdleCallback<"u"&&(Xp=i=>{let e=-1,t=setTimeout(()=>{e=requestIdleCallback(i,{timeout:400})},100);return()=>e<0?clearTimeout(t):cancelIdleCallback(e)});const Vr=typeof navigator<"u"&&(!((Hr=navigator.scheduling)===null||Hr===void 0)&&Hr.isInputPending)?()=>navigator.scheduling.isInputPending():null,JE=Lt.fromClass(class{constructor(e){this.view=e,this.working=null,this.workScheduled=0,this.chunkEnd=-1,this.chunkBudget=-1,this.work=this.work.bind(this),this.scheduleWork()}update(e){let t=this.view.state.field(Ht.state).context;(t.updateViewport(e.view.viewport)||this.view.viewport.to>t.treeLen)&&this.scheduleWork(),(e.docChanged||e.selectionSet)&&(this.view.hasFocus&&(this.chunkBudget+=50),this.scheduleWork()),this.checkAsyncSchedule(t)}scheduleWork(){if(this.working)return;let{state:e}=this.view,t=e.field(Ht.state);(t.tree!=t.context.tree||!t.context.isDone(e.doc.length))&&(this.working=Xp(this.work))}work(e){this.working=null;let t=Date.now();if(this.chunkEnda+1e3,l=s.context.work(()=>Vr&&Vr()||Date.now()>r,a+(o?0:1e5));this.chunkBudget-=Date.now()-t,(l||this.chunkBudget<=0)&&(s.context.takeTree(),this.view.dispatch({effects:Ht.setState.of(new Z1(s.context))})),this.chunkBudget>0&&!(l&&!o)&&this.scheduleWork(),this.checkAsyncSchedule(s.context)}checkAsyncSchedule(e){e.scheduleOn&&(this.workScheduled++,e.scheduleOn.then(()=>this.scheduleWork()).catch(t=>wt(this.view.state,t)).then(()=>this.workScheduled--),e.scheduleOn=null)}destroy(){this.working&&this.working()}isWorking(){return!!(this.working||this.workScheduled>0)}},{eventHandlers:{focus(){this.scheduleWork()}}}),L1=V.define({combine(i){return i.length?i[0]:null},enables:i=>[Ht.state,JE,Q.contentAttributes.compute([i],e=>{let t=e.facet(i);return t&&t.name?{"data-language":t.name}:{}})]});class RE{constructor(e,t=[]){this.language=e,this.support=t,this.extension=[e,t]}}const GE=V.define(),Vi=V.define({combine:i=>{if(!i.length)return" ";let e=i[0];if(!e||/\S/.test(e)||Array.from(e).some(t=>t!=e[0]))throw new Error("Invalid indent unit: "+JSON.stringify(i[0]));return e}});function js(i){let e=i.facet(Vi);return e.charCodeAt(0)==9?i.tabSize*e.length:e.length}function Bi(i,e){let t="",n=i.tabSize,a=i.facet(Vi)[0];if(a==" "){for(;e>=n;)t+=" ",e-=n;a=" "}for(let s=0;s=e?HE(i,t,e):null}class ar{constructor(e,t={}){this.state=e,this.options=t,this.unit=js(e)}lineAt(e,t=1){let n=this.state.doc.lineAt(e),{simulateBreak:a,simulateDoubleBreak:s}=this.options;return a!=null&&a>=n.from&&a<=n.to?s&&a==e?{text:"",from:e}:(t<0?a-1&&(s+=r-this.countColumn(n,n.search(/\S|$/))),s}countColumn(e,t=e.length){return Fi(e,this.state.tabSize,t)}lineIndent(e,t=1){let{text:n,from:a}=this.lineAt(e,t),s=this.options.overrideIndentation;if(s){let r=s(a);if(r>-1)return r}return this.countColumn(n,n.search(/\S|$/))}get simulatedBreak(){return this.options.simulateBreak||null}}const Kp=new ae;function HE(i,e,t){let n=e.resolveStack(t),a=e.resolveInner(t,-1).resolve(t,0).enterUnfinishedNodesBefore(t);if(a!=n.node){let s=[];for(let r=a;r&&!(r.fromn.node.to||r.from==n.node.from&&r.type==n.node.type);r=r.parent)s.push(r);for(let r=s.length-1;r>=0;r--)n={node:s[r],next:n}}return ef(n,i,t)}function ef(i,e,t){for(let n=i;n;n=n.next){let a=qE(n.node);if(a)return a(D0.create(e,t,n))}return 0}function VE(i){return i.pos==i.options.simulateBreak&&i.options.simulateDoubleBreak}function qE(i){let e=i.type.prop(Kp);if(e)return e;let t=i.firstChild,n;if(t&&(n=t.type.prop(ae.closedBy))){let a=i.lastChild,s=a&&n.indexOf(a.name)>-1;return r=>tf(r,!0,1,void 0,s&&!VE(r)?a.from:void 0)}return i.parent==null?QE:null}function QE(){return 0}class D0 extends ar{constructor(e,t,n){super(e.state,e.options),this.base=e,this.pos=t,this.context=n}get node(){return this.context.node}static create(e,t,n){return new D0(e,t,n)}get textAfter(){return this.textAfterPos(this.pos)}get baseIndent(){return this.baseIndentFor(this.node)}baseIndentFor(e){let t=this.state.doc.lineAt(e.from);for(;;){let n=e.resolve(t.from);for(;n.parent&&n.parent.from==n.from;)n=n.parent;if(UE(n,e))break;t=this.state.doc.lineAt(n.from)}return this.lineIndent(t.from)}continue(){return ef(this.context.next,this.base,this.pos)}}function UE(i,e){for(let t=e;t;t=t.parent)if(i==t)return!0;return!1}function $E(i){let e=i.node,t=e.childAfter(e.from),n=e.lastChild;if(!t)return null;let a=i.options.simulateBreak,s=i.state.doc.lineAt(t.from),r=a==null||a<=s.from?s.to:Math.min(s.to,a);for(let o=t.to;;){let l=e.childAfter(o);if(!l||l==n)return null;if(!l.type.isSkipped){if(l.from>=r)return null;let u=/^ */.exec(s.text.slice(t.to-s.from))[0].length;return{from:t.from,to:t.to+u}}o=l.to}}function YE({closing:i,align:e=!0,units:t=1}){return n=>tf(n,e,t,i)}function tf(i,e,t,n,a){let s=i.textAfter,r=s.match(/^\s*/)[0].length,o=n&&s.slice(r,r+n.length)==n||a==i.pos+r,l=e?$E(i):null;return l?o?i.column(l.from):i.column(l.to):i.baseIndent+(o?0:i.unit*t)}const XE=i=>i.baseIndent;function qr({except:i,units:e=1}={}){return t=>{let n=i&&i.test(t.textAfter);return t.baseIndent+(n?0:e*t.unit)}}const KE=200;function eW(){return re.transactionFilter.of(i=>{if(!i.docChanged||!i.isUserEvent("input.type")&&!i.isUserEvent("input.complete"))return i;let e=i.startState.languageDataAt("indentOnInput",i.startState.selection.main.head);if(!e.length)return i;let t=i.newDoc,{head:n}=i.newSelection.main,a=t.lineAt(n);if(n>a.from+KE)return i;let s=t.sliceString(a.from,n);if(!e.some(u=>u.test(s)))return i;let{state:r}=i,o=-1,l=[];for(let{head:u}of r.selection.ranges){let c=r.doc.lineAt(u);if(c.from==o)continue;o=c.from;let m=P0(r,c.from);if(m==null)continue;let d=/^\s*/.exec(c.text)[0],h=Bi(r,m);d!=h&&l.push({from:c.from,to:c.from+d.length,insert:h})}return l.length?[i,{changes:l,sequential:!0}]:i})}const tW=new ae;function nW(i){let e=i.firstChild,t=i.lastChild;return e&&e.too.prop(w1)==r.data:r?o=>o==r:void 0,this.style=Yp(e.map(o=>({tag:o.tag,class:o.class||a(Object.assign({},o,{tag:null}))})),{all:s}).style,this.module=n?new Mn(n):null,this.themeType=t.themeType}static define(e,t){return new sr(e,t||{})}}const kl=V.define(),iW=V.define({combine(i){return i.length?[i[0]]:null}});function Qr(i){let e=i.facet(kl);return e.length?e:i.facet(iW)}function aW(i,e){let t=[rW],n;return i instanceof sr&&(i.module&&t.push(Q.styleModule.of(i.module)),n=i.themeType),n?t.push(kl.computeN([Q.darkTheme],a=>a.facet(Q.darkTheme)==(n=="dark")?[i]:[])):t.push(kl.of(i)),t}class sW{constructor(e){this.markCache=Object.create(null),this.tree=Xe(e.state),this.decorations=this.buildDeco(e,Qr(e.state)),this.decoratedTo=e.viewport.to}update(e){let t=Xe(e.state),n=Qr(e.state),a=n!=Qr(e.startState),{viewport:s}=e.view,r=e.changes.mapPos(this.decoratedTo,1);t.length=s.to?(this.decorations=this.decorations.map(e.changes),this.decoratedTo=r):(t!=this.tree||e.viewportChanged||a)&&(this.tree=t,this.decorations=this.buildDeco(e.view,n),this.decoratedTo=s.to)}buildDeco(e,t){if(!t||!this.tree.length)return pe.none;let n=new n1;for(let{from:a,to:s}of e.visibleRanges)ZE(this.tree,t,(r,o,l)=>{n.add(r,o,this.markCache[l]||(this.markCache[l]=pe.mark({class:l})))},a,s);return n.finish()}}const rW=l1.high(Lt.fromClass(sW,{decorations:i=>i.decorations})),oW=Q.baseTheme({"&.cm-focused .cm-matchingBracket":{backgroundColor:"#328c8252"},"&.cm-focused .cm-nonmatchingBracket":{backgroundColor:"#bb555544"}}),nf=1e4,af="()[]{}",sf=V.define({combine(i){return p0(i,{afterCursor:!0,brackets:af,maxScanDistance:nf,renderMatch:cW})}}),lW=pe.mark({class:"cm-matchingBracket"}),uW=pe.mark({class:"cm-nonmatchingBracket"});function cW(i){let e=[],t=i.matched?lW:uW;return e.push(t.range(i.start.from,i.start.to)),i.end&&e.push(t.range(i.end.from,i.end.to)),e}function wm(i){let e=[],t=i.facet(sf);for(let n of i.selection.ranges){if(!n.empty)continue;let a=on(i,n.head,-1,t)||n.head>0&&on(i,n.head-1,1,t)||t.afterCursor&&(on(i,n.head,1,t)||n.headi.decorations}),dW=[mW,oW];function hW(i={}){return[sf.of(i),dW]}const gW=new ae;function Sl(i,e,t){let n=i.prop(e<0?ae.openedBy:ae.closedBy);if(n)return n;if(i.name.length==1){let a=t.indexOf(i.name);if(a>-1&&a%2==(e<0?1:0))return[t[a+e]]}return null}function Tl(i){let e=i.type.prop(gW);return e?e(i.node):i}function on(i,e,t,n={}){let a=n.maxScanDistance||nf,s=n.brackets||af,r=Xe(i),o=r.resolveInner(e,t);for(let l=o;l;l=l.parent){let u=Sl(l.type,t,s);if(u&&l.from0?e>=c.from&&ec.from&&e<=c.to))return pW(i,e,t,l,c,u,s)}}return fW(i,e,t,r,o.type,a,s)}function pW(i,e,t,n,a,s,r){let o=n.parent,l={from:a.from,to:a.to},u=0,c=o==null?void 0:o.cursor();if(c&&(t<0?c.childBefore(n.from):c.childAfter(n.to)))do if(t<0?c.to<=n.from:c.from>=n.to){if(u==0&&s.indexOf(c.type.name)>-1&&c.from0)return null;let u={from:t<0?e-1:e,to:t>0?e+1:e},c=i.doc.iterRange(e,t>0?i.doc.length:0),m=0;for(let d=0;!c.next().done&&d<=s;){let h=c.value;t<0&&(d+=h.length);let g=e+d*t;for(let f=t>0?0:h.length-1,b=t>0?h.length:-1;f!=b;f+=t){let x=r.indexOf(h[f]);if(!(x<0||n.resolveInner(g+f,1).type!=a))if(x%2==0==t>0)m++;else{if(m==1)return{start:u,end:{from:g+f,to:g+f+1},matched:x>>1==l>>1};m--}}t>0&&(d+=h.length)}return c.done?{start:u,matched:!1}:null}const bW=Object.create(null),zm=[ft.none],Im=[],km=Object.create(null),xW=Object.create(null);for(let[i,e]of[["variable","variableName"],["variable-2","variableName.special"],["string-2","string.special"],["def","variableName.definition"],["tag","tagName"],["attribute","attributeName"],["type","typeName"],["builtin","variableName.standard"],["qualifier","modifier"],["error","invalid"],["header","heading"],["property","propertyName"]])xW[i]=vW(bW,e);function Ur(i,e){Im.indexOf(i)>-1||(Im.push(i),console.warn(e))}function vW(i,e){let t=[];for(let o of e.split(" ")){let l=[];for(let u of o.split(".")){let c=i[u]||L[u];c?typeof c=="function"?l.length?l=l.map(c):Ur(u,`Modifier ${u} used at start of tag`):l.length?Ur(u,`Tag ${u} used as modifier`):l=Array.isArray(c)?c:[c]:Ur(u,`Unknown highlighting tag ${u}`)}for(let u of l)t.push(u)}if(!t.length)return 0;let n=e.replace(/ /g,"_"),a=n+" "+t.map(o=>o.id),s=km[a];if(s)return s.id;let r=km[a]=ft.define({id:zm.length,name:n,props:[Up({[n]:t})]});return zm.push(r),r.id}ye.RTL,ye.LTR;class rf{constructor(e,t,n,a){this.state=e,this.pos=t,this.explicit=n,this.view=a,this.abortListeners=[],this.abortOnDocChange=!1}tokenBefore(e){let t=Xe(this.state).resolveInner(this.pos,-1);for(;t&&e.indexOf(t.name)<0;)t=t.parent;return t?{from:t.from,to:this.pos,text:this.state.sliceDoc(t.from,this.pos),type:t.type}:null}matchBefore(e){let t=this.state.doc.lineAt(this.pos),n=Math.max(t.from,this.pos-250),a=t.text.slice(n-t.from,this.pos-t.from),s=a.search(of(e,!1));return s<0?null:{from:n+s,to:this.pos,text:a.slice(s)}}get aborted(){return this.abortListeners==null}addEventListener(e,t,n){e=="abort"&&this.abortListeners&&(this.abortListeners.push(t),n&&n.onDocChange&&(this.abortOnDocChange=!0))}}function Sm(i){let e=Object.keys(i).join(""),t=/\w/.test(e);return t&&(e=e.replace(/\w/g,"")),`[${t?"\\w":""}${e.replace(/[^\w\s]/g,"\\$&")}]`}function yW(i){let e=Object.create(null),t=Object.create(null);for(let{label:a}of i){e[a[0]]=!0;for(let s=1;stypeof a=="string"?{label:a}:a),[t,n]=e.every(a=>/^\w+$/.test(a.label))?[/\w*$/,/\w+$/]:yW(e);return a=>{let s=a.matchBefore(n);return s||a.explicit?{from:s?s.from:a.pos,options:e,validFor:t}:null}}class Tm{constructor(e,t,n,a){this.completion=e,this.source=t,this.match=n,this.score=a}}function a1(i){return i.selection.main.from}function of(i,e){var t;let{source:n}=i,a=e&&n[0]!="^",s=n[n.length-1]!="$";return!a&&!s?i:new RegExp(`${a?"^":""}(?:${n})${s?"$":""}`,(t=i.flags)!==null&&t!==void 0?t:i.ignoreCase?"i":"")}const B0=Wn.define();function zW(i,e,t,n){let{main:a}=i.selection,s=t-a.from,r=n-a.from;return{...i.changeByRange(o=>{if(o!=a&&t!=n&&i.sliceDoc(o.from+s,o.from+r)!=i.sliceDoc(t,n))return{range:o};let l=i.toText(e);return{changes:{from:o.from+s,to:n==a.from?o.to:o.from+r,insert:l},range:B.cursor(o.from+s+l.length)}}),scrollIntoView:!0,userEvent:"input.complete"}}const _m=new WeakMap;function IW(i){if(!Array.isArray(i))return i;let e=_m.get(i);return e||_m.set(i,e=wW(i)),e}const Ps=de.define(),Mi=de.define();class kW{constructor(e){this.pattern=e,this.chars=[],this.folded=[],this.any=[],this.precise=[],this.byWord=[],this.score=0,this.matched=[];for(let t=0;t=48&&z<=57||z>=97&&z<=122?2:z>=65&&z<=90?1:0:(k=Cg(z))!=k.toLowerCase()?1:k!=k.toUpperCase()?2:0;(!v||T==1&&b||I==0&&T!=0)&&(t[m]==z||n[m]==z&&(d=!0)?r[m++]=v:r.length&&(x=!1)),I=T,v+=mn(z)}return m==l&&r[0]==0&&x?this.result(-100+(d?-200:0),r,e):h==l&&g==0?this.ret(-200-e.length+(f==e.length?0:-100),[0,f]):o>-1?this.ret(-700-e.length,[o,o+this.pattern.length]):h==l?this.ret(-900-e.length,[g,f]):m==l?this.result(-100+(d?-200:0)+-700+(x?0:-1100),r,e):t.length==2?null:this.result((a[0]?-700:0)+-200+-1100,a,e)}result(e,t,n){let a=[],s=0;for(let r of t){let o=r+(this.astral?mn(Ot(n,r)):1);s&&a[s-1]==r?a[s-1]=o:(a[s++]=r,a[s++]=o)}return this.ret(e-n.length,a)}}class SW{constructor(e){this.pattern=e,this.matched=[],this.score=0,this.folded=e.toLowerCase()}match(e){if(e.length!1,activateOnTypingDelay:100,selectOnOpen:!0,override:null,closeOnBlur:!0,maxRenderedOptions:100,defaultKeymap:!0,tooltipClass:()=>"",optionClass:()=>"",aboveCursor:!1,icons:!0,addToOptions:[],positionInfo:TW,filterStrict:!1,compareCompletions:(e,t)=>(e.sortText||e.label).localeCompare(t.sortText||t.label),interactionDelay:75,updateSyncTime:100},{defaultKeymap:(e,t)=>e&&t,closeOnBlur:(e,t)=>e&&t,icons:(e,t)=>e&&t,tooltipClass:(e,t)=>n=>Am(e(n),t(n)),optionClass:(e,t)=>n=>Am(e(n),t(n)),addToOptions:(e,t)=>e.concat(t),filterStrict:(e,t)=>e||t})}});function Am(i,e){return i?e?i+" "+e:i:e}function TW(i,e,t,n,a,s){let r=i.textDirection==ye.RTL,o=r,l=!1,u="top",c,m,d=e.left-a.left,h=a.right-e.right,g=n.right-n.left,f=n.bottom-n.top;if(o&&d=f||v>e.top?c=t.bottom-e.top:(u="bottom",c=e.bottom-t.top)}let b=(e.bottom-e.top)/s.offsetHeight,x=(e.right-e.left)/s.offsetWidth;return{style:`${u}: ${c/b}px; max-width: ${m/x}px`,class:"cm-completionInfo-"+(l?r?"left-narrow":"right-narrow":o?"left":"right")}}const M0=de.define();function _W(i){let e=i.addToOptions.slice();return i.icons&&e.push({render(t){let n=document.createElement("div");return n.classList.add("cm-completionIcon"),t.type&&n.classList.add(...t.type.split(/\s+/g).map(a=>"cm-completionIcon-"+a)),n.setAttribute("aria-hidden","true"),n},position:20}),e.push({render(t,n,a,s){let r=document.createElement("span");r.className="cm-completionLabel";let o=t.displayLabel||t.label,l=0;for(let u=0;ul&&r.appendChild(document.createTextNode(o.slice(l,c)));let d=r.appendChild(document.createElement("span"));d.appendChild(document.createTextNode(o.slice(c,m))),d.className="cm-completionMatchedText",l=m}return lt.position-n.position).map(t=>t.render)}function $r(i,e,t){if(i<=t)return{from:0,to:i};if(e<0&&(e=0),e<=i>>1){let a=Math.floor(e/t);return{from:a*t,to:(a+1)*t}}let n=Math.ceil((i-e)/t);return{from:i-n*t,to:i-(n-1)*t}}class AW{constructor(e,t,n){this.view=e,this.stateField=t,this.applyCompletion=n,this.info=null,this.infoDestroy=null,this.placeInfoReq={read:()=>this.measureInfo(),write:l=>this.placeInfo(l),key:this},this.space=null,this.currentClass="";let a=e.state.field(t),{options:s,selected:r}=a.open,o=e.state.facet(Ge);this.optionContent=_W(o),this.optionClass=o.optionClass,this.tooltipClass=o.tooltipClass,this.range=$r(s.length,r,o.maxRenderedOptions),this.dom=document.createElement("div"),this.dom.className="cm-tooltip-autocomplete",this.updateTooltipClass(e.state),this.dom.addEventListener("mousedown",l=>{let{options:u}=e.state.field(t).open;for(let c=l.target,m;c&&c!=this.dom;c=c.parentNode)if(c.nodeName=="LI"&&(m=/-(\d+)$/.exec(c.id))&&+m[1]this.list.lastChild.getBoundingClientRect().bottom?this.range.to:null;c!=null&&(e.dispatch({effects:M0.of(c)}),l.preventDefault())}}),this.dom.addEventListener("focusout",l=>{let u=e.state.field(this.stateField,!1);u&&u.tooltip&&e.state.facet(Ge).closeOnBlur&&l.relatedTarget!=e.contentDOM&&e.dispatch({effects:Mi.of(null)})}),this.showOptions(s,a.id)}mount(){this.updateSel()}showOptions(e,t){this.list&&this.list.remove(),this.list=this.dom.appendChild(this.createListBox(e,t,this.range)),this.list.addEventListener("scroll",()=>{this.info&&this.view.requestMeasure(this.placeInfoReq)})}update(e){var t;let n=e.state.field(this.stateField),a=e.startState.field(this.stateField);if(this.updateTooltipClass(e.state),n!=a){let{options:s,selected:r,disabled:o}=n.open;(!a.open||a.open.options!=s)&&(this.range=$r(s.length,r,e.state.facet(Ge).maxRenderedOptions),this.showOptions(s,n.id)),this.updateSel(),o!=((t=a.open)===null||t===void 0?void 0:t.disabled)&&this.dom.classList.toggle("cm-tooltip-autocomplete-disabled",!!o)}}updateTooltipClass(e){let t=this.tooltipClass(e);if(t!=this.currentClass){for(let n of this.currentClass.split(" "))n&&this.dom.classList.remove(n);for(let n of t.split(" "))n&&this.dom.classList.add(n);this.currentClass=t}}positioned(e){this.space=e,this.info&&this.view.requestMeasure(this.placeInfoReq)}updateSel(){let e=this.view.state.field(this.stateField),t=e.open;(t.selected>-1&&t.selected=this.range.to)&&(this.range=$r(t.options.length,t.selected,this.view.state.facet(Ge).maxRenderedOptions),this.showOptions(t.options,e.id));let n=this.updateSelectedOption(t.selected);if(n){this.destroyInfo();let{completion:a}=t.options[t.selected],{info:s}=a;if(!s)return;let r=typeof s=="string"?document.createTextNode(s):s(a);if(!r)return;"then"in r?r.then(o=>{o&&this.view.state.field(this.stateField,!1)==e&&this.addInfoPane(o,a)}).catch(o=>wt(this.view.state,o,"completion info")):(this.addInfoPane(r,a),n.setAttribute("aria-describedby",this.info.id))}}addInfoPane(e,t){this.destroyInfo();let n=this.info=document.createElement("div");if(n.className="cm-tooltip cm-completionInfo",n.id="cm-completionInfo-"+Math.floor(Math.random()*65535).toString(16),e.nodeType!=null)n.appendChild(e),this.infoDestroy=null;else{let{dom:a,destroy:s}=e;n.appendChild(a),this.infoDestroy=s||null}this.dom.appendChild(n),this.view.requestMeasure(this.placeInfoReq)}updateSelectedOption(e){let t=null;for(let n=this.list.firstChild,a=this.range.from;n;n=n.nextSibling,a++)n.nodeName!="LI"||!n.id?a--:a==e?n.hasAttribute("aria-selected")||(n.setAttribute("aria-selected","true"),t=n):n.hasAttribute("aria-selected")&&(n.removeAttribute("aria-selected"),n.removeAttribute("aria-describedby"));return t&&CW(this.list,t),t}measureInfo(){let e=this.dom.querySelector("[aria-selected]");if(!e||!this.info)return null;let t=this.dom.getBoundingClientRect(),n=this.info.getBoundingClientRect(),a=e.getBoundingClientRect(),s=this.space;if(!s){let r=this.dom.ownerDocument.documentElement;s={left:0,top:0,right:r.clientWidth,bottom:r.clientHeight}}return a.top>Math.min(s.bottom,t.bottom)-10||a.bottom{r.target==a&&r.preventDefault()});let s=null;for(let r=n.from;rn.from||n.from==0))if(s=d,typeof u!="string"&&u.header)a.appendChild(u.header(u));else{let h=a.appendChild(document.createElement("completion-section"));h.textContent=d}}const c=a.appendChild(document.createElement("li"));c.id=t+"-"+r,c.setAttribute("role","option");let m=this.optionClass(o);m&&(c.className=m);for(let d of this.optionContent){let h=d(o,this.view.state,this.view,l);h&&c.appendChild(h)}}return n.from&&a.classList.add("cm-completionListIncompleteTop"),n.tonew AW(t,i,e)}function CW(i,e){let t=i.getBoundingClientRect(),n=e.getBoundingClientRect(),a=t.height/i.offsetHeight;n.topt.bottom&&(i.scrollTop+=(n.bottom-t.bottom)/a)}function Om(i){return(i.boost||0)*100+(i.apply?10:0)+(i.info?5:0)+(i.type?1:0)}function jW(i,e){let t=[],n=null,a=null,s=c=>{t.push(c);let{section:m}=c.completion;if(m){n||(n=[]);let d=typeof m=="string"?m:m.name;n.some(h=>h.name==d)||n.push(typeof m=="string"?{name:d}:m)}},r=e.facet(Ge);for(let c of i)if(c.hasResult()){let m=c.result.getMatch;if(c.result.filter===!1)for(let d of c.result.options)s(new Tm(d,c.source,m?m(d):[],1e9-t.length));else{let d=e.sliceDoc(c.from,c.to),h,g=r.filterStrict?new SW(d):new kW(d);for(let f of c.result.options)if(h=g.match(f.label)){let b=f.displayLabel?m?m(f,h.matched):[]:h.matched,x=h.score+(f.boost||0);if(s(new Tm(f,c.source,b,x)),typeof f.section=="object"&&f.section.rank==="dynamic"){let{name:v}=f.section;a||(a=Object.create(null)),a[v]=Math.max(x,a[v]||-1e9)}}}}if(n){let c=Object.create(null),m=0,d=(h,g)=>(h.rank==="dynamic"&&g.rank==="dynamic"?a[g.name]-a[h.name]:0)||(typeof h.rank=="number"?h.rank:1e9)-(typeof g.rank=="number"?g.rank:1e9)||(h.named.score-m.score||u(m.completion,d.completion))){let m=c.completion;!l||l.label!=m.label||l.detail!=m.detail||l.type!=null&&m.type!=null&&l.type!=m.type||l.apply!=m.apply||l.boost!=m.boost?o.push(c):Om(c.completion)>Om(l)&&(o[o.length-1]=c),l=c.completion}return o}class z1{constructor(e,t,n,a,s,r){this.options=e,this.attrs=t,this.tooltip=n,this.timestamp=a,this.selected=s,this.disabled=r}setSelected(e,t){return e==this.selected||e>=this.options.length?this:new z1(this.options,Cm(t,e),this.tooltip,this.timestamp,e,this.disabled)}static build(e,t,n,a,s,r){if(a&&!r&&e.some(u=>u.isPending))return a.setDisabled();let o=jW(e,t);if(!o.length)return a&&e.some(u=>u.isPending)?a.setDisabled():null;let l=t.facet(Ge).selectOnOpen?0:-1;if(a&&a.selected!=l&&a.selected!=-1){let u=a.options[a.selected].completion;for(let c=0;cc.hasResult()?Math.min(u,c.from):u,1e8),create:LW,above:s.aboveCursor},a?a.timestamp:Date.now(),l,!1)}map(e){return new z1(this.options,this.attrs,{...this.tooltip,pos:e.mapPos(this.tooltip.pos)},this.timestamp,this.selected,this.disabled)}setDisabled(){return new z1(this.options,this.attrs,this.tooltip,this.timestamp,this.selected,!0)}}class Ds{constructor(e,t,n){this.active=e,this.id=t,this.open=n}static start(){return new Ds(MW,"cm-ac-"+Math.floor(Math.random()*2e6).toString(36),null)}update(e){let{state:t}=e,n=t.facet(Ge),s=(n.override||t.languageDataAt("autocomplete",a1(t)).map(IW)).map(l=>(this.active.find(c=>c.source==l)||new Mt(l,this.active.some(c=>c.state!=0)?1:0)).update(e,n));s.length==this.active.length&&s.every((l,u)=>l==this.active[u])&&(s=this.active);let r=this.open,o=e.effects.some(l=>l.is(Z0));r&&e.docChanged&&(r=r.map(e.changes)),e.selection||s.some(l=>l.hasResult()&&e.changes.touchesRange(l.from,l.to))||!PW(s,this.active)||o?r=z1.build(s,t,this.id,r,n,o):r&&r.disabled&&!s.some(l=>l.isPending)&&(r=null),!r&&s.every(l=>!l.isPending)&&s.some(l=>l.hasResult())&&(s=s.map(l=>l.hasResult()?new Mt(l.source,0):l));for(let l of e.effects)l.is(M0)&&(r=r&&r.setSelected(l.value,this.id));return s==this.active&&r==this.open?this:new Ds(s,this.id,r)}get tooltip(){return this.open?this.open.tooltip:null}get attrs(){return this.open?this.open.attrs:this.active.length?DW:BW}}function PW(i,e){if(i==e)return!0;for(let t=0,n=0;;){for(;t-1&&(t["aria-activedescendant"]=i+"-"+e),t}const MW=[];function lf(i,e){if(i.isUserEvent("input.complete")){let n=i.annotation(B0);if(n&&e.activateOnCompletion(n))return 12}let t=i.isUserEvent("input.type");return t&&e.activateOnTyping?5:t?1:i.isUserEvent("delete.backward")?2:i.selection?8:i.docChanged?16:0}class Mt{constructor(e,t,n=!1){this.source=e,this.state=t,this.explicit=n}hasResult(){return!1}get isPending(){return this.state==1}update(e,t){let n=lf(e,t),a=this;(n&8||n&16&&this.touches(e))&&(a=new Mt(a.source,0)),n&4&&a.state==0&&(a=new Mt(this.source,1)),a=a.updateFor(e,n);for(let s of e.effects)if(s.is(Ps))a=new Mt(a.source,1,s.value);else if(s.is(Mi))a=new Mt(a.source,0);else if(s.is(Z0))for(let r of s.value)r.source==a.source&&(a=r);return a}updateFor(e,t){return this.map(e.changes)}map(e){return this}touches(e){return e.changes.touchesRange(a1(e.state))}}class A1 extends Mt{constructor(e,t,n,a,s,r){super(e,3,t),this.limit=n,this.result=a,this.from=s,this.to=r}hasResult(){return!0}updateFor(e,t){var n;if(!(t&3))return this.map(e.changes);let a=this.result;a.map&&!e.changes.empty&&(a=a.map(a,e.changes));let s=e.changes.mapPos(this.from),r=e.changes.mapPos(this.to,1),o=a1(e.state);if(o>r||!a||t&2&&(a1(e.startState)==this.from||ot.map(e))}}),gt=Et.define({create(){return Ds.start()},update(i,e){return i.update(e)},provide:i=>[Np.from(i,e=>e.tooltip),Q.contentAttributes.from(i,e=>e.attrs)]});function L0(i,e){const t=e.completion.apply||e.completion.label;let n=i.state.field(gt).active.find(a=>a.source==e.source);return n instanceof A1?(typeof t=="string"?i.dispatch({...zW(i.state,t,n.from,n.to),annotations:B0.of(e.completion)}):t(i,e.completion,n.from,n.to),!0):!1}const LW=OW(gt,L0);function Oa(i,e="option"){return t=>{let n=t.state.field(gt,!1);if(!n||!n.open||n.open.disabled||Date.now()-n.open.timestamp-1?n.open.selected+a*(i?1:-1):i?0:r-1;return o<0?o=e=="page"?0:r-1:o>=r&&(o=e=="page"?r-1:0),t.dispatch({effects:M0.of(o)}),!0}}const EW=i=>{let e=i.state.field(gt,!1);return i.state.readOnly||!e||!e.open||e.open.selected<0||e.open.disabled||Date.now()-e.open.timestampi.state.field(gt,!1)?(i.dispatch({effects:Ps.of(!0)}),!0):!1,WW=i=>{let e=i.state.field(gt,!1);return!e||!e.active.some(t=>t.state!=0)?!1:(i.dispatch({effects:Mi.of(null)}),!0)};class NW{constructor(e,t){this.active=e,this.context=t,this.time=Date.now(),this.updates=[],this.done=void 0}}const FW=50,JW=1e3,RW=Lt.fromClass(class{constructor(i){this.view=i,this.debounceUpdate=-1,this.running=[],this.debounceAccept=-1,this.pendingStart=!1,this.composing=0;for(let e of i.state.field(gt).active)e.isPending&&this.startQuery(e)}update(i){let e=i.state.field(gt),t=i.state.facet(Ge);if(!i.selectionSet&&!i.docChanged&&i.startState.field(gt)==e)return;let n=i.transactions.some(s=>{let r=lf(s,t);return r&8||(s.selection||s.docChanged)&&!(r&3)});for(let s=0;sFW&&Date.now()-r.time>JW){for(let o of r.context.abortListeners)try{o()}catch(l){wt(this.view.state,l)}r.context.abortListeners=null,this.running.splice(s--,1)}else r.updates.push(...i.transactions)}this.debounceUpdate>-1&&clearTimeout(this.debounceUpdate),i.transactions.some(s=>s.effects.some(r=>r.is(Ps)))&&(this.pendingStart=!0);let a=this.pendingStart?50:t.activateOnTypingDelay;if(this.debounceUpdate=e.active.some(s=>s.isPending&&!this.running.some(r=>r.active.source==s.source))?setTimeout(()=>this.startUpdate(),a):-1,this.composing!=0)for(let s of i.transactions)s.isUserEvent("input.type")?this.composing=2:this.composing==2&&s.selection&&(this.composing=3)}startUpdate(){this.debounceUpdate=-1,this.pendingStart=!1;let{state:i}=this.view,e=i.field(gt);for(let t of e.active)t.isPending&&!this.running.some(n=>n.active.source==t.source)&&this.startQuery(t);this.running.length&&e.open&&e.open.disabled&&(this.debounceAccept=setTimeout(()=>this.accept(),this.view.state.facet(Ge).updateSyncTime))}startQuery(i){let{state:e}=this.view,t=a1(e),n=new rf(e,t,i.explicit,this.view),a=new NW(i,n);this.running.push(a),Promise.resolve(i.source(n)).then(s=>{a.context.aborted||(a.done=s||null,this.scheduleAccept())},s=>{this.view.dispatch({effects:Mi.of(null)}),wt(this.view.state,s)})}scheduleAccept(){this.running.every(i=>i.done!==void 0)?this.accept():this.debounceAccept<0&&(this.debounceAccept=setTimeout(()=>this.accept(),this.view.state.facet(Ge).updateSyncTime))}accept(){var i;this.debounceAccept>-1&&clearTimeout(this.debounceAccept),this.debounceAccept=-1;let e=[],t=this.view.state.facet(Ge),n=this.view.state.field(gt);for(let a=0;ao.source==s.active.source);if(r&&r.isPending)if(s.done==null){let o=new Mt(s.active.source,0);for(let l of s.updates)o=o.update(l,t);o.isPending||e.push(o)}else this.startQuery(r)}(e.length||n.open&&n.open.disabled)&&this.view.dispatch({effects:Z0.of(e)})}},{eventHandlers:{blur(i){let e=this.view.state.field(gt,!1);if(e&&e.tooltip&&this.view.state.facet(Ge).closeOnBlur){let t=e.open&&Fp(this.view,e.open.tooltip);(!t||!t.dom.contains(i.relatedTarget))&&setTimeout(()=>this.view.dispatch({effects:Mi.of(null)}),10)}},compositionstart(){this.composing=1},compositionend(){this.composing==3&&setTimeout(()=>this.view.dispatch({effects:Ps.of(!1)}),20),this.composing=0}}}),GW=typeof navigator=="object"&&/Win/.test(navigator.platform),HW=l1.highest(Q.domEventHandlers({keydown(i,e){let t=e.state.field(gt,!1);if(!t||!t.open||t.open.disabled||t.open.selected<0||!i.key||i.key.length>1||i.ctrlKey&&!(GW&&i.altKey)||i.metaKey)return!1;let n=t.open.options[t.open.selected],a=t.active.find(r=>r.source==n.source),s=n.completion.commitCharacters||a.result.commitCharacters;return s&&s.indexOf(i.key)>-1&&L0(e,n),!1}})),uf=Q.baseTheme({".cm-tooltip.cm-tooltip-autocomplete":{"& > ul":{fontFamily:"monospace",whiteSpace:"nowrap",overflow:"hidden auto",maxWidth_fallback:"700px",maxWidth:"min(700px, 95vw)",minWidth:"250px",maxHeight:"10em",height:"100%",listStyle:"none",margin:0,padding:0,"& > li, & > completion-section":{padding:"1px 3px",lineHeight:1.2},"& > li":{overflowX:"hidden",textOverflow:"ellipsis",cursor:"pointer"},"& > completion-section":{display:"list-item",borderBottom:"1px solid silver",paddingLeft:"0.5em",opacity:.7}}},"&light .cm-tooltip-autocomplete ul li[aria-selected]":{background:"#17c",color:"white"},"&light .cm-tooltip-autocomplete-disabled ul li[aria-selected]":{background:"#777"},"&dark .cm-tooltip-autocomplete ul li[aria-selected]":{background:"#347",color:"white"},"&dark .cm-tooltip-autocomplete-disabled ul li[aria-selected]":{background:"#444"},".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after":{content:'"···"',opacity:.5,display:"block",textAlign:"center",cursor:"pointer"},".cm-tooltip.cm-completionInfo":{position:"absolute",padding:"3px 9px",width:"max-content",maxWidth:"400px",boxSizing:"border-box",whiteSpace:"pre-line"},".cm-completionInfo.cm-completionInfo-left":{right:"100%"},".cm-completionInfo.cm-completionInfo-right":{left:"100%"},".cm-completionInfo.cm-completionInfo-left-narrow":{right:"30px"},".cm-completionInfo.cm-completionInfo-right-narrow":{left:"30px"},"&light .cm-snippetField":{backgroundColor:"#00000022"},"&dark .cm-snippetField":{backgroundColor:"#ffffff22"},".cm-snippetFieldPosition":{verticalAlign:"text-top",width:0,height:"1.15em",display:"inline-block",margin:"0 -0.7px -.7em",borderLeft:"1.4px dotted #888"},".cm-completionMatchedText":{textDecoration:"underline"},".cm-completionDetail":{marginLeft:"0.5em",fontStyle:"italic"},".cm-completionIcon":{fontSize:"90%",width:".8em",display:"inline-block",textAlign:"center",paddingRight:".6em",opacity:"0.6",boxSizing:"content-box"},".cm-completionIcon-function, .cm-completionIcon-method":{"&:after":{content:"'ƒ'"}},".cm-completionIcon-class":{"&:after":{content:"'○'"}},".cm-completionIcon-interface":{"&:after":{content:"'◌'"}},".cm-completionIcon-variable":{"&:after":{content:"'𝑥'"}},".cm-completionIcon-constant":{"&:after":{content:"'𝐶'"}},".cm-completionIcon-type":{"&:after":{content:"'𝑡'"}},".cm-completionIcon-enum":{"&:after":{content:"'∪'"}},".cm-completionIcon-property":{"&:after":{content:"'□'"}},".cm-completionIcon-keyword":{"&:after":{content:"'🔑︎'"}},".cm-completionIcon-namespace":{"&:after":{content:"'▢'"}},".cm-completionIcon-text":{"&:after":{content:"'abc'",fontSize:"50%",verticalAlign:"middle"}}});class VW{constructor(e,t,n,a){this.field=e,this.line=t,this.from=n,this.to=a}}class E0{constructor(e,t,n){this.field=e,this.from=t,this.to=n}map(e){let t=e.mapPos(this.from,-1,st.TrackDel),n=e.mapPos(this.to,1,st.TrackDel);return t==null||n==null?null:new E0(this.field,t,n)}}class W0{constructor(e,t){this.lines=e,this.fieldPositions=t}instantiate(e,t){let n=[],a=[t],s=e.doc.lineAt(t),r=/^\s*/.exec(s.text)[0];for(let l of this.lines){if(n.length){let u=r,c=/^\t*/.exec(l)[0].length;for(let m=0;mnew E0(l.field,a[l.line]+l.from,a[l.line]+l.to));return{text:n,ranges:o}}static parse(e){let t=[],n=[],a=[],s;for(let r of e.split(/\r\n?|\n/)){for(;s=/[#$]\{(?:(\d+)(?::([^{}]*))?|((?:\\[{}]|[^{}])*))\}/.exec(r);){let o=s[1]?+s[1]:null,l=s[2]||s[3]||"",u=-1;o===0&&(o=1e9);let c=l.replace(/\\[{}]/g,m=>m[1]);for(let m=0;m=u&&d.field++}for(let m of a)if(m.line==n.length&&m.from>s.index){let d=s[2]?3+(s[1]||"").length:2;m.from-=d,m.to-=d}a.push(new VW(u,n.length,s.index,s.index+c.length)),r=r.slice(0,s.index)+l+r.slice(s.index+s[0].length)}r=r.replace(/\\([{}])/g,(o,l,u)=>{for(let c of a)c.line==n.length&&c.from>u&&(c.from--,c.to--);return l}),n.push(r)}return new W0(n,a)}}let qW=pe.widget({widget:new class extends Ji{toDOM(){let i=document.createElement("span");return i.className="cm-snippetFieldPosition",i}ignoreEvent(){return!1}}}),QW=pe.mark({class:"cm-snippetField"});class E1{constructor(e,t){this.ranges=e,this.active=t,this.deco=pe.set(e.map(n=>(n.from==n.to?qW:QW).range(n.from,n.to)),!0)}map(e){let t=[];for(let n of this.ranges){let a=n.map(e);if(!a)return null;t.push(a)}return new E1(t,this.active)}selectionInsideField(e){return e.ranges.every(t=>this.ranges.some(n=>n.field==this.active&&n.from<=t.from&&n.to>=t.to))}}const qi=de.define({map(i,e){return i&&i.map(e)}}),UW=de.define(),Zi=Et.define({create(){return null},update(i,e){for(let t of e.effects){if(t.is(qi))return t.value;if(t.is(UW)&&i)return new E1(i.ranges,t.value)}return i&&e.docChanged&&(i=i.map(e.changes)),i&&e.selection&&!i.selectionInsideField(e.selection)&&(i=null),i},provide:i=>Q.decorations.from(i,e=>e?e.deco:pe.none)});function N0(i,e){return B.create(i.filter(t=>t.field==e).map(t=>B.range(t.from,t.to)))}function $W(i){let e=W0.parse(i);return(t,n,a,s)=>{let{text:r,ranges:o}=e.instantiate(t.state,a),{main:l}=t.state.selection,u={changes:{from:a,to:s==l.from?l.to:s,insert:oe.of(r)},scrollIntoView:!0,annotations:n?[B0.of(n),$e.userEvent.of("input.complete")]:void 0};if(o.length&&(u.selection=N0(o,0)),o.some(c=>c.field>0)){let c=new E1(o,0),m=u.effects=[qi.of(c)];t.state.field(Zi,!1)===void 0&&m.push(de.appendConfig.of([Zi,tN,nN,uf]))}t.dispatch(t.state.update(u))}}function cf(i){return({state:e,dispatch:t})=>{let n=e.field(Zi,!1);if(!n||i<0&&n.active==0)return!1;let a=n.active+i,s=i>0&&!n.ranges.some(r=>r.field==a+i);return t(e.update({selection:N0(n.ranges,a),effects:qi.of(s?null:new E1(n.ranges,a)),scrollIntoView:!0})),!0}}const YW=({state:i,dispatch:e})=>i.field(Zi,!1)?(e(i.update({effects:qi.of(null)})),!0):!1,XW=cf(1),KW=cf(-1),eN=[{key:"Tab",run:XW,shift:KW},{key:"Escape",run:YW}],jm=V.define({combine(i){return i.length?i[0]:eN}}),tN=l1.highest(ji.compute([jm],i=>i.facet(jm)));function F0(i,e){return{...e,apply:$W(i)}}const nN=Q.domEventHandlers({mousedown(i,e){let t=e.state.field(Zi,!1),n;if(!t||(n=e.posAtCoords({x:i.clientX,y:i.clientY}))==null)return!1;let a=t.ranges.find(s=>s.from<=n&&s.to>=n);return!a||a.field==t.active?!1:(e.dispatch({selection:N0(t.ranges,a.field),effects:qi.of(t.ranges.some(s=>s.field>a.field)?new E1(t.ranges,a.field):null),scrollIntoView:!0}),!0)}}),Li={brackets:["(","[","{","'",'"'],before:")]}:;>",stringPrefixes:[]},Yn=de.define({map(i,e){let t=e.mapPos(i,-1,st.TrackAfter);return t??void 0}}),J0=new class extends Bn{};J0.startSide=1;J0.endSide=-1;const mf=Et.define({create(){return ie.empty},update(i,e){if(i=i.map(e.changes),e.selection){let t=e.state.doc.lineAt(e.selection.main.head);i=i.update({filter:n=>n>=t.from&&n<=t.to})}for(let t of e.effects)t.is(Yn)&&(i=i.update({add:[J0.range(t.value,t.value+1)]}));return i}});function iN(){return[sN,mf]}const Xr="()[]{}<>«»»«[]{}";function df(i){for(let e=0;e{if((aN?i.composing:i.compositionStarted)||i.state.readOnly)return!1;let a=i.state.selection.main;if(n.length>2||n.length==2&&mn(Ot(n,0))==1||e!=a.from||t!=a.to)return!1;let s=lN(i.state,n);return s?(i.dispatch(s),!0):!1}),rN=({state:i,dispatch:e})=>{if(i.readOnly)return!1;let n=hf(i,i.selection.main.head).brackets||Li.brackets,a=null,s=i.changeByRange(r=>{if(r.empty){let o=uN(i.doc,r.head);for(let l of n)if(l==o&&rr(i.doc,r.head)==df(Ot(l,0)))return{changes:{from:r.head-l.length,to:r.head+l.length},range:B.cursor(r.head-l.length)}}return{range:a=r}});return a||e(i.update(s,{scrollIntoView:!0,userEvent:"delete.backward"})),!a},oN=[{key:"Backspace",run:rN}];function lN(i,e){let t=hf(i,i.selection.main.head),n=t.brackets||Li.brackets;for(let a of n){let s=df(Ot(a,0));if(e==a)return s==a?dN(i,a,n.indexOf(a+a+a)>-1,t):cN(i,a,s,t.before||Li.before);if(e==s&&gf(i,i.selection.main.from))return mN(i,a,s)}return null}function gf(i,e){let t=!1;return i.field(mf).between(0,i.doc.length,n=>{n==e&&(t=!0)}),t}function rr(i,e){let t=i.sliceString(e,e+2);return t.slice(0,mn(Ot(t,0)))}function uN(i,e){let t=i.sliceString(e-2,e);return mn(Ot(t,0))==t.length?t:t.slice(1)}function cN(i,e,t,n){let a=null,s=i.changeByRange(r=>{if(!r.empty)return{changes:[{insert:e,from:r.from},{insert:t,from:r.to}],effects:Yn.of(r.to+e.length),range:B.range(r.anchor+e.length,r.head+e.length)};let o=rr(i.doc,r.head);return!o||/\s/.test(o)||n.indexOf(o)>-1?{changes:{insert:e+t,from:r.head},effects:Yn.of(r.head+e.length),range:B.cursor(r.head+e.length)}:{range:a=r}});return a?null:i.update(s,{scrollIntoView:!0,userEvent:"input.type"})}function mN(i,e,t){let n=null,a=i.changeByRange(s=>s.empty&&rr(i.doc,s.head)==t?{changes:{from:s.head,to:s.head+t.length,insert:t},range:B.cursor(s.head+t.length)}:n={range:s});return n?null:i.update(a,{scrollIntoView:!0,userEvent:"input.type"})}function dN(i,e,t,n){let a=n.stringPrefixes||Li.stringPrefixes,s=null,r=i.changeByRange(o=>{if(!o.empty)return{changes:[{insert:e,from:o.from},{insert:e,from:o.to}],effects:Yn.of(o.to+e.length),range:B.range(o.anchor+e.length,o.head+e.length)};let l=o.head,u=rr(i.doc,l),c;if(u==e){if(Pm(i,l))return{changes:{insert:e+e,from:l},effects:Yn.of(l+e.length),range:B.cursor(l+e.length)};if(gf(i,l)){let d=t&&i.sliceDoc(l,l+e.length*3)==e+e+e?e+e+e:e;return{changes:{from:l,to:l+d.length,insert:d},range:B.cursor(l+d.length)}}}else{if(t&&i.sliceDoc(l-2*e.length,l)==e+e&&(c=Dm(i,l-2*e.length,a))>-1&&Pm(i,c))return{changes:{insert:e+e+e+e,from:l},effects:Yn.of(l+e.length),range:B.cursor(l+e.length)};if(i.charCategorizer(l)(u)!=Dt.Word&&Dm(i,l,a)>-1&&!hN(i,l,e,a))return{changes:{insert:e+e,from:l},effects:Yn.of(l+e.length),range:B.cursor(l+e.length)}}return{range:s=o}});return s?null:i.update(r,{scrollIntoView:!0,userEvent:"input.type"})}function Pm(i,e){let t=Xe(i).resolveInner(e+1);return t.parent&&t.from==e}function hN(i,e,t,n){let a=Xe(i).resolveInner(e,-1),s=n.reduce((r,o)=>Math.max(r,o.length),0);for(let r=0;r<5;r++){let o=i.sliceDoc(a.from,Math.min(a.to,a.from+t.length+s)),l=o.indexOf(t);if(!l||l>-1&&n.indexOf(o.slice(0,l))>-1){let c=a.firstChild;for(;c&&c.from==a.from&&c.to-c.from>t.length+l;){if(i.sliceDoc(c.to-t.length,c.to)==t)return!1;c=c.firstChild}return!0}let u=a.to==e&&a.parent;if(!u)break;a=u}return!1}function Dm(i,e,t){let n=i.charCategorizer(e);if(n(i.sliceDoc(e-1,e))!=Dt.Word)return e;for(let a of t){let s=e-a.length;if(i.sliceDoc(s,e)==a&&n(i.sliceDoc(s-1,s))!=Dt.Word)return s}return-1}function gN(i={}){return[HW,gt,Ge.of(i),RW,pN,uf]}const pf=[{key:"Ctrl-Space",run:Yr},{mac:"Alt-`",run:Yr},{mac:"Alt-i",run:Yr},{key:"Escape",run:WW},{key:"ArrowDown",run:Oa(!0)},{key:"ArrowUp",run:Oa(!1)},{key:"PageDown",run:Oa(!0,"page")},{key:"PageUp",run:Oa(!1,"page")},{key:"Enter",run:EW}],pN=l1.highest(ji.computeN([Ge],i=>i.facet(Ge).defaultKeymap?[pf]:[])),fN=i=>{let{state:e}=i,t=e.doc.lineAt(e.selection.main.from),n=G0(i.state,t.from);return n.line?bN(i):n.block?vN(i):!1};function R0(i,e){return({state:t,dispatch:n})=>{if(t.readOnly)return!1;let a=i(e,t);return a?(n(t.update(a)),!0):!1}}const bN=R0(zN,0),xN=R0(ff,0),vN=R0((i,e)=>ff(i,e,wN(e)),0);function G0(i,e){let t=i.languageDataAt("commentTokens",e,1);return t.length?t[0]:{}}const $1=50;function yN(i,{open:e,close:t},n,a){let s=i.sliceDoc(n-$1,n),r=i.sliceDoc(a,a+$1),o=/\s*$/.exec(s)[0].length,l=/^\s*/.exec(r)[0].length,u=s.length-o;if(s.slice(u-e.length,u)==e&&r.slice(l,l+t.length)==t)return{open:{pos:n-o,margin:o&&1},close:{pos:a+l,margin:l&&1}};let c,m;a-n<=2*$1?c=m=i.sliceDoc(n,a):(c=i.sliceDoc(n,n+$1),m=i.sliceDoc(a-$1,a));let d=/^\s*/.exec(c)[0].length,h=/\s*$/.exec(m)[0].length,g=m.length-h-t.length;return c.slice(d,d+e.length)==e&&m.slice(g,g+t.length)==t?{open:{pos:n+d+e.length,margin:/\s/.test(c.charAt(d+e.length))?1:0},close:{pos:a-h-t.length,margin:/\s/.test(m.charAt(g-1))?1:0}}:null}function wN(i){let e=[];for(let t of i.selection.ranges){let n=i.doc.lineAt(t.from),a=t.to<=n.to?n:i.doc.lineAt(t.to);a.from>n.from&&a.from==t.to&&(a=t.to==n.to+1?n:i.doc.lineAt(t.to-1));let s=e.length-1;s>=0&&e[s].to>n.from?e[s].to=a.to:e.push({from:n.from+/^\s*/.exec(n.text)[0].length,to:a.to})}return e}function ff(i,e,t=e.selection.ranges){let n=t.map(s=>G0(e,s.from).block);if(!n.every(s=>s))return null;let a=t.map((s,r)=>yN(e,n[r],s.from,s.to));if(i!=2&&!a.every(s=>s))return{changes:e.changes(t.map((s,r)=>a[r]?[]:[{from:s.from,insert:n[r].open+" "},{from:s.to,insert:" "+n[r].close}]))};if(i!=1&&a.some(s=>s)){let s=[];for(let r=0,o;ra&&(s==r||r>m.from)){a=m.from;let d=/^\s*/.exec(m.text)[0].length,h=d==m.length,g=m.text.slice(d,d+u.length)==u?d:-1;ds.comment<0&&(!s.empty||s.single))){let s=[];for(let{line:o,token:l,indent:u,empty:c,single:m}of n)(m||!c)&&s.push({from:o.from+u,insert:l+" "});let r=e.changes(s);return{changes:r,selection:e.selection.map(r,1)}}else if(i!=1&&n.some(s=>s.comment>=0)){let s=[];for(let{line:r,comment:o,token:l}of n)if(o>=0){let u=r.from+o,c=u+l.length;r.text[c-r.from]==" "&&c++,s.push({from:u,to:c})}return{changes:s}}return null}function W1(i,e){return B.create(i.ranges.map(e),i.mainIndex)}function Qt(i,e){return i.update({selection:e,scrollIntoView:!0,userEvent:"select"})}function Ut({state:i,dispatch:e},t){let n=W1(i.selection,t);return n.eq(i.selection,!0)?!1:(e(Qt(i,n)),!0)}function or(i,e){return B.cursor(e?i.to:i.from)}function bf(i,e){return Ut(i,t=>t.empty?i.moveByChar(t,e):or(t,e))}function ot(i){return i.textDirectionAt(i.state.selection.main.head)==ye.LTR}const xf=i=>bf(i,!ot(i)),vf=i=>bf(i,ot(i));function yf(i,e){return Ut(i,t=>t.empty?i.moveByGroup(t,e):or(t,e))}const IN=i=>yf(i,!ot(i)),kN=i=>yf(i,ot(i));function SN(i,e,t){if(e.type.prop(t))return!0;let n=e.to-e.from;return n&&(n>2||/[^\s,.;:]/.test(i.sliceDoc(e.from,e.to)))||e.firstChild}function lr(i,e,t){let n=Xe(i).resolveInner(e.head),a=t?ae.closedBy:ae.openedBy;for(let l=e.head;;){let u=t?n.childAfter(l):n.childBefore(l);if(!u)break;SN(i,u,a)?n=u:l=t?u.to:u.from}let s=n.type.prop(a),r,o;return s&&(r=t?on(i,n.from,1):on(i,n.to,-1))&&r.matched?o=t?r.end.to:r.end.from:o=t?n.to:n.from,B.cursor(o,t?-1:1)}const TN=i=>Ut(i,e=>lr(i.state,e,!ot(i))),_N=i=>Ut(i,e=>lr(i.state,e,ot(i)));function wf(i,e){return Ut(i,t=>{if(!t.empty)return or(t,e);let n=i.moveVertically(t,e);return n.head!=t.head?n:i.moveToLineBoundary(t,e)})}const zf=i=>wf(i,!1),If=i=>wf(i,!0);function kf(i){let e=i.scrollDOM.clientHeightr.empty?i.moveVertically(r,e,t.height):or(r,e));if(a.eq(n.selection))return!1;let s;if(t.selfScroll){let r=i.coordsAtPos(n.selection.main.head),o=i.scrollDOM.getBoundingClientRect(),l=o.top+t.marginTop,u=o.bottom-t.marginBottom;r&&r.top>l&&r.bottomSf(i,!1),_l=i=>Sf(i,!0);function Nn(i,e,t){let n=i.lineBlockAt(e.head),a=i.moveToLineBoundary(e,t);if(a.head==e.head&&a.head!=(t?n.to:n.from)&&(a=i.moveToLineBoundary(e,t,!1)),!t&&a.head==n.from&&n.length){let s=/^\s*/.exec(i.state.sliceDoc(n.from,Math.min(n.from+100,n.to)))[0].length;s&&e.head!=n.from+s&&(a=B.cursor(n.from+s))}return a}const AN=i=>Ut(i,e=>Nn(i,e,!0)),ON=i=>Ut(i,e=>Nn(i,e,!1)),CN=i=>Ut(i,e=>Nn(i,e,!ot(i))),jN=i=>Ut(i,e=>Nn(i,e,ot(i))),PN=i=>Ut(i,e=>i.moveToLineBoundary(e,!1,!1)),DN=i=>Ut(i,e=>i.moveToLineBoundary(e,!0,!1));function BN(i,e,t){let n=!1,a=W1(i.selection,s=>{let r=on(i,s.head,-1)||on(i,s.head,1)||s.head>0&&on(i,s.head-1,1)||s.headBN(i,e);function Wt(i,e,t){let n=W1(i.state.selection,a=>{a.undirectional&&a.head>=a.anchor!=e&&(a=B.range(a.head,a.anchor));let s=t(a);return B.range(a.anchor,s.head,s.goalColumn,s.bidiLevel||void 0,s.assoc)});return n.eq(i.state.selection)?!1:(i.dispatch(Qt(i.state,n)),!0)}function Tf(i,e){return Wt(i,e,t=>i.moveByChar(t,e))}const _f=i=>Tf(i,!ot(i)),Af=i=>Tf(i,ot(i));function Of(i,e){return Wt(i,e,t=>i.moveByGroup(t,e))}const ZN=i=>Of(i,!ot(i)),LN=i=>Of(i,ot(i)),EN=i=>{let e=!ot(i);return Wt(i,e,t=>lr(i.state,t,e))},WN=i=>{let e=ot(i);return Wt(i,e,t=>lr(i.state,t,e))};function Cf(i,e){return Wt(i,e,t=>i.moveVertically(t,e))}const jf=i=>Cf(i,!1),Pf=i=>Cf(i,!0);function Df(i,e){return Wt(i,e,t=>i.moveVertically(t,e,kf(i).height))}const Mm=i=>Df(i,!1),Zm=i=>Df(i,!0),NN=i=>Wt(i,!0,e=>Nn(i,e,!0)),FN=i=>Wt(i,!1,e=>Nn(i,e,!1)),JN=i=>{let e=!ot(i);return Wt(i,e,t=>Nn(i,t,e))},RN=i=>{let e=ot(i);return Wt(i,e,t=>Nn(i,t,e))},GN=i=>Wt(i,!1,e=>B.cursor(i.lineBlockAt(e.head).from)),HN=i=>Wt(i,!0,e=>B.cursor(i.lineBlockAt(e.head).to)),Lm=({state:i,dispatch:e})=>(e(Qt(i,{anchor:0})),!0),Em=({state:i,dispatch:e})=>(e(Qt(i,{anchor:i.doc.length})),!0),Wm=({state:i,dispatch:e})=>(e(Qt(i,{anchor:i.selection.main.anchor,head:0})),!0),Nm=({state:i,dispatch:e})=>(e(Qt(i,{anchor:i.selection.main.anchor,head:i.doc.length})),!0),VN=({state:i,dispatch:e})=>(e(i.update({selection:{anchor:0,head:i.doc.length},userEvent:"select"})),!0),qN=({state:i,dispatch:e})=>{let t=ur(i).map(({from:n,to:a})=>B.undirectionalRange(n,Math.min(a+1,i.doc.length)));return e(i.update({selection:B.create(t),userEvent:"select"})),!0},QN=({state:i,dispatch:e})=>{let t=W1(i.selection,n=>{let a=Xe(i),s=a.resolveStack(n.from,1);if(n.empty){let r=a.resolveStack(n.from,-1);r.node.from>=s.node.from&&r.node.to<=s.node.to&&(s=r)}for(let r=s;r;r=r.next){let{node:o}=r;if((o.from=n.to||o.to>n.to&&o.from<=n.from)&&r.next)return B.undirectionalRange(o.from,o.to)}return n});return t.eq(i.selection)?!1:(e(Qt(i,t)),!0)};function Bf(i,e){let{state:t}=i,n=t.selection,a=t.selection.ranges.slice();for(let s of t.selection.ranges){let r=t.doc.lineAt(s.head);if(e?r.to0)for(let o=s;;){let l=i.moveVertically(o,e);if(l.headr.to){a.some(u=>u.head==l.head)||a.push(l);break}else{if(l.head==o.head)break;o=l}}}return a.length==n.ranges.length?!1:(i.dispatch(Qt(t,B.create(a,a.length-1))),!0)}const UN=i=>Bf(i,!1),$N=i=>Bf(i,!0),YN=({state:i,dispatch:e})=>{let t=i.selection,n=null;return t.ranges.length>1?n=B.create([t.main]):t.main.empty||(n=B.create([B.cursor(t.main.head)])),n?(e(Qt(i,n)),!0):!1};function Qi(i,e){if(i.state.readOnly)return!1;let t="delete.selection",{state:n}=i,a=n.changeByRange(s=>{let{from:r,to:o}=s;if(r==o){let l=e(s);lr&&(t="delete.forward",l=Ca(i,l,!0)),r=Math.min(r,l),o=Math.max(o,l)}else r=Ca(i,r,!1),o=Ca(i,o,!0);return r==o?{range:s}:{changes:{from:r,to:o},range:B.cursor(r,ra(i)))n.between(e,e,(a,s)=>{ae&&(e=t?s:a)});return e}const Mf=(i,e,t)=>Qi(i,n=>{let a=n.from,{state:s}=i,r=s.doc.lineAt(a),o,l;if(t&&!e&&a>r.from&&aMf(i,!1,!0),Zf=i=>Mf(i,!0,!1),Lf=(i,e)=>Qi(i,t=>{let n=t.head,{state:a}=i,s=a.doc.lineAt(n),r=a.charCategorizer(n);for(let o=null;;){if(n==(e?s.to:s.from)){n==t.head&&s.number!=(e?a.doc.lines:1)&&(n+=e?1:-1);break}let l=rt(s.text,n-s.from,e)+s.from,u=s.text.slice(Math.min(n,l)-s.from,Math.max(n,l)-s.from),c=r(u);if(o!=null&&c!=o)break;(u!=" "||n!=t.head)&&(o=c),n=l}return n}),Ef=i=>Lf(i,!1),XN=i=>Lf(i,!0),KN=i=>Qi(i,e=>{let t=i.lineBlockAt(e.head).to;return e.headQi(i,e=>{let t=i.moveToLineBoundary(e,!1).head;return e.head>t?t:Math.max(0,e.head-1)}),tF=i=>Qi(i,e=>{let t=i.moveToLineBoundary(e,!0).head;return e.head{if(i.readOnly)return!1;let t=i.changeByRange(n=>({changes:{from:n.from,to:n.to,insert:oe.of(["",""])},range:B.cursor(n.from)}));return e(i.update(t,{scrollIntoView:!0,userEvent:"input"})),!0},iF=({state:i,dispatch:e})=>{if(i.readOnly)return!1;let t=i.changeByRange(n=>{if(!n.empty||n.from==0||n.from==i.doc.length)return{range:n};let a=n.from,s=i.doc.lineAt(a),r=a==s.from?a-1:rt(s.text,a-s.from,!1)+s.from,o=a==s.to?a+1:rt(s.text,a-s.from,!0)+s.from;return{changes:{from:r,to:o,insert:i.doc.slice(a,o).append(i.doc.slice(r,a))},range:B.cursor(o)}});return t.changes.empty?!1:(e(i.update(t,{scrollIntoView:!0,userEvent:"move.character"})),!0)};function ur(i){let e=[],t=-1;for(let n of i.selection.ranges){let a=i.doc.lineAt(n.from),s=i.doc.lineAt(n.to);if(!n.empty&&n.to==s.from&&(s=i.doc.lineAt(n.to-1)),t>=a.number){let r=e[e.length-1];r.to=s.to,r.ranges.push(n)}else e.push({from:a.from,to:s.to,ranges:[n]});t=s.number+1}return e}function Wf(i,e,t){if(i.readOnly)return!1;let n=[],a=[];for(let s of ur(i)){if(t?s.to==i.doc.length:s.from==0)continue;let r=i.doc.lineAt(t?s.to+1:s.from-1),o=r.length+1;if(t){n.push({from:s.to,to:r.to},{from:s.from,insert:r.text+i.lineBreak});for(let l of s.ranges)a.push(B.range(Math.min(i.doc.length,l.anchor+o),Math.min(i.doc.length,l.head+o)))}else{n.push({from:r.from,to:s.from},{from:s.to,insert:i.lineBreak+r.text});for(let l of s.ranges)a.push(B.range(l.anchor-o,l.head-o))}}return n.length?(e(i.update({changes:n,scrollIntoView:!0,selection:B.create(a,i.selection.mainIndex),userEvent:"move.line"})),!0):!1}const aF=({state:i,dispatch:e})=>Wf(i,e,!1),sF=({state:i,dispatch:e})=>Wf(i,e,!0);function Nf(i,e,t){if(i.readOnly)return!1;let n=[];for(let s of ur(i))t?n.push({from:s.from,insert:i.doc.slice(s.from,s.to)+i.lineBreak}):n.push({from:s.to,insert:i.lineBreak+i.doc.slice(s.from,s.to)});let a=i.changes(n);return e(i.update({changes:a,selection:i.selection.map(a,t?1:-1),scrollIntoView:!0,userEvent:"input.copyline"})),!0}const rF=({state:i,dispatch:e})=>Nf(i,e,!1),oF=({state:i,dispatch:e})=>Nf(i,e,!0),lF=i=>{if(i.state.readOnly)return!1;let{state:e}=i,t=e.changes(ur(e).map(({from:a,to:s})=>(a>0?a--:s{let s;if(i.lineWrapping){let r=i.lineBlockAt(a.head),o=i.coordsAtPos(a.head,a.assoc||1);o&&(s=r.bottom+i.documentTop-o.bottom+i.defaultLineHeight/2)}return i.moveVertically(a,!0,s)}).map(t);return i.dispatch({changes:t,selection:n,scrollIntoView:!0,userEvent:"delete.line"}),!0};function uF(i,e){if(/\(\)|\[\]|\{\}/.test(i.sliceDoc(e-1,e+1)))return{from:e,to:e};let t=Xe(i).resolveInner(e),n=t.childBefore(e),a=t.childAfter(e),s;return n&&a&&n.to<=e&&a.from>=e&&(s=n.type.prop(ae.closedBy))&&s.indexOf(a.name)>-1&&i.doc.lineAt(n.to).from==i.doc.lineAt(a.from).from&&!/\S/.test(i.sliceDoc(n.to,a.from))?{from:n.to,to:a.from}:null}const Fm=Ff(!1),cF=Ff(!0);function Ff(i){return({state:e,dispatch:t})=>{if(e.readOnly)return!1;let n=e.changeByRange(a=>{let{from:s,to:r}=a,o=e.doc.lineAt(s),l=!i&&s==r&&uF(e,s);i&&(s=r=(r<=o.to?o:e.doc.lineAt(r)).to);let u=new ar(e,{simulateBreak:s,simulateDoubleBreak:!!l}),c=P0(u,s);for(c==null&&(c=Fi(/^\s*/.exec(e.doc.lineAt(s).text)[0],e.tabSize));ro.from&&s{let a=[];for(let r=n.from;r<=n.to;){let o=i.doc.lineAt(r);o.number>t&&(n.empty||n.to>o.from)&&(e(o,a,n),t=o.number),r=o.to+1}let s=i.changes(a);return{changes:a,range:B.range(s.mapPos(n.anchor,1),s.mapPos(n.head,1))}})}const mF=({state:i,dispatch:e})=>{if(i.readOnly)return!1;let t=Object.create(null),n=new ar(i,{overrideIndentation:s=>{let r=t[s];return r??-1}}),a=H0(i,(s,r,o)=>{let l=P0(n,s.from);if(l==null)return;/\S/.test(s.text)||(l=0);let u=/^\s*/.exec(s.text)[0],c=Bi(i,l);(u!=c||o.fromi.readOnly?!1:(e(i.update(H0(i,(t,n)=>{n.push({from:t.from,insert:i.facet(Vi)})}),{userEvent:"input.indent"})),!0),Rf=({state:i,dispatch:e})=>i.readOnly?!1:(e(i.update(H0(i,(t,n)=>{let a=/^\s*/.exec(t.text)[0];if(!a)return;let s=Fi(a,i.tabSize),r=0,o=Bi(i,Math.max(0,s-js(i)));for(;r(i.setTabFocusMode(),!0),hF=[{key:"Ctrl-b",run:xf,shift:_f,preventDefault:!0},{key:"Ctrl-f",run:vf,shift:Af},{key:"Ctrl-p",run:zf,shift:jf},{key:"Ctrl-n",run:If,shift:Pf},{key:"Ctrl-a",run:PN,shift:GN},{key:"Ctrl-e",run:DN,shift:HN},{key:"Ctrl-d",run:Zf},{key:"Ctrl-h",run:Al},{key:"Ctrl-k",run:KN},{key:"Ctrl-Alt-h",run:Ef},{key:"Ctrl-o",run:nF},{key:"Ctrl-t",run:iF},{key:"Ctrl-v",run:_l}],gF=[{key:"ArrowLeft",run:xf,shift:_f,preventDefault:!0},{key:"Mod-ArrowLeft",mac:"Alt-ArrowLeft",run:IN,shift:ZN,preventDefault:!0},{mac:"Cmd-ArrowLeft",run:CN,shift:JN,preventDefault:!0},{key:"ArrowRight",run:vf,shift:Af,preventDefault:!0},{key:"Mod-ArrowRight",mac:"Alt-ArrowRight",run:kN,shift:LN,preventDefault:!0},{mac:"Cmd-ArrowRight",run:jN,shift:RN,preventDefault:!0},{key:"ArrowUp",run:zf,shift:jf,preventDefault:!0},{mac:"Cmd-ArrowUp",run:Lm,shift:Wm},{mac:"Ctrl-ArrowUp",run:Bm,shift:Mm},{key:"ArrowDown",run:If,shift:Pf,preventDefault:!0},{mac:"Cmd-ArrowDown",run:Em,shift:Nm},{mac:"Ctrl-ArrowDown",run:_l,shift:Zm},{key:"PageUp",run:Bm,shift:Mm},{key:"PageDown",run:_l,shift:Zm},{key:"Home",run:ON,shift:FN,preventDefault:!0},{key:"Mod-Home",run:Lm,shift:Wm},{key:"End",run:AN,shift:NN,preventDefault:!0},{key:"Mod-End",run:Em,shift:Nm},{key:"Enter",run:Fm,shift:Fm},{key:"Mod-a",run:VN},{key:"Backspace",run:Al,shift:Al,preventDefault:!0},{key:"Delete",run:Zf,preventDefault:!0},{key:"Mod-Backspace",mac:"Alt-Backspace",run:Ef,preventDefault:!0},{key:"Mod-Delete",mac:"Alt-Delete",run:XN,preventDefault:!0},{mac:"Mod-Backspace",run:eF,preventDefault:!0},{mac:"Mod-Delete",run:tF,preventDefault:!0}].concat(hF.map(i=>({mac:i.key,run:i.run,shift:i.shift}))),pF=[{key:"Alt-ArrowLeft",mac:"Ctrl-ArrowLeft",run:TN,shift:EN},{key:"Alt-ArrowRight",mac:"Ctrl-ArrowRight",run:_N,shift:WN},{key:"Alt-ArrowUp",run:aF},{key:"Shift-Alt-ArrowUp",run:rF},{key:"Alt-ArrowDown",run:sF},{key:"Shift-Alt-ArrowDown",run:oF},{key:"Mod-Alt-ArrowUp",run:UN},{key:"Mod-Alt-ArrowDown",run:$N},{key:"Escape",run:YN},{key:"Mod-Enter",run:cF},{key:"Alt-l",mac:"Ctrl-l",run:qN},{key:"Mod-i",run:QN,preventDefault:!0},{key:"Mod-[",run:Rf},{key:"Mod-]",run:Jf},{key:"Mod-Alt-\\",run:mF},{key:"Shift-Mod-k",run:lF},{key:"Shift-Mod-\\",run:MN},{key:"Mod-/",run:fN},{key:"Alt-A",mac:"Ctrl-A",run:xN},{key:"Ctrl-m",mac:"Shift-Alt-m",run:dF}].concat(gF),fF={key:"Tab",run:Jf,shift:Rf};var Jm={};class Bs{constructor(e,t,n,a,s,r,o,l,u,c=0,m){this.p=e,this.stack=t,this.state=n,this.reducePos=a,this.pos=s,this.score=r,this.buffer=o,this.bufferBase=l,this.curContext=u,this.lookAhead=c,this.parent=m}toString(){return`[${this.stack.filter((e,t)=>t%3==0).concat(this.state)}]@${this.pos}${this.score?"!"+this.score:""}`}static start(e,t,n=0){let a=e.parser.context;return new Bs(e,[],t,n,n,0,[],0,a?new Rm(a,a.start):null,0,null)}get context(){return this.curContext?this.curContext.context:null}pushState(e,t){this.stack.push(this.state,t,this.bufferBase+this.buffer.length),this.state=e}reduce(e){var t;let n=e>>19,a=e&65535,{parser:s}=this.p,r=this.reducePos=2e3&&!(!((t=this.p.parser.nodeSet.types[a])===null||t===void 0)&&t.isAnonymous)&&(u==this.p.lastBigReductionStart?(this.p.bigReductionCount++,this.p.lastBigReductionSize=c):this.p.lastBigReductionSizel;)this.stack.pop();this.reduceContext(a,u)}storeNode(e,t,n,a=4,s=!1){if(e==0&&(!this.stack.length||this.stack[this.stack.length-1]0&&this.buffer[r-4]==0&&this.buffer[r-1]>-1){if(t==n)return;if(this.buffer[r-2]>=t){this.buffer[r-2]=n;return}}}if(!s||this.pos==n)this.buffer.push(e,t,n,a);else{let r=this.buffer.length;if(r>0&&(this.buffer[r-4]!=0||this.buffer[r-1]<0)){let o=!1;for(let l=r;l>0&&this.buffer[l-2]>n;l-=4)if(this.buffer[l-1]>=0){o=!0;break}if(o)for(;r>0&&this.buffer[r-2]>n;)this.buffer[r]=this.buffer[r-4],this.buffer[r+1]=this.buffer[r-3],this.buffer[r+2]=this.buffer[r-2],this.buffer[r+3]=this.buffer[r-1],r-=4,a>4&&(a-=4)}this.buffer[r]=e,this.buffer[r+1]=t,this.buffer[r+2]=n,this.buffer[r+3]=a}}shift(e,t,n,a){if(e&131072)this.pushState(e&65535,this.pos);else if((e&262144)==0){let s=e,{parser:r}=this.p;this.pos=a;let o=r.stateFlag(s,1);!o&&(a>n||t<=r.maxNode)&&(this.reducePos=a),this.pushState(s,o?n:Math.min(n,this.reducePos)),this.shiftContext(t,n),t<=r.maxNode&&this.buffer.push(t,n,a,4)}else this.pos=a,this.shiftContext(t,n),t<=this.p.parser.maxNode&&this.buffer.push(t,n,a,4)}apply(e,t,n,a){e&65536?this.reduce(e):this.shift(e,t,n,a)}useNode(e,t,n){let a=this.p.reused.length-1;(a<0||this.p.reused[a]!=e)&&(this.p.reused.push(e),a++);let s=this.reducePos=this.pos=n+e.length;this.pushState(t,n),this.buffer.push(a,n,s,-1),this.curContext&&this.updateContext(this.curContext.tracker.reuse(this.curContext.context,e,this,this.p.stream.reset(this.pos-e.length)))}split(){let e=this,t=e.buffer.length;for(t&&e.buffer[t-4]==0&&(t-=4);t>0&&e.buffer[t-2]>e.reducePos;)t-=4;let n=e.buffer.slice(t),a=e.bufferBase+t;for(;e&&a==e.bufferBase;)e=e.parent;return new Bs(this.p,this.stack.slice(),this.state,this.reducePos,this.pos,this.score,n,a,this.curContext,this.lookAhead,e)}recoverByDelete(e,t){let n=e<=this.p.parser.maxNode;n&&this.storeNode(e,this.pos,t,4),this.storeNode(0,this.pos,t,n?8:4),this.pos=this.reducePos=t,this.score-=190}canShift(e){for(let t=new bF(this);;){let n=this.p.parser.stateSlot(t.state,4)||this.p.parser.hasAction(t.state,e);if(n==0)return!1;if((n&65536)==0)return!0;t.reduce(n)}}recoverByInsert(e){if(this.stack.length>=300)return[];let t=this.p.parser.nextStates(this.state);if(t.length>8||this.stack.length>=120){let a=[];for(let s=0,r;sl&1&&o==r)||a.push(t[s],r)}t=a}let n=[];for(let a=0;a>19,a=t&65535,s=this.stack.length-n*3;if(s<0||e.getGoto(this.stack[s],a,!1)<0){let r=this.findForcedReduction();if(r==null)return!1;t=r}this.storeNode(0,this.pos,this.pos,4,!0),this.score-=100}return this.reducePos=this.pos,this.reduce(t),!0}findForcedReduction(){let{parser:e}=this.p,t=[],n=(a,s)=>{if(!t.includes(a))return t.push(a),e.allActions(a,r=>{if(!(r&393216))if(r&65536){let o=(r>>19)-s;if(o>1){let l=r&65535,u=this.stack.length-o*3;if(u>=0&&e.getGoto(this.stack[u],l,!1)>=0)return o<<19|65536|l}}else{let o=n(r,s+1);if(o!=null)return o}})};return n(this.state,0)}forceAll(){for(;!this.p.parser.stateFlag(this.state,2);)if(!this.forceReduce()){this.storeNode(0,this.pos,this.pos,4,!0);break}return this}get deadEnd(){if(this.stack.length!=3)return!1;let{parser:e}=this.p;return e.data[e.stateSlot(this.state,1)]==65535&&!e.stateSlot(this.state,4)}restart(){this.storeNode(0,this.pos,this.pos,4,!0),this.state=this.stack[0],this.stack.length=0}sameState(e){if(this.state!=e.state||this.stack.length!=e.stack.length)return!1;for(let t=0;t0&&this.emitLookAhead()}}class Rm{constructor(e,t){this.tracker=e,this.context=t,this.hash=e.strict?e.hash(t):0}}class bF{constructor(e){this.start=e,this.state=e.state,this.stack=e.stack,this.base=this.stack.length}reduce(e){let t=e&65535,n=e>>19;n==0?(this.stack==this.start.stack&&(this.stack=this.stack.slice()),this.stack.push(this.state,0,0),this.base+=3):this.base-=(n-1)*3;let a=this.start.p.parser.getGoto(this.stack[this.base-3],t,!0);this.state=a}}class Ms{constructor(e,t,n){this.stack=e,this.pos=t,this.index=n,this.buffer=e.buffer,this.index==0&&this.maybeNext()}static create(e,t=e.bufferBase+e.buffer.length){return new Ms(e,t,t-e.bufferBase)}maybeNext(){let e=this.stack.parent;e!=null&&(this.index=this.stack.bufferBase-e.bufferBase,this.stack=e,this.buffer=e.buffer)}get id(){return this.buffer[this.index-4]}get start(){return this.buffer[this.index-3]}get end(){return this.buffer[this.index-2]}get size(){return this.buffer[this.index-1]}next(){this.index-=4,this.pos-=4,this.index==0&&this.maybeNext()}fork(){return new Ms(this.stack,this.pos,this.index)}}function ja(i,e=Uint16Array){if(typeof i!="string")return i;let t=null;for(let n=0,a=0;n=92&&r--,r>=34&&r--;let l=r-32;if(l>=46&&(l-=46,o=!0),s+=l,o)break;s*=46}t?t[a++]=s:t=new e(s)}return t}class Ua{constructor(){this.start=-1,this.value=-1,this.end=-1,this.extended=-1,this.lookAhead=0,this.mask=0,this.context=0}}const Gm=new Ua;class xF{constructor(e,t){this.input=e,this.ranges=t,this.chunk="",this.chunkOff=0,this.chunk2="",this.chunk2Pos=0,this.next=-1,this.token=Gm,this.rangeIndex=0,this.pos=this.chunkPos=t[0].from,this.range=t[0],this.end=t[t.length-1].to,this.readNext()}resolveOffset(e,t){let n=this.range,a=this.rangeIndex,s=this.pos+e;for(;sn.to:s>=n.to;){if(a==this.ranges.length-1)return null;let r=this.ranges[++a];s+=r.from-n.to,n=r}return s}clipPos(e){if(e>=this.range.from&&ee)return Math.max(e,t.from);return this.end}peek(e){let t=this.chunkOff+e,n,a;if(t>=0&&t=this.chunk2Pos&&no.to&&(this.chunk2=this.chunk2.slice(0,o.to-n)),a=this.chunk2.charCodeAt(0)}}return n>=this.token.lookAhead&&(this.token.lookAhead=n+1),a}acceptToken(e,t=0){let n=t?this.resolveOffset(t,-1):this.pos;if(n==null||n=this.chunk2Pos&&this.posthis.range.to?e.slice(0,this.range.to-this.pos):e,this.chunkPos=this.pos,this.chunkOff=0}}readNext(){return this.chunkOff>=this.chunk.length&&(this.getChunk(),this.chunkOff==this.chunk.length)?this.next=-1:this.next=this.chunk.charCodeAt(this.chunkOff)}advance(e=1){for(this.chunkOff+=e;this.pos+e>=this.range.to;){if(this.rangeIndex==this.ranges.length-1)return this.setDone();e-=this.range.to-this.pos,this.range=this.ranges[++this.rangeIndex],this.pos=this.range.from}return this.pos+=e,this.pos>=this.token.lookAhead&&(this.token.lookAhead=this.pos+1),this.readNext()}setDone(){return this.pos=this.chunkPos=this.end,this.range=this.ranges[this.rangeIndex=this.ranges.length-1],this.chunk="",this.next=-1}reset(e,t){if(t?(this.token=t,t.start=e,t.lookAhead=e+1,t.value=t.extended=-1):this.token=Gm,this.pos!=e){if(this.pos=e,e==this.end)return this.setDone(),this;for(;e=this.range.to;)this.range=this.ranges[++this.rangeIndex];e>=this.chunkPos&&e=this.chunkPos&&t<=this.chunkPos+this.chunk.length)return this.chunk.slice(e-this.chunkPos,t-this.chunkPos);if(e>=this.chunk2Pos&&t<=this.chunk2Pos+this.chunk2.length)return this.chunk2.slice(e-this.chunk2Pos,t-this.chunk2Pos);if(e>=this.range.from&&t<=this.range.to)return this.input.read(e,t);let n="";for(let a of this.ranges){if(a.from>=t)break;a.to>e&&(n+=this.input.read(Math.max(a.from,e),Math.min(a.to,t)))}return n}}class O1{constructor(e,t){this.data=e,this.id=t}token(e,t){let{parser:n}=t.p;vF(this.data,e,t,this.id,n.data,n.tokenPrecTable)}}O1.prototype.contextual=O1.prototype.fallback=O1.prototype.extend=!1;O1.prototype.fallback=O1.prototype.extend=!1;function vF(i,e,t,n,a,s){let r=0,o=1<0){let g=i[h];if(l.allows(g)&&(e.token.value==-1||e.token.value==g||yF(g,e.token.value,a,s))){e.acceptToken(g);break}}let c=e.next,m=0,d=i[r+2];if(e.next<0&&d>m&&i[u+d*3-3]==65535){r=i[u+d*3-1];continue e}for(;m>1,g=u+h+(h<<1),f=i[g],b=i[g+1]||65536;if(c=b)m=h+1;else{r=i[g+2],e.advance();continue e}}break}}function Hm(i,e,t){for(let n=e,a;(a=i[n])!=65535;n++)if(a==t)return n-e;return-1}function yF(i,e,t,n){let a=Hm(t,n,e);return a<0||Hm(t,n,i)e)&&!n.type.isError)return t<0?Math.max(0,Math.min(n.to-1,e-25)):Math.min(i.length,Math.max(n.from+1,e+25));if(t<0?n.prevSibling():n.nextSibling())break;if(!n.parent())return t<0?0:i.length}}class wF{constructor(e,t){this.fragments=e,this.minRepeat=t,this.i=0,this.fragment=null,this.safeFrom=-1,this.safeTo=-1,this.trees=[],this.start=[],this.index=[],this.lastRepeat=null,this.lastRepeatPos=-1,this.nextFragment()}nextFragment(){let e=this.fragment=this.i==this.fragments.length?null:this.fragments[this.i++];if(e){for(this.safeFrom=e.openStart?Vm(e.tree,e.from+e.offset,1)-e.offset:e.from,this.safeTo=e.openEnd?Vm(e.tree,e.to+e.offset,-1)-e.offset:e.to;this.trees.length;)this.trees.pop(),this.start.pop(),this.index.pop();this.trees.push(e.tree),this.start.push(-e.offset),this.index.push(0),this.nextStart=this.safeFrom}else this.nextStart=1e9}nodeAt(e){if(ee)return this.nextStart=r,null;if(s instanceof Ze){let o=r>this.lastRepeatPos&&s.type.id>=this.minRepeat;if(r==e||o){let l=r+s.length,u;if(r>=this.safeFrom&&l<=this.safeTo&&(!(u=s.prop(ae.lookAhead))||l+u=Math.max(this.safeFrom,e)&&(this.trees.push(s),this.start.push(r),this.index.push(0))}else this.index[t]++,this.nextStart=r+s.length}}}class zF{constructor(e,t){this.stream=t,this.tokens=[],this.mainToken=null,this.actions=[],this.tokens=e.tokenizers.map(n=>new Ua)}getActions(e){let t=0,n=null,{parser:a}=e.p,{tokenizers:s}=a,r=a.stateSlot(e.state,3),o=e.curContext?e.curContext.hash:0,l=0;for(let u=0;um.end+25&&(l=Math.max(m.lookAhead,l)),m.value!=0)){let d=t;if(m.extended>-1&&(t=this.addActions(e,m.extended,m.end,t)),t=this.addActions(e,m.value,m.end,t),!c.extend&&(n=m,t>d))break}}for(;this.actions.length>t;)this.actions.pop();return l&&e.setLookAhead(l),!n&&e.pos==this.stream.end&&(n=new Ua,n.value=e.p.parser.eofTerm,n.start=n.end=e.pos,t=this.addActions(e,n.value,n.end,t)),this.mainToken=n,this.actions}getMainToken(e){if(this.mainToken)return this.mainToken;let t=new Ua,{pos:n,p:a}=e;return t.start=n,t.end=Math.min(n+1,a.stream.end),t.value=n==a.stream.end?a.parser.eofTerm:0,t}updateCachedToken(e,t,n){let a=this.stream.clipPos(n.pos);if(t.token(this.stream.reset(a,e),n),e.value>-1){let{parser:s}=n.p;for(let r=0;r=0&&n.p.parser.dialect.allows(o>>1)){(o&1)==0?e.value=o>>1:e.extended=o>>1;break}}}else e.value=0,e.end=this.stream.clipPos(a+1)}putAction(e,t,n,a){for(let s=0;se.bufferLength*4?new wF(n,e.minRepeatTerm):null}get parsedPos(){return this.minStackPos}advance(){let e=this.stacks,t=this.minStackPos,n=this.stacks=[],a,s;if(this.bigReductionCount>300&&e.length==1){let[r]=e;for(;r.forceReduce()&&r.stack.length&&r.stack[r.stack.length-2]>=this.lastBigReductionStart;);this.bigReductionCount=this.lastBigReductionSize=0}for(let r=0;rt)n.push(o);else{if(this.advanceStack(o,n,e))continue;{a||(a=[],s=[]),a.push(o);let l=this.tokens.getMainToken(o);s.push(l.value,l.end)}}break}}if(!n.length){let r=a&&SF(a);if(r)return bt&&console.log("Finish with "+this.stackID(r)),this.stackToTree(r);if(this.parser.strict)throw bt&&a&&console.log("Stuck with token "+(this.tokens.mainToken?this.parser.getName(this.tokens.mainToken.value):"none")),new SyntaxError("No parse at "+t);this.recovering||(this.recovering=5)}if(this.recovering&&a){let r=this.stoppedAt!=null&&a[0].pos>this.stoppedAt?a[0]:this.runRecovery(a,s,n);if(r)return bt&&console.log("Force-finish "+this.stackID(r)),this.stackToTree(r.forceAll())}if(this.recovering){let r=this.recovering==1?1:this.recovering*3;if(n.length>r)for(n.sort((o,l)=>l.score-o.score);n.length>r;)n.pop();n.some(o=>o.reducePos>t)&&this.recovering--}else if(n.length>1){e:for(let r=0;r500&&u.buffer.length>500)if((o.score-u.score||o.buffer.length-u.buffer.length)>0)n.splice(l--,1);else{n.splice(r--,1);continue e}}}n.length>12&&(n.sort((r,o)=>o.score-r.score),n.splice(12,n.length-12))}this.minStackPos=n[0].pos;for(let r=1;r-1&&n.length&&(!s||(n.prop(ae.contextHash)||0)==r))return e.useNode(n,o,t),n;if(n.children.length==0||n.positions[0]>0)break;let l=n.children[0];if(l instanceof Ze&&(!a||l.type.id>=this.parser.minRepeatTerm))n=l;else break}return null}advanceStack(e,t,n){let a=e.pos,{parser:s}=this,r=bt?this.stackID(e)+" -> ":"";if(this.stoppedAt!=null&&a>this.stoppedAt)return e.forceReduce()?e:null;if(this.fragments){let u=e.reducePos0)return e.reduce(o),bt&&console.log(r+this.stackID(e)+` (via always-reduce ${s.getName(o&65535)})`),!0;if(e.stack.length>=8400)for(;e.stack.length>6e3&&e.forceReduce(););let l=this.tokens.getActions(e);for(let u=0;ua?t.push(g):n.push(g)}return!1}advanceFully(e,t){let n=e.pos;for(;;){if(!this.advanceStack(e,null,null))return!1;if(e.pos>n)return qm(e,t),!0}}runRecovery(e,t,n){let a=null,s=!1;for(let r=0;r ":"";if(o.deadEnd&&(s||(s=!0,o.restart(),bt&&console.log(c+this.stackID(o)+" (restarted)"),this.advanceFully(o,n))))continue;let m=o.split(),d=c;for(let h=0;h<10&&m.forceReduce()&&(bt&&console.log(d+this.stackID(m)+" (via force-reduce)"),!this.advanceFully(m,n));h++)bt&&(d=this.stackID(m)+" -> ");for(let h of o.recoverByInsert(l))bt&&console.log(c+this.stackID(h)+" (via recover-insert)"),this.advanceFully(h,n);this.stream.end>o.pos?(u==o.pos&&(u++,l=0),o.recoverByDelete(l,u),bt&&console.log(c+this.stackID(o)+` (via recover-delete ${this.parser.getName(l)})`),qm(o,n)):(!a||a.scoree.topRules[o][1]),a=[];for(let o=0;o=0)s(c,l,o[u++]);else{let m=o[u+-c];for(let d=-c;d>0;d--)s(o[u++],l,m);u++}}}this.nodeSet=new A0(t.map((o,l)=>ft.define({name:l>=this.minRepeatTerm?void 0:o,id:l,props:a[l],top:n.indexOf(l)>-1,error:l==0,skipped:e.skippedNodes&&e.skippedNodes.indexOf(l)>-1}))),e.propSources&&(this.nodeSet=this.nodeSet.extend(...e.propSources)),this.strict=!1,this.bufferLength=Gp;let r=ja(e.tokenData);this.context=e.context,this.specializerSpecs=e.specialized||[],this.specialized=new Uint16Array(this.specializerSpecs.length);for(let o=0;otypeof o=="number"?new O1(r,o):o),this.topRules=e.topRules,this.dialects=e.dialects||{},this.dynamicPrecedences=e.dynamicPrecedences||null,this.tokenPrecTable=e.tokenPrec,this.termNames=e.termNames||null,this.maxNode=this.nodeSet.types.length-1,this.dialect=this.parseDialect(),this.top=this.topRules[Object.keys(this.topRules)[0]]}createParse(e,t,n){let a=new IF(this,e,t,n);for(let s of this.wrappers)a=s(a,e,t,n);return a}getGoto(e,t,n=!1){let a=this.goto;if(t>=a[0])return-1;for(let s=a[t+1];;){let r=a[s++],o=r&1,l=a[s++];if(o&&n)return l;for(let u=s+(r>>1);s0}validAction(e,t){return!!this.allActions(e,n=>n==t?!0:null)}allActions(e,t){let n=this.stateSlot(e,4),a=n?t(n):void 0;for(let s=this.stateSlot(e,1);a==null;s+=3){if(this.data[s]==65535)if(this.data[s+1]==1)s=cn(this.data,s+2);else break;a=t(cn(this.data,s+1))}return a}nextStates(e){let t=[];for(let n=this.stateSlot(e,1);;n+=3){if(this.data[n]==65535)if(this.data[n+1]==1)n=cn(this.data,n+2);else break;if((this.data[n+2]&1)==0){let a=this.data[n+1];t.some((s,r)=>r&1&&s==a)||t.push(this.data[n],a)}}return t}configure(e){let t=Object.assign(Object.create(Zs.prototype),this);if(e.props&&(t.nodeSet=this.nodeSet.extend(...e.props)),e.top){let n=this.topRules[e.top];if(!n)throw new RangeError(`Invalid top rule name ${e.top}`);t.top=n}return e.tokenizers&&(t.tokenizers=this.tokenizers.map(n=>{let a=e.tokenizers.find(s=>s.from==n);return a?a.to:n})),e.specializers&&(t.specializers=this.specializers.slice(),t.specializerSpecs=this.specializerSpecs.map((n,a)=>{let s=e.specializers.find(o=>o.from==n.external);if(!s)return n;let r=Object.assign(Object.assign({},n),{external:s.to});return t.specializers[a]=Qm(r),r})),e.contextTracker&&(t.context=e.contextTracker),e.dialect&&(t.dialect=this.parseDialect(e.dialect)),e.strict!=null&&(t.strict=e.strict),e.wrap&&(t.wrappers=t.wrappers.concat(e.wrap)),e.bufferLength!=null&&(t.bufferLength=e.bufferLength),t}hasWrappers(){return this.wrappers.length>0}getName(e){return this.termNames?this.termNames[e]:String(e<=this.maxNode&&this.nodeSet.types[e].name||e)}get eofTerm(){return this.maxNode+1}get topNode(){return this.nodeSet.types[this.top[1]]}dynamicPrecedence(e){let t=this.dynamicPrecedences;return t==null?0:t[e]||0}parseDialect(e){let t=Object.keys(this.dialects),n=t.map(()=>!1);if(e)for(let s of e.split(" ")){let r=t.indexOf(s);r>=0&&(n[r]=!0)}let a=null;for(let s=0;sn)&&t.p.parser.stateFlag(t.state,2)&&(!e||e.scorei.external(t,n)<<1|e}return i.get}const TF=Up({null:L.null,instanceof:L.operatorKeyword,this:L.self,"new super assert open to with void":L.keyword,"class interface extends implements enum var":L.definitionKeyword,"module package import":L.moduleKeyword,"switch while for if else case default do break continue return try catch finally throw":L.controlKeyword,"requires exports opens uses provides public private protected static transitive abstract final strictfp synchronized native transient volatile throws":L.modifier,IntegerLiteral:L.integer,FloatingPointLiteral:L.float,"StringLiteral TextBlock":L.string,CharacterLiteral:L.character,LineComment:L.lineComment,BlockComment:L.blockComment,BooleanLiteral:L.bool,PrimitiveType:L.standard(L.typeName),TypeName:L.typeName,Identifier:L.variableName,"MethodName/Identifier":L.function(L.variableName),Definition:L.definition(L.variableName),ArithOp:L.arithmeticOperator,LogicOp:L.logicOperator,BitOp:L.bitwiseOperator,CompareOp:L.compareOperator,AssignOp:L.definitionOperator,UpdateOp:L.updateOperator,Asterisk:L.punctuation,Label:L.labelName,"( )":L.paren,"[ ]":L.squareBracket,"{ }":L.brace,".":L.derefOperator,", ;":L.separator}),_F={__proto__:null,void:34,byte:36,short:36,int:36,long:36,char:36,float:36,double:36,boolean:36,extends:50,super:52,this:64,public:70,protected:72,private:74,abstract:76,static:78,final:80,strictfp:82,default:84,synchronized:86,native:88,transient:90,volatile:92,sealed:95,non:97,instanceof:140,true:158,false:158,null:166,class:170,new:176,throws:196,implements:204,permits:211,record:215,interface:226,enum:236,open:289,module:291,requires:296,transitive:298,exports:300,to:302,opens:304,uses:306,provides:308,with:310,package:314,import:318,if:330,else:332,while:336,for:340,var:347,assert:354,switch:358,case:366,throw:370,do:374,break:378,continue:382,return:386,try:392,catch:396,finally:404},AF=Zs.deserialize({version:14,states:"#5QQ]QPOOQ%QQPOOO(wQQO'#HlO+OQQO'#CbOOQO'#Cb'#CbO+VQPO'#CaOOQO'#Co'#CoO,{QPO'#DOO-iQQO'#HvOOQO'#Hv'#HvO0^QQO'#HqO0eQQO'#HqOOQO'#Hq'#HqOOQO'#Hp'#HpOOQO'#Hz'#HzO0lQPO'#GwO2`QPO'#DOO2gQPO'#CkO4vQPO'#DfO4}QPO'#CiO6ZQQO'#FsO6bQPO'#DyO7rOSO'#EQOOQO'#IW'#IWO+VQPO'#EzO8iQPO'#EzOOQO'#EV'#EVO:QQQO'#ITOnQPO'#HzO>uQPO'#EcO>uQPO'#EjO>uQPO'#EuO>uQPO'#EpO>}QPO'#I[O?cQQO'#FRO+VQPO'#C`O?kQPO'#C`O+VQPO'#FnO?pQPO'#FpO@OQPO'#FvO@OQPO'#FyO>uQPO'#GOO@TQPO'#F{O6bQPO'#GSO6bQPO'#G[O@OQPO'#GUO]QPO'#G^O@YQPO'#G`O@eQPO'#GbO@pQPO'#GdO@wQPO'#GgOAeQQO'#CjOBTQQO'#CjOB_QPO'#I`OCzQPO'#DOODbQPO'#E]OBbQPO'#E^OESQPO'#I`OEeQPO'#E]OEmQPO'#IhOErQPO'#FOOOQO'#I^'#I^OOQO'#G}'#G}Q%QQPOOOGhQPO'#HzOOQO'#Hl'#HlOHZQQO,58{OOQO'#Hj'#HjOOQO'#Hr'#HrOJtQPO,59_OLSQPO,59jOOQO-E:r-E:rO+VQPO,58zOLyQPO,58zO+VQPO,5uQPO,5:}O>uQPO,5;UO>uQPO,5;aO>uQPO,5;[O>uQPO,5gO6bQPO'#EUO@zQPO,5=QO!0rQPO,5:}O!1TQPO,5;UO!1]QPO,5;aO!1eQPO,5;[O!-SQPO,5>vO!1sQPO,5>vO!-SQPO,5>vO!2OQPO,5;mO!2aQQO,58zO!2iQQO,5zOB_QPO,5:vO!;WQPO,5:wOErQPO,5;jO!;`QPO'#E_OBbQPO'#E_O!;kQPO'#IaO!;sQPO,5:xOB_QPO,5>zO!-SQPO,5>zOEmQPO,5?SOOQO,5:w,5:wO!+VQPO'#CkOOQO,5?S,5?SO!?pQPO'#FPOOQO,5;j,5;jO!?wQPO,5;jO!-SQPO'#EaOOQO-E:{-E:{OOQO,5;i,5;iO+VQPO,58}O!?|QPO'#ChOOQO1G.k1G.kO!2aQQO1G.fO+VQPO1G.fO!@WQQO1G1tOOQO,59f,59fO!@`QPO,59fOOQO-E:t-E:tO!@eQPO,5>iO!@|QPO,59zO>uQPO'#HOO!ATQPO,5>yOOQO1G2U1G2UOOQO1G0Y1G0YO!AnQPO'#CsO!B^QPO'#HvO!BkQPO'#CtO!ByQPO'#HuO!CRQPO,59^OOQO1G.v1G.vO!#aQPO1G.vO!CiQPO,59_O!CvQQO'#HlO!DXQQO'#CbO!DjQPO,59yOOQO,59i,59iO>uQPO,59yOOQO,59W,59WO!DuQQO,59WO!DzQPO,59iO!,oQPO'#GyO!E]QPO,5>eOOQO1G.q1G.qO!EeQPO'#C}O!EvQPO1G.qO>uQPO'#GzO!E{QPO,5>mOOQO1G/k1G/kOOQO1G0[1G0[O!-SQPO'#HPO!FTQPO1G1cO6bQPO1G1cOOQO1G/l1G/lO!F]QQO1G.oOOQO1G.o1G.oO!HZQQO1G/mO!IxQQO1G/mO!KgQQO1G/mO!KnQQO1G/mO!KuQQO1G/mO!MdQQO1G/mO!MkQQO1G/mO# YQQO1G/mO# aQQO1G/mO# kQQO1G/mO# rQQO1G/|O!)dQPO'#DOO# yQQO'#HvO!*jQPO'#DuOOQO1G/y1G/yO##`QQO1G1dOOOO-E:y-E:yOOQO1G0W1G0WO##vQPO'#E{OOQO1G1Q1G1QO#$jQPO1G2UO!-{QPO1G1QO!0rQPO1G0iO!1TQPO1G0pO!1]QPO1G0{O!1eQPO1G0vOOQO1G0]1G0]O#$oQQO1G1XO}QPO'#I[OOQO1G1X1G1XO#&iQQO1G1XO#&qQQO1G1YOOQO1G1]1G1]O#&xQPO1G1]O#'TQQO'#I]O#'bQPO,5:sOOQO1G1z1G1zOOQO1G4R1G4ROOQO1G2l1G2lO#'gQPO'#EYO!-SQPO'#EdO!-SQPO'#EeO!-SQPO'#EhOOQO1G0i1G0iO#'nQPO1G0iO#'sQPO1G0iO#'{QPO1G0iO#(WQPO1G0iO#(fQPO'#ElO#(|QPO1G0pO#)UQPO1G0pO#)ZQPO'#EwOOQO1G0{1G0{O#)nQPO1G0{O#)sQPO'#EsO!-SQPO'#ErOOQO1G0v1G0vO#*pQPO1G0vO#*uQPO1G0vO#*}QPO1G0vO!1sQPO1G4bO#+YQPO'#FXO#+aQPO'#FXOOQO'#HX'#HXO#+iQQO1G1^O#-fQQO1G4bO!-SQPO1G4bO|OOQO1G0b1G0bOOQO1G4f1G4fO#DXQPO1G0bOOQO1G0c1G0cOOQO1G1U1G1UO!?wQPO1G1UOOQO,5:y,5:yO!-SQPO'#E`O#D^QPO,5:yOBbQPO'#HQO#DiQPO,5>{OOQO1G0d1G0dOEmQPO'#IbO#DqQPO1G4fOB_QPO1G4fOOQO1G4n1G4nO!)tQPO'#C}O!)dQPO'#DOOOQO,5;k,5;kO#D|QPO,5;kO#ETQPO,5;kO#E[QQO'#ITO#EcQQO'#IVO#EjQQO'#FQO#EuQPO'#FQO#E}QPO'#IcOOQO,5:{,5:{OOQO1G.i1G.iO#F]QQO'#HnO#FmQQO'#FUO#HTQPO'#F`OOQO'#Hn'#HnO#H_QPO'#HnO#H|QPO'#IkO#IUQPO,59SOOQO7+$Q7+$QO!2aQQO7+$QOOQO7+'`7+'`OOQO1G/Q1G/QO#IZQPO'#DdO#IeQQO'#IPOOQO'#IP'#IPOOQO1G/f1G/fOOQO,5=j,5=jOOQO-E:|-E:|O#IuQWO,58{O#I|QPO,59`OOQO,59`,59`O!-SQPO'#HxO!!tQPO'#GuO#J[QPO,5>aOOQO1G.x1G.xOOQO7+$b7+$bOOQO1G.r1G.rO#JdQQO1G.rO>uQPO1G/eOOQO1G/e1G/eO#JiQPO1G.rO#JnQPO1G/eOOQO1G/T1G/TOOQO,5=e,5=eOOQO-E:w-E:wOOQO7+$]7+$]OOQO,5=f,5=fOOQO-E:x-E:xOOQO,5=k,5=kOOQO-E:}-E:}O6bQPO7+&}O#JyQQO7+&}O6bQPO7+%hO#LgQQO,59_OOQO,5:a,5:aOB_QPO,5:aO#MvQPO'#EtO#NUQPO'#EtOOQO'#HW'#HWO#NpQPO,5;gOOQO,5;g,5;gOOQO7+'p7+'pOOQO7+&l7+&lOOQO7+&T7+&TO#'nQPO7+&TO#'sQPO7+&TO#'{QPO7+&TO#(WQPO7+&TO#(|QPO7+&[O#)UQPO7+&[OOQO7+&g7+&gO#)nQPO7+&gOOQO7+&b7+&bO#*pQPO7+&bO#*uQPO7+&bO#*}QPO7+&bOOQO7+&u7+&uOOQO'#FU'#FUOvOvO$ dQPO7+&sO$ rQPO7+&wOOQO7+&t7+&tOOQO7+&w7+&wO6bQPO'#G|O$!QQPO,5>wOOQO1G0_1G0_O$!]QPO,5:tOOQO,5:t,5:tOOQO,5;O,5;OOOQO'#Eg'#EgOOQO,5;P,5;POOQO,5;S,5;SO$!dQPO'#EmO!*jQPO'#EmO$!uQPO'#IdO$!}QPO,5;WO$#SQPO'#EnOOQO7+&[7+&[O$#ZQPO7+&[O$#`QPO'#ExO>uQPO'#ExO$#qQPO'#IfO$#|QPO,5;cOB_QPO'#I`O!-SQPO'#I`O$$UQPO'#E]OOQO'#HU'#HUO$$]QPO,5;_OOQO,5;_,5;_OOQO,5;^,5;^O$%YQQO7+&xO$'VQQO7+)|O$)PQQO,5;sOOQO,5;s,5;sO$)WQPO,5;sOOQO-E;V-E;VOOQO7+&x7+&xOOQO7+)|7+)|O}O$4VQPO,5;{O$4^QPO'#IjO$4fQPO,5;zO+VQPO'#HZO$4kQPO,5?VOOQO1G.n1G.nOOQO<d,5>dOOQO,5=a,5=aOOQO-E:s-E:sO$5QQPO7+$^OOQO7+%P7+%POOQO7+$^7+$^O>uQPO7+%PO$5VQQO<uQPO,5;XOOQO,5;X,5;XO$;zQPO,5;XO!,oQPO'#HSO$<]QPO,5?OOOQO1G0r1G0rODbQPO'#E]O$WQPO'#EyOOQO1G0}1G0}O$>_QPO1G0}OB_QPO,5;`OOQO-E;S-E;SOOQO1G0y1G0yOOQO<dQQO1G1_O$>kQQO<uQPO,5=VO!*jQPO,5=VOOQO1G2o1G2oOOQO<lOOQO1G/j1G/jOOQO<uQPO1G0sOOQO1G0s1G0sO$HSQPO1G0sOOQO,5=n,5=nOOQO-E;Q-E;QO$uQPO1G2qOOQO<uQPO7+&_OOQO1G0u1G0uOOQO7+&j7+&jOOQO7+'V7+'VO+VQPO'#H^O$JtQPO,5?XO$J|QPO7+'VO$KRQQO'#InOOQOAN@yAN@yO$K^QQOAN@yOOQOAN@uAN@uO$KeQPOAN@uO$KjQQO<`!>cP!=^!>{!=^P!=^P!?O!?R!?VP!{#?U#?XP0oP#?]!)]PPP#Ae#Cm#C|#DY#Dr#ET#EW#Ed#El#Eo#EsP#EvP#FU#FX#F[#F`#Ff#FiwuOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/u)usOPVW_abepy!Q![!]!_!b!f!g!i!j!p!v#O#R#W#Y#Z#_#`#d#j#k#n#o#p#q#r#s#t#u#v#w#x#{#|#}$O$T$]$_$b$e$k$l$m$t$u$v$w$x%U%Y%]%a%d%e%h%j%m%q%y%z&P&Q&V&W&Z&`&a&d&j&l&{&|'S'`'k'l'm'n't'w'z'{(Q(R(S(U(W(d(f(k(m(u)R)Z)])b)d)e)g)h)r){*U*V*`*i*k*l*n*o*r+W+^+a+g+k+r+s+v+y+},^,`,b,c,g,j,m,n,s,x-R-T-U-Y-[-t.^.a.b.i.n.p.s/W/Y/^/e/i/m/u/}0T0j0u1S1V1Z1]1^1j2Q2R2X2Z2[2e2i2k2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3`3b3c3d3h3i3m3n$xlOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%j%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j-T-U-[/W/Y/^/e/u/}0T1S1V1Z2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3nv!tT!S!U!V!y!{$r$s%t,V,W,X,Y/P/R1O1P1w2rQ$ShS&_#`)dQ'V$UU']$[$n-VQ'd$^W(w%U,n/i1]U)o%p(^,]Q)q%qS*[&W-RU+U'_.W/vQ+]'eQ-s*oQ.T+YQ.X+ZQ0Q-_Q0]-tR0g.Yw!tT!S!U!V!y!{$r$s%t,V,W,X,Y/P/R1O1P1w2rT%r!s*R${rOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j-T-U-[/W/Y/^/e/u/}0T1S1V1Z2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3n$OcObepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g-T-U-[/W/Y/^/e/u/}0T1S1V1Z2Z2i2n3n^!lP!h!p'k+a.p0u|#RW!Y#`$T$Z%{&]&`&d(d(u)d*]*o+g,`,m-l-t.a/n1aS#ea3mQ$g|Q$h}Q$i!OQ$j!PW%Y!f%]+r.sS%`!i)]Q%f!jQ'W$VQ'X$WQ'Y$XQ'Z$YQ)[%aS)`%d)bQ*e&fQ*m&|S+n'w.nQ-o*nS.f+k.iQ.m+oQ0i._Q0m.eQ1r0hQ2^1sw3g,j2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i$ScOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g-T-U-[/W/Y/^/e/u/}0T1S1V1Z2Z2i2n3m3nU%i!l.f0mS)R%Y)`Q)c%fw3g,j2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3iV#da%h3m'fYOPVabeipy!Q![!]!_!b!h!j!p#W#_#a#d#j#k#n#o#p#q#r#s#t#u#v#w#x#{#|#}$]$_$b$e$k$m$t$u$v$w$x%U%e%h%j%m%q%z&P&a&j&l&{&}'S'`'k'l'm'n't'z'{(R(W(e(f(k(m(y)Z)e)g)h)r){*U*V*i*k*p*r+W+^+a+h+k+s+t+v+},^,b,c,g,j,n-T-U-Y-[.b.e.i.p/W/Y/^/e/i/u/}0T0u1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3`3b3c3d3h3i3m3nQ&U#YQ*Y&VX/k,s/o1^2R'fYOPVabeipy!Q![!]!_!b!h!j!p#W#_#a#d#j#k#n#o#p#q#r#s#t#u#v#w#x#{#|#}$]$_$b$e$k$m$t$u$v$w$x%U%e%h%j%m%q%z&P&a&j&l&{&}'S'`'k'l'm'n't'z'{(R(W(e(f(k(m(y)Z)e)g)h)r){*U*V*i*k*p*r+W+^+a+h+k+s+t+v+},^,b,c,g,j,n-T-U-Y-[.b.e.i.p/W/Y/^/e/i/u/}0T0u1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3`3b3c3d3h3i3m3nX/k,s/o1^2R'fZOPVabeipy!Q![!]!_!b!h!j!p#W#_#a#d#j#k#n#o#p#q#r#s#t#u#v#w#x#{#|#}$]$_$b$e$k$m$t$u$v$w$x%U%e%h%j%m%q%z&P&a&j&l&{&}'S'`'k'l'm'n't'z'{(R(W(e(f(k(m(y)Z)e)g)h)r){*U*V*i*k*p*r+W+^+a+h+k+s+t+v+},^,b,c,g,j,n-T-U-Y-[.b.e.i.p/W/Y/^/e/i/u/}0T0u1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3`3b3c3d3h3i3m3nX/l,s/o1^2RS#XY/kS$m!Q'`S'_$[$nQ'e$^S)l%j)hQ.W+YQ.Y+ZR/v-V%mXOabepy![!]!_!b#W#j#k#n#o#p#q#r#s#t#u#v#w#x#{#|$]$_$b$e$t$u$v$w$x%U%j%m%q%z&j&l'l'm'n'{(R(f(k(m)Z)g)h)r){*U*V*i*k+^+},^,b,c,g,j,n-T-U-Y-[/W/Y/^/e/i/u/}0T1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3nQ&S#WR-g*V'c]OPVabeipy![!]!_!b!h!j!p#W#_#a#d#j#k#n#o#p#q#r#s#t#u#v#w#x#{#|#}$]$_$b$e$t$u$v$w$x%U%e%h%j%m%q%z&P&a&j&l&{&}'S'k'l'm'n't'z'{(R(e(f(k(m(y)Z)e)g)h)r){*U*V*i*k*p*r+^+a+h+k+s+t+v+},^,b,c,g,j,n,s-T-U-Y-[.b.e.i.p/W/Y/^/e/i/o/u/}0T0u1S1V1Z1]1^2R2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3`3b3c3d3h3i3m3n!w#PW!f!v#Q#R#`$O$T%X%Y%]%d%y&Q&W&`&d&|(d(u)R)b)d*l*n*o+g+r,`,m,x-R-t.a.s/m1j2Q2X2[2e2kW#ba#d%h3mR*b&aviOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/u[!hP!p'k+a.p0uY#aa#d%h&a3mQ&}#{Q(e$vW(y%U,n/i1]S*p'S*rS+h't.bS+o'w.nS+t'z+vS.e+k.iR/o,sh#TW!Y!f$T$Z%](d*o+r,`-t.sQ*P%{Q*^&]Q-j*]R0X-lU)}%z){0TQ,P(UR.v+y$ScOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g-T-U-[/W/Y/^/e/u/}0T1S1V1Z2Z2i2n3m3nw3g,j2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3ivwOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/u`!nP!p'k+a+k.i.p0uQ%V!cQ%g!kQ%o!qS&o#k2wQ'j$fQ)Q%WQ)V%^Q,u)OQ/p,tQ0n.fQ1W/^R1t0m${qOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j-T-U-[/W/Y/^/e/u/}0T1S1V1Z2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3n!^#od#g$y$z%S&n&p&r&s&t&u&v&z'P'c'f)p)|+{,a,d-n.Z.y/[1R1Y1|2P3lg2y/b3U3V3X3Y3Z3[3]3a3e3f!Y#rd#g$y$z%S&n&r&s&u&v&z'P'c'f)p)|+{,a,d-n.Z.y/[1R1Y1|2P3lc2|/b3U3X3Y3[3]3a3e3fR'O#{%TgOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%U%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j,n-T-U-[/W/Y/^/e/i/u/}0T1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3n%ToOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%U%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j,n-T-U-[/W/Y/^/e/i/u/}0T1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3n%SoOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%U%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j,n-T-U-[/W/Y/^/e/i/u/}0T1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3nQ$f{Q$t!WQ$u!XQ${!^R,k(oQ$`mS(V$l+XQ+T'^S+z(Q(XS-W)j)kQ.S+VQ.l+nQ.z,RQ/y-XQ0e.VQ0r.mQ1d/wQ1q0fR2V1cQ'o$gY*v'W'p'q'r'sQ,Q(VW-w*w*x*y*zQ.k+nQ.w+zU0^-x-y-zS0q.l.mQ0x.zS1m0_0`Q1u0rR2]1na!nP!p'k+a+k.i.p0u`!nP!p'k+a+k.i.p0uT+u'z+vd!jP!h!p'k+a+k.e.i.p0uQ's$gQ'v$hQ(P$jQ*z'WQ*|'XQ+S'ZV+s'z+t+vQ%b!iR,})]Q)Y%`R,|)[Q%l!mQ)T%[Q)X%_Q-P)aR/s-QvuOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/u`!nP!p'k+a+k.i.p0uS*q'S*rT+u'z+vQ'r$gS*y'W'sR-z*zQ'q$gQ'y$iU*x'W'r'sQ+O'YQ+m'uS-y*y*zQ-|*{Q0`-zR0b-}Q+e'mQ+f'nR+x'{Q'p$gQ'}$jW*w'W'q'r'sU+Q'Z(O(PU-x*x*y*zS.Q+R+SS0_-y-zQ0d.RR1n0`Q'u$hS*{'X'vR-}*|Q+i'tR0k.bQ+l'uS-{*{+mS0a-|-}R1o0bT.g+k.iQ(O$jS+R'Z(PR.R+SQ'|$jW+P'Z'}(O(PU.P+Q+R+SS0c.Q.RR1p0dvuOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/u`!nP!p'k+a+k.i.p0uT+u'z+vQ'x$iS*}'Y'yR.O+OQ+p'wR0s.nR.r+qQ'T$SR*u'VT*q'S*rQ%k!mS)W%_%lR,z)XQ)g%jR-U)h$zoOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j-T-U-[/W/Y/^/e/u/}0T1S1V1Z2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3nX(x%U,n/i1]%SmOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%U%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j,n-T-U-[/W/Y/^/e/i/u/}0T1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3nU'^$[$n-VS+V'_/vQ.V+YR0f.WX(T$l(Q(U+y_)s%q)r-[/}2Z2i2nQ)u%qR0R-_Q([$oQ)w%sR-b)xT,S(Z,TvwOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/uR1W/^wwOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/uvvOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/uQ%P!`R%R!aR$w!ZvwOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/uR(f$vR$x!ZR(n${T,f(m,gT,e(m,gX({%V(|)Q,vR,t(}Q/n,sR1a/oQ)P%VQ,r(|Q,w)QR/q,vR%W!cQ(z%UV/g,n/i1]QyOQ#jbY$cy#j)h-T/uQ)h%jQ-T)gR/u-UvVOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/uv!gP!p#d&a'S'k't'w'z*r+a+k+v,s.b.i.n.p0u|!xV!g#O#Z#_#}$k%a%e&P&V&Z&{(S(W)e*`+W.^0j2R3`!f#OW!f!v#R$O$T%Y%]%d%y&Q&W&|(d(u)R)b*l*n*o+r,`,m,x-R-t.s/m1j2Q2X2[2e2kQ#Z_S#_a3m$`#}ep![!]!b#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$e%m%q%z&j&l'l'm'n'{(R(f(k)Z)r){*U*i*k+^+},b,c,j-Y-[/W/Y/^/e/}0T1S1V1Z2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3nQ$k!QS%a!i)]S%e!j+sS&P#W*VQ&V#YU&Z#`&d)dQ&{#{W(S$l(Q(U+yQ(W$mQ)e%hQ*`&`Q+W'`Q.^+gQ0j.aQ2R1^Z3`$v%U,n/i1]Q*W&SR-h*W^#QW#`$O&|(d(u*l!Q%X!f!v$T%]%d&Q&W&`&d)b)d*n*o+g+r,`,m-R-t.a.s/m2Q2e[%x#Q%X%y,x2X2kS%y#R%YQ,x)RQ2X1jR2k2[#Q`OPaby!_!p#d#j#{$b$t$u$v$w$x%U%h%j&a'S'k't'w'z(m)g)h*r+a+k+v,^,g,n,s-T-U.b.i.n.p/i/u0u1]3m[!wV!g#_&{)e3`T#[`!wQ0U-cR1i0UQ&b#bR*c&bQ&g#eR*f&gQ$QfR'Q$QQ+_'fS.[+_1XR1X/bQ!pPU%n!p+a0uQ+a'kR0u.pQ%|#TR*Q%|Q&k#hU*h&k/r3kQ/r,{R3k3jQ)^%bR-O)^Q-Z)mR/{-ZQ.c+iR0l.cQ.i+kR0o.iQ+v'zR.t+vQ.o+pR0t.oQ*r'SR-u*rQ(U$lQ+y(QT,O(U+yQ0O-]R1g0OQ-`)uR0S-`Q,T(ZR.{,TQ/P,VR0{/PQ1x0|S2`1x2bR2b1zQ,g(mR/`,gQ(|%VS,q(|,vR,v)QQ1_/mR2S1_Q,o(zR/j,odxOby#j%j)g)h-T-U/uQ$|!_Q'h$bQ(b$tQ(c$uQ(h$wQ(i$xS,f(m,gR/V,^)ftOPVW_abepy!Q![!]!_!b!f!g!i!j!p!v#O#R#W#Y#Z#_#`#d#j#k#n#o#p#q#r#s#t#u#v#w#x#{#|#}$O$T$]$_$b$e$k$l$m$t$u$v$w$x%U%Y%]%a%d%e%h%j%m%y%z&P&Q&V&W&Z&`&a&d&j&l&{&|'S'`'k'l'm'n't'w'z'{(Q(R(S(U(W(d(f(k(m(u)R)Z)])b)d)e)g)h){*U*V*`*i*k*l*n*o*r+W+^+a+g+k+r+s+v+y+},^,`,b,c,g,j,m,n,s,x-R-T-U-Y-t.^.a.b.i.n.p.s/W/Y/^/e/i/m/u0T0j0u1S1V1Z1]1^1j2Q2R2X2[2e2k2w2x2y2z2{2|2}3O3P3Q3R3S3T3`3b3c3d3h3i3m3n_)t%q)r-[/}2Z2i2nQ!sTQ$o!SQ$p!UQ$q!VQ%s!yQ%u!{Q(`$rQ(a$sQ)x%tQ*R2rS.},V,XQ/R,WQ/S,YQ0z/PS0|/R1OQ1z1PR2_1w&{SOTabehpy!S!U!V![!]!_!b!y!{#`#j#k#n#o#p#q#r#s#t#u#v#w#x#|$U$[$]$^$_$b$e$n$r$s$t$u$v$w$x%U%j%p%q%t%z&W&l'_'e(R(^(f(k(m)d)g)h)r){*i*k*o+Y+Z+^+},V,W,X,Y,],^,b,c,g,j,n-R-T-U-V-[-_-t.W.Y/P/R/W/Y/^/e/i/u/v/}0T1O1P1S1V1Z1]1w2Z2i2n2r2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3nQ)v%qQ-])rQ/|-[Q1f/}Q2j2ZQ2l2iR2p2nxdOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/^/uU#ga$e3mS#ye3hS$ap3iQ$y![Q$z!]Q%S!bQ&n#kQ&p#nQ&q#oQ&r#pQ&s#qQ&t#rQ&u#sQ&v#tQ&w#uS&x#v3QQ&y#wQ&z#xQ'P#|Q'c$]Y'f$_$v,b/Y1V^)p%q)r-[/}2Z2i2nU)|%z){0TS*j&l3TQ+{(RQ,a(fQ,d(kS-m*i3bQ-n*kQ.Z+^Q.y+}Q/[,cQ/b,jQ1R/WQ1Y/eQ1|1SQ2P1ZQ3U2wQ3V2xQ3W2yQ3X2zQ3Y2{Q3Z2|Q3[2}Q3]3OQ3^3PQ3_3RQ3a3SQ3e3cQ3f3dR3l3nvWOby!_#j$b$t$u$w$x%j(m)g)h,^,g-T-U/u`!fP!p'k+a+k.i.p0uW!vV#}&P3`S#`a3m#|$Oep![!]!b#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$e%q%z&l(R(f(k)r){*i*k+^+},b,c,j-[/W/Y/^/e/}0T1S1V1Z2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3nQ$TiS%]!h.eS%d!j+sf&Q#W%m&j'l'm'n'{)Z*U*V-YQ&W#_Q&`#aS&d#d&aQ&|#{Q(d$vW(u%U,n/i1]Q)b%eQ)d%hQ*l&{Q*n&}S*o'S*rS+g't.bS+r'z+vQ,`(eQ,m(yQ-R)eQ-t*pQ.a+hQ.s+tS/m,s/oQ2Q1^R2e2R'b]OPVabeipy![!]!_!b!h!j!p#W#_#a#d#j#k#n#o#p#q#r#s#t#u#v#w#x#{#|#}$]$_$b$e$t$u$v$w$x%U%e%h%j%m%q%z&P&a&j&l&{&}'S'k'l'm'n't'z'{(R(e(f(k(m(y)Z)e)g)h)r){*U*V*i*k*p*r+^+a+h+k+s+t+v+},^,b,c,g,j,n,s-T-U-Y-[.b.e.i.p/W/Y/^/e/i/o/u/}0T0u1S1V1Z1]1^2R2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3`3b3c3d3h3i3m3nQ$l!QQ(Q$kS(X$m+WQ+X'`R,R(W'sUOPVabeipy!Q![!]!_!b!h!j!p#W#Y#_#a#d#j#k#n#o#p#q#r#s#t#u#v#w#x#{#|#}$]$_$b$e$k$m$t$u$v$w$x%U%e%h%j%m%q%z&P&V&a&j&l&{&}'S'`'k'l'm'n't'z'{(R(W(e(f(k(m(y)Z)e)g)h)r){*U*V*i*k*p*r+W+^+a+h+k+s+t+v+},^,b,c,g,j,n,s-T-U-Y-[.b.e.i.p/W/Y/^/e/i/o/u/}0T0u1S1V1Z1]1^2R2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3`3b3c3d3h3i3m3nR&T#W%OnObepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%U%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j,n-T-U-[/W/Y/^/e/i/u/}0T1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3nQ#haQ&S#WQ'O#{W)m%m'm'n'{Q*g&jQ+c'lQ,{)ZQ-f*UQ-g*VQ/z-YR3j3mQ*T&RR-e*SU#ca%h3mR&e#d#c_OPV`aby!_!g!p!w#_#d#j#{$b$t$u$v$w$x%U%h%j&a&{'S'k't'w'z(m)e)g)h*r+a+k+v,^,g,n,s-T-U.b.i.n.p/i/u0u1]3`3m#c^OPV`aby!_!g!p!w#_#d#j#{$b$t$u$v$w$x%U%h%j&a&{'S'k't'w'z(m)e)g)h*r+a+k+v,^,g,n,s-T-U.b.i.n.p/i/u0u1]3`3ml#SW!Y!f$T$Z%]%{&]*]*o+r-l-t.sU&[#`&d)dQ*a&`Q,_(dQ,l(uQ.`+gQ/X,`Q/f,mQ0i.aQ1`/nR2U1aQ*O%zQ-c){R1h0TR-d){T#fa3m$vkOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%q%z&l(R(f(k(m)g)r){*i*k+^+},^,b,c,g,j-T-U-[/W/Y/^/e/u/}0T1S1V1Z2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3nW(v%U,n/i1]T)i%j)h%SjOabepy![!]!_!b#j#k#n#o#p#q#r#s#t#u#v#w#x#|$]$_$b$e$t$u$v$w$x%U%j%q%z&l(R(f(k(m)g)h)r){*i*k+^+},^,b,c,g,j,n-T-U-[/W/Y/^/e/i/u/}0T1S1V1Z1]2Z2i2n2w2x2y2z2{2|2}3O3P3Q3R3S3T3b3c3d3h3i3m3nT'[$[-VQ'g$_Q(g$vQ/Z,bQ1T/YR2O1V[!oP!p'k+a.p0uT.g+k.iU#UW!Y(dQ%Z!fU'U$T$Z,`Q)U%]S-r*o+rT0[-t.sd!kP!p'k'z+a+k+v.i.p0uV%^!h+t.eR%c!iW%[!f%]+r.sQ)a%dR-Q)bQ)n%mV+d'm'n'{R+j'tT.h+k.iR+q'w`!mP!p'k+a+k.i.p0uT%_!h.eR-^)rR)v%qT/O,V/PQ0}/RR1y1OR1y1PR/c,j",nodeNames:"⚠ LineComment BlockComment Program ModuleDeclaration MarkerAnnotation Identifier ScopedIdentifier . Annotation ) ( AnnotationArgumentList LambdaExpression Definition FormalParameters ReceiverParameter void PrimitiveType TypeName ScopedTypeName GenericType TypeArguments AnnotatedType Wildcard extends super , ArrayType ] Dimension [ this FormalParameter Modifiers public protected private abstract static final strictfp default synchronized native transient volatile sealed non SpreadParameter VariableDeclarator AssignOp } { ArrayInitializer InferredParameters Block BinaryExpression CompareOp CompareOp CompareOp LogicOp LogicOp BitOp BitOp BitOp ArithOp ArithOp BitOp InstanceofExpression instanceof TypePattern TernaryExpression LogicOp : UpdateExpression UpdateOp IntegerLiteral FloatingPointLiteral BooleanLiteral CharacterLiteral StringLiteral TextBlock null ClassLiteral class ParenthesizedExpression ObjectCreationExpression new ArgumentList ClassBody ; FieldDeclaration MethodDeclaration TypeParameters TypeParameter TypeBound Throws throws ClassDeclaration Superclass SuperInterfaces implements InterfaceTypeList Permits permits RecordDeclaration record RecordHeader RecordComponent RecordBody CompactConstructorDeclaration InterfaceDeclaration interface ExtendsInterfaces InterfaceBody ConstantDeclaration EnumDeclaration enum EnumBody EnumConstant EnumBodyDeclarations AnnotationTypeDeclaration AnnotationTypeBody AnnotationTypeElementDeclaration StaticInitializer ConstructorDeclaration ConstructorBody ExplicitConstructorInvocation FieldAccess ArrayAccess MethodInvocation MethodName MethodReference ArrayCreationExpression Dimension UnaryExpression LogicOp BitOp CastExpression AssignmentExpression AssignOp ElementValueArrayInitializer ElementValuePair open module ModuleBody ModuleDirective requires transitive exports to opens uses provides with PackageDeclaration package ImportDeclaration import Asterisk ExpressionStatement LabeledStatement Label IfStatement if else WhileStatement while ForStatement for ForSpec LocalVariableDeclaration var EnhancedForStatement ForSpec AssertStatement assert SwitchStatement switch SwitchBlock SwitchRule SwitchLabel case ThrowStatement throw DoStatement do BreakStatement break ContinueStatement continue ReturnStatement return SynchronizedStatement TryStatement try CatchClause catch CatchFormalParameter CatchType FinallyClause finally TryWithResourcesStatement ResourceSpecification Resource ClassContent",maxTerm:296,nodeProps:[["isolate",-4,1,2,80,81,""],["group",-27,4,56,91,99,106,112,117,122,156,158,161,162,164,167,169,172,174,176,178,184,186,188,190,192,194,195,203,"Statement",-25,6,13,32,57,69,72,75,77,78,79,80,81,82,83,84,86,87,129,130,131,133,134,136,139,140,"Expression",-7,17,18,19,20,21,23,28,"Type"],["openedBy",10,"(",52,"{"],["closedBy",11,")",53,"}"]],propSources:[TF],skippedNodes:[0,1,2],repeatNodeCount:30,tokenData:"#$g_R!_OX%QXY'fYZ)bZ^'f^p%Qpq'fqr*|rs,^st%Qtu2zuv4avw5qwx7Xxy?pyz@^z{@z{|Ap|}CW}!OCt!O!PEa!P!QNZ!Q!R!+P!R![!.k![!]!;T!]!^!osw<}wx9}x#O<}#O#P&Z#P;'S<};'S;=`?d<%lO<}P>rVOY>oZw>owx?Xx#O>o#P;'S>o;'S;=`?^<%lO>oP?^O!rPP?aP;=`<%l>oT?gP;=`<%l<}T?mP;=`<%l8P_?wVZZ&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QV@eVYR&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QVATX$fP&}S!eQOY%QYZ%lZr%Qrs%qs!_%Q!_!`5T!`;'S%Q;'S;=`&s<%lO%QVAwZ!dR&}SOY%QYZ%lZr%Qrs%qs{%Q{|Bj|!_%Q!_!`5T!`;'S%Q;'S;=`&s<%lO%QVBqV!nR&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QVC_VkR&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_C}[&pW!dR&}SOY%QYZ%lZr%Qrs%qs}%Q}!OBj!O!_%Q!_!`5T!`!aDs!a;'S%Q;'S;=`&s<%lO%QVDzV&vR&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_EhZWY&}SOY%QYZ%lZr%Qrs%qs!O%Q!O!PFZ!P!Q%Q!Q![Gi![;'S%Q;'S;=`&s<%lO%QVF`X&}SOY%QYZ%lZr%Qrs%qs!O%Q!O!PF{!P;'S%Q;'S;=`&s<%lO%QVGSV&rR&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QTGpc&}S!pPOY%QYZ%lZr%Qrs%qs!Q%Q!Q![Gi![!f%Q!f!gH{!g!hIi!h!iH{!i#R%Q#R#SMc#S#W%Q#W#XH{#X#YIi#Y#ZH{#Z;'S%Q;'S;=`&s<%lO%QTISV&}S!pPOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QTIn]&}SOY%QYZ%lZr%Qrs%qs{%Q{|Jg|}%Q}!OJg!O!Q%Q!Q![KX![;'S%Q;'S;=`&s<%lO%QTJlX&}SOY%QYZ%lZr%Qrs%qs!Q%Q!Q![KX![;'S%Q;'S;=`&s<%lO%QTK`c&}S!pPOY%QYZ%lZr%Qrs%qs!Q%Q!Q![KX![!f%Q!f!gH{!g!h%Q!h!iH{!i#R%Q#R#SLk#S#W%Q#W#XH{#X#Y%Q#Y#ZH{#Z;'S%Q;'S;=`&s<%lO%QTLpZ&}SOY%QYZ%lZr%Qrs%qs!Q%Q!Q![KX![#R%Q#R#SLk#S;'S%Q;'S;=`&s<%lO%QTMhZ&}SOY%QYZ%lZr%Qrs%qs!Q%Q!Q![Gi![#R%Q#R#SMc#S;'S%Q;'S;=`&s<%lO%Q_Nb]&}S!eQOY%QYZ%lZr%Qrs%qsz%Qz{! Z{!P%Q!P!Q!'|!Q!_%Q!_!`5T!`;'S%Q;'S;=`&s<%lO%Q_! `X&}SOY! ZYZ! {Zr! Zrs!#hsz! Zz{!$v{;'S! Z;'S;=`!&[<%lO! Z_!!QT&}SOz!!az{!!s{;'S!!a;'S;=`!#b<%lO!!aZ!!dTOz!!az{!!s{;'S!!a;'S;=`!#b<%lO!!aZ!!vVOz!!az{!!s{!P!!a!P!Q!#]!Q;'S!!a;'S;=`!#b<%lO!!aZ!#bOQZZ!#eP;=`<%l!!a_!#kXOY!$WYZ! {Zr!$Wrs!&bsz!$Wz{!'Q{;'S!$W;'S;=`!'v<%lO!$W_!$ZXOY! ZYZ! {Zr! Zrs!#hsz! Zz{!$v{;'S! Z;'S;=`!&[<%lO! Z_!${Z&}SOY! ZYZ! {Zr! Zrs!#hsz! Zz{!$v{!P! Z!P!Q!%n!Q;'S! Z;'S;=`!&[<%lO! Z_!%uV&}SQZOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_!&_P;=`<%l! Z_!&eXOY!$WYZ! {Zr!$Wrs!!asz!$Wz{!'Q{;'S!$W;'S;=`!'v<%lO!$W_!'TZOY! ZYZ! {Zr! Zrs!#hsz! Zz{!$v{!P! Z!P!Q!%n!Q;'S! Z;'S;=`!&[<%lO! Z_!'yP;=`<%l!$W_!(TV&}SPZOY!'|YZ%lZr!'|rs!(js;'S!'|;'S;=`!)p<%lO!'|_!(oVPZOY!)UYZ%lZr!)Urs!)vs;'S!)U;'S;=`!*y<%lO!)U_!)ZVPZOY!'|YZ%lZr!'|rs!(js;'S!'|;'S;=`!)p<%lO!'|_!)sP;=`<%l!'|_!){VPZOY!)UYZ%lZr!)Urs!*bs;'S!)U;'S;=`!*y<%lO!)UZ!*gSPZOY!*bZ;'S!*b;'S;=`!*s<%lO!*bZ!*vP;=`<%l!*b_!*|P;=`<%l!)UT!+Wq&}S!oPOY%QYZ%lZr%Qrs%qs!O%Q!O!P!-_!P!Q%Q!Q![!.k![!d%Q!d!e!1u!e!f%Q!f!gH{!g!hIi!h!iH{!i!n%Q!n!o!0a!o!z%Q!z!{!3s!{#R%Q#R#S!0}#S#U%Q#U#V!1u#V#W%Q#W#XH{#X#YIi#Y#ZH{#Z#`%Q#`#a!0a#a#l%Q#l#m!3s#m;'S%Q;'S;=`&s<%lO%QT!-fa&}S!pPOY%QYZ%lZr%Qrs%qs!Q%Q!Q![Gi![!f%Q!f!gH{!g!hIi!h!iH{!i#W%Q#W#XH{#X#YIi#Y#ZH{#Z;'S%Q;'S;=`&s<%lO%QT!.ri&}S!oPOY%QYZ%lZr%Qrs%qs!O%Q!O!P!-_!P!Q%Q!Q![!.k![!f%Q!f!gH{!g!hIi!h!iH{!i!n%Q!n!o!0a!o#R%Q#R#S!0}#S#W%Q#W#XH{#X#YIi#Y#ZH{#Z#`%Q#`#a!0a#a;'S%Q;'S;=`&s<%lO%QT!0hV&}S!oPOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QT!1SZ&}SOY%QYZ%lZr%Qrs%qs!Q%Q!Q![!.k![#R%Q#R#S!0}#S;'S%Q;'S;=`&s<%lO%QT!1zY&}SOY%QYZ%lZr%Qrs%qs!Q%Q!Q!R!2j!R!S!2j!S;'S%Q;'S;=`&s<%lO%QT!2q`&}S!oPOY%QYZ%lZr%Qrs%qs!Q%Q!Q!R!2j!R!S!2j!S!n%Q!n!o!0a!o#R%Q#R#S!1u#S#`%Q#`#a!0a#a;'S%Q;'S;=`&s<%lO%QT!3x_&}SOY%QYZ%lZr%Qrs%qs!O%Q!O!P!4w!P!Q%Q!Q![!7V![!c%Q!c!i!7V!i#T%Q#T#Z!7V#Z;'S%Q;'S;=`&s<%lO%QT!4|]&}SOY%QYZ%lZr%Qrs%qs!Q%Q!Q![!5u![!c%Q!c!i!5u!i#T%Q#T#Z!5u#Z;'S%Q;'S;=`&s<%lO%QT!5zc&}SOY%QYZ%lZr%Qrs%qs!Q%Q!Q![!5u![!c%Q!c!i!5u!i!r%Q!r!sIi!s#R%Q#R#S!4w#S#T%Q#T#Z!5u#Z#d%Q#d#eIi#e;'S%Q;'S;=`&s<%lO%QT!7^i&}S!oPOY%QYZ%lZr%Qrs%qs!O%Q!O!P!8{!P!Q%Q!Q![!7V![!c%Q!c!i!7V!i!n%Q!n!o!0a!o!r%Q!r!sIi!s#R%Q#R#S!:V#S#T%Q#T#Z!7V#Z#`%Q#`#a!0a#a#d%Q#d#eIi#e;'S%Q;'S;=`&s<%lO%QT!9Qa&}SOY%QYZ%lZr%Qrs%qs!Q%Q!Q![!5u![!c%Q!c!i!5u!i!r%Q!r!sIi!s#T%Q#T#Z!5u#Z#d%Q#d#eIi#e;'S%Q;'S;=`&s<%lO%QT!:[]&}SOY%QYZ%lZr%Qrs%qs!Q%Q!Q![!7V![!c%Q!c!i!7V!i#T%Q#T#Z!7V#Z;'S%Q;'S;=`&s<%lO%QV!;[X!lR&}SOY%QYZ%lZr%Qrs%qs![%Q![!]!;w!];'S%Q;'S;=`&s<%lO%QV!l!`;'S%Q;'S;=`&s<%lO%QU!>PX!fQ&}SOY%QYZ%lZr%Qrs%qs!_%Q!_!`5T!`;'S%Q;'S;=`&s<%lO%QU!>sV!]Q&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QV!?aX!TR&}SOY%QYZ%lZr%Qrs%qs!_%Q!_!`+p!`;'S%Q;'S;=`&s<%lO%QV!@TY&gR&}SOY%QYZ%lZr%Qrs%qs!_%Q!_!`!>l!`!a!@s!a;'S%Q;'S;=`&s<%lO%QU!@zY!fQ&}SOY%QYZ%lZr%Qrs%qs!_%Q!_!`5T!`!a!=x!a;'S%Q;'S;=`&s<%lO%Q_!AsV&kX!kQ&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_!BaX&]Z&}SOY%QYZ%lZr%Qrs%qs#]%Q#]#^!B|#^;'S%Q;'S;=`&s<%lO%QV!CRX&}SOY%QYZ%lZr%Qrs%qs#b%Q#b#c!Cn#c;'S%Q;'S;=`&s<%lO%QV!CsX&}SOY%QYZ%lZr%Qrs%qs#h%Q#h#i!D`#i;'S%Q;'S;=`&s<%lO%QV!DeX&}SOY%QYZ%lZr%Qrs%qs#X%Q#X#Y!EQ#Y;'S%Q;'S;=`&s<%lO%QV!EVX&}SOY%QYZ%lZr%Qrs%qs#f%Q#f#g!Er#g;'S%Q;'S;=`&s<%lO%QV!EwX&}SOY%QYZ%lZr%Qrs%qs#Y%Q#Y#Z!Fd#Z;'S%Q;'S;=`&s<%lO%QV!FiX&}SOY%QYZ%lZr%Qrs%qs#T%Q#T#U!GU#U;'S%Q;'S;=`&s<%lO%QV!GZX&}SOY%QYZ%lZr%Qrs%qs#V%Q#V#W!Gv#W;'S%Q;'S;=`&s<%lO%QV!G{X&}SOY%QYZ%lZr%Qrs%qs#X%Q#X#Y!Hh#Y;'S%Q;'S;=`&s<%lO%QV!HoV'ZR&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_!I]b&aZ&}SOY%QYZ%lZr%Qrs%qst%Qtu!IUu!Q%Q!Q![!IU![!c%Q!c!}!IU!}#R%Q#R#S!IU#S#T%Q#T#o!IU#o$g%Q$g;'S!IU;'S;=`!Je<%lO!IU_!JhP;=`<%l!IU_!JrVoZ&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QV!K`VmR&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QU!K|X!cQ&}SOY%QYZ%lZr%Qrs%qs!_%Q!_!`5T!`;'S%Q;'S;=`&s<%lO%QV!LpV!VR&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_!M`Z'dX!bQ&}SOY%QYZ%lZr%Qrs%qs!_%Q!_!`5T!`#p%Q#p#q!NR#q;'S%Q;'S;=`&s<%lO%QU!NYV!`Q&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QV!NvV!UR&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QT# dV$OP&}SOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_#!Su&}S&XZ&_ZOX%QXY'fYZ)bZ^'f^p%Qpq'fqr%Qrs%qst%Qtu2zu!Q%Q!Q![2z![!c%Q!c!}2z!}#R%Q#R#S2z#S#T%Q#T#o2z#o#y%Q#y#z'f#z$f%Q$f$g'f$g#BY2z#BY#BZ# y#BZ$IS2z$IS$I_# y$I_$I|2z$I|$JO# y$JO$JT2z$JT$JU# y$JU$KV2z$KV$KW# y$KW&FU2z&FU&FV# y&FV;'S2z;'S;=`4Z<%lO2z",tokenizers:[0,1,2,3],topRules:{Program:[0,3],ClassContent:[1,206]},dynamicPrecedences:{21:1,246:-1,252:-1},specialized:[{term:245,get:i=>_F[i]||-1}],tokenPrec:9164}),OF=Os.define({name:"java",parser:AF.configure({props:[Kp.add({IfStatement:qr({except:/^\s*({|else\b)/}),TryStatement:qr({except:/^\s*({|catch|finally)\b/}),LabeledStatement:XE,SwitchBlock:i=>{let e=i.textAfter,t=/^\s*\}/.test(e),n=/^\s*(case|default)\b/.test(e);return i.baseIndent+(t?0:n?1:2)*i.unit},Block:YE({closing:"}"}),BlockComment:()=>null,Statement:qr({except:/^{/})}),tW.add({"Block SwitchBlock ClassBody ElementValueArrayInitializer ModuleBody EnumBody ConstructorBody InterfaceBody ArrayInitializer":nW,BlockComment(i){return{from:i.from+2,to:i.to-2}}})]}),languageData:{commentTokens:{line:"//",block:{open:"/*",close:"*/"}},indentOnInput:/^\s*(?:case |default:|\{|\})$/}});function CF(){return new RE(OF)}const jF=" ";function PF(i,e){let t="",n=e;for(let a=0;a{var b,x;const o=s.trim(),l=a,{chars:u,comment:c}=PF(s,a);a=c;const m=l?0:((b=/^[}\])\s]*/.exec(o)[0].match(/[}\])]/g))==null?void 0:b.length)??0,d=n.slice(0,Math.max(0,n.length-m));BF.test(o)&&((x=d.at(-1))!=null&&x.inCase)&&(d.at(-1).inCase=!1);const h=DF(d);for(const v of u)"{[(".includes(v)?n.push({line:r,char:v}):n.pop();const g=n.at(-1);(g==null?void 0:g.line)===r&&g.char==="{"&&/^switch\b/.test(o)&&(g.char="switch"),(g==null?void 0:g.char)==="switch"&&MF.test(o)&&(g.inCase=!0);const f=r+1;return ft||l&&!o.startsWith("*")?s:o===""?"":jF.repeat(h)+(l?" ":"")+o}).join(` +`)}const ZF=[["nextInt","","int","Ganze Zahl einlesen","Read a whole number","Ler um número inteiro"],["nextDouble","","double","Kommazahl einlesen","Read a decimal number","Ler um número decimal"],["nextLine","","String","Ganze Zeile als Text einlesen","Read a whole line as text","Ler uma linha inteira como texto"],["next","","String","Ein Wort einlesen (bis zum Leerzeichen)","Read one word (up to a space)","Ler uma palavra (até ao espaço)"],["nextBoolean","","boolean","true oder false einlesen","Read true or false","Ler true ou false"],["nextLong","","long","Große ganze Zahl einlesen","Read a large whole number","Ler um número inteiro grande"],["hasNextInt","","boolean","Kommt als Nächstes eine ganze Zahl?","Is the next input a whole number?","A próxima entrada é um número inteiro?"],["hasNextDouble","","boolean","Kommt als Nächstes eine Kommazahl?","Is the next input a decimal number?","A próxima entrada é um número decimal?"],["hasNextLine","","boolean","Gibt es noch eine Zeile?","Is there another line?","Existe mais uma linha?"],["hasNext","","boolean","Gibt es noch ein Wort?","Is there another word?","Existe mais uma palavra?"],["close","","void","Eingabe schließen","Close the input","Fechar a entrada"]],LF=[["length","","int","Anzahl der Zeichen","Number of characters","Número de caracteres"],["charAt","index","char","Zeichen an Stelle index (ab 0)","Character at position index (from 0)","Carácter na posição index (a partir de 0)"],["equals","text","boolean","Gleicher Text? (statt ==)","Same text? (instead of ==)","Mesmo texto? (em vez de ==)"],["equalsIgnoreCase","text","boolean","Gleicher Text, groß/klein egal?","Same text, ignoring case?","Mesmo texto, ignorando maiúsculas?"],["compareTo","text","int","Alphabetisch vergleichen (<0, 0, >0)","Compare alphabetically (<0, 0, >0)","Comparar alfabeticamente (<0, 0, >0)"],["substring","von, bis","String","Teiltext von Stelle von bis vor bis","Part of the text from start up to before end","Parte do texto do início até antes do fim"],["indexOf","text","int","Erste Stelle des Textes (−1 = fehlt)","First position of the text (−1 = missing)","Primeira posição do texto (−1 = não existe)"],["lastIndexOf","text","int","Letzte Stelle des Textes (−1 = fehlt)","Last position of the text (−1 = missing)","Última posição do texto (−1 = não existe)"],["contains","text","boolean","Kommt der Text darin vor?","Does it contain the text?","Contém o texto?"],["startsWith","text","boolean","Fängt damit an?","Starts with it?","Começa com isto?"],["endsWith","text","boolean","Hört damit auf?","Ends with it?","Termina com isto?"],["toUpperCase","","String","In GROSSBUCHSTABEN","In UPPER CASE","Em MAIÚSCULAS"],["toLowerCase","","String","In kleinbuchstaben","In lower case","Em minúsculas"],["trim","","String","Leerzeichen vorn und hinten weg","Remove spaces at both ends","Remover espaços no início e no fim"],["replace","alt, neu","String","Text ersetzen","Replace text","Substituir texto"],["split","trenner","String[]",'In Teile zerlegen, z. B. split(";")','Split into parts, e.g. split(";")','Dividir em partes, p. ex. split(";")'],["isEmpty","","boolean","Leerer Text?","Empty text?","Texto vazio?"],["toCharArray","","char[]","Als Array von Zeichen","As an array of characters","Como array de caracteres"]],Hf=[["println","wert","void","Ausgeben, danach neue Zeile","Print, then a new line","Escrever e mudar de linha"],["print","wert","void","Ausgeben ohne neue Zeile","Print without a new line","Escrever sem mudar de linha"],["printf","format, werte","PrintStream",'Formatiert ausgeben, z. B. "%.2f"','Print formatted, e.g. "%.2f"','Escrever formatado, p. ex. "%.2f"']],EF=[...Hf,["close","","void","Datei speichern und schließen","Save and close the file","Guardar e fechar o ficheiro"]],WF=[["readLine","","String","Nächste Zeile lesen (null = Ende)","Read the next line (null = end)","Ler a próxima linha (null = fim)"],["close","","void","Datei schließen","Close the file","Fechar o ficheiro"]],NF=[["exists","","boolean","Gibt es die Datei?","Does the file exist?","O ficheiro existe?"],["getName","","String","Name der Datei","Name of the file","Nome do ficheiro"],["length","","long","Größe in Bytes","Size in bytes","Tamanho em bytes"]],FF=[["getMessage","","String","Fehlermeldung als Text","Error message as text","Mensagem de erro como texto"],["printStackTrace","","void","Fehler mit Zeilen ausgeben","Print the error with its lines","Mostrar o erro com as linhas"]],JF=[["getSource","","Object","Welcher Knopf wurde geklickt?","Which button was clicked?","Que botão foi clicado?"],["getActionCommand","","String","Beschriftung des Knopfs","Label of the button","Texto do botão"]],RF=[["setBackground","farbe","void","Hintergrundfarbe, z. B. Color.RED","Background colour, e.g. Color.RED","Cor de fundo, p. ex. Color.RED"],["setForeground","farbe","void","Schriftfarbe","Text colour","Cor do texto"],["setFont","schrift","void",'Schrift, z. B. new Font("Arial", Font.BOLD, 24)','Font, e.g. new Font("Arial", Font.BOLD, 24)','Letra, p. ex. new Font("Arial", Font.BOLD, 24)'],["setVisible","true","void","Anzeigen (true) oder verstecken (false)","Show (true) or hide (false)","Mostrar (true) ou esconder (false)"],["setEnabled","true","void","Anklickbar (true) oder grau (false)","Clickable (true) or greyed out (false)","Clicável (true) ou cinzento (false)"],["setSize","breite, höhe","void","Größe in Pixeln","Size in pixels","Tamanho em píxeis"]],GF=[["add","baustein","Component","Baustein hinzufügen","Add a component","Adicionar um componente"],["setLayout","layout","void","Anordnung, z. B. new FlowLayout()","Layout, e.g. new FlowLayout()","Disposição, p. ex. new FlowLayout()"],["remove","baustein","void","Baustein entfernen","Remove a component","Remover um componente"]],HF=[["setTitle","text","void","Titel oben im Fenster","Title at the top of the window","Título no topo da janela"],["setDefaultCloseOperation","JFrame.EXIT_ON_CLOSE","void","Was beim Schließen passiert","What happens when closing","O que acontece ao fechar"],["setLocationRelativeTo","null","void","Mit null: Fenster in die Mitte","With null: centre the window","Com null: janela no centro"],["setResizable","false","void","Größe änderbar?","Can the size change?","Pode mudar de tamanho?"],["pack","","void","Größe passend zum Inhalt","Size to fit the content","Tamanho ajustado ao conteúdo"],["getContentPane","","JPanel","Inhaltsfläche des Fensters","Content area of the window","Área de conteúdo da janela"],["dispose","","void","Fenster schließen","Close the window","Fechar a janela"]],VF=[["setText","text","void","Text setzen","Set the text","Definir o texto"],["getText","","String","Text holen","Get the text","Obter o texto"]],qF=[["addActionListener","e -> { }","void","Was beim Klick passiert","What happens on click","O que acontece ao clicar"],["setOpaque","true","void","Hintergrund sichtbar (für Farben)","Show the background (for colours)","Mostrar o fundo (para cores)"],["setBorderPainted","false","void","Rahmen zeichnen?","Draw the border?","Desenhar a borda?"]],QF=[["setOpaque","true","void","Hintergrund sichtbar (für Farben)","Show the background (for colours)","Mostrar o fundo (para cores)"],["setHorizontalAlignment","JLabel.CENTER","void","Text links, mittig oder rechts","Text left, centre or right","Texto à esquerda, centro ou direita"]],UF=[["addActionListener","e -> { }","void","Was bei Enter passiert","What happens on Enter","O que acontece ao carregar em Enter"],["setEditable","false","void","Darf man hineinschreiben?","Can you type into it?","Pode-se escrever?"],["setColumns","anzahl","void","Breite in Zeichen","Width in characters","Largura em caracteres"],["requestFocus","","void","Cursor hineinsetzen","Put the cursor into it","Pôr o cursor no campo"]],$F=[["length",null,"int","Anzahl der Elemente (ohne Klammern)","Number of elements (no brackets)","Número de elementos (sem parênteses)"]],eo=[["add","wert","boolean","Element hinten anhängen","Append an element at the end","Acrescentar um elemento no fim"],["get","index","E","Element an Stelle index holen (ab 0)","Get the element at index (from 0)","Obter o elemento na posição index (a partir de 0)"],["size","","int","Anzahl der Elemente","Number of elements","Número de elementos"],["set","index, wert","E","Element an Stelle index ersetzen","Replace the element at index","Substituir o elemento na posição index"],["remove","index","E","Element an Stelle index entfernen","Remove the element at index","Remover o elemento na posição index"],["contains","wert","boolean","Ist das Element in der Liste?","Is the element in the list?","O elemento está na lista?"],["indexOf","wert","int","Stelle des Elements (-1 = nicht da)","Position of the element (-1 = not found)","Posição do elemento (-1 = não existe)"],["isEmpty","","boolean","Ist die Liste leer?","Is the list empty?","A lista está vazia?"],["clear","","void","Alle Elemente entfernen","Remove all elements","Remover todos os elementos"]],to={Scanner:ZF,String:LF,PrintStream:Hf,PrintWriter:EF,BufferedReader:WF,FileReader:[["close","","void","Datei schließen","Close the file","Fechar o ficheiro"]],File:NF,Exception:FF,ActionEvent:JF,Component:RF,Container:GF,JFrame:HF,JPanel:[],JButton:qF,JLabel:QF,JTextField:UF,TextHolder:VF,ArrayList:eo,List:eo,LinkedList:eo},YF={JFrame:["Container","Component"],JPanel:["Container","Component"],JButton:["TextHolder","Component"],JLabel:["TextHolder","Component"],JTextField:["TextHolder","Component"],PrintWriter:[]},Vf={mbot:[["forward","cm","void","Geradeaus vorwärts fahren","Drive forward","Andar para a frente"],["backward","cm","void","Rückwärts fahren","Drive backward","Andar para trás"],["turnLeft","grad","void","Auf der Stelle nach links drehen","Turn left on the spot","Rodar para a esquerda"],["turnRight","grad","void","Auf der Stelle nach rechts drehen","Turn right on the spot","Rodar para a direita"],["stop","","void","Motoren anhalten","Stop the motors","Parar os motores"],["drive","links, rechts","void","Räder einzeln in Prozent (−100–100), fährt weiter bis stop()","Wheels separately in percent (−100–100), keeps going until stop()","Rodas separadas em percentagem (−100–100), continua até stop()"],["resetTimer","","void","Stoppuhr auf 0 setzen","Reset the stopwatch to 0","Pôr o cronómetro a 0"],["pause","ms","void","Millisekunden warten","Wait milliseconds","Esperar milissegundos"],["setLed","rot, gruen, blau","void","LEDs in einer Farbe (je 0–255)","LEDs in a colour (0–255 each)","LEDs numa cor (0–255 cada)"],["ledOff","","void","LEDs aus","LEDs off","Desligar LEDs"],["led","nr","LED",'Eine LED (0–4), dann .setColor("grün") oder .setColor("aus")','One LED (0–4), then .setColor("green") or .setColor("off")','Um LED (0–4), depois .setColor("green") ou .setColor("off")'],["showText",'"Hallo"',"void","Text auf dem Bildschirm zeigen","Show text on the screen","Mostrar texto no ecrã"],["emotion",'"smile"',"void","Gefühl zeigen: LEDs, Ton, Bewegung (smile, hello, sad …)","Show a feeling: LEDs, sound, motion (smile, hello, sad …)","Mostrar um sentimento: LEDs, som, movimento (smile, hello, sad …)"],["playTone","hz, ms","void","Ton spielen, z. B. playTone(440, 500)","Play a tone, e.g. playTone(440, 500)","Tocar um som, p. ex. playTone(440, 500)"],["getDistance","","int","Abstand vorn in cm (Ultraschall)","Distance ahead in cm (ultrasonic)","Distância à frente em cm (ultrassom)"],["getLine","","int","Liniensensor: 0 = keine Linie, 15 = alle vier auf der Linie","Line sensor: 0 = no line, 15 = all four on the line","Sensor de linha: 0 = sem linha, 15 = os quatro na linha"],["isLineLeft","","boolean","Linie unter dem linken mittleren Fühler","Line under the left middle probe","Linha sob a sonda central esquerda"],["isLineRight","","boolean","Linie unter dem rechten mittleren Fühler","Line under the right middle probe","Linha sob a sonda central direita"],["getBrightness","","int","Helligkeit 0–100","Brightness 0–100","Luminosidade 0–100"],["getLoudness","","int","Lautstärke 0–100","Loudness 0–100","Volume 0–100"],["getColor","","String",'Farbe unter dem mBot2, z. B. "rot"','Colour under the mBot2, e.g. "red"','Cor por baixo do mBot2, p. ex. "red"'],["isButtonA","","boolean","Taste A ist gedrückt","Button A is pressed","O botão A está premido"],["isButtonB","","boolean","Taste B ist gedrückt","Button B is pressed","O botão B está premido"],["isJoystickUp","","boolean","Joystick nach oben gedrückt","Joystick pushed up","Joystick para cima"],["isJoystickDown","","boolean","Joystick nach unten gedrückt","Joystick pushed down","Joystick para baixo"],["isJoystickLeft","","boolean","Joystick nach links gedrückt","Joystick pushed left","Joystick para a esquerda"],["isJoystickRight","","boolean","Joystick nach rechts gedrückt","Joystick pushed right","Joystick para a direita"],["getPitch","","int","Neigung nach vorn (+) oder hinten (−) in Grad","Tilt forward (+) or back (−) in degrees","Inclinação para a frente (+) ou trás (−) em graus"],["getRoll","","int","Neigung zur Seite in Grad","Tilt sideways in degrees","Inclinação lateral em graus"],["isShaken","","boolean","Der mBot2 wird geschüttelt","The mBot2 is being shaken","O mBot2 está a ser abanado"],["getTimer","","double","Stoppuhr in Sekunden","Stopwatch in seconds","Cronómetro em segundos"],["getBattery","","int","Akku in Prozent","Battery in percent","Bateria em percentagem"]],System:[["out",null,"PrintStream","Ausgabe in die Konsole","Output to the console","Saída para a consola"],["in",null,"InputStream","Eingabe von der Tastatur (für Scanner)","Keyboard input (for Scanner)","Entrada do teclado (para Scanner)"],["err",null,"PrintStream","Fehlerausgabe","Error output","Saída de erros"],["currentTimeMillis","","long","Uhrzeit in Millisekunden","Time in milliseconds","Hora em milissegundos"],["exit","0","void","Programm beenden","End the program","Terminar o programa"]],Math:[["random","","double","Zufallszahl von 0 bis unter 1","Random number from 0 to below 1","Número aleatório de 0 até menos de 1"],["abs","zahl","double","Betrag (ohne Minus)","Absolute value (no minus)","Valor absoluto (sem menos)"],["sqrt","zahl","double","Wurzel","Square root","Raiz quadrada"],["pow","basis, exponent","double","Hoch: pow(2, 3) = 8","Power: pow(2, 3) = 8","Potência: pow(2, 3) = 8"],["max","a, b","double","Größere von zwei Zahlen","Larger of two numbers","Maior de dois números"],["min","a, b","double","Kleinere von zwei Zahlen","Smaller of two numbers","Menor de dois números"],["round","zahl","long","Runden","Round","Arredondar"],["floor","zahl","double","Abrunden","Round down","Arredondar para baixo"],["ceil","zahl","double","Aufrunden","Round up","Arredondar para cima"],["PI",null,"double","Kreiszahl π = 3.14159…","Pi π = 3.14159…","Pi π = 3,14159…"]],Integer:[["parseInt","text","int","Text in ganze Zahl umwandeln","Turn text into a whole number","Converter texto em número inteiro"],["toString","zahl","String","Zahl in Text umwandeln","Turn a number into text","Converter número em texto"],["MAX_VALUE",null,"int","Größte int-Zahl","Largest int value","Maior valor int"],["MIN_VALUE",null,"int","Kleinste int-Zahl","Smallest int value","Menor valor int"]],Double:[["parseDouble","text","double","Text in Kommazahl umwandeln","Turn text into a decimal number","Converter texto em número decimal"],["toString","zahl","String","Zahl in Text umwandeln","Turn a number into text","Converter número em texto"]],String:[["valueOf","wert","String","Wert in Text umwandeln","Turn a value into text","Converter valor em texto"],["format","format, werte","String",'Formatierter Text, z. B. "%.2f"','Formatted text, e.g. "%.2f"','Texto formatado, p. ex. "%.2f"'],["join","trenner, teile","String","Teile mit Trenner verbinden","Join parts with a separator","Juntar partes com um separador"]],Character:[["isDigit","zeichen","boolean","Ist es eine Ziffer?","Is it a digit?","É um algarismo?"],["isLetter","zeichen","boolean","Ist es ein Buchstabe?","Is it a letter?","É uma letra?"],["isUpperCase","zeichen","boolean","Ist es ein Großbuchstabe?","Is it upper case?","É maiúscula?"],["toUpperCase","zeichen","char","In Großbuchstaben","To upper case","Para maiúscula"],["toLowerCase","zeichen","char","In Kleinbuchstaben","To lower case","Para minúscula"]],Files:[["readString",'Path.of("datei.txt")',"String","Ganze Datei als Text lesen","Read the whole file as text","Ler o ficheiro inteiro como texto"],["writeString","pfad, text","Path","Text in Datei schreiben","Write text to a file","Escrever texto num ficheiro"],["readAllLines","pfad","List","Alle Zeilen lesen","Read all lines","Ler todas as linhas"],["exists","pfad","boolean","Gibt es die Datei?","Does the file exist?","O ficheiro existe?"]],Path:[["of",'"datei.txt"',"Path","Pfad zu einer Datei","Path to a file","Caminho para um ficheiro"]],JFrame:[["EXIT_ON_CLOSE",null,"int","Programm endet beim Schließen","Program ends when closed","O programa termina ao fechar"]],JLabel:[["CENTER",null,"int","Mittig","Centred","Ao centro"],["LEFT",null,"int","Links","Left","À esquerda"],["RIGHT",null,"int","Rechts","Right","À direita"]],Font:[["BOLD",null,"int","Fett","Bold","Negrito"],["PLAIN",null,"int","Normal","Plain","Normal"],["ITALIC",null,"int","Kursiv","Italic","Itálico"]],Color:[["RED","Rot","Red","Vermelho"],["GREEN","Grün","Green","Verde"],["BLUE","Blau","Blue","Azul"],["YELLOW","Gelb","Yellow","Amarelo"],["ORANGE","Orange","Orange","Laranja"],["WHITE","Weiß","White","Branco"],["BLACK","Schwarz","Black","Preto"],["GRAY","Grau","Grey","Cinzento"],["LIGHT_GRAY","Hellgrau","Light grey","Cinzento-claro"],["PINK","Rosa","Pink","Rosa"],["CYAN","Türkis","Cyan","Ciano"],["MAGENTA","Magenta","Magenta","Magenta"]].map(([i,e,t,n])=>[i,null,"Color",e,t,n])};function qf(i,e){const[t,n,a,s,r,o]=i;return{name:t,kind:n===null?"field":"method",params:!!n,returns:a,description:e==="de"?s:e==="pt"?o:r}}const Ol=i=>i.replace(/<.*>$/,""),Qf=i=>{var e;return(e=/<\s*([^<>,]+?)\s*>$/.exec(i))==null?void 0:e[1]};function Uf(i){if(/\[\]$/.test(i))return $F;if(i=Ol(i),/Exception$|^Throwable$/.test(i))return to.Exception;if(!to[i])return;const t=new Set,n=[];for(const a of[i,...YF[i]??[]])for(const s of to[a]??[])t.has(s[0])||(t.add(s[0]),n.push(s));return n}function _R(i,e="de"){return(Uf(i)??[]).map(t=>qf(t,e))}const XF="[A-Z]\\w*|int|long|double|float|boolean|char|byte|short|var";function KF(i,e){var a,s;const t=new RegExp(`(?:^|[^\\w.])(${XF})\\s*(?:<([^<>;]*)>)?((?:\\s*\\[\\s*\\])*)\\s+${e}\\s*(?:\\[\\s*\\])*\\s*(=\\s*([^;]*))?(?=[=;,):]|$)`,"gm");let n;for(const r of i.matchAll(t)){let o=r[1];if(o==="var"){const u=r[5]??"";if(o=((a=/^new\s+([A-Z]\w*)/.exec(u))==null?void 0:a[1])??(/^"/.test(u)?"String":""),!o)continue}if(/^(return|new|else|case|throw)$/.test(o))continue;const l=(s=r[2])==null?void 0:s.replace(/\s+/g,"");n=o+(l?`<${l}>`:"")+(r[3]??"").replace(/\s+/g,"")}return n}function eJ(i){let e=0,t;const n=/^"(?:[^"\\]|\\.)*"/.exec(i);if(n)t='"',e=n[0].length;else{const r=/^[A-Za-z_]\w*/.exec(i);if(!r)return;t=r[0],e=r[0].length}const a=[{name:t,call:!1,indices:0}],s=(r,o)=>{let l=0;for(;e0;){const n=i[t-1];if(/[\w.]/.test(n))t--;else if(n===")"||n==="]"){const a=n===")"?"(":"[";let s=0,r=t-1;for(;r>=0;r--)if(i[r]===n)s++;else if(i[r]===a&&--s===0)break;if(r<0)return t;t=r}else if(n==='"'){const a=i.lastIndexOf('"',t-2);if(a<0)return t;t=a}else break}return t}const Um=(i,e)=>i.slice(0,Math.max(0,i.length-2*e));function $f(i,e,t,n){const a=e?t==null?void 0:t.statics(Ol(i)):t==null?void 0:t.members(Ol(i));if(a)return a;const s=e?Vf[i]:Uf(i);return s==null?void 0:s.map(r=>qf(r,n))}function nJ(i,e,t,n){var s,r;const a=(r=(s=$f(i,t,n,"en"))==null?void 0:s.find(o=>o.name===e))==null?void 0:r.returns;return a==="E"?Qf(i)??"Object":a}function iJ(i,e,t){const n=eJ(e);if(!n)return;const[a,...s]=n.links;let r,o=!1;if(n.head==='"')r="String";else if(a.name==="this"&&(t!=null&&t.thisType)&&!a.call&&!a.indices)r=t.thisType;else{if(r=KF(i,a.name),!r&&(Vf[a.name]||t!=null&&t.statics(a.name))&&!a.call&&(r=a.name,o=!0),!r)return;a.indices&&(r=Um(r,a.indices))}for(const l of s){const u=nJ(r,l.name,o,t);if(!u)return;r=Um(u,l.indices),o=!1}return{type:r,isStatic:o}}function aJ(i,e,t="de",n){const a=i.lastIndexOf(` +`,e-1)+1,s=i.slice(a,e),r=/\.\s*(\w*)$/.exec(s);if(!r)return;const o=r.index,l=s.slice(tJ(s,o),o);if(!l||/^\d/.test(l))return;const u=iJ(i,l,n);if(!u)return;const c=$f(u.type,u.isStatic,n,t);if(!c)return;const m=Qf(u.type)??"Object";return{from:e-r[1].length,members:c.map(d=>d.returns==="E"?{...d,returns:m}:d)}}const $m=Wn.define(),V0=de.define(),sJ=pe.mark({class:"cm-ph"}),rJ=pe.mark({class:"cm-err"}),Ym=pe.line({class:"cm-debug-line"});function Xm(i,e){const t=i.doc.length,n=[];e.current!==void 0&&e.currentr===Ym;n.sort((r,o)=>r.from-o.from||Number(a(o.deco))-Number(a(r.deco))||r.to-o.to);const s=new n1;for(const r of n)s.add(r.from,r.to,r.deco);return s.finish()}const cr=Et.define({create:()=>({marks:{placeholders:[],problems:[]},decorations:pe.none}),update(i,e){for(const a of e.effects)if(a.is(V0))return{marks:a.value,decorations:Xm(e.state,a.value)};if(!e.docChanged)return i;const t=a=>({from:e.changes.mapPos(a.from,1),to:e.changes.mapPos(a.to,-1)}),n={...i.marks,placeholders:i.marks.placeholders.map(t).filter(a=>a.fromQ.decorations.from(i,e=>e.decorations)}),Km={ClassDeclaration:"class",InterfaceDeclaration:"class",EnumDeclaration:"class",MethodDeclaration:"method",ConstructorDeclaration:"method",ForStatement:"loop",EnhancedForStatement:"loop",WhileStatement:"loop",DoStatement:"loop",IfStatement:"if",SwitchStatement:"if",TryStatement:"try"};function oJ(i,e){const t=i.lineAt(e);if(!t.text.trimEnd().endsWith("{"))return t.number;let n=0;for(let a=t.number;a<=i.lines;a++)for(const s of i.line(a).text.replace(/"(?:[^"\\]|\\.)*"|\/\/.*$/g,""))if(s==="{")n++;else if(s==="}"&&--n===0)return a;return t.number}function lJ(i){const{state:e}=i,t=e.doc,n=i.contentDOM.querySelector(".cm-line");if(!n)return[];const a=getComputedStyle(n),s=i.scrollDOM.getBoundingClientRect(),r=i.contentDOM.getBoundingClientRect(),o=s.left-i.scrollDOM.scrollLeft,l=s.top-i.scrollDOM.scrollTop,u=r.left-o+parseFloat(a.paddingLeft)+parseFloat(a.borderLeftWidth),c=r.right-o-6,m=i.documentTop-l,d=e.tabSize,h=i.defaultCharacterWidth,g=(I,z,k,T)=>{const A=t.line(z),D=Fi(/^\s*/.exec(A.text)[0],d),P=u+D*h-7,j=i.lineBlockAt(A.from).top+m+T,O=i.lineBlockAt(t.line(k).from).bottom+m-T;return new ir(I,P,j,Math.max(c-P,20),Math.max(O-j,4))},f=[],b=Xe(e).topNode,x=[];for(let I=b.firstChild;I;I=I.nextSibling){if(Km[I.name]==="class"||I.name==="MethodDeclaration"){x.length=0;break}I.name!=="ImportDeclaration"&&I.name!=="PackageDeclaration"&&!I.name.includes("Comment")&&x.push(I)}x.length&&f.push(g("cm-scope cm-scope-method",t.lineAt(x[0].from).number,t.lineAt(x[x.length-1].to).number,1));const v=[];Xe(e).iterate({from:i.viewport.from,to:i.viewport.to,enter:I=>{var A;const z=Km[I.name];if(!z||I.name==="IfStatement"&&((A=I.node.parent)==null?void 0:A.name)==="IfStatement")return;const k=t.lineAt(I.from).number,T=Math.max(t.lineAt(I.to).number,oJ(t,I.from));v.push({kind:z,from:k,to:T}),f.push(g(`cm-scope cm-scope-${z}`,k,T,1))}});for(let I=1;I<=t.lines;I++){let z;for(const T of v)T.from<=I&&I<=T.to&&(!z||T.from>=z.from)&&(z=T);if(!z||z.kind!=="loop"&&z.kind!=="if"||I===z.from)continue;const k=t.line(I).text.trim();!k||k.startsWith("}")||k.endsWith("{")||k.startsWith("//")||k.startsWith("case ")||k.startsWith("default")||f.push(g("cm-scope cm-scope-method cm-scope-stmt",I,I,2))}const w=e.field(cr).marks.lines;return w&&w.fromi.docChanged||i.viewportChanged||i.geometryChanged||Xe(i.state)!==Xe(i.startState)||i.transactions.some(e=>e.effects.some(t=>t.is(V0)))});class mJ extends xn{toDOM(){const e=document.createElement("span");return e.className="cm-breakpoint",e}}const Cl=new mJ,Kf=de.define(),e2=de.define(),jl=Et.define({create:()=>ie.empty,update(i,e){i=i.map(e.changes);for(const t of e.effects){if(t.is(e2)&&(i=ie.of(t.value.map(a=>Cl.range(a)),!0)),!t.is(Kf))continue;let n=!1;i.between(t.value,t.value,()=>{n=!0}),i=n?i.update({filter:a=>a!==t.value}):i.update({add:[Cl.range(t.value)]})}return i}});function dJ(i){const t={mousedown:(n,a)=>{const s=i.breakpointLine(n.state.doc.lineAt(a.from).number-1);return s===void 0||s>=n.state.doc.lines?!1:(n.dispatch({effects:Kf.of(n.state.doc.line(s+1).from)}),queueMicrotask(()=>i.onBreakpoints()),!0)}};return[jl,hE({class:"cm-breakpoint-gutter",markers:n=>n.state.field(jl),initialSpacer:()=>Cl,domEventHandlers:t}),yE({domEventHandlers:t})]}function q0(i,e){return i.field(cr).marks.placeholders.find(t=>e>=t.from&&e<=t.to)}const hJ=Q.inputHandler.of((i,e,t,n)=>{if(e!==t)return!1;const a=q0(i.state,e);return a?(i.dispatch({changes:{from:a.from,to:a.to,insert:n},selection:{anchor:a.from+n.length},userEvent:"input.type"}),!0):!1}),gJ=re.transactionFilter.of(i=>{if(!i.docChanged||!(i.isUserEvent("input.paste")||i.isUserEvent("input.drop")))return i;const e=[];if(i.changes.iterChanges((a,s,r,o,l)=>e.push({from:a,to:s,text:l.toString()})),e.length!==1||e[0].from!==e[0].to)return i;const t=q0(i.startState,e[0].from);if(!t)return i;const{text:n}=e[0];return{changes:{from:t.from,to:t.to,insert:n},selection:{anchor:t.from+n.length},userEvent:"input.paste",scrollIntoView:!0}}),ed=i=>e=>{const t=e.state.selection.main;if(!t.empty)return!1;const n=q0(e.state,t.head);return!n||(i?t.head>=n.to:t.head<=n.from)?!1:(e.dispatch({changes:{from:n.from,to:n.to},selection:{anchor:n.from},userEvent:"delete"}),!0)},pJ=Q.updateListener.of(i=>{if(!i.selectionSet||i.docChanged||!i.transactions.some(n=>n.isUserEvent("select.pointer")))return;const e=i.state.selection.main;if(!e.empty)return;const t=i.state.field(cr).marks.placeholders.find(n=>e.head>n.from&&e.headi.view.dispatch({selection:B.range(t.from,t.to)}))}),fJ=sr.define([{tag:[L.keyword,L.controlKeyword,L.definitionKeyword,L.modifier,L.operatorKeyword,L.standard(L.typeName),L.bool,L.null],color:"var(--syn-keyword)",fontWeight:"600"},{tag:[L.string,L.character],color:"var(--syn-string)"},{tag:L.number,color:"var(--syn-number)"},{tag:[L.lineComment,L.blockComment],color:"var(--syn-comment)",fontStyle:"italic"}]);function bJ(i){const e=i,t=`\${// ${e.code}}`,n=(a,s,r,o=0)=>F0(s,{label:a,detail:r,type:"keyword",boost:o});return[n("if",`if (\${${e.condition}}) { + ${t} +}`,e.branch,2),n("if … else",`if (\${${e.condition}}) { + ${t} +} else { + \${// ${e.code}} +}`,e.branchElse,1),n("for",`for (int \${i} = \${0}; \${i} < \${10}; \${i}++) { + ${t} +}`,e.forLoop,2),n("while",`while (\${${e.condition}}) { + ${t} +}`,e.whileLoop,2),n("do … while",`do { + ${t} +} while (\${${e.condition}});`,e.doLoop,1),n("switch",`switch (\${${e.selector}}) { + case \${1} -> { + ${t} + } + default -> { + \${// ${e.code}} + } +}`,e.switchCase,1),n("System.out.println","System.out.println(${});",e.output,3),...["syso","sysout","sout"].map(a=>n(a,"System.out.println(${});",`System.out.println · ${e.output}`,2)),...["main","psvm"].map(a=>n(a,`public static void main(String[] args) { + ${t} +}`,"public static void main(String[] args)",2)),vJ(e.input),n("scanner.nextInt","int ${zahl} = scanner.nextInt();",e.input,1),n("scanner.next","String ${text} = scanner.next();",e.input),n("scanner.nextDouble","double ${wert} = scanner.nextDouble();",e.input),n("try … catch",`try { + ${t} +} catch (\${Exception} e) { + \${// ${e.code}} +}`,"try … catch",1),n("public class",`public class \${Main} { + ${t} +}`,"public class",-2),...["import java.util.Scanner;","import javax.swing.*;","import java.awt.*;","import java.awt.event.*;"].map((a,s)=>n(a,a,"import",1-s)),...["int","double","String","boolean","char","long","final","break;","continue;","return","true","false","else","null","new","public","private","static","void","class","extends","implements","interface","this"].map(a=>({label:a,type:"keyword",boost:-1})),...["Math","JFrame","JButton","JLabel","JTextField","ActionListener","ActionEvent","Color","FlowLayout","GridLayout","BorderLayout"].map(a=>({label:a,type:"type",boost:-2})),...["Math.random()","Math.abs(","Math.sqrt(","Math.max(","Math.min(",".length()",".equals("].map(a=>({label:a,type:"function",boost:-2}))]}function xJ(i){if(/^\s*import\s+java\.util\.(?:Scanner|\*)\s*;/m.test(i))return;const e=/^\s*package\s+[\w.]+\s*;[^\n]*\n?/.exec(i),t=e?e[0].length:0,n=i.slice(t).replace(/^\s*\n/,"");return{from:t,insert:`import java.util.Scanner; +${/^\s*import\b/.test(n)?"":` +`}`}}function vJ(i){const e=F0("Scanner ${scanner} = new Scanner(System.in);",{label:"Scanner scanner = new Scanner(System.in);",detail:i,type:"keyword",boost:3}),t=e.apply;return{...e,apply(n,a,s,r){const o=xJ(n.state.doc.toString());if(!o)return t(n,a,s,r);const l=n.state.changes(o);n.dispatch({changes:l,userEvent:"input.complete"}),t(n,a,l.mapPos(s),l.mapPos(r,1))}}}function yJ(i){const t={label:i.kind==="field"?i.name:`${i.name}(${i.params?"…":""})`,detail:i.returns==="void"||!i.returns?i.description:i.description?`${i.returns} · ${i.description}`:i.returns,type:i.kind==="field"?"property":"method"};return i.kind==="field"?{...t,apply:i.name}:i.params?F0(`${i.name}(\${})`,t):{...t,apply:`${i.name}()`}}function wJ(){const i=s1();return i==="de"?"de":i==="pt-PT"?"pt":"en"}function zJ(i){const e=new Set;for(const t of i.matchAll(/\b(?:int|long|double|float|boolean|char|String|Scanner)(?:\s*\[\s*\])*\s+([A-Za-z_]\w*)/g))e.add(t[1]);return[...e].map(t=>({label:t,type:"variable",boost:1}))}class IJ{constructor(e,t,n){y(this,"view");y(this,"readOnly",new Ni);const a=r=>{var h,g;const o=r.matchBefore(/[\w.]+/);if(!o||o.from===o.to&&!r.explicit)return null;const l=r.state.doc.lineAt(r.pos),u=l.text.slice(0,r.pos-l.from);if(/\/\//.test(u)||(((h=u.match(/"/g))==null?void 0:h.length)??0)%2===1)return null;const c=aJ(r.state.doc.toString(),r.pos,wJ(),(g=t.ownTypes)==null?void 0:g.call(t,r.pos));if(c)return{from:c.from,options:c.members.map((f,b)=>({...yJ(f),boost:50-b})),validFor:/^\w*$/};const m=/\bvoid\s+[\w.]*$/.test(u),d=bJ(t.words()).filter(f=>!(m&&(f.label==="main"||f.label==="psvm")));return{from:o.from,options:[...d,...zJ(r.state.doc.toString())],validFor:/^\w*$/}},s=[dJ(t),IE(),CF(),aW(fJ),Vi.of(" "),re.tabSize.of(4),eW(),hW(),iN(),cr,cJ,hJ,gJ,pJ,this.readOnly.of(re.readOnly.of(!1)),gN({override:[a],icons:!1}),l1.highest(ji.of([{key:"Mod-z",run:()=>(t.onUndo(!1),!0),preventDefault:!0},{key:"Mod-Shift-z",run:()=>(t.onUndo(!0),!0),preventDefault:!0},{key:"Mod-y",run:()=>(t.onUndo(!0),!0),preventDefault:!0},{key:"Backspace",run:ed(!1)},{key:"Delete",run:ed(!0)}])),ji.of([...oN,...pf,fF,...pF]),Q.contentAttributes.of({"aria-label":n,autocapitalize:"off",autocorrect:"off",spellcheck:"false"}),Q.updateListener.of(r=>{r.docChanged&&!r.transactions.some(o=>o.annotation($m))?queueMicrotask(()=>t.onChange()):r.selectionSet&&!r.docChanged&&queueMicrotask(()=>t.onCaret())})];this.view=new Q({parent:e,state:re.create({doc:"",extensions:s})})}get text(){return this.view.state.doc.toString()}get caret(){return this.view.state.selection.main.head}get hasFocus(){return this.view.hasFocus}get breakpoints(){const e=new Set,t=this.view.state.doc;return this.view.state.field(jl).between(0,t.length,n=>{e.add(t.lineAt(n).number-1)}),e}setBreakpoints(e){const t=this.view.state.doc,n=[...new Set(e)].filter(a=>a>=0&&at.line(a+1).from);this.view.dispatch({effects:e2.of(n)})}lineAt(e){return this.view.state.doc.lineAt(Math.min(e,this.view.state.doc.length)).number-1}setText(e){const t=Math.min(this.caret,e.length),n=this.text;let a=0;for(;a{const l=e.line(o+1),u=/^\s*/.exec(l.text)[0],c=/^\s*/.exec(r)[0];u!==c&&s.push({from:l.from,to:l.from+u.length,insert:c})}),s.length>0&&this.view.dispatch({changes:s,userEvent:"input.indent"}),this.view.focus()}setMarks(e,t){const n=[V0.of(e)];e.current!==void 0&&e.current {}); + } catch (Exception e) { + } + int n = 0; + for (java.awt.Window w : java.awt.Window.getWindows()) if (w.isShowing()) n++; + return n; + } + + public static void run(String dir, String name) { + closeAll(); + try { + java.net.URLClassLoader loader = new java.net.URLClassLoader(new java.net.URL[] { new java.io.File(dir).toURI().toURL() }); + loader.loadClass(name).getMethod("main", String[].class).invoke(null, (Object) new String[0]); + } catch (java.lang.reflect.InvocationTargetException e) { + e.getCause().printStackTrace(); + } catch (NoSuchMethodException e) { + System.err.println("Die Klasse " + name + " hat keine Methode public static void main(String[] args)."); + } catch (Exception e) { + e.printStackTrace(); + } + } +} +`;let ln,Es=0;function TJ(i){return new Promise((e,t)=>{const n=document.createElement("script");n.src=i,n.onload=()=>e(),n.onerror=()=>t(new Error(i)),document.head.append(n)})}function _J(i){return ln??(ln=(async()=>{await TJ(kJ),await cheerpjInit({status:"none"}),cheerpjCreateDisplay(-1,-1,i);const e=await fetch(td);if(!e.ok)throw new Error(td);if(cheerpOSAddStringFile(Ls,new Uint8Array(await e.arrayBuffer())),cheerpOSAddStringFile("/str/VisuStructRunner.java",SJ),await cheerpjRunMain("com.sun.tools.javac.Main",Ls,"/str/VisuStructRunner.java","-d","/files/")!==0)throw new Error("javac");return await(await cheerpjRunLibrary("/files/")).VisuStructRunner})()),ln.catch(()=>ln=void 0),ln}function AJ(i){const e=i.match(/public\s+(?:final\s+)?class\s+(\w+)/)??i.match(/\bclass\s+(\w+)/);return e?e[1]:"Main"}function OJ(i){return/\bFiles\s*\.\s*\w+\s*\(|\bnew\s+(?:File|FileReader|FileWriter|PrintWriter|BufferedReader)\s*\(/.test(i)}function CJ(i,e){return i.replace(/"([\w.-]+\.(?:txt|csv|json))"/g,`"${e}$1"`)}function t2(i){i=i.replace(/\bFiles\s*\.\s*readString\s*\(\s*(?:Path\s*\.\s*of|Paths\s*\.\s*get)\s*\(\s*("(?:[^"\\]|\\.)*")\s*\)\s*\)/g,'new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get($1)), "UTF-8")');const e=/\bFiles\s*\.\s*writeString\s*\(\s*(?:Path\s*\.\s*of|Paths\s*\.\s*get)\s*\(\s*("(?:[^"\\]|\\.)*")\s*\)\s*,/g;let t="",n=0;for(let a=e.exec(i);a;a=e.exec(i)){let s=1,r=a.index+a[0].length,o=!1;for(;r0;r++){const u=i[r];o?u==="\\"?r++:u==='"'&&(o=!1):u==='"'?o=!0:u==="("?s++:u===")"&&s--}if(s>0)break;const l=i.slice(a.index+a[0].length,r-1).trim();t+=i.slice(n,a.index)+`java.nio.file.Files.write(java.nio.file.Paths.get(${a[1]}), (${l}).getBytes("UTF-8"))`,n=r,e.lastIndex=r}return t+i.slice(n)}function jJ(i){if(/\bclass\s+\w+/.test(i))return i;const e=[];i=i.replace(/^[ \t]*import\s+[\w.]+(?:\.\*)?\s*;[ \t]*$/gm,a=>(e.push(a.trim()),""));const t=[...e,"import java.util.*;","import java.awt.*;","import java.awt.event.*;","import javax.swing.*;"].join(` +`)+` + +`;if(/\bstatic\s+void\s+main\s*\(/.test(i))return`${t}public class Main { +${i} +} +`;const n=OJ(i)?" throws Exception":"";return`${t}public class Main { + public static void main(String[] args)${n} { +${i} + } +} +`}async function PJ(){ln&&await(await ln).closeAll()}async function n2(i,e,t){const n=new Map;for(const a of(await i.list(e)).split(` +`).filter(Boolean)){const s=await i.read(e+a);t.get(a)!==s&&n.set(a,s)}return n}function DJ(i,e){const t=Es,n=`/files/run${t}/data/`,a=new Map([...ph(),...i]);let s=!1;const r=async()=>{if(!(s||Es!==t||!ln)){try{const l=await ln,u=await n2(l,n,a);for(const[c,m]of u)a.set(c,m);if(u.size&&e(u),await l.openWindows()===0)return}catch{return}o=window.setTimeout(r,1500)}};let o=window.setTimeout(r,1500);return()=>{s=!0,window.clearTimeout(o)}}async function BJ(i,e){const t=await ln,n=`/files/run${++Es}/`;await t.mkdirs(n);const a=`${n}data/`,s=new Map(ph());await t.mkdirs(a);for(const[u,c]of s)cheerpOSAddStringFile(`/str/${u}`,c),await t.copy(`/str/${u}`,a+u);const r=jJ(t2(CJ(i,a))),o=AJ(r);if(cheerpOSAddStringFile(`/str/${o}.java`,r),await cheerpjRunMain("com.sun.tools.javac.Main",Ls,`/str/${o}.java`,"-d",n,"-encoding","UTF-8")!==0)return{result:"compile-error",files:new Map};e(),await t.run(n,o);const l=await n2(t,a,s);return await t.openWindows()>0?{result:"windows",files:l}:(await new Promise(u=>setTimeout(u,500)),{result:await t.openWindows()>0?"windows":"finished",files:l})}async function AR(i,e,t){const n=await ln,a=`/files/run${++Es}/`,s=`${a}src/`,r=[];for(const l of i){const u=`${s}${l.pkg?l.pkg.replace(/\./g,"/")+"/":""}${l.name}.java`;await n.write(u,t2(l.text)),r.push(u)}const o=`${a}classes/`;return await n.mkdirs(o),await cheerpjRunMain("com.sun.tools.javac.Main",Ls,...r,"-d",o,"-encoding","UTF-8")!==0?{result:"compile-error",files:new Map}:(t(),await n.run(o,e),await n.openWindows()>0?{result:"windows",files:new Map}:(await new Promise(l=>setTimeout(l,500)),{result:await n.openWindows()>0?"windows":"finished",files:new Map}))}const i2="visustruct.live.target",nd="visustruct.live.javaClass",id="visustruct.live.javaMain",ad="visustruct.live.swing",sd="visustruct.console.height",rd=150;function no(i){try{return localStorage.getItem(i)==="1"}catch{return!1}}function MJ(i){try{return localStorage.getItem(i)}catch{return null}}function ZJ(i,e){try{localStorage.setItem(i,e)}catch{}}function LJ(){try{const i=localStorage.getItem(i2);return i==="javascript"||i==="python"?i:"java"}catch{return"java"}}const ze=i=>i.replace(/&/g,"&").replace(//g,">");function EJ(i){let e="",t=i;for(;;){const n=t.indexOf(Wi);if(n<0)break;const a=t.indexOf(t0,n);if(a<0)break;e+=ze(t.slice(0,n))+`${ze(t.slice(n+1,a))}`,t=t.slice(a+1)}return e+ze(t)}const Y1=(i,e)=>i.length===e.length&&i.every((t,n)=>t===e[n]);function Pa(i,e){let t;for(const n of i)en.to||(!t||n.to-n.fromt.path.length)&&(t=n);return t}const WJ=900,NJ=2e3;class FJ{constructor(e,t,n,a){y(this,"element");y(this,"view");y(this,"editor");y(this,"code");y(this,"problemLine");y(this,"hint");y(this,"spans",[]);y(this,"highlighted");y(this,"html","");y(this,"target",LJ());y(this,"last");y(this,"textFor",new WeakMap);y(this,"form",{asClass:no(nd),withMain:no(id)});y(this,"shown",new WeakMap);y(this,"parsed");y(this,"placeholders",[]);y(this,"problems",[]);y(this,"problemTimer");y(this,"showProblems",!0);y(this,"run");y(this,"debugLine");y(this,"breakpoints",new Set);y(this,"swing",no(ad));y(this,"swingElement");y(this,"swingDisplay");y(this,"stopWatchingFiles");y(this,"runButton");y(this,"stepButton");y(this,"stopButton");y(this,"indentButton");y(this,"debugPanel");y(this,"debugVars");y(this,"consoleElement");y(this,"consoleResizer");y(this,"consoleLines");y(this,"consoleForm");y(this,"consoleNotice");y(this,"onRobotRun");y(this,"onReference");y(this,"onSwap");this.onHide=e,this.onSelect=t,this.onCode=n,this.onUndo=a,this.element=document.createElement("aside"),this.element.className="livecode",this.consoleElement=document.createElement("section"),this.consoleElement.className="console",this.consoleElement.hidden=!0,this.consoleResizer=this.makeConsoleResizer(),this.swingElement=document.createElement("section"),this.swingElement.className="console livecode-swing",this.swingElement.hidden=!0,this.swingDisplay=document.createElement("div"),this.swingDisplay.className="livecode-swing-display",this.build()}get labels(){return{condition:p("canvas_stub_condition"),selector:p("web_live_ph_selector"),code:p("web_live_ph_code"),start:p("inspector_for_init"),step:p("inspector_for_step"),end:p("web_live_ph_end")}}build(){this.run&&window.clearTimeout(this.run.timer),this.element.innerHTML=` +
+

${ze(p("web_live_title"))}

+ + + + + + + + +
+

+

+      
+

+ + `,this.consoleElement.innerHTML=` +
+

${ze(p("web_console"))}

+ +
+
+ +

+ `,this.view=this.element.querySelector(".livecode-view"),this.editor=this.element.querySelector(".livecode-editor"),this.problemLine=this.element.querySelector(".livecode-problem"),this.hint=this.element.querySelector(".hint"),this.element.querySelector(".learn-hide").addEventListener("click",()=>this.onHide()),this.element.querySelector(".livecode-reference").addEventListener("click",()=>{var t;return(t=this.onReference)==null?void 0:t.call(this)}),this.element.querySelector(".livecode-swap").addEventListener("click",()=>{var t;return(t=this.onSwap)==null?void 0:t.call(this)}),this.runButton=this.element.querySelector("[data-run=play]"),this.stepButton=this.element.querySelector("[data-run=step]"),this.stopButton=this.element.querySelector("[data-run=stop]"),this.indentButton=this.element.querySelector(".livecode-indent"),this.indentButton.addEventListener("click",()=>this.code.indent()),this.debugPanel=this.element.querySelector(".livecode-debug"),this.debugVars=this.element.querySelector(".livecode-vars"),this.swingElement.innerHTML=` +
+

${ze(p("web_live_swing_windows"))}

+ +
+ `,this.swingElement.append(this.swingDisplay),this.swingElement.querySelector(".console-hide").addEventListener("click",()=>{this.swingElement.hidden=!0,PJ()});const e=this.consoleElement;this.consoleResizer.title=p("web_console_resize"),this.element.append(this.swingElement,this.consoleResizer,e),this.consoleLines=e.querySelector(".livecode-console-lines"),this.consoleForm=e.querySelector(".livecode-console-input"),this.consoleNotice=e.querySelector(".livecode-console-notice"),e.querySelector(".console-hide").addEventListener("click",()=>this.hideConsole()),this.runButton.addEventListener("click",()=>{var t;return(t=this.run)!=null&&t.paused?this.resume():this.startRun(!1)}),this.stepButton.addEventListener("click",()=>{var t;return(t=this.run)!=null&&t.paused?this.stepOnce():this.startRun(!0)}),this.stopButton.addEventListener("click",()=>this.stopRun(!0)),this.consoleForm.addEventListener("submit",t=>{t.preventDefault(),this.submitInput()}),this.run=void 0,this.view.addEventListener("click",t=>{const n=t.target.closest(".ln");if(!n||!this.view.classList.contains("selectable"))return;const a=Pa(this.spans,Number(n.dataset.line));a&&this.onSelect(a.path)}),this.code=new IJ(this.editor,{onChange:()=>this.codeChanged(),onCaret:()=>this.caretMoved(),onUndo:t=>this.onUndo(t),words:()=>this.snippetWords,breakpointLine:t=>{var n;return(n=Pa(this.spans,t))==null?void 0:n.from},onBreakpoints:()=>this.breakpoints=this.code.breakpoints},p("web_live_edit_label")),this.editor.querySelector(".cm-gutters").title=p("web_debug_gutter_title"),this.breakpoints=new Set,this.debugLine=void 0,this.highlighted=void 0,this.html="",this.parsed=void 0,this.showMode()}javaFor(e,t){const n=this.textFor.get(e);if(n!==void 0)return n;const a=this.shown.get(t);return a?yc(a.text,a.doc,e,this.labels,{},this.form):ci(e,this.labels,this.form)}adoptJava(e,t){this.textFor.set(e,t),this.parsed=void 0,this.last&&this.refresh(this.last.doc,this.last.highlight,this.last.context)}documentFromJavaText(e){return Wo({caption:"",elements:[]},Eo(e,this.labels))}get javaForm(){return this.form}setJavaForm(e){this.form=e;try{localStorage.setItem(nd,e.asClass?"1":"0"),localStorage.setItem(id,e.withMain?"1":"0")}catch{}this.textFor=new WeakMap,this.shown=new WeakMap,this.parsed=void 0,this.last&&this.refresh(this.last.doc,this.last.highlight,this.last.context)}get swingSupport(){return this.swing}setSwingSupport(e){this.swing=e;try{localStorage.setItem(ad,e?"1":"0")}catch{}e||(this.swingElement.hidden=!0)}get language(){return this.target}setTarget(e){this.target=e;try{localStorage.setItem(i2,e)}catch{}this.showMode(),this.last&&this.refresh(this.last.doc,this.last.highlight,this.last.context)}showMode(){const e=this.target==="java";this.view.hidden=e,this.editor.hidden=!e,this.problemLine.hidden=!e,this.indentButton.hidden=!e,this.hint.textContent=p(e?"web_live_hint_edit":"web_live_hint"),this.element.querySelector(".livecode-lang").textContent={java:"Java",javascript:"JavaScript",python:"Python"}[this.target]}refresh(e,t,n){this.last={doc:e,highlight:t,context:n},this.target==="java"?this.refreshEditor(e,t,n):this.refreshView(e,t,n.editable)}refreshView(e,t,n){var l;const a=Zh(e,this.target,this.labels);this.spans=a.spans;const s=t&&a.spans.find(u=>Y1(u.path,t));this.view.classList.toggle("selectable",n);const r=a.text.split(` +`).map((u,c)=>`
${EJ(u)||" "}
`).join("");r!==this.html&&(this.view.innerHTML=r),this.html=r;const o=s?`${s.from}-${s.to}`:void 0;o&&o!==this.highlighted&&((l=this.view.querySelector(`.ln[data-line="${s.from}"]`))==null||l.scrollIntoView({block:"nearest"})),this.highlighted=o}startRun(e){var a,s;if((a=this.onRobotRun)!=null&&a.call(this,e))return;const t=["web_parse_missing_import","web_parse_missing_scanner","web_parse_unknown_type"],n=this.target==="java"?this.javaProblems.find(r=>t.includes(r.key)):void 0;if(n){this.stopRun(!1),this.setConsoleVisible(!0),this.consoleLines.replaceChildren(),this.consoleNotice.textContent=p("web_parse_line_fmt",this.code.lineAt(n.from)+1,p(n.key,n.arg??"")),this.consoleNotice.classList.add("error"),this.showProblems=!0,this.drawMarks((s=this.last)==null?void 0:s.highlight);return}if(this.swing&&this.target==="java"&&!e&&this.code.breakpoints.size===0)return void this.startJavaRun();this.last&&(this.stopRun(!1),this.run={engine:new wi(this.last.doc,this.last.context.resolve),doc:this.last.doc,printed:0,paused:!1,stepping:e,debugged:!1},this.breakpoints=this.code.breakpoints,this.debugPanel.hidden=!0,this.setConsoleVisible(!0),this.consoleLines.replaceChildren(),this.consoleNotice.textContent="",this.consoleNotice.classList.remove("error"),this.setRunning(!0),e?this.pause():this.continueRun(!1))}async startJavaRun(){var e;this.stopRun(!1),(e=this.stopWatchingFiles)==null||e.call(this),this.setConsoleVisible(!0),this.consoleLines.replaceChildren(),this.consoleLines.id="console",this.consoleForm.hidden=!0,this.consoleNotice.classList.remove("error"),this.runButton.disabled=this.stepButton.disabled=!0;try{this.consoleNotice.textContent=p("web_live_swing_loading"),await _J(this.swingDisplay),this.consoleNotice.textContent=p("web_live_swing_compiling");const{result:t,files:n}=await BJ(this.code.text,()=>this.swingElement.hidden=!1);this.showWrittenFiles(n),this.consoleNotice.textContent=p({"compile-error":"web_live_swing_compile_failed",windows:"web_live_swing_running",finished:"web_live_run_finished"}[t]),this.consoleNotice.classList.toggle("error",t==="compile-error"),this.swingElement.hidden=t!=="windows",t==="windows"&&(this.stopWatchingFiles=DJ(n,a=>this.showWrittenFiles(a)))}catch{this.consoleNotice.textContent=p("web_live_swing_failed"),this.consoleNotice.classList.add("error")}this.runButton.disabled=this.stepButton.disabled=!1}continueRun(e){const t=this.run;if(!t)return;const{engine:n}=t;for(let a=0;athis.continueRun(!1),0))}afterSteps(){const e=this.run,t=e.engine.state;return this.printNewLines(),t.inputRequest?(this.askInput(),!0):t.isHalted||!e.engine.canStep?(this.showWrittenFiles(t.files),this.finishRun(t.isHalted&&t.notice?t1(t.notice):p("web_live_run_finished"),t.isHalted),!0):!1}atBreakpoint(e){if(!e||e.callPath||e.kind==="forLoopIncrement"||e.kind==="forLoopStart"||e.kind==="callEnd")return!1;const t=this.lineOf(e.path);return t!==void 0&&this.breakpoints.has(t)}lineOf(e){var t;return e&&((t=this.spans.find(n=>Y1(n.path,e)))==null?void 0:t.from)}pause(){var a,s;const e=this.run;e.paused=!0,e.debugged=!0;const t=e.engine.currentStepPath;this.debugLine=this.lineOf(t),this.consoleNotice.classList.remove("error"),this.consoleNotice.textContent=this.debugLine===void 0?"":p("web_debug_paused_fmt",this.debugLine+1),this.showVariables(),this.setRunning(!0);const n=(a=this.last)==null?void 0:a.highlight;t&&!(n&&Y1(n,t))?this.onSelect(t):this.drawMarks((s=this.last)==null?void 0:s.highlight)}resume(){const e=this.run;e!=null&&e.paused&&(e.paused=!1,e.stepping=!1,this.leavePause(),this.continueRun(!0))}stepOnce(){var a,s;const e=this.run;if(!(e!=null&&e.paused))return;e.paused=!1,e.stepping=!0,this.leavePause();const{engine:t}=e,n=(a=t.steps[t.state.stepIndex])==null?void 0:a.kind;t.step(),(n==="forLoopStart"||n==="forLoopIncrement")&&t.canStep&&((s=t.steps[t.state.stepIndex])==null?void 0:s.kind)==="forLoopCondition"&&t.step(),this.afterSteps()||this.pause()}leavePause(){var e;this.debugLine=void 0,this.consoleNotice.textContent="",this.setRunning(!0),this.drawMarks((e=this.last)==null?void 0:e.highlight)}showVariables(){const e=this.run,t=e.engine.state.variables;this.debugPanel.hidden=!1;const n=[...t.keys()].sort((a,s)=>a.localeCompare(s));if(n.length===0)this.debugVars.innerHTML=`

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

`;else{const a=document.createElement("table");for(const s of n){const r=t.get(s),o=_e(r),l=a.insertRow();l.insertCell().textContent=s;const u=l.insertCell();r.kind==="grid"?u.append(rg(r)):u.textContent=o,e.values&&e.values.get(s)!==o&&l.classList.add("changed")}this.debugVars.replaceChildren(a)}e.values=new Map(n.map(a=>[a,_e(t.get(a))]))}printNewLines(e){const t=this.run;if(!t)return;const n=t.engine.state.outputLines;for(;t.printeds.focus())}submitInput(){const e=this.run;if(!(e!=null&&e.engine.state.inputRequest))return;const t=this.consoleForm.querySelector("input"),{prompt:n}=e.engine.state.inputRequest;if(e.engine.provideInput(t.value),e.engine.state.inputRequest)return this.askInput();const a=e.heldLine;if(e.heldLine=void 0,this.printNewLines({prompt:n,value:t.value,heldLine:a}),t.value="",this.consoleForm.hidden=!0,!e.stepping)return this.continueRun(!1);this.afterSteps()||this.pause()}stopRun(e){var t;this.run&&(window.clearTimeout(this.run.timer),this.run.heldLine!==void 0&&this.consoleLine(this.run.heldLine),e&&this.finishRun(p("web_live_run_stopped"),!1),this.run=void 0,this.debugLine=void 0,this.debugPanel.hidden=!0,this.setRunning(!1),this.drawMarks((t=this.last)==null?void 0:t.highlight))}finishRun(e,t){var n,a;this.run&&window.clearTimeout(this.run.timer),this.consoleForm.hidden=!0,this.consoleNotice.textContent=e,this.consoleNotice.classList.toggle("error",t),(n=this.run)!=null&&n.debugged?this.showVariables():this.debugPanel.hidden=!0,this.run=void 0,this.debugLine=void 0,this.setRunning(!1),this.drawMarks((a=this.last)==null?void 0:a.highlight)}showTranscript(e){this.stopRun(!1),this.setConsoleVisible(!0),this.consoleForm.hidden=!0,this.consoleLines.replaceChildren();for(const t of e.lines){const n=this.consoleLine(t.text);if(t.typed!==void 0){const a=document.createElement("span");a.className="typed",a.textContent=t.typed,n.append(a)}}e.pending!==void 0&&this.consoleLine(e.pending).classList.add("pending"),this.consoleLines.scrollTop=this.consoleLines.scrollHeight,this.consoleNotice.textContent=e.notice??"",this.consoleNotice.classList.toggle("error",e.error)}hideConsole(){this.stopRun(!1),this.setConsoleVisible(!1)}setConsoleVisible(e){this.consoleElement.hidden!==!e&&(this.consoleElement.hidden=!e,this.consoleResizer.hidden=!e)}makeConsoleResizer(){const e=document.createElement("div");e.className="console-resizer",e.hidden=!0,e.tabIndex=0,e.setAttribute("role","separator"),e.setAttribute("aria-orientation","horizontal");const t=this.consoleElement,n=r=>Math.round(Math.max(rd,Math.min(r,this.element.getBoundingClientRect().height-160))),a=(r,o)=>{t.style.height=r===void 0?"":`${n(r)}px`,o&&ZJ(sd,r===void 0?"":String(n(r)))},s=Number(MJ(sd));return s>0&&(t.style.height=`${Math.max(rd,s)}px`),e.addEventListener("pointerdown",r=>{if(r.button!==0)return;r.preventDefault(),e.setPointerCapture(r.pointerId);const o=r.clientY,l=t.getBoundingClientRect().height;e.classList.add("dragging");const u=m=>a(l-(m.clientY-o),!1),c=m=>{e.removeEventListener("pointermove",u),e.removeEventListener("pointerup",c),e.removeEventListener("pointercancel",c),e.classList.remove("dragging"),a(l-(m.clientY-o),!0)};e.addEventListener("pointermove",u),e.addEventListener("pointerup",c),e.addEventListener("pointercancel",c)}),e.addEventListener("dblclick",()=>a(void 0,!0)),e.addEventListener("keydown",r=>{const o=r.key==="ArrowUp"?20:r.key==="ArrowDown"?-20:0;o&&(r.preventDefault(),a(t.getBoundingClientRect().height+o,!0))}),e}setRunning(e){var a,s;const t=!!((a=this.run)!=null&&a.paused);this.runButton.disabled=e&&!t,this.stepButton.disabled=e&&!t,this.stopButton.disabled=!e,this.indentButton.disabled=e;const n=p(t?"web_debug_continue":"web_live_run_title");this.runButton.dataset.tip=n,this.runButton.setAttribute("aria-label",t?n:p("web_live_run")),this.element.classList.toggle("running",e&&!t),this.element.classList.toggle("debugging",t),this.code.setReadOnly(e||!((s=this.last)!=null&&s.context.editable))}textForDocument(e,t){const n=this.textFor.get(e);if(n!==void 0)return n;const a=this.shown.get(t.owner);return a?JJ(a.text,yc(a.text,a.doc,e,this.labels,{subprograms:t.subprograms},this.form)):ci(e,this.labels,this.form)}refreshEditor(e,t,n){var r;const a=this.textForDocument(e,n);this.textFor.set(e,a),this.shown.set(n.owner,{doc:e,text:a}),this.run&&this.run.doc!==e&&this.stopRun(!1),this.code.setReadOnly(!n.editable||!!this.run),this.code.text!==a?(this.code.setText(a),this.analyze(a,n)):this.parsed||this.analyze(a,n);const s=zg(e,this.labels,this.form);this.spans=a===s.text?s.spans:((r=this.parsed)==null?void 0:r.spans)??[],this.drawMarks(t)}analyze(e,t){this.parsed=Eo(e,this.labels,{subprograms:t.subprograms}),this.placeholders=this.parsed.placeholders,this.problems=this.parsed.problems}get javaProblems(){var e;return(e=this.last)!=null&&e.doc.pseudocode?[]:this.problems}drawMarks(e){var r;const t=e&&this.spans.find(o=>Y1(o.path,e)),n=t?`${t.from}-${t.to}`:void 0,a=((r=this.last)==null?void 0:r.context.editable)===!1&&t?t.from:void 0;this.code.setMarks({placeholders:this.placeholders,problems:this.showProblems?this.javaProblems:[],lines:t&&a===void 0?{from:t.from,to:t.to}:void 0,current:this.debugLine??a},n!==void 0&&n!==this.highlighted&&!this.code.hasFocus);const s=this.showProblems?this.javaProblems[0]:void 0;this.problemLine.textContent=s?p("web_parse_line_fmt",this.code.lineAt(s.from)+1,p(s.key,s.arg??"")):"",this.highlighted=n}codeChanged(){var u,c,m,d;const e=(u=this.last)==null?void 0:u.context,t=(c=this.last)==null?void 0:c.doc;if(!e||!t)return;const n=this.code.text;this.analyze(n,e);const a=Wo(t,this.parsed),s=JSON.stringify([a.caption,a.elements])===JSON.stringify([t.caption,t.elements]),r=s?t:a;this.textFor.set(r,n),this.shown.set(e.owner,{doc:r,text:n}),this.showProblems=!1,window.clearTimeout(this.problemTimer),this.problemTimer=window.setTimeout(()=>{var h;this.showProblems=!0,this.drawMarks((h=this.last)==null?void 0:h.highlight)},WJ);const o=this.code.lineAt(this.code.caret),l=(m=Pa(this.parsed.spans,o))==null?void 0:m.path;s?(this.spans=this.parsed.spans,this.drawMarks((d=this.last)==null?void 0:d.highlight),l&&this.onSelect(l)):this.onCode(r,l)}caretMoved(){var n,a;const e=Pa(this.spans,this.code.lineAt(this.code.caret)),t=(n=this.last)==null?void 0:n.highlight;e&&((a=this.last)!=null&&a.context.editable)&&!(t&&Y1(t,e.path))&&this.onSelect(e.path)}get snippetWords(){const e=this.labels;return{condition:e.condition,selector:e.selector,code:e.code,start:e.start,step:e.step,branch:p("element_verzweigung"),branchElse:p("element_verzweigung"),switchCase:p("element_fallauswahl"),forLoop:p("element_forSchleife"),whileLoop:p("element_whileSchleife"),doLoop:p("element_doUntilSchleife"),output:p("inspector_io_mode_output"),input:p("inspector_io_mode_input")}}}function JJ(i,e){const t=i.split(` +`),n=e.split(` +`);let a=0;for(;aa?Gf(e,a+1,n.length-s):e}const RJ=5e3;function GJ(i,e,t,n={}){const a=new wi(i,e),s=new ds(t),r=c=>({pose:{...s.pose},trail:s.trail.map(m=>({...m})),leds:[...s.leds],screen:s.screen,tone:c}),o=[r()];let l=0;const u=(c,m)=>({frames:o,stop:c,notice:m,bumps:s.bumps,distance:Math.round(s.trail.slice(1).reduce((d,h,g)=>d+Math.hypot(h.x-s.trail[g].x,h.y-s.trail[g].y),0))});for(let c=0;ch!==0);s.tick(s0),d&&o.push(r())}return u("limit")}const yn=i=>i.replace(/&/g,"&").replace(//g,">").replace(/"/g,"""),io=300;class HJ{constructor(){y(this,"element");y(this,"rail");y(this,"heightBar");y(this,"onHide",()=>{});y(this,"onToggleStacked",()=>{});y(this,"stage");y(this,"status");y(this,"picker");y(this,"playButton");y(this,"stackButton");y(this,"view");y(this,"loading");y(this,"worlds",[]);y(this,"worldsKey");y(this,"setup",Ii);y(this,"result");y(this,"lastKey");y(this,"pending");y(this,"playTimer");y(this,"input");y(this,"simulation");this.element=document.createElement("aside"),this.element.className="robotpreview",this.element.innerHTML=` + +
+

🤖 ${yn(p("web_visubot_preview_title"))}

+ + + +
+

${yn(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=`${_t}🤖 ${yn(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=K(async()=>{const{Robot3D:e}=await import("./robot3d-DZxNwb67.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]??Ii)}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=GJ(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=se.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&&bg(s.tone[0],s.tone[1]),this.showFrame(s,io-30),this.playTimer=window.setTimeout(n,io)};this.playTimer=window.setTimeout(n,io)}stopPlaying(e){var t;this.playTimer!==void 0&&window.clearTimeout(this.playTimer),this.playTimer=void 0,this.playButton.innerHTML=se.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(`⚠︎ ${t1(e.notice)}`),this.status.textContent=t.join(" · ")}pause(){window.clearTimeout(this.pending),this.pending=void 0,this.lastKey=void 0,this.stopPlaying(!1)}}const VJ={left:12,top:10},qJ=8,Ws=8e3,xi=16,ao=12,a2="#fafafa";function s2(i){const e=i.caption.trim();return e===""?p("diagram_title_placeholder"):e}function od(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 ld(i,e){return od(i.caption)||od(e)||"VisuStruct"}function QJ(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,xi,"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+"…",xi,"bold")>e;)r=r.slice(0,-1);return[a[0],r+"…"]}return a}function ud(i,e,t,n=320){const a={...i,elements:i.elements.map(Xa)},s=new Vd(e,t).layout(a,VJ),r=Math.min(Ws,Math.max(n,s.canvasSize.width)),o=Math.min(Ws,Math.max(n,s.canvasSize.height));if(r<=2||o<=2)return;const l=QJ(s2(i),r-2*ao,t),u=Math.ceil(xi*1.2),c=Math.min(56,l.length*u+2),m=c+o,d=new $d(e,t).render(s,{width:r,height:o},void 0,qJ);d.setAttribute("y",String(c)),d.removeAttribute("class");const h=Se("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:m,viewBox:`0 0 ${r} ${m}`});h.append(Se("rect",{x:0,y:0,width:r,height:m,fill:a2}));const g=Se("text",{x:ao,y:0,"font-family":Ns,"font-size":xi,"font-weight":600,fill:"black"});return l.forEach((f,b)=>{const x=Se("tspan",{x:ao,y:b*u+xi});x.textContent=f,g.append(x)}),h.append(g,d),{svg:h,width:r,height:m}}function r2(i){return` +`+new XMLSerializer().serializeToString(i.svg)}async function cd(i,e){const t=Math.max(1,Math.min(e,Ws/i.width,Ws/i.height)),n=URL.createObjectURL(new Blob([r2(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=a2,r.fillRect(0,0,s.width,s.height),r.drawImage(a,0,0,s.width,s.height),s}finally{URL.revokeObjectURL(n)}}function UJ(i){return new Promise((e,t)=>i.toBlob(n=>n?e(n):t(new Error("PNG konnte nicht erzeugt werden.")),"image/png"))}function $J(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),c=r(l),[m,d]=c.s>u.s?[l,c]:[o,u],h=a*d.s,g=s*d.s;return{page:m,draw:{x:32+(d.cw-h)/2,y:32+(d.ch-g)/2,width:h,height:g}}}async function YJ(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 XJ(i,e,t,n,a){const{page:s,draw:r}=$J(n.width,n.height),o=await YJ(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`,c=new TextEncoder,m=[["<< /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 +`,o,` +endstream`],[`<< /Length ${u.length} >> +stream +${u} +endstream`],[`<< /Creator ${md("VisuStruct")} /Title ${md(a)} >>`]],d=[];let h=0;const g=x=>{const v=typeof x=="string"?c.encode(x):x;d.push(v),h+=v.length};g(`%PDF-1.4 +%âãÏÓ +`);const f=[];m.forEach((x,v)=>{f.push(h),g(`${v+1} 0 obj +`),x.forEach(g),g(` +endobj +`)});const b=h;g(`xref +0 ${m.length+1} +0000000000 65535 f +`);for(const x of f)g(`${String(x).padStart(10,"0")} 00000 n +`);return g(`trailer +<< /Size ${m.length+1} /Root 1 0 R /Info ${m.length} 0 R >> +startxref +${b} +%%EOF +`),new Blob(d,{type:"application/pdf"})}function KJ(i){const{data:e}=i.getContext("2d").getImageData(0,0,i.width,i.height),t=new Uint8Array(i.width*i.height*3);for(let n=0,a=0;nObject.entries(At).map(([i,e])=>{if(i==="getColor")return` def ${i}(self): + farbe = ${e.python} + return FARBNAMEN.get(farbe, farbe) +`;const t=typeof e.simulated=="boolean"?`bool(${e.python})`:e.python;return` def ${i}(self): + return ${t} +`}).join(` +`);function nR(i){const e=Object.entries(ts).map(([n,a])=>` ${JSON.stringify(n)}: (${a.join(", ")}), +`).join(""),t=Object.entries(eR).map(([n,a])=>` ${JSON.stringify(n)}: ${JSON.stringify(i==="de"?a:n)}, +`).join("");return`import event, time, cyberpi, mbot2, mbuild + +FARBEN = { +${e}} + +FARBNAMEN = { +${t}} + + +class Led: + def __init__(self, nr): + self.nr = nr + + def setColor(self, farbe): + r, g, b = FARBEN.get(farbe, (0, 0, 0)) + cyberpi.led.on(r, g, b, id=self.nr + 1) + + +class MBot: + def forward(self, cm=10): + mbot2.straight(cm) + + def backward(self, cm=10): + mbot2.straight(-cm) + + def turnLeft(self, grad=90): + mbot2.turn(-grad) + + def turnRight(self, grad=90): + mbot2.turn(grad) + + def stop(self): + mbot2.EM_stop("ALL") + + def drive(self, links, rechts): + mbot2.drive_power(links, -rechts) + + def setLed(self, r, g, b): + cyberpi.led.on(r, g, b) + + def ledOff(self): + cyberpi.led.off() + + def led(self, nr): + return Led(nr) + + def playTone(self, hz, ms): + cyberpi.audio.play_tone(hz, ms / 1000) + + def pause(self, ms): + time.sleep(ms / 1000) + + def resetTimer(self): + cyberpi.timer.reset() + + def emotion(self, name): + getattr(cyberpi.emotion, name)() + + def showText(self, text): + cyberpi.display.clear() + cyberpi.display.show_label(str(text), 24, "center") + +${tR()} + +mbot = MBot() +`}const iR=i=>` + +laeuft = False + + +@event.start +def beim_einschalten(): + mbot.showText(${JSON.stringify(i)}) + + +@event.is_press("a") +def taste_a(): + global laeuft + if laeuft: + return + laeuft = True + cyberpi.display.clear() + try: + programm() + finally: + mbot.stop() + laeuft = False +`;function aR(i,e,t,n="A = Start"){const a={pythonWithoutMatch:!0},s=dd(ls(i,"python",a)),r=e.filter(h=>h!==i&&zt(h.caption)).map(h=>dd(ls(h,"python",a))),o=[s,...r].join(` +`);if(/\binput\(/u.test(o))return{error:"input"};if(/\bopen\(|\bos\.path\b/u.test(o))return{error:"files"};const l=new Set,u=h=>h.split(` +`).filter(g=>(/^import \w+$/u.test(g)&&l.add(g),!/^import \w+$/u.test(g))).join(` +`).trim(),c=u(s);if(c===""||/^#[^\n]*$/u.test(c))return{error:"empty"};const m=c.split(` +`).map(h=>h.trim()===""?"":" "+h).join(` +`);return{source:`# VisuStruct VisuBot +${nR(t)}${[...l].join(` +`)} + +`+r.map(h=>u(h)+` + + +`).join("")+`def programm(): +${m} +`+iR(n)}}function dd(i){return i.split(` +`).map(e=>{const t=/^(\s*)(.*)$/u.exec(e);return t[2].startsWith("#")?e:t[1]+o2(t[2])}).join(` +`)}const sR=/^(==|!=|<=|>=|\+=|-=|\*=|\/=|=|<|>|,|:)/u,rR=/^(and|or|not|in|if|elif|while|return|for|else)\b/u;function o2(i){let e="",t="",n=0;for(let a=0;a0)){if(h==="+"&&e.trim()!==""&&!/[-+*/%(,=<>]\s*$/u.test(e)){t.push(e),e="";continue}e+=h}}if(n>0&&(e+=i.slice(a)),t.push(e),t.length<2)return t[0];const s=/^\s*/u.exec(t[0])[0],r=/\s*$/u.exec(t[t.length-1])[0],o=t.map(d=>d.trim()),l=d=>d.startsWith('"')||d.startsWith("'")||d.startsWith("str("),u=o.findIndex(l);if(u<0)return i;const c=u>0?[`str(${o.slice(0,u).join(" + ")})`]:[],m=o.slice(u).map(d=>l(d)?d:`str(${d})`);return s+[...c,...m].join(" + ")+r}const h1=i=>i.replace(/&/g,"&").replace(//g,">");function oR(i,e){const t=document.createElement("dialog");t.className="about mbot-upload",t.setAttribute("aria-labelledby","mbot-upload-title"),t.innerHTML=` +
+

⬆ ${h1(p("web_visubot_upload_title"))}

+ +
+
+
    +
  1. ${h1(p("web_visubot_upload_step1"))}
  2. +
  3. ${h1(p("web_visubot_upload_step2"))}
  4. +
  5. ${h1(p("web_visubot_upload_step3"))}
  6. +
+ +

+ +
`;const n=t.querySelector(".mbot-upload-status"),a=t.querySelector("progress"),s=t.querySelector("[data-action=upload-start]");let r=!1;const o=()=>!r&&t.close();t.querySelector("[data-action=upload-close]").addEventListener("click",o),t.addEventListener("cancel",u=>r&&u.preventDefault()),t.addEventListener("click",u=>u.target===t&&o()),t.addEventListener("close",()=>t.remove());const l=aR(i,e,x3(),p("web_visubot_upload_label"));"error"in l&&(n.textContent=`⚠︎ ${p(`web_visubot_upload_error_${l.error}`)}`,s.hidden=!0),s.addEventListener("click",async()=>{if("source"in l){r=!0,s.disabled=!0,a.hidden=!1,a.value=0,n.textContent=p("web_visubot_upload_busy");try{await ge.upload(l.source,(u,c)=>a.value=u/c),a.value=1,n.textContent=`✓ ${p("web_visubot_upload_done")}`,n.classList.add("done")}catch(u){const c=u;n.textContent=c.name==="NotFoundError"?"":`⚠︎ ${p("web_visubot_upload_failed")} (${c.message})`,a.hidden=!0,await ge.disconnect(c.name==="NotFoundError"?void 0:c.message).catch(()=>{})}finally{r=!1,s.disabled=!1}}}),document.body.append(t),t.showModal()}const gd=[S.verzweigung,S.whileSchleife,S.doUntilSchleife,S.anweisung],pd=()=>[{description:p("web_file_type"),accept:{"application/xml":[".visustruct",".strk"]}}],so=i=>p(`element_${S[i]}`),lR={[S.verzweigung]:"age >= 18",[S.whileSchleife]:"i < 10",[S.doUntilSchleife]:"again == 1",[S.fallauswahl]:"day"},uR={statement:'int number = 5 | double x = 1.5 | String text = "Your text" | boolean ok = true | const double PI = 3.14',input:'input: int age "Enter age" | input: double price "Enter price" | input: String name "Enter name"',output:'output: number | output: "Your text" | output: "Your age: " + age'};function fd(i){switch(i.type){case S.anweisung:{const e=$a(i.textLines.join(` +`));return e==="input"?"input:":e==="output"?"output:":void 0}case S.verzweigung:return"if";case S.whileSchleife:case S.doUntilSchleife:return"while";case S.fallauswahl:return"switch";default:return}}function cR(i){switch(i.type){case S.anweisung:{const e=$a(i.textLines.join(` +`));return e==="input"?'int age "Enter age"':e==="output"?'"Your age: " + age':p("inspector_placeholder_statement")}case S.verzweigung:case S.whileSchleife:case S.doUntilSchleife:case S.endlosschleife:return p("inspector_placeholder_condition");case S.fallauswahl:return p("inspector_placeholder_selector");case S.aufruf:return p("inspector_placeholder_call");case S.aussprung:return p("inspector_placeholder_break");default:return""}}function me(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}const mR=760,bd=[{value:1,label:"settings_ui_scale_small"},{value:1.22,label:"settings_ui_scale_medium"},{value:1.5,label:"settings_ui_scale_large"},{value:1.82,label:"settings_ui_scale_extra_large"}],ro=[{value:14,label:"settings_ui_scale_small"},{value:17,label:"settings_ui_scale_medium"},{value:20,label:"settings_ui_scale_large"},{value:24,label:"settings_ui_scale_extra_large"}];function xd(i){document.documentElement.style.setProperty("--code-size",`${i}px`)}const dR=/Mac|iPhone|iPad/.test(navigator.platform);function Da(i){const e=s1(),t=e==="pt-PT"?"pt":e==="de"?"de":"en",n=/\/app\/(index\.html)?$/.test(location.pathname)?"../":"https://visustruct.org/",a=Hn()?"visubot":"index";return`${n}${t}/${a}.html${i?`#${i}`:""}`}function Nt(i,e,t,n){const a=n?`${e} (${n})`:e;return``}function wn(i,e=!1){return dR?`${e?"⇧":""}⌘${i}`:[p("web_key_ctrl"),...e?[p("web_key_shift")]:[],i].join("+")}const E=vR,vd="visustruct.ui.scale.canvas",yd="visustruct.ui.scale.code",wd="visustruct.learn.open",zd="visustruct.files.open",Id="visustruct.files.width",kd="visustruct.learn.width",Sd="visustruct.live.open",hR="visustruct.live.width",Td="visustruct.robotPreview.open",_d="visustruct.codeMain",Ad="visustruct.palette.width",gR="visustruct.editor.width",Od="visustruct.visubot.collapsedGroups",Cd="visustruct.robotPreview.stacked",jd="visustruct.robotPreview.width",Pd="visustruct.robotPreview.height",Dd="visustruct.editor.hidden",oo="visustruct.palette.compact",Bd="visustruct.palette.hidden",pR='',fR=80;class bR{constructor(e){y(this,"tabs",[]);y(this,"tabIndex",0);y(this,"nextTabSerial",1);y(this,"clipboard");y(this,"zoom",1);y(this,"simulating",!1);y(this,"exportButton");y(this,"closeExport");y(this,"learn");y(this,"shell");y(this,"railButton");y(this,"liveRailButton");y(this,"editorRailButton");y(this,"topbar",me("div",{class:"topbar"}));y(this,"bottombar",me("div",{class:"bottombar"}));y(this,"editorHidden",!1);y(this,"setPaletteHidden");y(this,"files");y(this,"filesRailButton");y(this,"closeSettings");y(this,"escapeSettings");y(this,"exerciseSaveTimer");y(this,"paletteObserver");y(this,"resizeObserver");y(this,"renderedHostSize",{width:-1,height:-1});y(this,"simPath");y(this,"sim");y(this,"simButton");y(this,"pseudocodeBox");y(this,"coding",!1);y(this,"code");y(this,"codeButton");y(this,"liveCoding",!1);y(this,"codeTyping");y(this,"live");y(this,"preview",new HJ);y(this,"previewOpen",!1);y(this,"previewOpenedForSim",!1);y(this,"codeMain",!1);y(this,"previewStacked",!1);y(this,"previewResizer");y(this,"measure",L2());y(this,"metrics",E2());y(this,"engine",new Vd(this.metrics,this.measure));y(this,"renderer",new $d(this.metrics,this.measure));y(this,"layout");y(this,"flat",[]);y(this,"canvasHost");y(this,"svg");y(this,"overlay");y(this,"inspector");y(this,"captionInput");y(this,"undoButton");y(this,"redoButton");y(this,"deleteButton");y(this,"statusLine");y(this,"drag");y(this,"downloads",null);y(this,"inViewer","claude"in window);y(this,"visuBot");y(this,"stopLinkListener");y(this,"tabStrip");this.root=e,this.tabs.push(this.makeTab());const t=new URLSearchParams(location.search);t.has("visubot")?Sr("on"):t.has("visustruct")&&Sr("off"),Hu(ui()),this.learn=new wM(this.learnHost()),this.shell=document.createElement("div"),this.shell.className="shell",e.replaceWith(this.shell),this.live=new FJ(()=>this.setLiveCoding(!1),l=>{this.selected=l,this.render()},(l,u)=>this.commitFromCode(l,u),l=>l?this.redo():this.undo()),this.live.onRobotRun=l=>this.runRobot(l),this.live.onSwap=()=>this.setCodeMain(!this.codeMain),this.live.onReference=()=>{this.learn.showReference(),this.setLearning(!0)},this.files=new LM({open:(l,u,c)=>this.openFromWorkspace(l,u,c),hide:()=>this.setFilesOpen(!1),message:l=>this.showMessage(l),progressLoaded:()=>this.learn.restore(),chooseWorld:l=>this.chooseWorld(l,!1)});const n=me("div",{class:"columns"});n.append(this.filesRail(),this.files.element,this.panelResizer(this.files.element,"files-resizer",Id,p("web_files_resize"),1),this.learnRail(),this.learn.element,this.learnResizer(),this.editorRail(),e,this.panelResizer(e,"editor-resizer",gR,p("web_editor_resize"),()=>this.codeMain?-1:1,()=>this.live.element),this.liveResizer(),this.live.element,this.liveRail(),this.previewResizer=this.panelResizer(this.preview.element,"preview-resizer",jd,p("web_visubot_preview_resize"),-1),this.preview.element,this.preview.rail),this.setupPreview(),this.shell.append(this.topbar,n,this.bottombar);const a=nt(wd),s=new URLSearchParams(location.search).has("learn");this.showWorldInURL(),this.setLearning(s||(a===null?window.innerWidth>1100:a==="1"),s),this.setFilesOpen(nt(zd)==="1");const r=Number(nt(vd));bd.some(l=>l.value===r)&&(this.zoom=r),this.setLiveCoding(nt(Sd)==="1"),this.setEditorHidden(nt(Dd)==="1"),this.buildUI(),this.setCodeMain(nt(_d)==="1"),this.render(),window.addEventListener("pointermove",l=>this.onPointerMove(l)),window.addEventListener("pointerup",l=>this.onPointerUp(l)),window.addEventListener("pointercancel",()=>this.endDrag()),window.addEventListener("keydown",l=>this.onKeyDown(l)),window.addEventListener("beforeunload",l=>{(this.tabs.some(u=>u.dirty&&!u.exerciseId)||!this.files.ready&&be.hasContent())&&l.preventDefault()}),this.setupFileDrop();const o=window.claude;typeof(o==null?void 0:o.use)=="function"&&o.use("downloads").then(l=>this.downloads=l).catch(()=>{})}get tab(){return this.tabs[this.tabIndex]}get doc(){return this.tab.doc}set doc(e){this.tab.doc=e}get fileName(){return this.tab.fileName??`${un(this.tab)}.visustruct`}get fileHandle(){return this.tab.fileHandle}set fileHandle(e){this.tab.fileHandle=e}get dirty(){return this.tab.dirty}set dirty(e){this.tab.dirty=e}get undoStack(){return this.tab.undoStack}get redoStack(){return this.tab.redoStack}get selected(){return this.tab.selected}set selected(e){this.tab.selected=e}buildUI(){var he,Ie,fe,J;this.root.className="app",this.root.innerHTML=` +
+ ${Hn()?SM:'VisuStruct'} ${E(p("web_brand_suffix"))} +
+ ${Nt("new",p("toolbar_new"),se.newFile)} + ${Nt("open",p("menu_open"),se.open,wn("O"))} + ${Nt("save",p("menu_save"),se.save,wn("S"))} +
+
+ + +
+
+ + + + +
+ + +
+
+ + + + `,this.topbar.replaceChildren(this.root.querySelector(".toolbar")),this.bottombar.replaceChildren(this.root.querySelector(".statusbar"));const e=C=>this.root.querySelector(C)??this.topbar.querySelector(C)??this.bottombar.querySelector(C);this.canvasHost=e(".canvas"),this.inspector=e(".inspector"),this.captionInput=e(".caption"),this.undoButton=e("[data-action=undo]"),this.redoButton=e("[data-action=redo]"),this.deleteButton=e("[data-action=delete]"),this.statusLine=e(".status"),this.simButton=e("[data-action=simulate]"),this.pseudocodeBox=e("[data-action=pseudocode]"),this.pseudocodeBox.addEventListener("change",()=>this.commit({...this.doc,pseudocode:this.pseudocodeBox.checked||void 0})),e("[data-action=hide-editor]").addEventListener("click",()=>this.setEditorHidden(!0)),e("[data-action=swap-main]").addEventListener("click",()=>this.setCodeMain(!this.codeMain)),this.labelSwap(),this.sim=new RB(()=>this.doc,C=>{this.simPath=C,this.simulating&&this.renderDiagramOnly(),this.scrollToSimPath()},C=>this.findSubprogram(C),()=>this.setSimulating(!1),C=>{this.simulating&&this.liveCoding&&this.live.showTranscript(C)}),this.root.append(this.sim.element),Hn()?(this.visuBot??(this.visuBot=new TM),this.sim.setRobot(this.visuBot)):(this.preview.hostSimulation(void 0),(he=this.visuBot)==null||he.dispose(),this.visuBot=void 0),this.simButton.addEventListener("click",()=>this.setSimulating(!this.simulating)),this.codeButton=e("[data-action=code]"),this.code=new Mb(()=>this.doc,(C,N)=>this.offerDownload(C,new Blob([N],{type:"text/plain"})),()=>this.setCoding(!1),C=>this.commit({...this.doc,pseudocode:C||void 0}),()=>this.tabs.filter(C=>C!==this.tab&&zt(C.doc.caption)).map(C=>C.doc)),this.root.append(this.code.element),this.codeButton.addEventListener("click",()=>this.setCoding(!this.coding)),(Ie=this.paletteObserver)==null||Ie.disconnect();const t=()=>Number(nt(Ad))||0,n=()=>this.root.classList.toggle("compact-palette",nt(oo)==="1"||(t()>0?t()<150:this.root.getBoundingClientRect().widthnt(Bd)==="1",s=(C,N)=>{const q=C===void 0?void 0:Math.round(Math.max(80,Math.min(360,C)));a()?this.root.style.setProperty("--palette-width","36px"):q===void 0?this.root.style.removeProperty("--palette-width"):this.root.style.setProperty("--palette-width",`${q}px`),N&&Ve(Ad,q===void 0?"":String(q)),n()},r=C=>{Ve(Bd,C?"1":"0"),this.root.classList.toggle("palette-hidden",C),s(t()>0?t():void 0,!1)};r(a()),this.setPaletteHidden=r,e("[data-action=hide-palette]").addEventListener("click",()=>r(!0)),e("[data-action=show-palette]").addEventListener("click",()=>r(!1));const o=e(".palette-resizer"),l=e(".palette"),u=()=>getComputedStyle(this.shell).direction==="rtl"?-1:1;o.addEventListener("pointerdown",C=>{if(C.button!==0)return;C.preventDefault(),o.setPointerCapture(C.pointerId);const N=C.clientX,q=l.getBoundingClientRect().width,Y=u();this.shell.classList.add("resizing");const ue=ce=>s(q+Y*(ce.clientX-N),!1),X=ce=>{o.removeEventListener("pointermove",ue),o.removeEventListener("pointerup",X),o.removeEventListener("pointercancel",X),this.shell.classList.remove("resizing");const le=q+Y*(ce.clientX-N);le<50?r(!0):s(le,!0)};o.addEventListener("pointermove",ue),o.addEventListener("pointerup",X),o.addEventListener("pointercancel",X)}),o.addEventListener("dblclick",()=>s(void 0,!0)),o.addEventListener("keydown",C=>{const N=C.key==="ArrowRight"?20:C.key==="ArrowLeft"?-20:0;N&&(C.preventDefault(),s(l.getBoundingClientRect().width+u()*N,!0))}),this.paletteObserver=new ResizeObserver(n),this.paletteObserver.observe(this.root);const c=e("[data-action=compact-palette]");c.checked=nt(oo)==="1",c.addEventListener("change",()=>{Ve(oo,c.checked?"1":"0"),n()});const m=(C,N,q,Y,ue)=>{const X=document.createElement("li");X.className="palette-item",X.dataset.item=ue,X.dataset.scope=Ud(Y().type)??"method",X.append(this.paletteIcon(N),document.createTextNode(q)),X.addEventListener("pointerdown",ce=>this.beginDrag(ce,{kind:"palette",make:Y,label:q})),X.tabIndex=0,X.addEventListener("keydown",ce=>{(ce.key==="Enter"||ce.key===" ")&&this.insertNearSelection(Y())}),C.append(X)},d=e(".palette-basic");for(const{item:C}of N2)m(d,C,so(nu(C).type),()=>nu(C),C);const h=Hn();this.root.classList.toggle("visubot-mode",h),this.shell.classList.toggle("robot-world",h),h||this.preview.pause(),document.documentElement.classList.toggle("visubot-theme",h);const g=e(".palette-visubot");if(g.hidden=!h,e(".palette-visubot-title").hidden=!h,h){const C={[S.verzweigung]:"verzweigung",[S.whileSchleife]:"whileSchleife"},N=new Set((nt(Od)??"").split(",").filter(Boolean)),q=(X,ce)=>{const le=document.createElement("li");le.className="palette-group";const Te=document.createElement("button");Te.type="button",Te.textContent=p(`web_visubot_group_${ce}`);const Fe=Fn=>{Te.setAttribute("aria-expanded",String(Fn));for(const mr of X.querySelectorAll(`[data-group="${ce}"]`))mr.hidden=!Fn};return Te.addEventListener("click",()=>{const Fn=Te.getAttribute("aria-expanded")!=="true";Fn?N.delete(ce):N.add(ce),Ve(Od,[...N].join(",")),Fe(Fn)}),le.append(Te),X.append(le),()=>Fe(!N.has(ce))},Y=(X,ce,le)=>{for(const Te of new Set(ce.map(Fe=>Fe.group))){const Fe=q(X,Te);for(const Fn of ce.filter(mr=>mr.group===Te))le(Fn).dataset.group=Te;Fe()}};Y(g,CM,X=>(m(g,C[X.type]??"anweisung",p(X.key),X.make,X.key),g.lastElementChild));const ue=e(".palette-visubot-sensors");ue.replaceChildren(),Y(ue,vg,X=>{const ce=p(X.key),le=document.createElement("li");le.className="palette-item palette-sensor",le.dataset.item=X.key,le.title=X.text;const Te=document.createElement("code");return Te.textContent=X.text,le.append(document.createTextNode(ce),Te),le.addEventListener("pointerdown",Fe=>this.beginDrag(Fe,{kind:"sensor",text:X.text,label:X.text})),le.tabIndex=0,le.addEventListener("keydown",Fe=>{(Fe.key==="Enter"||Fe.key===" ")&&this.insertSensor(X.text)}),ue.append(le),le})}e(".palette-visubot-sensors").hidden=!h,e(".palette-visubot-sensors-title").hidden=!h,this.tabStrip=e(".tabs"),this.exportButton=e("[data-action=export]");const f=e(".export-menu");this.exportButton.setAttribute("aria-haspopup","menu"),this.exportButton.addEventListener("click",()=>{var C;f.hidden=!f.hidden,f.hidden||(C=f.querySelector("button"))==null||C.focus()}),f.addEventListener("click",C=>{var q;const N=(q=C.target.closest("[data-export]"))==null?void 0:q.dataset.export;N&&(f.hidden=!0,this.exportDiagram(N))}),f.addEventListener("keydown",C=>{C.key==="Escape"&&(f.hidden=!0,this.exportButton.focus())}),this.closeExport&&document.removeEventListener("pointerdown",this.closeExport),this.closeExport=C=>{!f.hidden&&!f.parentElement.contains(C.target)&&(f.hidden=!0)},document.addEventListener("pointerdown",this.closeExport);const b=e("[data-action=language]");b.value=s1(),b.addEventListener("change",()=>void this.changeLanguage(()=>ah(b.value),"language"));const x=[e("[data-action=mbot-link]"),e("[data-action=mbot-link-settings]")],v=e(".settings-mbot-link small"),w=()=>{const C=ge.connected,N=ge.connecting?p("web_visubot_connecting"):p(C?"web_visubot_disconnect":"web_visubot_connect");x[0].hidden=!Hn()||!br(),I.hidden=x[0].hidden,x[0].classList.toggle("connected",C);const q=ge.connecting?"⏳":C?"🟢":"🔌";x[0].textContent=`${q} mBot2`,x[0].title=N,x[1].textContent=`${q} ${N}`,x[1].disabled=!br(),x[1].parentElement.hidden=!Hn(),v.textContent=br()?xg():p("web_visubot_no_serial")};for(const C of x)C.addEventListener("click",()=>void OM());const I=e("[data-action=mbot-upload]");I.addEventListener("click",()=>oR(this.doc,this.tabs.filter(C=>C!==this.tab).map(C=>C.doc))),(fe=this.stopLinkListener)==null||fe.call(this),this.stopLinkListener=ge.listen(w),w();for(const C of this.topbar.querySelectorAll("[data-action=visubot] [data-world]"))C.addEventListener("click",()=>void this.chooseWorld(C.dataset.world,!0));const z=e("[data-action=keywords]");z.checked=X2(),z.addEventListener("change",()=>void this.changeLanguage(()=>ih(z.checked),"keywords"));const k=e("[data-action=code-scopes]");k.checked=Xf(),k.addEventListener("change",()=>uJ(k.checked));const T=e("[data-action=live-language]");T.value=this.live.language;const A=e("[data-action=java-class]"),D=e("[data-action=java-main]"),P=e("[data-action=java-swing]");P.checked=this.live.swingSupport,P.addEventListener("change",()=>this.live.setSwingSupport(P.checked));const j=()=>{A.checked=this.live.javaForm.asClass,D.checked=this.live.javaForm.withMain,e(".settings-menu .java-only").hidden=this.live.language!=="java"};j(),T.addEventListener("change",()=>{this.live.setTarget(T.value),j()});for(const C of[A,D])C.addEventListener("change",()=>this.live.setJavaForm({asClass:A.checked,withMain:D.checked}));const O=e("[data-action=zoom]");O.value=String(this.zoom),O.addEventListener("change",()=>{this.zoom=Number(O.value),Ve(vd,O.value),this.renderDiagramOnly()});const Z=e("[data-action=code-size]"),W=Number(nt(yd));Z.value=String(ro.some(C=>C.value===W)?W:ro[0].value),xd(Number(Z.value)),Z.addEventListener("change",()=>{Ve(yd,Z.value),xd(Number(Z.value))}),this.setupSettingsMenu(e("[data-action=settings]"),e(".settings-menu")),e("[data-action=about]").addEventListener("click",()=>{e(".settings-menu").hidden=!0,this.showAbout()}),e("[data-action=cut]").addEventListener("click",()=>this.cutSelection()),e("[data-action=copy]").addEventListener("click",()=>this.copySelection()),e("[data-action=paste]").addEventListener("click",()=>this.paste());const U=e("input[type=file]");U.addEventListener("change",async()=>{var N;const C=(N=U.files)==null?void 0:N[0];U.value="",C&&this.loadXML(await C.text(),C.name)}),e("[data-action=new]").addEventListener("click",()=>this.addTab()),e("[data-action=open]").addEventListener("click",()=>this.open(U)),e("[data-action=save]").addEventListener("click",()=>this.save()),this.undoButton.addEventListener("click",()=>this.undo()),this.redoButton.addEventListener("click",()=>this.redo()),this.deleteButton.addEventListener("click",()=>this.deleteSelection());let ee;this.captionInput.addEventListener("focus",()=>ee=this.doc),this.captionInput.addEventListener("input",()=>{this.doc={...this.doc,caption:this.captionInput.value},this.dirty=!0,this.updateStatus(),this.refreshLive()}),this.captionInput.addEventListener("change",()=>{ee&&ee.caption!==this.doc.caption&&this.pushUndo(ee),ee=this.doc}),this.canvasHost.addEventListener("pointerdown",C=>this.onCanvasPointerDown(C)),(J=this.resizeObserver)==null||J.disconnect(),this.resizeObserver=new ResizeObserver(()=>{const{clientWidth:C,clientHeight:N}=this.canvasHost;C===this.renderedHostSize.width&&N===this.renderedHostSize.height||this.renderDiagramOnly()}),this.resizeObserver.observe(this.canvasHost)}showWorldInURL(){const e=new URLSearchParams(location.search);for(const a of["learn","visubot","visustruct","visuobject","visuflow"])e.delete(a);const t=e.toString(),n=ui()==="on"?"visubot":"visustruct";history.replaceState(history.state,"",`${location.pathname}?${n}${t?`&${t}`:""}${location.hash}`)}async chooseWorld(e,t){if(e==="object"){gg(),location.href=`${location.pathname}?visuobject${location.hash}`;return}if(e==="flow"){fg(),location.href=`${location.pathname}?visuflow${location.hash}`;return}e===ui()&&kM()||await this.changeLanguage(async()=>{Sr(e),Hu(e),this.showWorldInURL()},t?`visubot] [data-world=${e}`:void 0)}async changeLanguage(e,t){var n,a;this.setSimulating(!1),this.setCoding(!1),await e(),u2(),this.sim.end(),this.live.build(),this.preview.relabel(),this.placePreview(),this.files.build(),this.buildUI(),this.render(),this.learn.render(),this.labelLearnRail(),this.labelLiveRail(),this.labelEditorRail(),this.labelFilesRail(),t!==void 0&&((n=this.topbar.querySelector("[data-action=settings]"))==null||n.click(),(a=this.topbar.querySelector(`[data-action=${t}]`))==null||a.focus())}revealAreas(e){var n;const t=[];for(const a of e)a==="editor"&&this.editorHidden?(this.setEditorHidden(!1),t.push(()=>this.setEditorHidden(!0))):a==="palette"&&this.root.classList.contains("palette-hidden")?((n=this.setPaletteHidden)==null||n.call(this,!1),t.push(()=>{var s;return(s=this.setPaletteHidden)==null?void 0:s.call(this,!0)})):a==="livecode"&&!this.liveCoding?(this.setLiveCoding(!0),t.push(()=>this.setLiveCoding(!1))):a==="files"&&!this.shell.classList.contains("files-open")&&(this.setFilesOpen(!0),t.push(()=>this.setFilesOpen(!1)));return()=>t.reverse().forEach(a=>a())}setFilesOpen(e){this.shell.classList.toggle("files-open",e),Ve(zd,e?"1":"0"),this.keepAColumnOpen(),this.canvasHost&&this.renderDiagramOnly()}filesRail(){return this.filesRailButton=me("button",{class:"learn-rail files-rail"}),this.labelFilesRail(),this.filesRailButton.addEventListener("click",()=>this.setFilesOpen(!0)),this.filesRailButton}labelFilesRail(){this.filesRailButton&&(this.filesRailButton.title=p("web_files_show"),this.filesRailButton.innerHTML=`${_t}📁 ${E(p("web_files_title"))}`)}openFromWorkspace(e,t,n){const a=this.tabs.find(s=>{var r;return((r=s.workspace)==null?void 0:r.dir)===t.dir&&s.workspace.base===t.base});if(a){this.tabIndex=this.tabs.indexOf(a),this.render();return}e?this.loadXML(e,`${t.base}.visustruct`):n!==void 0&&((this.dirty||this.tab.fileName||this.tab.exerciseId)&&this.addTab(),this.doc=this.live.documentFromJavaText(n),this.tab.fileName=`${t.base}.visustruct`,this.resetHistory()),this.tab.workspace=t,this.tab.fileHandle=void 0,n!==void 0&&(this.live.adoptJava(this.doc,n),this.setLiveCoding(!0)),this.render()}async saveToWorkspace(){if(!this.files.ready||this.tab.fileHandle&&!this.tab.workspace)return!1;const e=this.doc.caption.trim()||un(this.tab),t=this.live.language==="java"?this.live.javaFor(this.doc,this.tab):void 0;try{const n=await this.files.save(e,u1(this.doc),t,this.tab.workspace);if(!n)return this.setFilesOpen(!0),!0;this.tab.workspace=n,this.tab.fileName=`${n.base}.visustruct`,this.dirty=!1,this.render(),this.showMessage(p("web_files_saved_fmt",n.path))}catch(n){this.showMessage(n.message)}return!0}setLearning(e,t=!0){this.shell.classList.toggle("learning",e),t&&Ve(wd,e?"1":"0"),this.keepAColumnOpen(),this.canvasHost&&this.renderDiagramOnly()}setEditorHidden(e){this.editorHidden=e,this.shell.classList.toggle("editor-hidden",e),Ve(Dd,e?"1":"0"),e&&!this.liveCoding&&!this.shell.classList.contains("learning")&&this.setLiveCoding(!0),!e&&this.canvasHost&&this.render()}keepAColumnOpen(){this.editorHidden&&!this.liveCoding&&!this.shell.classList.contains("learning")&&!this.shell.classList.contains("files-open")&&this.setEditorHidden(!1)}editorRail(){return this.editorRailButton=me("button",{class:"learn-rail editor-rail"}),this.labelEditorRail(),this.editorRailButton.addEventListener("click",()=>this.setEditorHidden(!1)),this.editorRailButton}labelEditorRail(){this.editorRailButton&&(this.editorRailButton.title=p("web_editor_show"),this.editorRailButton.innerHTML=`${_t}✎ ${E(p("web_editor_title"))}`)}showAbout(){const e=(n,a,s)=>``,t=me("dialog",{class:"about","aria-labelledby":"about-title"});t.innerHTML=` +
+

${E(p("about_nav_title"))}

+ +
+
+
+ +
+

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

+

${E(p("web_about_version_fmt").replace("%@","0.14.1"))}

+

Holger Sebastiao

+ ${e("about_web_label","https://www.visustruct.org","www.visustruct.org")} + ${e("about_developer_label","https://www.sebastiao.org","www.sebastiao.org")} + ${e("about_project_github_label","https://github.com/code4teaching/VisuStruct","code4teaching/VisuStruct")} +
+
+

${E(p("about_dateiformat_heading"))}

+

${E(p("about_dateiformat_part1"))}.visustruct${E(p("about_dateiformat_part2"))}

+

${E(p("about_dateiformat_strk"))}

+

${E(p("web_about_software"))}

+

${E(p("web_about_software_text"))} ${E(p("web_about_licenses"))}

+

${E(p("about_copyright"))}

+
`,t.querySelector("[data-action=about-done]").addEventListener("click",()=>t.close()),t.addEventListener("click",n=>n.target===t&&t.close()),t.addEventListener("close",()=>t.remove()),document.body.append(t),t.showModal()}setupSettingsMenu(e,t){const n=a=>{t.hidden=!a,e.setAttribute("aria-expanded",String(a))};e.addEventListener("click",()=>n(t.hidden)),this.closeSettings&&document.removeEventListener("pointerdown",this.closeSettings),this.escapeSettings&&document.removeEventListener("keydown",this.escapeSettings),this.closeSettings=a=>{!t.hidden&&!e.parentElement.contains(a.target)&&n(!1)},document.addEventListener("pointerdown",this.closeSettings),this.escapeSettings=a=>{a.key!=="Escape"||t.hidden||(n(!1),e.focus())},document.addEventListener("keydown",this.escapeSettings)}learnRail(){return this.railButton=me("button",{class:"learn-rail"}),this.labelLearnRail(),this.railButton.addEventListener("click",()=>this.setLearning(!0)),this.railButton}liveRail(){return this.liveRailButton=me("button",{class:"learn-rail live-rail"}),this.labelLiveRail(),this.liveRailButton.addEventListener("click",()=>this.setLiveCoding(!0)),this.liveRailButton}labelLiveRail(){this.liveRailButton&&(this.liveRailButton.title=p("web_live_show"),this.liveRailButton.innerHTML=`${_t}</> ${E(p("web_live_title"))}`)}labelLearnRail(){this.railButton&&(this.railButton.title=p("web_learn_show"),this.railButton.innerHTML=`${_t}🎓 ${E(p("web_learn_title"))}`)}learnHost(){return{collapse:()=>this.setLearning(!1),showEditor:()=>{this.editorHidden&&this.setEditorHidden(!1)},showLiveCode:()=>{this.liveCoding||this.setLiveCoding(!0)},showJava:()=>this.openJavaColumn(),showFiles:()=>{this.shell.classList.contains("files-open")||this.setFilesOpen(!0)},reveal:e=>this.revealAreas(e),openExercise:(e,t)=>{const n=$h(e);n!=="code"&&this.setEditorHidden(!1),n!=="struktogramm"&&this.openJavaColumn();const a=this.tabs.findIndex(r=>r.exerciseId===e.id);if(a>=0){this.switchTab(a),this.setSimulating(!1);return}const s=this.makeTab();s.doc=t,s.exerciseId=e.id,s.selected=t.elements.length>0?[0]:void 0,this.isPristine(this.tab)?this.tabs[this.tabIndex]=s:this.tabs.push(s),this.tabIndex=this.tabs.indexOf(s),this.setSimulating(!1),this.render()},openJavaCode:e=>{this.openJavaColumn();const t=this.makeTab();t.doc=this.live.documentFromJavaText(e),this.isPristine(this.tab)?this.tabs[this.tabIndex]=t:this.tabs.push(t),this.tabIndex=this.tabs.indexOf(t),this.setSimulating(!1),this.live.adoptJava(t.doc,e),this.render()},openDiagram:(e,t)=>{this.setEditorHidden(!1),this.loadXML(u1(e),e.caption.trim()?`${e.caption.trim()}.visustruct`:t)},exerciseDocument:e=>{const t=this.tabs.find(a=>a.exerciseId===e);if(t)return t.doc;const n=this.tab;if(!(n.exerciseId||this.isPristine(n)))return n.exerciseId=e,be.updateExercise(e,{xml:u1(n.doc)}),n.doc},subprogramsFor:e=>{const t=this.tabs.find(n=>n.exerciseId===e);return n=>this.findSubprogram(n,t)},stopSimulation:()=>this.setSimulating(!1),resetExercise:(e,t)=>{const n=this.tabs.find(a=>a.exerciseId===e);n&&(n.undoStack.push(n.doc),n.doc=t,n.redoStack=[],n.selected=[0],n===this.tab&&this.render())},preview:e=>{const t=ud(e,this.metrics,this.measure,0);if(!t)return;const n=t.svg.getAttribute("width");return n&&(t.svg.style.maxWidth=`${n}px`),t.svg.removeAttribute("width"),t.svg.removeAttribute("height"),t.svg}}}isPristine(e){return!e.dirty&&!e.fileName&&!e.exerciseId&&e.undoStack.length===0}rememberExercise(){const e=this.tab;e.exerciseId&&(clearTimeout(this.exerciseSaveTimer),this.exerciseSaveTimer=window.setTimeout(()=>{e.exerciseId&&be.updateExercise(e.exerciseId,{xml:u1(e.doc)})},300))}paletteIcon(e){const t=Se("svg",{viewBox:"0 0 28 20",width:28,height:20,class:"icon"}),n={fill:"none",stroke:"currentColor","stroke-width":1.5};t.append(Se("rect",{x:1,y:1,width:26,height:18,...n}));const a=s=>t.append(Se("path",{d:s,...n}));switch(e){case"verzweigung":a("M1 1 L14 10 L27 1 M14 10 V19");break;case"fallauswahl":a("M1 1 L20 10 L27 1 M1 10 H27 M10 10 V19 M20 10 V19");break;case"forZaehlSchleife":case"whileSchleife":a("M7 7 H27 M7 7 V19");break;case"doUntilSchleife":a("M7 1 V13 H27");break;case"endlosschleife":a("M7 6 H27 M7 6 V14 H27");break;case"aufruf":a("M5 1 V19 M23 1 V19");break;case"aussprung":a("M6 1 L1 10 L6 19");break}return t}render(){const e={...this.doc,elements:this.doc.elements.map(Xa)};this.layout=this.engine.layout(e),this.flat=H2(this.layout.elements),this.selected&&!Jt(this.doc,this.selected)&&(this.selected=void 0);const t=this.zoom,n=this.canvasHost;this.renderedHostSize={width:n.clientWidth,height:n.clientHeight};const a={width:Math.max(320,this.layout.canvasSize.width,Math.floor(n.clientWidth/t)),height:Math.max(240,this.layout.canvasSize.height+60,Math.floor(n.clientHeight/t))};this.pseudocodeBox.checked=!!this.doc.pseudocode,this.renderer.usesSimulationHighlight=this.simulating,this.renderer.fillsSelection=this.liveCoding,this.svg=this.renderer.render(this.layout,a,this.simulating?this.simPath:this.selected),this.svg.setAttribute("width",String(Math.floor(a.width*t))),this.svg.setAttribute("height",String(Math.floor(a.height*t))),this.overlay=Se("g",{class:"drop-overlay"}),this.svg.append(this.overlay),this.canvasHost.replaceChildren(this.svg),document.activeElement!==this.captionInput&&(this.captionInput.value=this.doc.caption),this.undoButton.disabled=this.simulating||this.undoStack.length===0,this.redoButton.disabled=this.simulating||this.redoStack.length===0,this.deleteButton.disabled=this.simulating||!this.selected||!dr(this.doc,this.selected),this.captionInput.readOnly=this.simulating,this.codeButton.disabled=this.simulating,this.exportButton.disabled=this.simulating,this.coding&&this.code.refresh(),this.refreshLive(),this.refreshPreview(),this.renderTabs(),this.renderInspector(),this.updateStatus()}refreshLive(){this.liveCoding&&this.live.refresh(this.doc,this.simulating?this.simPath:this.selected,{owner:this.tab,subprograms:new Set(this.tabs.filter(e=>e!==this.tab).flatMap(e=>{var t;return((t=zt(e.doc.caption))==null?void 0:t.name)??[]})),editable:!this.simulating,resolve:e=>this.findSubprogram(e)})}updateStatus(){this.rememberExercise(),document.title=`${this.dirty?"• ":""}${this.fileName} – VisuStruct Web`,this.statusLine.textContent=`${this.fileName}${this.dirty?` (${p("web_status_modified")})`:""}`}renderInspector(){const e=this.selected,t=e?Jt(this.doc,e):void 0,n=this.inspector;if(!e||!t){n.replaceChildren(me("h2",{},p("web_inspector_title")),me("p",{class:"hint"},p("inspector_no_selection")),me("p",{class:"hint"},p("web_inspector_help_drop")),me("p",{class:"hint"},p("web_inspector_help_files")));return}if(n.replaceChildren(me("h2",{},`${p("web_inspector_title")} · ${so(t.type)}`)),t.type===S.anweisung){const a=$a(t.textLines.join(` +`)),s=me("div",{class:"segmented",role:"group","aria-label":p("inspector_io_mode_title")});for(const[r,o]of[["statement",p("inspector_io_mode_statement")],["input",p("inspector_io_mode_input")],["output",p("inspector_io_mode_output")]]){const l=me("button",{"aria-pressed":String(r===a)},o);l.addEventListener("click",()=>{var m,d;const u=((m=Jt(this.doc,e))==null?void 0:m.textLines.join(` +`))??"";if(r===$a(u))return;const c=j2(r,u);this.commit(N1(this.doc,e,c.split(` +`))),(d=this.inspector.querySelector("textarea"))==null||d.focus()}),s.append(l)}n.append(s,me("p",{class:"hint mono-hint"},uR[a]))}if(t.type===S.forSchleife){const a=me("div",{class:"for-fields"}),s=K0(t.textLines);[[p("inspector_for_init"),p("inspector_for_placeholder_init")],[p("inspector_for_condition"),p("inspector_for_placeholder_condition")],[p("inspector_for_step"),p("inspector_for_placeholder_step")]].forEach(([o,l],u)=>{const c=me("input",{placeholder:l,spellcheck:"false",autocomplete:"off"});c.value=s[u],this.liveEdit(c,m=>{const d=Jt(this.doc,e);if(!d)return;const h=K0(d.textLines);return h[u]=B2(m),N1(this.doc,e,h)}),a.append(me("label",{},o,c))}),n.append(a)}else if(t.type!==S.leerElement){const a=lR[t.type];a&&n.append(me("p",{class:"hint mono-hint"},a));const s=fd(t),r=me("textarea",{rows:"3",spellcheck:"false"}),o=t.textLines.join(` +`),l=t.type===S.anweisung,u=s?X0(s,o):o;r.value=l&&u.trim()==="ø"?"":u,r.placeholder=cR(t),this.liveEdit(r,m=>{const d=fd(Jt(this.doc,e)??t);if(l&&!d&&m.trim()==="")return N1(this.doc,e,["ø"]);const h=d?D2(d,X0(d,m)):m;return N1(this.doc,e,h.split(` +`))});const c=me("div",{class:"editor-row"});s&&c.append(me("span",{class:"fixed-prefix"},s)),c.append(r),n.append(c)}this.renderCaseControls(e)}renderCaseControls(e){var l;const t=A2(e,this.doc);if(!t)return;const n=((l=Jt(this.doc,t))==null?void 0:l.cases)??[],a=O2(e,t),s=me("div",{class:"case-controls"});if(a!==void 0&&n[a]){const u=me("input",{placeholder:p("web_case_name_placeholder"),spellcheck:"false",autocomplete:"off"});u.value=n[a].name,this.liveEdit(u,c=>c.trim()===""?void 0:_2(this.doc,t,a,c)),s.append(me("label",{},p("web_case_name"),u))}const r=me("button",{},`+ ${p("inspector_add_case")}`);r.addEventListener("click",()=>{const u=S2(this.doc,t);this.commit(u.doc,u.path)});const o=me("button",{class:"danger-text"},`- ${p("inspector_remove_case")}`);o.disabled=n.length<=2||a===void 0,o.addEventListener("click",()=>{if(a===void 0)return;const u=T2(this.doc,t,a);this.commit(u.doc,u.path)}),s.append(me("div",{class:"group"},r,o)),this.inspector.append(s)}liveEdit(e,t){let n;e.addEventListener("focus",()=>n=this.doc),e.addEventListener("input",()=>{const a=Fd(e.value);if(a!==e.value){const r=e.selectionStart;e.value=a,e.setSelectionRange(r,r)}const s=t(a);s&&(this.doc=s,this.dirty=!0,this.renderDiagramOnly())}),e.addEventListener("blur",()=>{n&&n!==this.doc&&this.pushUndo(n),n=void 0,this.renderDiagramOnly()})}renderDiagramOnly(){const e=this.selected,t=this.inspector,n=document.createElement("aside");this.inspector=n,this.render(),this.inspector=t,this.selected=e}setSimulating(e){var t;e!==this.simulating&&(document.activeElement instanceof HTMLElement&&document.activeElement.blur(),this.endDrag(),this.simulating=e,this.root.classList.toggle("simulating",e),this.simButton.setAttribute("aria-pressed",String(e)),this.simButton.innerHTML=`${e?se.stop:se.play}${E(p(e?"web_simulation_end":"web_simulation_start"))}`,this.simButton.dataset.tip=p(e?"web_simulation_end_title":"web_simulation_start_title"),this.simButton.setAttribute("aria-label",p(e?"web_simulation_end":"web_simulation_start")),e?(this.setCoding(!1),this.setEditorHidden(!1),(t=this.visuBot)==null||t.setWorlds(Md(this.tab.exerciseId)),this.visuBot&&!this.previewOpen&&(this.setPreviewOpen(!0),this.previewOpenedForSim=!0),this.placeSimulationRobot(),this.sim.begin()):(this.sim.end(),this.placeSimulationRobot(),this.previewOpenedForSim&&this.setPreviewOpen(!1),this.simPath=void 0,!this.selected&&this.doc.elements.length>0&&(this.selected=[0])),this.render())}runRobot(e){return!this.visuBot||!/\bmbot\s*\./u.test(JSON.stringify(this.tabs.map(t=>t.doc)))?!1:(this.simulating?this.sim.reset():this.setSimulating(!0),e?this.sim.step():this.sim.play(),!0)}setCoding(e){e!==this.coding&&(e&&(this.setLiveCoding(!1),this.setEditorHidden(!1)),this.coding=e,this.root.classList.toggle("coding",e),this.codeButton.setAttribute("aria-pressed",String(e)),e?this.code.refresh():this.code.close(),this.renderDiagramOnly())}openJavaColumn(){if(this.live.language!=="java"){const e="[data-action=live-language]",t=this.topbar.querySelector(e)??this.root.querySelector(e);t?(t.value="java",t.dispatchEvent(new Event("change"))):this.live.setTarget("java")}this.liveCoding||this.setLiveCoding(!0)}setCodeMain(e){this.codeMain=e,Ve(_d,e?"1":"0"),e&&!this.liveCoding&&this.setLiveCoding(!0),e&&this.editorHidden&&this.setEditorHidden(!1),this.shell.classList.toggle("code-main",e),this.labelSwap(),this.canvasHost&&this.render()}labelSwap(){const e=p(this.codeMain?"web_swap_to_editor":"web_swap_to_code");for(const t of this.shell.querySelectorAll("[data-action=swap-main]"))t.dataset.tip=e,t.setAttribute("aria-label",e),t.setAttribute("aria-pressed",String(this.codeMain))}setupPreview(){const e=o=>{this.previewOpenedForSim=!1,this.setPreviewOpen(o)};this.preview.onHide=()=>e(!1),this.preview.rail.addEventListener("click",()=>e(!0)),this.preview.onToggleStacked=()=>{this.previewStacked=!this.previewStacked,Ve(Cd,this.previewStacked?"1":"0"),this.previewStacked&&!this.liveCoding&&this.setLiveCoding(!0),this.placePreview()},this.previewStacked=nt(Cd)==="1";const t=nt(Td);this.previewOpen=t===null||t==="1";const n=this.preview.heightBar,a=this.preview.element,s=(o,l)=>{var m;const u=Math.max(160,(((m=a.parentElement)==null?void 0:m.getBoundingClientRect().height)??600)-120),c=o===void 0?void 0:Math.round(Math.max(160,Math.min(o,u)));a.style.height=c===void 0?"":`${c}px`,l&&Ve(Pd,c===void 0?"":String(c))},r=Number(nt(Pd));r>0&&(a.style.height=`${r}px`),n.addEventListener("pointerdown",o=>{if(o.button!==0)return;o.preventDefault(),n.setPointerCapture(o.pointerId);const l=o.clientY,u=a.getBoundingClientRect().height;this.shell.classList.add("resizing");const c=d=>s(u-(d.clientY-l),!1),m=d=>{n.removeEventListener("pointermove",c),n.removeEventListener("pointerup",m),n.removeEventListener("pointercancel",m),this.shell.classList.remove("resizing"),s(u-(d.clientY-l),!0)};n.addEventListener("pointermove",c),n.addEventListener("pointerup",m),n.addEventListener("pointercancel",m)}),n.addEventListener("dblclick",()=>s(void 0,!0)),n.addEventListener("keydown",o=>{const l=o.key==="ArrowUp"?20:o.key==="ArrowDown"?-20:0;l&&(o.preventDefault(),s(a.getBoundingClientRect().height+l,!0))}),this.placePreview()}setPreviewOpen(e){this.previewOpen=e,Ve(Td,e?"1":"0"),e||this.preview.pause(),this.placePreview(),this.placeSimulationRobot(),this.canvasHost&&this.render()}placeSimulationRobot(){const e=this.visuBot,t=!!e&&this.simulating&&this.previewOpen;this.preview.hostSimulation(t?e.viewport:void 0),t||e==null||e.restoreViewport()}placePreview(){const e=this.previewStacked&&this.liveCoding;this.preview.setStacked(this.previewStacked),this.shell.classList.toggle("preview",this.previewOpen),this.shell.classList.toggle("preview-stacked",e),e?this.preview.element.parentElement!==this.live.element&&this.live.element.append(this.preview.element):this.preview.element.previousElementSibling!==this.previewResizer&&this.previewResizer.after(this.preview.element)}refreshPreview(){!this.previewOpen||!Hn()||this.preview.update(this.doc,e=>this.findSubprogram(e),Md(this.tab.exerciseId),this.tab.exerciseId??"",this.tabs.map(e=>e.doc))}setLiveCoding(e){e&&this.coding&&this.setCoding(!1),this.liveCoding=e,this.shell.classList.toggle("live",e),this.placePreview(),e||this.live.hideConsole(),Ve(Sd,e?"1":"0"),this.keepAColumnOpen(),this.canvasHost&&this.render()}learnResizer(){return this.panelResizer(this.learn.element,"learn-resizer",kd,p("web_learn_resize"),1)}liveResizer(){return this.panelResizer(this.live.element,"live-resizer",hR,p("web_live_resize"),-1,()=>this.root)}yieldingPanels(){return[{panel:this.preview.element,key:jd},{panel:this.learn.element,key:kd},{panel:this.files.element,key:Id}].filter(({panel:e})=>e.offsetParent!==null&&e.parentElement===this.live.element.parentElement)}panelResizer(e,t,n,a,s,r){const o=me("div",{class:t,role:"separator","aria-orientation":"vertical",tabindex:"0",title:a}),l=d=>{var b;const h=((b=e.parentElement)==null?void 0:b.getBoundingClientRect().width)??0;if(h===0)return xR(d);const g=[this.files.element,this.learn.element,this.live.element,this.preview.element].filter(x=>x!==e&&x.offsetParent!==null&&getComputedStyle(x).flexGrow==="0").reduce((x,v)=>x+v.getBoundingClientRect().width,0),f=parseFloat(getComputedStyle(e).minWidth)||200;return Math.round(Math.max(f,Math.min(d,h-g-240)))},u=(d,h)=>{e.style.width=d===void 0?"":`${l(d)}px`,h&&Ve(n,d===void 0?"":String(l(d)))},c=Number(nt(n));c>0&&u(c,!1);const m=()=>{const d=typeof s=="function"?s():s;return getComputedStyle(this.shell).direction==="rtl"?-d:d};return o.addEventListener("pointerdown",d=>{if(d.button!==0)return;d.preventDefault(),o.setPointerCapture(d.pointerId);const h=d.clientX,g=e.getBoundingClientRect().width,f=m();this.shell.classList.add("resizing");const b=r?this.pushResize(e,n,r(),g):void 0,x=(I,z)=>(b??u)(g+f*(I.clientX-h),z),v=I=>x(I,!1),w=I=>{o.removeEventListener("pointermove",v),o.removeEventListener("pointerup",w),o.removeEventListener("pointercancel",w),this.shell.classList.remove("resizing"),x(I,!0)};o.addEventListener("pointermove",v),o.addEventListener("pointerup",w),o.addEventListener("pointercancel",w)}),o.addEventListener("dblclick",()=>u(void 0,!0)),o.addEventListener("keydown",d=>{const h=d.key==="ArrowRight"?20:d.key==="ArrowLeft"?-20:0;h&&(d.preventDefault(),u(e.getBoundingClientRect().width+m()*h,!0))}),o}pushResize(e,t,n,a){const s=(c,m)=>Math.max(parseFloat(getComputedStyle(c).minWidth)||0,m),r=s(e,200),o=Math.max(0,n.getBoundingClientRect().width-s(n,240)),l=this.yieldingPanels().map(c=>({...c,start:c.panel.getBoundingClientRect().width,min:s(c.panel,200),changed:!1})),u=l.reduce((c,m)=>c+Math.max(0,m.start-m.min),0);return(c,m)=>{const d=Math.round(Math.max(r,Math.min(c,a+o+u)));let h=Math.max(0,d-a-o,r-c);for(const g of l){const f=Math.min(h,Math.max(0,g.start-g.min));h-=f,g.changed||(g.changed=f>0),g.changed&&(g.panel.style.width=`${Math.round(g.start-f)}px`,m&&Ve(g.key,String(Math.round(g.start-f))))}e.style.width=`${d}px`,m&&Ve(t,String(d))}}findSubprogram(e,t=this.tab){const n=lo(e);if(n==="")return;const a=this.tabs.find(s=>s!==t&&(lo(s.doc.caption)===n||lo(un(s))===n));return a==null?void 0:a.doc}scrollToSimPath(){const e=this.simPath;if(!this.simulating||!e)return;const t=this.flat.find(o=>fo(o.idPath,e));if(!t)return;const n=this.canvasHost,a=this.zoom,s={x:t.frame.x*a,y:t.frame.y*a,width:t.frame.width*a,height:t.frame.height*a},r=24;s.yn.scrollTop+n.clientHeight&&(n.scrollTop=s.y-r),(s.xn.scrollLeft+n.clientWidth-r)&&(n.scrollLeft=Math.max(0,s.x-r))}commit(e,t){this.codeTyping=void 0,this.pushUndo(this.doc),this.doc=e,this.dirty=!0,t&&(this.selected=t),this.render()}commitFromCode(e,t){const n=Date.now(),a=this.codeTyping;!a||a.tab!==this.tab||n-a.last>1e3||n-a.start>5e3?(this.pushUndo(this.doc),this.codeTyping={tab:this.tab,start:n,last:n}):a.last=n,this.doc=e,this.dirty=!0,this.selected=hr(t??this.selected,e),this.render()}pushUndo(e){for(this.undoStack.push(e);this.undoStack.length>fR;)this.undoStack.shift();this.tab.redoStack=[]}undo(){const e=this.undoStack.pop();e&&(this.codeTyping=void 0,this.redoStack.push(this.doc),this.doc=e,this.dirty=!0,this.selected=hr(this.selected,this.doc),this.render())}redo(){const e=this.redoStack.pop();e&&(this.codeTyping=void 0,this.undoStack.push(this.doc),this.doc=e,this.dirty=!0,this.selected=hr(this.selected,this.doc),this.render())}resetHistory(){this.setSimulating(!1),this.tab.undoStack=[],this.tab.redoStack=[],this.selected=void 0,this.dirty=!1,this.render()}makeTab(){return{doc:w2(),serial:this.nextTabSerial++,dirty:!1,undoStack:[],redoStack:[],selected:[0]}}addTab(e=this.makeTab()){this.setSimulating(!1),this.tabs.push(e),this.tabIndex=this.tabs.length-1,this.render()}switchTab(e){e===this.tabIndex||!this.tabs[e]||(document.activeElement instanceof HTMLElement&&document.activeElement.blur(),this.setSimulating(!1),this.tabIndex=e,this.render())}async closeTab(e){if(this.tabs.length<=1)return;const t=this.tabs[e];t.dirty&&!t.exerciseId&&(this.switchTab(e),!await this.confirmDiscard())||(this.setSimulating(!1),this.tabs.splice(e,1),(this.tabIndex>e||this.tabIndex>=this.tabs.length)&&(this.tabIndex=Math.max(0,this.tabIndex-1)),this.render())}renderTabs(){const e=this.tabStrip;e.replaceChildren(),this.tabs.forEach((n,a)=>{const s=document.createElement("div");s.className="tab"+(a===this.tabIndex?" active":""),s.setAttribute("role","tab"),s.setAttribute("aria-selected",String(a===this.tabIndex));const r=document.createElement("button");r.className="tab-label",r.textContent=un(n),r.title=n.fileName??un(n),r.addEventListener("click",()=>this.switchTab(a)),s.append(r);const o=n.dirty&&!n.exerciseId;if(this.tabs.length>1){const l=document.createElement("button");l.className="tab-close"+(o?" unsaved":""),l.innerHTML='✕',l.title=p("a11y_close_tab"),l.setAttribute("aria-label",`${p("a11y_close_tab")}: ${un(n)}`),l.addEventListener("click",()=>this.closeTab(a)),s.append(l)}else o&&s.append(Object.assign(document.createElement("span"),{className:"tab-close unsaved",innerHTML:'●'}));o&&r.setAttribute("aria-label",`${un(n)} (${p("web_status_modified")})`),e.append(s)});const t=document.createElement("button");t.className="tab-add",t.textContent="+",t.title=p("a11y_new_diagram_tab"),t.setAttribute("aria-label",p("a11y_new_diagram_tab")),t.addEventListener("click",()=>this.addTab()),e.append(t)}copySelection(){const e=this.selected&&Jt(this.doc,this.selected);return e?(this.clipboard=structuredClone(e),this.showMessage(p("web_copied")),!0):!1}cutSelection(){this.selected&&dr(this.doc,this.selected)&&this.copySelection()&&this.deleteSelection()}paste(){this.clipboard&&this.insertNearSelection(structuredClone(this.clipboard))}deleteSelection(){!this.selected||!dr(this.doc,this.selected)||(this.commit(vi(this.doc,this.selected)),this.selected=void 0,this.render())}insertSensor(e,t=this.selected){if(!t||In(this.doc,t))return;const n=Pt(this.doc,t);if(!gd.includes(n.type))return;const a=(n.textLines??[]).join(" ").trim();this.commit(N1(this.doc,t,[a?`${a} ${e}`:e]),t);const s=this.inspector.querySelector("textarea");s&&(s.focus(),s.setSelectionRange(s.value.length,s.value.length))}insertNearSelection(e){const t=this.selected;if(t&&In(this.doc,t))return this.commit(Pn(this.doc,t,e),t);if(t){const n=[...t.slice(0,-1),t[t.length-1]+1];return this.commit(co(this.doc,e,t),n)}if(this.doc.elements.length===1&&In(this.doc,[0]))return this.commit(Pn(this.doc,[0],e),[0]);this.commit(ai(this.doc,[],this.doc.elements.length,e),[this.doc.elements.length])}confirmDiscard(){return this.dirty?new Promise(e=>{const t=document.createElement("div");t.className="confirm",t.innerHTML=`
+

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

+

${E(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=Nl(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:pd()}),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([u1(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:pd()}),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=ld(this.doc,un(this.tab));return this.offerDownload(`${s}.visustruct`,new Blob([u1(this.doc)],{type:"application/xml"}))}const t=ud(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=ld(this.doc,un(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([r2(t)],{type:"image/svg+xml"}));break}case"png":{const s=await cd(t,a);await this.offerDownload(`${n}.png`,await UJ(s));break}case"pdf":{const s=await cd(t,Math.max(a,3)),r=await XJ(KJ(s),s.width,s.height,t,s2(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==="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&&fo(n.idPath,this.selected);this.selected=n==null?void 0:n.idPath,this.render(),n&&e.pointerType!=="touch"&&!(In(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=Pt(this.doc,e.path);t.textContent=`${so(n.type)}: ${Ml(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||In(this.doc,s.idPath)?void 0:gd.includes(Pt(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 c=u.frame.y+u.frame.height;return t>c?n.kind==="move"&&n.path.length===1&&n.path[0]===a.length-1?void 0:{kind:"rootAppend",frame:{x:u.frame.x,y:c,width:u.frame.width,height:0}}:t=n.path.length&&n.path.every((u,c)=>r[c]===u)?void 0:In(this.doc,r)?{kind:"replace",path:r,frame:s.frame}:{kind:t"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e])}function Md(i){if(!i)return[];for(const e of[...jt.flatMap(t=>t.steps.flatMap(n=>n.blocks)),...On.flatMap(t=>t.blocks)])if(!(e.kind!=="exercise"||e.exercise.id!==i))return e.exercise.tests.flatMap(t=>{const n=t.world?Fa(t.world):void 0;return n?[n]:[]});return[]}let Ft,Pl,Dl;function Zd(i){const e=i.dataset.tip;if(!e)return;Ft??(Ft=Object.assign(document.createElement("div"),{className:"tooltip",role:"tooltip"})),Ft.isConnected||document.body.append(Ft),Ft.textContent=e,Ft.hidden=!1;const t=i.getBoundingClientRect(),n=Ft.offsetWidth,a=Ft.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!==Dl&&(uo(),e&&(Dl=e,Pl=window.setTimeout(()=>Zd(e),350)))}),document.addEventListener("focusin",i=>{const e=i.target.closest("[data-tip]");uo(),e!=null&&e.matches(":focus-visible")&&Zd(e)});for(const i of["pointerdown","focusout","scroll","keydown"])document.addEventListener(i,uo,!0)}const Bl="visustruct.reloadedAfterError";function c2(){try{const i=Number(sessionStorage.getItem(Bl));if(i&&Date.now()-i<3e4)return!1;sessionStorage.setItem(Bl,String(Date.now()))}catch{return!1}return location.reload(),!0}function wR(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=>{c2()&&i.preventDefault()});const zR=K2();Promise.all([ah(zR,!1),ih(Y2(),!1)]).then(()=>{u2(),yR();const i=new URLSearchParams(location.search);i.has("visuobject")&&gg(),i.has("visuflow")&&fg();const e=document.getElementById("app"),t=!i.has("visustruct")&&!i.has("visubot");if(hg()&&t)return K(async()=>{const{ObjectApp:n}=await import("./objectApp-Cf8h-zzC.js").then(a=>a.g);return{ObjectApp:n}},[],import.meta.url).then(({ObjectApp:n})=>void new n(e));if(pg()&&t)return K(async()=>{const{FlowApp:n}=await import("./flowApp-C_31XWhB.js");return{FlowApp:n}},[],import.meta.url).then(({FlowApp:n})=>void new n(e));new bR(e)}).then(()=>{try{sessionStorage.removeItem(Bl)}catch{}}).catch(i=>{/dynamically imported module|Importing a module script failed|error loading dynamically/i.test(String(i))&&c2()||wR(i)});export{Qn as C,IJ as J,Qb as L,K as _,uJ as a,PJ as b,Xf as c,AR as d,fg as e,Sr as f,pR as g,la as h,se as i,BM as j,DM as k,s1 as l,_R as m,gg as n,od as o,_J as p,r2 as q,hc as r,WM as s,p as t,cd as u,UJ as v,Lo as w,XJ as x,KJ as y}; diff --git a/website/app/assets/index-DaVEKYYQ.css b/website/app/assets/index-DaVEKYYQ.css new file mode 100644 index 00000000..9cd6b076 --- /dev/null +++ b/website/app/assets/index-DaVEKYYQ.css @@ -0,0 +1 @@ +:root{--bg: #f2f2f7;--panel: #ffffff;--text: #1c1c1e;--muted: #6e6e73;--border: #d1d1d6;--accent: #007aff;--accent-soft: rgba(0, 122, 255, .18);--accent-faint: rgba(0, 122, 255, .08);--accent-glow: rgba(0, 122, 255, .35);--area-editor: #007aff;--area-code: #7c3aed;color-scheme:light}:root.visubot-theme{--bg: #f1f0f8;--text: #2f3454;--muted: #6a6890;--border: #d6d3e8;--accent: #e07000;--accent-soft: rgba(253, 161, 21, .24);--accent-faint: rgba(253, 161, 21, .1);--accent-glow: rgba(224, 112, 0, .35)}:root.visubot-theme .selection-frame{stroke:#e07000e6}*{box-sizing:border-box}html,body{margin:0;height:100%;background:var(--bg);color:var(--text);font:14px/1.4 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.app{display:grid;grid-template:"tools tools" auto "pal work" 1fr "pal insp" auto / var(--palette-width, 210px) minmax(0,1fr);height:100%;flex:1;min-width:0}.shell{display:flex;flex-direction:column;height:100vh;height:100dvh}.columns{display:flex;flex:1;min-height:0}.columns>.app{min-width:240px}.toolbar{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;padding:8px 12px;background:var(--panel);border-bottom:1px solid var(--border)}button.icon{display:inline-flex;align-items:center;justify-content:center;min-width:34px;height:32px;padding:0 7px}button.icon svg{display:block}.tooltip{position:fixed;z-index:1000;max-width:260px;padding:4px 8px;border-radius:6px;background:#1c1c1e;color:#fff;font-size:12px;line-height:1.35;pointer-events:none;box-shadow:0 2px 8px #0003}.tooltip[hidden]{display:none}.diagram-tools{grid-area:tools;display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:5px 8px;background:var(--panel);border-bottom:1px solid var(--border)}.diagram-tools button.icon{min-width:30px;height:30px;padding:0 5px}.diagram-tools .sim-toggle{margin-inline-start:auto;display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 10px;white-space:nowrap}.diagram-tools{container-type:inline-size}@container (max-width: 520px){.diagram-tools .sim-toggle span{display:none}}.diagram-tools .sep{width:1px;height:20px;margin-inline:3px;background:var(--border)}.menu-host{position:relative}.export-menu{position:absolute;top:calc(100% + 4px);inset-inline-end:0;z-index:30;display:grid;min-width:180px;padding:4px;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #00000026}.export-menu[hidden]{display:none}.export-menu button{border:none;background:none;text-align:start;padding:7px 10px;border-radius:6px}.export-menu button:hover,.export-menu button:focus-visible{background:var(--accent-soft)}.settings{position:relative;margin-inline-start:auto}.settings>button{display:inline-flex;align-items:center;padding:6px 8px}.settings-menu{position:absolute;top:calc(100% + 6px);inset-inline-end:0;z-index:30;display:grid;width:290px;max-width:calc(100vw - 24px);max-height:calc(100dvh - 80px);overflow-y:auto;padding:4px 0;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #00000026}.settings-menu[hidden]{display:none}.settings-menu section,.settings-menu footer{display:grid;gap:10px;padding:10px 14px 12px}.settings-menu section+section,.settings-menu footer{border-top:1px solid var(--border)}.settings-menu footer{display:flex;align-items:center;justify-content:space-between;gap:10px}.settings-version{font-size:12px;color:var(--muted)}.settings-menu section[hidden]{display:none}.settings-menu h3{margin:0;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}.settings-menu label{display:grid;gap:4px;font-size:13px;font-weight:600;color:var(--muted)}.settings-menu select{width:100%;max-width:none}.settings-menu label.check{grid-template-columns:auto 1fr;align-items:start;gap:8px;font-weight:500;color:var(--text);cursor:pointer}.settings-menu label.check input{margin:2px 0 0}.settings-menu label small,.settings-menu label.check small{display:block;font-weight:400;color:var(--muted)}.settings-menu .about-button{justify-self:start;padding:6px 10px;font-size:13px}dialog.about{width:min(560px,calc(100vw - 32px));max-height:calc(100dvh - 48px);padding:0;color:var(--text);background:var(--panel);border:1px solid var(--border);border-radius:12px;box-shadow:0 12px 40px #00000040}dialog.about::backdrop{background:#00000059}dialog.about header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;border-bottom:1px solid var(--border)}dialog.about h2{margin:0;font-size:16px}.about-body{padding:20px 24px 24px;font-size:14px;line-height:1.5}.about-body p{margin:0 0 8px;color:var(--muted)}.about-head{display:flex;gap:16px;padding-bottom:16px;margin-bottom:8px;border-bottom:1px solid var(--border)}.about-head .logo{flex:none;width:40px;height:40px;color:var(--accent)}.about-head h3{margin:0 0 6px;font-size:20px}.about-head h3 small{font-weight:400;color:var(--muted)}.about-body .about-version{font-variant-numeric:tabular-nums}.about-body .about-author{color:var(--text);font-weight:600}.about-link{margin:0 0 2px}.about-body h4{margin:16px 0 6px;font-size:15px}.about-body code{font-weight:600;color:var(--text)}.about-body .about-copy{margin-top:16px}.brand{font-weight:700;font-size:16px;display:flex;align-items:center;gap:8px}.visubot-logo{width:auto;height:30px;margin:-4px 0}.visubot-bot{color:#f08a00;margin-left:-8px}.brand small{font-weight:500;color:var(--muted);font-size:12px}.logo{width:20px;height:20px;border:2px solid currentColor;background:linear-gradient(to bottom right,transparent 47%,currentColor 47% 53%,transparent 53%) left / 50% 60% no-repeat,linear-gradient(to bottom left,transparent 47%,currentColor 47% 53%,transparent 53%) right / 50% 60% no-repeat}.group{display:flex;flex-wrap:wrap;gap:6px}button,select{font:inherit;padding:6px 12px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);cursor:pointer;min-height:34px}select{max-width:180px}button:hover:not(:disabled),select:hover{border-color:var(--accent)}button:disabled{opacity:.4;cursor:default}.palette,.inspector{background:var(--panel);padding:12px;overflow-y:auto}.palette{grid-area:pal;border-inline-end:1px solid var(--border)}.inspector{grid-area:insp;border-top:1px solid var(--border);max-height:34vh}h2{font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:0 0 4px}.hint{color:var(--muted);font-size:12px;margin:0 0 10px}.palette ul{list-style:none;margin:0;padding:0;display:grid;gap:6px}.palette-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--border);border-radius:8px;cursor:grab;line-height:1.25;user-select:none;-webkit-user-select:none;touch-action:none}.palette-item:hover,.palette-item:focus-visible{border-color:var(--accent);outline:none}.palette-item .icon{flex:none;color:var(--text)}.workspace{grid-area:work;display:flex;flex-direction:column;min-width:0;min-height:0}.caption{font:600 18px system-ui,-apple-system,sans-serif;border:none;border-bottom:1px solid var(--border);padding:10px 16px;background:var(--panel);outline:none}.canvas{flex:1;overflow:auto;scrollbar-gutter:stable;background:#fafafa}.canvas svg{display:block;user-select:none;-webkit-user-select:none}.dragging,.dragging *{cursor:grabbing!important}.drop-line{fill:var(--accent)}.drop-replace{fill:var(--accent-soft);stroke:var(--accent);stroke-width:3}.drag-ghost{position:fixed;left:0;top:0;z-index:10;pointer-events:none;padding:6px 10px;border-radius:8px;background:var(--accent);color:#fff;font-weight:600;box-shadow:0 4px 14px #0003;white-space:nowrap;max-width:260px;overflow:hidden;text-overflow:ellipsis}.inspector label{display:block;font-weight:600;margin:8px 0 4px}.inspector textarea{width:100%;font:14px ui-monospace,SF Mono,Menlo,Consolas,monospace;padding:8px;border:1px solid var(--border);border-radius:8px;resize:vertical}.statusbar{display:flex;flex-wrap:wrap;gap:2px 16px;align-items:baseline;padding:4px 12px;font-size:12px;color:var(--muted);background:var(--panel);border-top:1px solid var(--border)}.status{flex:1 1 auto;min-width:0}.site-links{display:flex;gap:12px;margin-inline-start:auto}.site-links a{color:inherit}.site-links a:hover,.site-links a:focus-visible{color:var(--accent)}a.brand{color:inherit;text-decoration:none}.file-drag .canvas{outline:3px dashed var(--accent);outline-offset:-8px}@media(min-width:821px){.app.compact-palette{--palette-width: 100px}.app.compact-palette .palette{padding:8px 6px}.app.compact-palette .palette h2{font-size:10px;letter-spacing:0;text-align:center}.app.compact-palette .palette .hint{display:none}.app.compact-palette .palette-item{flex-direction:column;gap:3px;padding:6px 2px;font-size:10.5px;line-height:1.15;text-align:center;overflow-wrap:break-word}}@media(max-width:820px){.app{grid-template:"tools" auto "pal" auto "work" 1fr "insp" auto / minmax(0,1fr)}.palette,.inspector{min-width:0}.palette{border-inline-end:none;border-bottom:1px solid var(--border);padding:8px}.palette .hint,.palette h2{display:none}.palette ul{display:flex;overflow-x:auto;overflow-y:hidden}.palette-item{white-space:nowrap}.inspector{max-height:30vh}}.status.message{color:var(--text);font-weight:600}.confirm{position:fixed;top:0;right:0;bottom:0;left:0;z-index:20;display:grid;place-items:center;background:#00000040;padding:16px}.confirm-card{background:var(--panel);border-radius:12px;padding:16px 18px;max-width:360px;box-shadow:0 10px 30px #0003}.confirm-card p{margin:0 0 8px}.confirm-card .group{justify-content:flex-end;margin-top:12px}.files-ask{width:min(360px,100%)}.files-ask input{width:100%;box-sizing:border-box;margin-top:4px}.files-choices{display:flex;flex-wrap:wrap;gap:6px;margin:4px 0 10px}.files-choice{display:inline-flex;align-items:center;gap:6px}.files-choice svg{width:16px;height:16px}button.danger{background:#d70015;border-color:#d70015;color:#fff}.simpanel{display:none;grid-area:insp;background:var(--panel);border-inline-start:1px solid var(--border);padding:12px;overflow-y:auto}.app.simulating{grid-template:"tools tools" auto "work insp" 1fr / minmax(0,1fr) 320px}.app.simulating.visubot-mode{grid-template:"tools tools" auto "work insp" 1fr / minmax(0,1fr) min(440px,45%)}.app.simulating .palette,.app.simulating .inspector{display:none}.app.simulating .simpanel{display:block}.app.simulating .caption{cursor:default}button.sim-toggle{font-weight:600}button.sim-toggle{background:var(--accent);border-color:var(--accent);color:#fff}.simpanel section{margin-bottom:14px}.sim-buttons{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:6px 0 10px}.sim-option{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px;font-size:13px}.mono,.sim-vars td{font:13px/1.5 ui-monospace,SF Mono,Menlo,Consolas,monospace}.sim-trace,.sim-output,.sim-vars{background:var(--bg);border-radius:8px;padding:8px 10px;overflow-wrap:anywhere}.sim-output{max-height:220px;overflow-y:auto;white-space:pre-wrap}.sim-vars table{border-collapse:collapse;width:100%}.sim-vars td{padding:2px 0;vertical-align:top}.sim-vars td:first-child{color:var(--muted);padding-inline-end:12px;width:1%;white-space:nowrap}.sim-vars table.sim-grid{width:auto}.sim-vars .sim-grid td,.sim-vars .sim-grid td:first-child{border:1px solid var(--border);color:inherit;font-size:11px;padding:0 4px;text-align:center;width:auto}.sim-vars .sim-grid td.sim-grid-true{font-weight:700}.simpanel .placeholder{color:var(--muted);font:13px system-ui,-apple-system,sans-serif;margin:0}.sim-notice{margin:0 0 14px;padding:8px 10px;border-radius:8px;background:#34c75926;font-weight:600}.sim-edit{width:100%;margin:-6px 0 14px}.sim-notice.error{background:#ff3b3026;color:#b0000f}.sim-input.active{padding:8px 10px;margin-left:-10px;margin-right:-10px;border-radius:10px;background:var(--accent-faint);outline:2px solid var(--accent)}.sim-prompt{margin:4px 0 6px;font-weight:600}.sim-input-row{display:flex;gap:6px}.sim-input-row input{flex:1;min-width:0;font:inherit;padding:6px 10px;border:1px solid var(--border);border-radius:8px}.sim-input-error{color:#b0000f;margin:6px 0 0;font-size:13px}@media(max-width:820px){.app.simulating{grid-template:"tools" auto "work" minmax(200px,1fr) "insp" auto / minmax(0,1fr)}.simpanel{border-inline-start:none;border-top:1px solid var(--border);max-height:48vh}}.codepanel{display:none;grid-area:code;background:var(--panel);border-inline-start:1px solid var(--border);padding:12px;overflow-y:auto;min-height:0}.app.coding{grid-template:"tools tools tools" auto "pal work code" 1fr "pal insp code" auto / var(--palette-width, 210px) minmax(0,1fr) 400px}.app.coding .codepanel{display:block}.app.coding .inspector{max-height:34vh}button[data-action=code][aria-pressed=true]{border-color:var(--accent);background:var(--accent-soft)}.code-head,.runner-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.code-close{min-height:28px;padding:2px 10px}.segmented{display:flex;margin-bottom:8px}.segmented button{flex:1;border-radius:0;min-height:30px;padding:4px 8px}.segmented button:first-child{border-radius:8px 0 0 8px}.segmented button:last-child{border-radius:0 8px 8px 0}.segmented button+button{border-inline-start:none}.segmented button[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:#fff}.segmented[hidden]{display:none}.check{display:flex;gap:8px;align-items:center;font-size:13px;margin-bottom:4px}.code-actions{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}.code-actions [hidden]{display:none}button.primary{background:var(--accent);border-color:var(--accent);color:#fff}.code-view,.runner-out{margin:0;padding:10px 12px;border-radius:10px;background:var(--bg);font:13px/1.5 ui-monospace,SF Mono,Menlo,Consolas,monospace;overflow:auto;white-space:pre;-moz-tab-size:4;tab-size:4}.runner{margin:12px 0}.runner-out{background:#0b1220;color:#e5e7eb;min-height:3em;max-height:240px;white-space:pre-wrap}.runner-out.error{outline:2px solid #ff453a}.runner-input{margin-top:8px}.runner-input label{display:block;font-weight:600;margin-bottom:4px}@media(max-width:820px){.app.coding{grid-template:"tools" auto "pal" auto "work" minmax(240px,1fr) "insp" auto "code" auto / minmax(0,1fr)}.codepanel{border-inline-start:none;border-top:1px solid var(--border);max-height:50vh}}.tabs{display:flex;align-items:flex-end;gap:2px;padding:6px 8px 0;background:var(--bg);border-bottom:1px solid var(--border);overflow-x:auto;overflow-y:hidden;scrollbar-width:thin}.tab{display:flex;align-items:center;max-width:220px;border:1px solid var(--border);border-bottom:none;border-radius:8px 8px 0 0;background:#ffffff80}.tab.active{background:var(--panel);margin-bottom:-1px;padding-bottom:1px}.tab button{border:none;background:none;min-height:30px;border-radius:8px 8px 0 0}.tab-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:4px 6px 4px 12px}.tab.active .tab-label{font-weight:600}.tab-close{padding:2px 8px;color:var(--muted);font-size:11px}.tab-close:hover{color:var(--text)}.tab-dot,.tab-close.unsaved .tab-x{display:none}.tab-close.unsaved .tab-dot{display:inline;color:var(--text);font-size:10px}.tab-close.unsaved:hover .tab-dot{display:none}button.tab-close.unsaved:hover .tab-x{display:inline}span.tab-close{padding:2px 10px 2px 4px}.tab-add{min-height:28px;padding:2px 10px;margin:0 0 3px 4px;border-radius:8px}.inspector .segmented{margin:6px 0 4px;max-width:420px}.mono-hint{font:11px/1.45 ui-monospace,SF Mono,Menlo,Consolas,monospace;overflow-wrap:anywhere}.editor-row{display:flex;gap:8px;align-items:flex-start}.editor-row textarea{flex:1;min-width:0}.fixed-prefix{font:14px ui-monospace,SF Mono,Menlo,Consolas,monospace;color:var(--muted);padding-top:9px}.inspector input:not([type]){width:100%;font:14px ui-monospace,SF Mono,Menlo,Consolas,monospace;padding:7px 8px;border:1px solid var(--border);border-radius:8px}.for-fields{display:grid;gap:4px}.for-fields label,.case-controls label{margin:4px 0 0;font-size:12px;color:var(--muted);font-weight:600}.case-controls{margin-top:12px;padding-top:10px;border-top:1px solid var(--border)}.case-controls .group{margin-top:8px}button.danger-text:not(:disabled){color:#d70015}.print-sheet{display:none}.files{display:none;flex:0 1 auto;flex-direction:column;width:260px;min-width:200px;min-height:0;background:var(--panel);border-inline-end:1px solid var(--border)}.shell.files-open .files{display:flex}.shell.files-open .files-rail{display:none}.files-head{display:flex;align-items:center;gap:4px;margin:10px 12px 6px}.files-head h2{flex:1;margin:0;font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.files-head button.icon{min-width:30px;height:30px;padding:0 5px}.files-head [hidden]{display:none}.files-body{flex:1;min-height:0;overflow:auto;padding:0 8px 12px;font-size:14px}.files-where{margin:0 4px 6px;font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.files-hint,.files-empty{margin:8px 4px;font-size:13px;color:var(--muted)}.start-ask .files-start{margin-bottom:2px}.start-ask .hint{font-size:13px;color:var(--muted)}.start-without{display:block;margin:12px auto 0;border:none;background:none;color:var(--accent);text-decoration:underline}.start-without+.hint{text-align:center}.files-start{display:flex;align-items:center;gap:6px;width:100%;margin:8px 0;justify-content:center}.files-row{display:flex;align-items:center;border-radius:6px}.files-row:hover,.files-row:focus-within{background:var(--accent-soft)}.files-row.current>.files-name{font-weight:600}.files-name{flex:1;min-width:0;display:flex;align-items:center;gap:6px;padding:4px 6px 4px calc(6px + var(--depth) * 16px);border:none;background:none;text-align:start;font:inherit;color:var(--text);cursor:pointer}.files-name:disabled{cursor:default;color:var(--muted)}.files-name svg{flex:none;width:16px;height:16px;color:var(--muted)}.files-name span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.files-name small{margin-inline-start:auto;padding:0 6px;border-radius:6px;background:var(--accent);color:#fff;font-size:11px;font-weight:600}.files-row .files-delete{visibility:hidden;min-width:26px;height:26px;padding:0 4px;border:none;background:none;color:var(--muted)}.files-row:hover .files-delete,.files-row:focus-within .files-delete{visibility:visible}.files-error{color:#c62828}.files-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.shell.files-open .files-resizer{display:block}.files-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px}.files-resizer:hover:after,.files-resizer:focus-visible:after{background:var(--accent)}.learn{display:none;flex:0 1 auto;width:400px;min-width:280px;flex-direction:column;background:var(--panel);border-inline-end:1px solid var(--border);min-height:0}.shell.learning .learn{display:flex}.learn-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.shell.learning .learn-resizer{display:block}.learn-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.learn-resizer:hover:after,.learn-resizer:focus-visible:after,.shell.resizing .learn-resizer:after{background:var(--accent)}.learn-resizer:focus-visible{outline:none}.shell.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.learn-head{display:flex;align-items:flex-start;gap:6px;margin:10px 12px 0}.learn-tabs{flex:1;min-width:0}.learn-hide{flex:none;min-height:30px;padding:4px 7px;display:inline-flex;align-items:center;color:var(--muted)}.learn-rail{flex:none;display:flex;flex-direction:column;align-items:center;gap:10px;width:36px;padding:10px 0;border:none;border-radius:0;border-inline-end:1px solid var(--border);background:var(--panel);cursor:pointer}.learn-rail:hover{background:var(--accent-soft)}.learn-rail span{writing-mode:vertical-rl;white-space:nowrap}.shell.learning .learn-rail:not(.live-rail):not(.editor-rail):not(.files-rail):not(.robotpreview-rail):not(.palette-rail){display:none}.live-rail{border-inline-end:none;border-inline-start:1px solid var(--border)}.live-rail svg{transform:scaleX(-1)}.shell.live .live-rail{display:none}.editor-rail{display:none;border-inline-start:1px solid var(--border)}.shell.editor-hidden .editor-rail{display:flex}.shell.editor-hidden .app,.shell.editor-hidden .live-resizer,.shell.editor-hidden:not(.live) .learn-resizer{display:none}.shell.editor-hidden .livecode,.shell.editor-hidden:not(.live) .learn{flex:1 1 0;width:auto!important;min-width:0}.learn-body{overflow-y:auto;scrollbar-gutter:stable;padding:4px 16px 24px;flex:1;min-height:0;line-height:1.5}.learn-body h2.learn-title{display:flex;align-items:center;gap:8px;font-size:20px;text-transform:none;letter-spacing:0;color:var(--text);margin:2px 0 10px}.learn-section{font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:18px 0 6px}.learn-list{list-style:none;padding:0;margin:0;display:grid;gap:6px}.learn-item{display:flex;align-items:center;gap:10px;width:100%;text-align:start;padding:8px 10px}.learn-item.done{border-color:#34c759}.learn-num{flex:none;min-width:28px;height:28px;border-radius:14px;background:var(--accent-soft);color:var(--accent);display:grid;place-items:center;font-weight:700;font-size:12px;padding:0 6px}.learn-item.done .learn-num{background:#34c7592e;color:#248a3d}.learn-item-text{flex:1;display:grid;min-width:0}.learn-item-text small{color:var(--muted)}.learn-status{flex:none;color:var(--muted);font-size:12px}.learn-item.done .learn-status{color:#248a3d;font-weight:700}.learn-back,.link-button{border:none;background:none;padding:6px 0;min-height:0;color:var(--accent)}.link-button{padding:0;text-align:start}.learn-lesson-head{position:sticky;top:-4px;z-index:3;margin:-4px -16px 10px;padding:4px 16px 8px;background:var(--panel);border-bottom:1px solid var(--border)}.learn-lesson-head .learn-progress{margin-bottom:8px}.learn-lesson-head .learn-step-title{margin:0}.learn-head-row{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}.learn-nav.learn-nav-top{margin-top:0;gap:6px}.learn-nav-top button{padding:3px 10px;min-height:0;font-size:13px}.learn-kicker{margin:4px 0 0;color:var(--muted);font-size:12px}.learn-progress{display:flex;gap:4px;margin-bottom:14px}.learn-progress button{flex:1 1 0;min-width:0;padding:3px 0;font-size:13px;font-variant-numeric:tabular-nums;border-radius:6px}.learn-progress button.past{border-color:var(--accent);color:var(--accent)}.learn-progress button.current{border-color:var(--accent);background:var(--accent);color:#fff;font-weight:600}.learn-progress button.robot-step:not(.current){border-color:#0fa3c6;background:#0fa3c61f}.learn-progress button.robot-step.current{border-color:#0fa3c6;background:#0fa3c6}.learn-step-title{font-size:16px;margin:0 0 6px}.learn-text p,.learn-text ul,.learn-text ol{margin:0 0 10px}.learn-text ul,.learn-text ol{padding-inline-start:22px}.learn-text code,.learn-tests code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;background:var(--bg);border-radius:4px;padding:1px 4px}.learn-text h3{font-size:15px;margin:18px 0 4px}.reference-group{border:1px solid var(--border);border-radius:8px;margin:0 0 8px;padding:0 12px}.reference-group summary{cursor:pointer;font-weight:600;padding:9px 0}.reference-group[open] summary{border-bottom:1px solid var(--border)}.reference-group>h3:first-of-type{margin-top:10px}.lesson-code{background:var(--bg);border-radius:8px;padding:8px 10px;margin:0 0 10px;overflow-x:auto;overflow-y:hidden;font-size:12.5px}.learn-open-code{display:block;margin:-4px 0 12px}.lesson-code code{background:none;padding:0}.lesson-note{border-inline-start:3px solid var(--accent);background:var(--accent-soft);border-radius:6px;padding:8px 10px;margin:0 0 10px}.lesson-note p:last-child{margin-bottom:0}.learn-images{display:flex;gap:8px;flex-wrap:wrap}.learn-images img{width:150px;height:200px;object-fit:cover;border-radius:8px}.learn-file{margin:0 0 14px;border:1px solid var(--border);border-radius:10px;overflow:hidden;background:var(--panel)}.learn-file figcaption{display:flex;align-items:center;gap:6px;padding:6px 10px;background:var(--bg);border-bottom:1px solid var(--border);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;font-weight:600}.learn-file-text{margin:0;padding:8px 10px;overflow-x:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;line-height:1.5;white-space:pre}.learn-file.written{margin:8px 0;border-color:#15803d}.learn-file.written figcaption{background:#dcfce7}.learn-file-text .ln{display:inline-block;min-width:2ch;margin-inline-end:10px;color:var(--muted);text-align:end;-webkit-user-select:none;user-select:none}.learn-brag{display:grid;grid-template-columns:48px minmax(0,1fr);gap:10px;align-items:start;border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin:0 0 14px;background:var(--accent-soft)}.learn-brag img{width:48px;height:48px;border-radius:50%}.learn-brag-title{margin:0 0 4px;font-weight:700}.learn-brag .learn-text p:last-child{margin-bottom:0}.learn-game{border:2px solid var(--accent);border-radius:12px;padding:12px 14px;margin:0 0 14px}.learn-game-head{display:flex;align-items:center;gap:10px;font-size:1.05em}.learn-game-head img{width:40px;height:40px;border-radius:50%}.learn-game-status{margin:6px 0;color:var(--muted);font-size:.9em}.learn-game-values{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.learn-game-values code{background:var(--accent-soft);border-radius:6px;padding:2px 8px}.learn-game-condition{font-size:1.15em;font-weight:600;padding:10px 12px;border-radius:8px;background:var(--bg, #f2f2f7);margin-bottom:10px;overflow-wrap:anywhere}.learn-game-answers button{flex:1;font-weight:600;padding-block:10px}.learn-game-true:not(:disabled){border-color:#15803d;color:#15803d}.learn-game-false:not(:disabled){border-color:#b91c1c;color:#b91c1c}.learn-game-feedback:empty{display:none}.learn-game-feedback{margin-top:10px;padding:10px 12px;border-radius:8px}.learn-game-feedback.right{background:#dcfce7}.learn-game-feedback.wrong{background:#fee2e2}.learn-game-feedback p{margin:0 0 6px;font-weight:700}.learn-game-steps{margin-bottom:10px;line-height:1.6}.learn-game-result{font-size:1.2em;font-weight:700}.learn-game-question{font-weight:600;margin:10px 0 8px}.learn-game-code{margin:0 0 8px;padding:8px 0;border-radius:8px;background:var(--bg, #f2f2f7);font-size:13px;line-height:1.5;overflow-x:auto}.learn-game-code .ln{padding:0 10px 0 calc(10px + 2ch);text-indent:-2ch;border-inline-start:3px solid transparent;white-space:pre-wrap;overflow-wrap:anywhere;transition:background .2s}.learn-game-code .ln.hit{background:#fef3c7;border-inline-start-color:#d97706}.learn-bomb{display:flex;align-items:center;gap:10px;margin-bottom:6px;font-weight:700}.learn-bomb-icon{font-size:28px;line-height:1}.learn-bomb.hurry .learn-bomb-icon{animation:learn-bomb-shake .25s infinite alternate}.learn-bomb.boom .learn-bomb-icon{animation:learn-bomb-boom .5s ease-out}@keyframes learn-bomb-shake{0%{transform:rotate(-8deg)}to{transform:rotate(8deg)}}@keyframes learn-bomb-boom{0%{transform:scale(.6)}60%{transform:scale(1.5)}to{transform:scale(1)}}.learn-bomb-time{min-width:7ch;font-variant-numeric:tabular-nums}.learn-bomb-fuse{flex:1;height:8px;border-radius:4px;background:#e5e7eb;overflow:hidden}.learn-bomb-fuse span{display:block;height:100%;background:#f59e0b;transition:width .2s linear}.learn-bomb.hurry .learn-bomb-fuse span{background:#dc2626}.learn-bomb.defused .learn-bomb-fuse span{background:#15803d}.learn-bomb-code .ln{display:block;width:100%;margin:0;border-radius:0;border-block:0;border-inline-end:0;background:none;color:inherit;font:inherit;line-height:inherit;min-height:0;height:auto;padding-block:1px;text-align:start;cursor:pointer}.learn-bomb-code .ln:not(:disabled):hover{background:#fef3c7}.learn-bomb-code .ln:disabled{cursor:default;opacity:1}.learn-bomb-code .ln.right,.learn-bomb-code .ln.right:hover{background:#dcfce7;border-inline-start-color:#15803d}.learn-bomb-code .ln.wrong,.learn-bomb-code .ln.wrong:hover{background:#fee2e2;border-inline-start-color:#b91c1c}.learn-bomb-fix code{white-space:pre-wrap}.learn-game-options{display:grid;gap:6px}.learn-game-options button{text-align:start;padding:8px 12px}.learn-game-options.pictures{grid-template-columns:repeat(auto-fill,minmax(130px,1fr))}.learn-game-options.pictures button{padding:6px}.learn-game-options button.right{border-color:#15803d;background:#dcfce7;color:inherit;opacity:1}.learn-game-options button.wrong{border-color:#b91c1c;background:#fee2e2;color:inherit;opacity:1}.learn-order-hint{margin:0 0 6px;font-size:13px;opacity:.75}.learn-order button{display:flex;align-items:center;gap:10px}.learn-order-badge{flex:none;display:inline-grid;place-items:center;width:24px;height:24px;border-radius:50%;border:1.5px solid currentColor;font-size:13px;font-weight:700;opacity:.5}.learn-order button.right .learn-order-badge,.learn-order button:disabled .learn-order-badge:not(:empty){opacity:1}.learn-game-file{margin:0;padding:2px 0;font-size:13px;line-height:1.45;white-space:pre;background:none}.learn-game-explain{margin-bottom:10px}.learn-swing-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px;align-items:start}.learn-swing-window{border:1px solid var(--border);border-radius:8px;overflow:hidden;background:#fff;color:#1c1c1e}.learn-swing-title{padding:3px 8px;font-size:12px;text-align:center;background:#e5e5ea;border-bottom:1px solid #d1d1d6;min-height:1.4em}.learn-swing-body{display:grid;gap:6px;padding:10px}.learn-swing-label{padding:4px 2px;min-height:1.4em}.learn-swing-label.changed,.learn-swing-button.changed{animation:swing-changed 1s ease-out}@keyframes swing-changed{0%{background:#ffd60acc}}.learn-swing-button{padding:6px 10px;background:#fff;color:#1c1c1e;border:1px solid #a1a1aa;border-radius:6px}.learn-swing-button:disabled{opacity:1;cursor:default}.learn-swing-button.pressed{background:var(--accent);border-color:var(--accent);color:#fff;transform:scale(.96)}.learn-swing-event{margin:0;padding:0 10px 8px;font-size:12px;min-height:1.4em}.learn-swing-event.heard{color:#b45309;font-weight:600}.learn-swing-event.nobody{color:#6b7280;font-style:italic}.learn-swing-console{margin:0 10px 10px;padding:6px 8px;border-radius:6px;background:#1c1c1e;color:#f2f2f7;font-size:12px}.learn-swing-console[hidden]{display:none}.learn-swing-clicks{margin:8px 0 0}.learn-swing-try{font-weight:400!important;font-style:italic}.learn-layout-window{width:100%;border:1px solid #a1a1aa;border-radius:6px;overflow:hidden;background:#fff;color:#1c1c1e}.learn-layout-title{height:10px;background:#e5e5ea;border-bottom:1px solid #d1d1d6}.learn-layout-body{height:80px;padding:3px;gap:3px;font-size:12px}.learn-layout-body.grid{display:grid;grid-auto-rows:1fr}.learn-layout-body.flow{display:flex;flex-direction:column;gap:3px}.learn-layout-row{display:flex;justify-content:center;gap:3px}.learn-layout-body.border{display:grid;grid-template:"N N N" auto "W C E" 1fr "S S S" auto / auto 1fr auto}.learn-layout-cell{display:flex;align-items:center;justify-content:center;min-width:22px;padding:2px 6px;border:1px solid #a1a1aa;border-radius:4px;background:#f4f4f5;font-weight:600}.learn-figure{margin:0 0 14px;display:grid;gap:6px;justify-items:start}.learn-preview{width:100%;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:#fafafa}.learn-preview>svg{display:block;width:100%;margin:0 auto;height:auto}.learn-figure figcaption{color:var(--muted);font-size:13px}.learn-exercise{border:1px solid var(--accent);border-radius:10px;padding:10px 12px;margin:0 0 14px;display:grid;gap:8px}.learn-exercise h4{margin:0;font-size:15px;display:flex;gap:8px;align-items:center}.learn-badge{font-size:12px;color:#248a3d;background:#34c7592e;border-radius:10px;padding:1px 8px}.learn-where{margin:0;font-size:13px;font-weight:600;color:var(--muted)}.area-name{display:inline-block;color:#fff;border-radius:10px;padding:0 8px}.area-name.area-editor{background:var(--area-editor)}.area-name.area-code{background:var(--area-code)}.columns>.app{border-top:3px solid var(--area-editor)}.livecode{border-top:3px solid var(--area-code)}.livecode-head h2,.live-rail span{color:var(--area-code)}.editor-rail span{color:var(--area-editor)}.live-rail,.editor-rail{font-weight:600}.learn-exercise .learn-text p:last-child{margin-bottom:0}.learn-result:empty{display:none}.learn-result{border-radius:8px;padding:8px 10px}.learn-result.ok{background:#34c75924}.learn-result.fail{background:#ff950024}.learn-result.info{background:var(--bg)}.learn-result-head{margin:0 0 6px;font-weight:600}.learn-tests{list-style:none;padding:0;margin:0;display:grid;gap:6px}.learn-test-detail{display:grid;padding-inline-start:16px;font-size:13px}.learn-error{color:#c4291c}.learn-solution summary{cursor:pointer;color:var(--accent)}.learn-solution[open]{display:grid;gap:6px;justify-items:start}.learn-checklist{list-style:none;padding:0;margin:0 0 14px;display:grid;gap:6px}.learn-checklist li{display:flex;gap:8px;align-items:baseline;justify-content:space-between}.learn-checklist li{align-items:center;justify-content:flex-start;padding:4px 6px;border-radius:8px}.learn-check-text{flex:1}.learn-checklist li[data-rating=sun]{background:color-mix(in srgb,#f5b800 14%,transparent)}.learn-checklist li[data-rating=cloud]{background:color-mix(in srgb,#8a97a8 14%,transparent)}.learn-checklist li[data-rating=umbrella]{background:color-mix(in srgb,#3b82f6 12%,transparent)}.learn-rating{display:inline-flex;gap:2px;flex:none}.learn-rating-button{min-width:34px;min-height:34px;padding:2px;font-size:1.15em;line-height:1;border-radius:8px;opacity:.45;filter:grayscale(.7)}.learn-rating-button[aria-pressed=true]{opacity:1;filter:none;border-color:var(--accent);background:var(--accent-soft)}.learn-rating-legend{display:flex;flex-wrap:wrap;gap:4px 14px;margin:0 0 8px;font-size:.9em;color:var(--muted, inherit)}.learn-review{margin:12px 0 0}.learn-review:empty{display:none}.learn-review-title{margin:0 0 4px;font-weight:700}.learn-review-icon{flex:none;width:1.6em;text-align:center}.learn-checklist li.learn-review-deviation{border:1px solid var(--accent);background:var(--accent-soft)}.learn-competences{border:1px solid var(--accent);border-radius:10px;padding:10px 12px;margin:0 0 14px;background:var(--accent-soft)}.learn-competences-title{margin:0 0 4px;font-weight:700}.learn-competences ul{margin:0;padding-left:1.3em}.learn-return{width:100%;margin:0 0 12px;border-color:var(--accent);background:var(--accent-soft)}.learn-nav+.learn-return{margin:12px 0 0}.learn-check-link{flex:none;font-size:13px}.learn-quiz fieldset{border:1px solid var(--border);border-radius:10px;padding:8px 12px 10px;margin:0 0 10px;display:grid;gap:6px}.learn-quiz legend{font-weight:600;padding:0 4px}.learn-option{text-align:start}.learn-option.right{border-color:#34c759;background:#34c75924}.learn-option.wrong{border-color:#ff3b30;background:#ff3b301a}.learn-match{display:grid;gap:6px}.learn-match-left{display:grid;grid-template-columns:8.5em minmax(0,1fr);align-items:center;gap:8px}.learn-match-select{min-width:0;width:100%;max-width:none}.learn-match-select.right{border-color:#34c759;background:#34c75924}.learn-match-select.wrong{border-color:#ff3b30;background:#ff3b301a}.learn-explanation{margin:0;color:var(--muted);font-size:13px}.learn-score{font-weight:600}.learn-nav{display:flex;justify-content:space-between;gap:8px;margin-top:18px}@media(max-width:1100px){.learn{width:340px}}@media(max-width:900px){.learn{width:300px}}.livecode{display:none;flex:0 1 auto;width:420px;min-width:200px;flex-direction:column;gap:6px;padding:10px 12px 12px;background:var(--panel);border-inline-start:1px solid var(--border);min-height:0}.shell.live .livecode{display:flex}.livecode-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px}.livecode-head h2{margin:0;font-size:16px}.livecode-lang{margin-inline-start:auto;padding:2px 8px;border-radius:6px;background:var(--accent-soft);color:var(--accent);font-size:12px;font-weight:600}.livecode .learn-hide svg{transform:scaleX(-1)}.livecode .hint{margin:0}.livecode-view{flex:1;min-height:0;padding:10px 0;font-size:var(--code-size, 14px)}.livecode-view .ln{padding:0 12px;min-height:1.5em;border-inline-start:3px solid transparent}.livecode-view.selectable .ln{cursor:pointer}.livecode-view .ln.sel{background:var(--accent-soft);border-inline-start-color:var(--accent)}.livecode-view .ph{color:var(--muted);font-style:italic}.livecode-editor{flex:1;min-height:0;padding:0;font-size:var(--code-size, 14px);white-space:normal;overflow:hidden;--syn-keyword: #7f0055;--syn-string: #2a00ff;--syn-number: #986801;--syn-comment: #3f7f5f}.livecode-editor[hidden],.livecode-view[hidden],.livecode-problem[hidden]{display:none}.livecode-editor .cm-editor{height:100%;background:transparent}.livecode-editor .cm-editor.cm-focused{outline:2px solid var(--accent-soft);outline-offset:-2px;border-radius:10px}.livecode-editor .cm-scroller{font:inherit;font-family:ui-monospace,SF Mono,Menlo,Consolas,monospace;line-height:1.5}.livecode-editor .cm-gutters{background:transparent;border-inline-end:1px solid var(--border);color:var(--muted)}.livecode-editor .cm-lineNumbers .cm-gutterElement{padding:0 8px 0 10px;min-width:2ch}.livecode-editor .cm-activeLineGutter{background:transparent;color:var(--text)}.livecode-editor .cm-content{padding:10px 0;caret-color:var(--text)}.livecode-editor .cm-line{padding:0 12px;border-inline-start:3px solid transparent}.livecode-editor .cm-scopeLayer .cm-scope{border:1px solid color-mix(in srgb,var(--scope) 28%,transparent);border-left:3px solid var(--scope);border-radius:8px;background:color-mix(in srgb,var(--scope) 9%,#fff)}.livecode-editor .cm-scopeLayer .cm-scope-class{--scope: #34c47c}.livecode-editor .cm-scopeLayer .cm-scope-method{--scope: #f2b100}.livecode-editor .cm-scopeLayer .cm-scope-loop{--scope: #ec5fa6}.livecode-editor .cm-scopeLayer .cm-scope-if{--scope: #3b9cf0}.livecode-editor .cm-scopeLayer .cm-scope-try{--scope: #9a7cf0}:root.no-code-scopes .livecode-editor .cm-scopeLayer .cm-scope:not(.cm-scope-sel){display:none}:root:not(.no-code-scopes) .ns-scope-method{fill:color-mix(in srgb,#f2b100 14%,#fff)}:root:not(.no-code-scopes) .ns-scope-loop{fill:color-mix(in srgb,#ec5fa6 14%,#fff)}:root:not(.no-code-scopes) .ns-scope-if{fill:color-mix(in srgb,#3b9cf0 14%,#fff)}:root:not(.no-code-scopes) .palette-item[data-scope=method]{background:color-mix(in srgb,#f2b100 14%,#fff)}:root:not(.no-code-scopes) .palette-item[data-scope=loop]{background:color-mix(in srgb,#ec5fa6 14%,#fff)}:root:not(.no-code-scopes) .palette-item[data-scope=if]{background:color-mix(in srgb,#3b9cf0 14%,#fff)}.livecode-editor .cm-scopeLayer .cm-scope-sel{background:transparent;border:2px solid var(--accent);box-shadow:0 0 0 3px var(--accent-faint)}.livecode-editor .cm-line.cm-debug-line{background:#ffd60a59;border-inline-start-color:#e0a800}.livecode-editor .cm-breakpoint-gutter .cm-gutterElement,.livecode-editor .cm-lineNumbers .cm-gutterElement{cursor:pointer}.livecode-editor .cm-breakpoint-gutter .cm-gutterElement{display:flex;align-items:center;justify-content:center;width:14px;padding-inline-start:4px}.livecode-editor .cm-breakpoint{display:inline-block;width:10px;height:10px;border-radius:50%;background:#d33}.livecode-editor .cm-breakpoint-gutter .cm-gutterElement:not(:has(.cm-breakpoint)):hover:before{content:"";width:10px;height:10px;border-radius:50%;background:#dd33334d}.livecode-debug{flex:none;max-height:30%;overflow-y:auto}.livecode-debug[hidden]{display:none}.livecode-debug h2{margin:0 0 4px;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.livecode-vars tr.changed td{animation:var-changed 1.6s ease-out;font-weight:700}@keyframes var-changed{0%{background:#ffd60ab3}to{background:transparent}}.livecode-editor .cm-ph,.livecode-editor .cm-ph *{color:var(--muted)!important;font-style:italic;font-weight:400!important}.livecode-editor .cm-err{text-decoration:underline wavy #d33;text-decoration-skip-ink:none;text-underline-offset:3px}.livecode-editor .cm-selectionBackground,.livecode-editor .cm-focused .cm-selectionBackground{background:color-mix(in srgb,var(--accent) 25%,transparent)!important}.livecode-editor .cm-matchingBracket{background:color-mix(in srgb,var(--accent) 20%,transparent);outline:1px solid color-mix(in srgb,var(--accent) 50%,transparent)}.cm-tooltip.cm-tooltip-autocomplete{border:1px solid var(--border);border-radius:8px;background:var(--panel);box-shadow:0 4px 16px #0000001f;overflow:hidden}.cm-tooltip.cm-tooltip-autocomplete>ul{font:14px/1.4 ui-monospace,SF Mono,Menlo,Consolas,monospace;max-height:16em}.cm-tooltip.cm-tooltip-autocomplete>ul>li{padding:4px 10px}.cm-tooltip.cm-tooltip-autocomplete>ul>li[aria-selected]{background:var(--accent);color:#fff}.cm-tooltip-autocomplete .cm-completionDetail{margin-inline-start:12px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-style:normal;color:var(--muted)}.cm-tooltip-autocomplete li[aria-selected] .cm-completionDetail{color:#ffffffd9}.livecode-run{padding:3px 10px;font-size:13px;margin-inline-start:6px}.console{display:flex;flex:none;flex-direction:column;gap:6px;height:180px;min-height:80px;padding:6px 10px 8px;background:var(--bg);border:1px solid var(--border);border-radius:8px}.console[hidden],.console-resizer[hidden]{display:none}.console-head{display:flex;align-items:center;gap:8px}.console-head h2{margin:0;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}.console-hide{margin-inline-start:auto;padding:0 8px;font-size:14px}.console-resizer{flex:none;height:10px;margin-block:-5px;cursor:row-resize;touch-action:none;position:relative}.console-resizer:after{content:"";position:absolute;inset-inline:0;top:4px;height:2px}.console-resizer:hover:after,.console-resizer:focus-visible:after,.console-resizer.dragging:after{background:var(--accent)}.console-resizer:focus-visible{outline:none}.livecode-console-lines{flex:1;min-height:0;overflow:auto;font-size:var(--code-size, 14px);white-space:pre-wrap}.livecode-console-lines .typed{color:var(--accent)}.livecode-console-lines .pending:after{content:"▌";color:var(--accent);animation:blink 1s steps(1) infinite}@keyframes blink{50%{opacity:0}}.livecode-console-input{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.livecode-console-input[hidden]{display:none}.livecode-console-input label{display:flex;flex:1;align-items:center;gap:6px;min-width:0;font-size:var(--code-size, 14px)}.livecode-console-input input{flex:1;min-width:60px;padding:4px 8px;font:inherit}.livecode-console-error,.livecode-console-notice{margin:0;font-size:13px;color:var(--muted)}.livecode-console-error{flex-basis:100%;color:#c62828}.livecode-console-notice.error{color:#c62828}.livecode-problem{margin:0;min-height:1.4em;font-size:13px;color:#c62828}.live-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.shell.live .live-resizer{display:block}.live-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.live-resizer:hover:after,.live-resizer:focus-visible:after,.shell.resizing .live-resizer:after{background:var(--accent)}.live-resizer:focus-visible{outline:none}@media(max-width:1100px){.livecode{width:340px}}@media(max-width:700px){.shell.learning .learn-resizer,.shell.live .live-resizer,.shell.files-open .files-resizer{display:none}.shell .files{width:auto!important;max-height:40vh;border-inline-end:none;border-bottom:1px solid var(--border)}.shell .learn,.shell .livecode,.columns>.app{width:auto!important;min-width:0}.livecode{height:40vh;height:40dvh;border-inline-start:none;border-top:1px solid var(--border)}.learn-rail{flex-direction:row;justify-content:center;width:auto;padding:4px 0;border-inline-end:none;border-bottom:1px solid var(--border)}.learn-rail span{writing-mode:horizontal-tb}.live-rail{border-inline-start:none;border-bottom:none;border-top:1px solid var(--border)}.columns{flex-direction:column}.editor-rail{border-inline-start:none;border-bottom:1px solid var(--border)}.learn{width:auto;height:45vh;height:45dvh;border-inline-end:none;border-bottom:1px solid var(--border)}.columns>.app,.shell.editor-hidden .livecode{flex:1;min-height:0;height:auto}}@media print{@page{margin:12mm}body>*:not(.print-sheet){display:none!important}body{background:#fff!important}.print-sheet{display:block}.print-sheet svg{display:block;width:100%;height:auto;max-height:100vh}}.learn .term{text-decoration:underline dotted var(--accent);text-decoration-thickness:2px;text-underline-offset:3px;cursor:help;border-radius:3px}.learn .term:focus-visible,.learn .term[aria-expanded=true]{outline:none;background:var(--accent-soft)}.term-tip{position:fixed;z-index:1000;max-width:min(300px,calc(100vw - 16px));padding:8px 10px;background:var(--panel);color:var(--text);border:1px solid var(--border);border-radius:8px;box-shadow:0 4px 16px #0000002e;font-size:14px;line-height:1.4}.term-tip[hidden]{display:none}.learn .ui-pointer{color:var(--accent);font-weight:600;border-bottom:2px solid var(--accent-soft);cursor:pointer;border-radius:3px}.learn .ui-pointer:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.ui-spot{outline:3px solid var(--accent)!important;outline-offset:-3px;box-shadow:inset 0 0 0 9999px var(--accent-faint);animation:ui-spot-pulse 1.2s ease-in-out infinite}@keyframes ui-spot-pulse{50%{outline-color:var(--accent-glow)}}@media(prefers-reduced-motion:reduce){.ui-spot{animation:none}}.learn-graphic{display:block;width:100%;max-width:440px;height:auto;margin:0 auto;border-radius:8px;border:1px solid var(--border)}.learn-graphic-toggle{display:block;width:100%;padding:0;border:0;background:none;cursor:zoom-in}.learn-graphic-toggle[aria-pressed=true]{cursor:zoom-out}.learn-graphic-hint{margin:4px 0 0;text-align:center;font-size:.85em;color:var(--muted)}.lesson-table{overflow-x:auto;margin:8px 0}.lesson-table table{border-collapse:collapse;font-size:13px;font-variant-numeric:tabular-nums}.lesson-table th,.lesson-table td{border:1px solid var(--border);padding:3px 8px;text-align:start;white-space:nowrap}.lesson-table th{background:var(--bg)}.learn-hints .lesson-note{margin-top:8px}.learn-teacher{margin-top:24px;border-top:1px solid var(--border);padding-top:12px}.learn-teacher summary{cursor:pointer;color:var(--muted)}.learn-teacher input{flex:1;min-width:0}.shell.editor-hidden:not(.live):not(.learning) .files{flex:1 1 0;width:auto!important}.livecode-swing{height:380px}.livecode-swing[hidden]{display:none}.livecode-swing-display{position:relative;flex:1;min-height:0;overflow:hidden;border-radius:6px;background:#e9ecf0}.learn-caesar-stage{display:flex;flex-direction:column;align-items:center;gap:8px}.learn-caesar-disc{width:min(100%,320px);touch-action:none;user-select:none;-webkit-user-select:none}.learn-caesar-disc text{font:600 19px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.learn-caesar-disc .outer-disc{fill:#f3e6c8;stroke:#8a6d3b;stroke-width:3}.learn-caesar-disc .outer-letters text{fill:#3d2f14;cursor:pointer}.learn-caesar-disc .inner{cursor:grab;transition:transform .25s ease}.learn-caesar-disc .inner.dragging{cursor:grabbing;transition:none}.learn-caesar-disc .inner-disc{fill:#6b4f2a;stroke:#3d2f14;stroke-width:2}.learn-caesar-disc .inner-letters text{fill:#fff8e8}.learn-caesar-disc .tick{stroke:#8a6d3b;stroke-width:1;opacity:.6}.learn-caesar-disc .hub{fill:#f3e6c8;stroke:#3d2f14;stroke-width:2}.learn-caesar-disc .window{fill:var(--accent-soft);stroke:var(--accent);stroke-width:2.5}.learn-caesar-disc .marked text{fill:var(--accent);font-size:23px}.learn-caesar-disc .inner-letters .marked text{fill:#ffd54a}.learn-caesar-disc .key{font-size:40px;font-weight:700;fill:#3d2f14}.learn-caesar-disc .key-label{font-size:15px;fill:#6e5a33}.learn-caesar-controls,.learn-caesar-mode{display:flex;justify-content:center;gap:8px}.learn-caesar-controls button{min-width:56px;font-size:1.05em}.learn-caesar-mode{margin:10px 0 6px}.learn-caesar-mode button.active{background:var(--accent);border-color:var(--accent);color:#fff}.learn-caesar-fields{display:grid;gap:8px}.learn-caesar-fields label,.learn-caesar-fields>div{display:grid;gap:3px;color:var(--muted);font-size:.9em}.learn-caesar-fields input,.learn-caesar-output{font:600 1.15em ui-monospace,Menlo,Consolas,monospace;letter-spacing:.08em;padding:6px 8px;border:1px solid var(--border);border-radius:8px;color:var(--text);background:var(--panel);overflow-wrap:anywhere}.learn-caesar-output{background:var(--bg)}.learn-rescue-path{display:flex;align-items:center;gap:6px;margin:8px 0 2px}.learn-rescue-ludwig{width:32px;height:32px;border-radius:50%;flex:none}.learn-rescue-dot{flex:1;height:6px;max-width:48px;border-radius:3px;background:var(--border);transition:background .3s}.learn-rescue-dot.done{background:#15803d}.learn-rescue-tower{position:relative;font-size:34px;line-height:1;margin-inline-start:auto}.learn-rescue-zora,.learn-rescue-fox{position:absolute;font-size:15px}.learn-rescue-zora{top:-4px;left:50%;transform:translate(-50%)}.learn-rescue-fox{bottom:-2px;right:-12px;transition:transform .8s,opacity .8s}.learn-rescue.freed .learn-rescue-fox{transform:translate(60px);opacity:0}.learn-rescue.freed .learn-rescue-zora{display:none}.learn-rescue-free{font-size:24px;line-height:1;animation:learn-rescue-jump .6s ease-out 3}@keyframes learn-rescue-jump{50%{transform:translateY(-12px)}}.learn-rescue-answer{display:flex;gap:8px;align-items:center}.learn-rescue-number{width:6ch;font-size:1.1em;padding:6px 8px;text-align:center}.learn-rescue-label{margin:14px 0 4px;color:var(--muted);font-size:.9em}.learn-rescue-alphabet{display:flex;flex-wrap:wrap;gap:2px;margin-bottom:12px}.learn-rescue-letter{display:inline-flex;flex-direction:column;align-items:center;min-width:22px;padding:2px 0;border-radius:4px;background:var(--bg)}.learn-rescue-letter small{font-size:10px;color:var(--muted)}.learn-rescue-letter.hit{background:#fde68a;outline:2px solid #d97706}.learn-rescue-charat{font-weight:600}.learn-rescue-moved{font-weight:400!important}.learn-rescue-word{font:inherit;padding:1px 4px;border:1px solid var(--accent);border-radius:4px}.learn-rescue-gate{padding:8px 0;margin-bottom:8px}.learn-cw{--cw-cell: 30px;display:flex;flex-wrap:wrap;gap:12px 20px;margin-bottom:10px}.learn-cw-grid{display:grid;gap:2px}.learn-cw-cell{position:relative;width:var(--cw-cell);height:var(--cw-cell)}.learn-cw-cell input{width:100%;height:100%;box-sizing:border-box;padding:0;border:1px solid #6e6e73;border-radius:3px;background:#fff;color:#1c1c1e;text-align:center;font:600 16px/1 ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase}.learn-cw-cell input:disabled{opacity:1;-webkit-text-fill-color:#1c1c1e}.learn-cw-cell.key input{background:#fde68a}.learn-cw-cell.given input{color:#1d4ed8;-webkit-text-fill-color:#1d4ed8}.learn-cw-cell.arrived input{animation:learn-cw-arrive .6s ease-out}.learn-cw-cell input.wrong{border-color:#b91c1c;background:#fee2e2}@keyframes learn-cw-arrive{0%{transform:scale(1.6)}}.learn-cw-number,.learn-cw-keyindex{position:absolute;font-size:8px;line-height:1;pointer-events:none;color:#6e6e73;z-index:1}.learn-cw-number{top:2px;left:2px}.learn-cw-keyindex{bottom:2px;right:2px;color:#b45309}.learn-cw-keyword{margin:8px 0 0;font-weight:600}.learn-cw-keybox{display:inline-block;width:22px;height:24px;margin-inline-end:2px;border-bottom:2px solid #d97706;background:#fef3c7;text-align:center;line-height:24px;white-space:pre}.learn-cw-cluebox{flex:1;min-width:200px}.learn-cw-clues{margin:4px 0 10px;padding-inline-start:24px}.learn-cw-clues li{cursor:pointer}@media(max-width:380px){.learn-cw{--cw-cell: 28px}}.learn-cloze{border:2px solid var(--accent);border-radius:12px;padding:12px 14px;margin:0 0 14px}.learn-cloze-title{display:block;font-size:1.05em;margin-bottom:4px}.learn-cloze p{margin:0 0 8px}.learn-cloze-hint{color:var(--muted);font-size:.9em}.learn-cloze-code{margin:0 0 10px;padding:8px 10px;border-radius:8px;background:var(--bg, #f2f2f7);font-size:13px;line-height:1.9;overflow-x:auto}.learn-cloze-code .ln{white-space:pre;min-height:1.9em}.learn-cloze-gap{font-size:13px;padding:1px 3px;margin:0 1px;min-width:0;max-width:none;border:1px solid #8e8e93;border-bottom-width:2px;border-radius:4px;background:#fff;color:#1c1c1e;text-align:center}.learn-cloze-gap.right{border-color:#34c759;background:#34c75924}.learn-cloze-gap.wrong{border-color:#ff3b30;background:#ff3b301a}.learn-cloze-gap.shown{border-color:#d97706;background:#fef3c7}.learn-cloze-gap:disabled{opacity:1;-webkit-text-fill-color:currentColor}.learn-cloze-actions{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.learn-cloze-check{font-weight:600}.learn-cloze-status:empty{display:none}.learn-cloze-status{padding:8px 12px;border-radius:8px;font-weight:600}.learn-cloze-status.right{background:#dcfce7}.learn-cloze-status.wrong{background:#fee2e2}.learn-pap{border:2px solid var(--accent);border-radius:12px;padding:12px 14px;margin:0 0 14px}.learn-pap-title{display:block;font-size:1.05em;margin-bottom:4px}.learn-pap p{margin:0 0 8px}.learn-pap-hint{color:var(--muted);font-size:.9em}.learn-pap-plan{display:block;width:100%;max-width:420px;margin:0 auto 10px;background:#fff;border-radius:8px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;fill:#1c1c1e}.learn-pap-slot{cursor:pointer;outline:none}.learn-pap-slot .learn-pap-shape{stroke:#8e8e93;stroke-width:2}.learn-pap-slot:focus-visible .learn-pap-shape,.learn-pap-slot.over .learn-pap-shape{stroke:var(--accent);stroke-width:3}.learn-pap-slot.right .learn-pap-shape{stroke:#34c759;stroke-width:3}.learn-pap-slot.wrong .learn-pap-shape{stroke:#ff3b30;stroke-width:3}.learn-pap-slot.shown .learn-pap-shape{stroke:#d97706}.learn-pap-legend{display:grid;grid-template-columns:auto 1fr;gap:4px 10px;align-items:center;max-width:420px;margin:0 auto 12px;padding:8px 10px;border-radius:8px;background:var(--bg, #f2f2f7);font-size:.9em}.learn-pap-legend dt{line-height:0}.learn-pap-legend dd{margin:0}.learn-pap-work{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);gap:8px;align-items:start;margin-bottom:10px}.learn-pap-work.done{grid-template-columns:minmax(0,1fr)}.learn-pap-left .learn-pap-plan{margin-bottom:8px}.learn-pap-tray{position:sticky;top:0;display:flex;flex-direction:column;align-items:center;gap:4px;max-height:100vh;overflow-y:auto;padding:6px 2px;border-radius:8px;background:var(--bg, #f2f2f7)}.learn-pap-tray:empty,.learn-pap-tray:not(:has(.learn-pap-card:not([hidden]))){display:none}.learn-pap-card svg{max-width:100%;height:auto}.learn-pap-card{padding:2px;max-width:100%;border:2px solid transparent;border-radius:10px;background:none;line-height:0;touch-action:none;cursor:grab;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;fill:#1c1c1e}.learn-pap-card.selected{border-color:var(--accent);background:var(--accent-soft)}.learn-pap-card.dragging{opacity:.3}.learn-pap-ghost{position:fixed;z-index:1000;pointer-events:none;transform:translate(-50%,-50%);opacity:.9}.learn-pap-actions{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.learn-pap-check{font-weight:600}.learn-pap-status:empty{display:none}.learn-pap-status{padding:8px 12px;border-radius:8px;font-weight:600}.learn-pap-status.right{background:#dcfce7}.learn-pap-status.wrong{background:#fee2e2}.learn-mark{color:inherit;padding:0 3px;border-radius:3px}.learn-mark.blau{background:#e4f1fd}.learn-mark.orange{background:#ffedd5}.learn-mark.gruen{background:#dcfce7}.learn-mark.gelb{background:#fdf4db}.learn-mark.rosa{background:#fce9f2}.startup-error{max-width:520px;margin:15vh auto 0;padding:0 16px;font:16px/1.5 system-ui,-apple-system,sans-serif;color:var(--text)}.startup-error h1{font-size:22px}.startup-error button{font-size:16px;padding:8px 16px}.startup-error pre{margin-top:24px;color:var(--muted);font-size:12px;white-space:pre-wrap}.visubot-stage{position:relative;height:280px;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:linear-gradient(#dfe9f3,#f6f3ec)}.visubot-live{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 8px;font-size:12px;color:var(--muted)}.visubot-live:empty{display:none}.visubot-live.connected{color:#0f8a5f;font-weight:600}.visubot-worlds{display:flex;gap:6px;margin:0 0 6px}.visubot-worlds button.active{background:var(--accent);border-color:var(--accent);color:#fff}.visubot-canvas{display:block;width:100%;height:100%;touch-action:none}.visubot-status{font-size:12px;color:var(--muted);margin:6px 0 0}.visubot-controls{margin-top:8px;font-size:13px}.visubot-controls summary{cursor:pointer;font-weight:600}.visubot-controls .hint{color:var(--muted);font-size:12px;margin:4px 0 6px}.visubot-controls label{display:grid;grid-template-columns:9.5em 1fr 2.5em;align-items:center;gap:6px;margin:2px 0}.visubot-controls output{text-align:end;font-variant-numeric:tabular-nums}.visubot-presses{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}.visubot-presses button{min-width:2.2em}.visubot-presses button.pressed{background:var(--accent);border-color:var(--accent);color:#fff}.visubot-check{margin-top:8px;font-size:13px}.visubot-check summary{cursor:pointer;font-weight:600}.visubot-check .hint{color:var(--muted);font-size:12px;margin:4px 0 6px}.visubot-check-sensors{margin-top:8px;border-collapse:collapse;font-variant-numeric:tabular-nums}.visubot-check-sensors th{text-align:start;font-weight:400;padding:1px 12px 1px 0}.palette-visubot-title{font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:14px 0 6px}.palette-sensor{display:flex;flex-direction:column;align-items:flex-start;gap:2px;border-style:dashed}.palette-sensor code{font-size:12px;color:var(--muted)}.palette-visubot .palette-item{border-color:#a7a0d3;background:color-mix(in srgb,#a7a0d3 16%,transparent)}.visubot-model{margin:12px 0}.visubot-model .visubot-stage{height:300px}.visubot-model-hint{font-size:13px;margin:4px 0 0}.visubot-part-label{position:absolute;pointer-events:none;padding:2px 8px;border-radius:6px;background:#14181ed9;color:#fff;font-size:13px;white-space:nowrap;z-index:1}.robot-part-link{text-decoration:underline 2px #f2b705;text-underline-offset:3px;cursor:pointer}.robot-part-link:hover,.robot-part-link:focus-visible{background:color-mix(in srgb,#f2b705 25%,transparent);outline:none}.visubot-quiz-question{font-size:15px;margin:12px 0 6px}.visubot-quiz-question.done{color:var(--success, #2f9e44)}.visubot-quiz-feedback{min-height:1.4em;margin:6px 0}.visubot-quiz-feedback.right{color:var(--success, #2f9e44)}.visubot-quiz-feedback.wrong{color:var(--danger, #c92a2a)}.diagram-tools .mbot-link{margin-inline-start:auto;height:30px;padding:0 10px;white-space:nowrap}.diagram-tools .mbot-link:not([hidden])+.sim-toggle,.diagram-tools .mbot-upload:not([hidden])+.sim-toggle{margin-inline-start:6px}.diagram-tools .mbot-upload{margin-inline-start:6px;height:30px;padding:0 10px;white-space:nowrap}.mbot-upload-steps{margin:0 0 12px;padding-inline-start:22px;line-height:1.5}.mbot-upload progress{width:100%;height:10px}.mbot-upload-status.done{color:var(--success, #2f9e44);font-weight:600}.settings-mbot-link{display:grid;gap:4px;margin-top:8px}.settings-mbot-link small{font-size:12px;color:var(--muted)}.world-chooser{margin-bottom:4px}.segmented.world-chooser{display:grid;grid-template-columns:1fr 1fr}.segmented.world-chooser button{border-radius:0;border-inline-start:1px solid var(--border)}.segmented.world-chooser button:nth-child(2n){border-inline-start:none}.segmented.world-chooser button:nth-child(n+3){border-top:none}.segmented.world-chooser button:first-child{border-start-start-radius:8px}.segmented.world-chooser button:nth-child(2){border-start-end-radius:8px}.segmented.world-chooser button:nth-last-child(2){border-end-start-radius:8px}.segmented.world-chooser button:last-child{border-end-end-radius:8px}.segmented.world-chooser button[aria-pressed=true]{border-color:var(--accent)}.world-hint{display:block;font-size:12px;color:var(--muted);margin-bottom:8px}.start-world{margin-bottom:14px}.robotpreview,.robotpreview-rail,.preview-resizer{display:none}.shell.robot-world.preview .robotpreview{display:flex}.shell.robot-world:not(.preview) .robotpreview-rail{display:flex;border-inline-end:none;border-inline-start:1px solid var(--border)}.robotpreview-rail svg{transform:scaleX(-1)}.shell.robot-world.preview:not(.preview-stacked) .preview-resizer{display:block}.robotpreview{flex:0 1 auto;width:360px;min-width:220px;flex-direction:column;gap:6px;padding:10px 12px 12px;background:var(--panel);border-inline-start:1px solid var(--border);min-height:0;overflow-y:auto}.robotpreview .hint{margin:0;font-size:.85em;color:var(--muted, inherit)}.robotpreview .robotpreview-stage{flex:1 1 auto;height:auto;min-height:160px}.robotpreview .robotpreview-status{margin:0;min-height:1.3em}.robotpreview-height{display:none}.robotpreview.simulation>.visubot-worlds,.robotpreview.simulation>.robotpreview-stage,.robotpreview.simulation>.robotpreview-status,.robotpreview.simulation .robotpreview-play{display:none}.robotpreview .visubot-viewport{display:flex;flex:1 1 auto;flex-direction:column;min-height:0}.robotpreview .visubot-viewport .visubot-stage{flex:1 1 auto;height:auto;min-height:160px}.visubot-elsewhere{display:none;margin:0 0 8px;font-size:12px;color:var(--muted)}.visubot:not(:has(>.visubot-viewport)) .visubot-elsewhere{display:block}.shell.preview-stacked .robotpreview{flex:0 0 auto;width:auto!important;height:320px;min-width:0;margin:4px -12px -12px;padding-top:0;border-inline-start:none;border-top:1px solid var(--border);overflow:visible}.shell.preview-stacked .robotpreview-height{display:block;height:10px;margin:-5px 0 0;cursor:row-resize;touch-action:none;position:relative}.robotpreview-height:after{content:"";position:absolute;inset-inline:0;top:4px;height:2px;background:transparent;transition:background .15s}.robotpreview-height:hover:after,.robotpreview-height:focus-visible:after,.shell.resizing .robotpreview-height:after{background:var(--accent)}.robotpreview-height:focus-visible{outline:none}.preview-resizer{flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.preview-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.preview-resizer:hover:after,.preview-resizer:focus-visible:after,.shell.resizing .preview-resizer:after{background:var(--accent)}.preview-resizer:focus-visible{outline:none}.palette-group{grid-column:1 / -1}.palette-group button{display:flex;align-items:center;gap:6px;width:100%;margin-top:4px;padding:2px 0;border:none;background:none;color:var(--muted);font-size:12px;font-weight:600;text-align:start;cursor:pointer}.palette-group button:before{content:"▾";transition:transform .15s}.palette-group button[aria-expanded=false]:before{transform:rotate(-90deg)}.palette-item[hidden]{display:none}.editor-resizer{display:none;flex:none;width:10px;margin-inline:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.editor-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.editor-resizer:hover:after,.editor-resizer:focus-visible:after,.shell.resizing .editor-resizer:after{background:var(--accent)}.editor-resizer:focus-visible{outline:none}.shell.code-main.live:not(.editor-hidden) .editor-resizer{display:block}.shell.code-main.live:not(.editor-hidden) .live-resizer{display:none}.shell.code-main.live:not(.editor-hidden) .app{flex:0 1 auto;width:460px;min-width:300px}.shell.code-main.live:not(.editor-hidden) .livecode{flex:1 1 0;width:auto!important;min-width:0}.shell.code-main.live:not(.editor-hidden) .livecode{order:1}.shell.code-main.live:not(.editor-hidden) .editor-resizer{order:2}.shell.code-main.live:not(.editor-hidden) .app{order:3;border-inline-start:1px solid var(--border)}.shell.code-main.live:not(.editor-hidden) .live-rail,.shell.code-main.live:not(.editor-hidden) .preview-resizer,.shell.code-main.live:not(.editor-hidden) .robotpreview,.shell.code-main.live:not(.editor-hidden) .robotpreview-rail{order:4}[data-action=swap-main]{font-size:16px;line-height:1}[data-action=swap-main][aria-pressed=true]{color:var(--accent)}.palette-resizer{grid-area:pal;justify-self:end;width:10px;margin-inline-end:-5px;z-index:5;cursor:col-resize;touch-action:none;position:relative}.palette-resizer:after{content:"";position:absolute;inset-block:0;inset-inline-start:4px;width:2px;background:transparent;transition:background .15s}.palette-resizer:hover:after,.palette-resizer:focus-visible:after,.shell.resizing .palette-resizer:after{background:var(--accent)}.palette-resizer:focus-visible{outline:none}.app.simulating .palette-resizer{display:none}:root.visuobject-theme{--bg: #edf4f6;--text: #17292e;--muted: #566a70;--border: #cddde1;--accent: #0e7c86;--accent-soft: rgba(14, 124, 134, .2);--accent-faint: rgba(14, 124, 134, .08);--accent-glow: rgba(14, 124, 134, .35)}.visuobject-obj,.visuobject .brand .logo{color:var(--accent)}.shell.visuobject button.text-button{padding:5px 10px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);font:inherit;cursor:pointer}.shell.visuobject button.text-button:hover{border-color:var(--accent);color:var(--accent)}:root.visuobject-theme{--vo-bar: #e3edf0}.vo-columns{display:grid;grid-template-columns:var(--vo-cols, 260px 1px minmax(0, 45fr) 1px minmax(0, 55fr));flex:1;min-height:0;border-top:1px solid var(--border)}.vo-columns.vo-resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.vo-pane{display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--panel)}.vo-pane.collapsed>:not(.vo-strip){display:none}.vo-strip{display:none;flex:1;align-items:center;justify-content:center;padding:12px 0;border:0;background:var(--vo-bar);color:var(--muted);font:600 14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;writing-mode:vertical-rl;cursor:pointer}.vo-pane.collapsed>.vo-strip{display:flex}.vo-strip:hover,.vo-strip:focus-visible{color:var(--accent);background:var(--accent-faint);outline:none}.vo-splitter{position:relative;z-index:4;background:var(--border);cursor:col-resize;touch-action:none;outline:none}.vo-splitter:after{content:"";position:absolute;top:0;right:-4px;bottom:0;left:-4px}.vo-splitter:hover,.vo-splitter:focus-visible,.vo-resizing .vo-splitter{background:var(--accent)}.vo-splitter.fixed{cursor:default;background:var(--border)}.vo-bar{display:flex;flex-wrap:wrap;align-items:stretch;min-height:40px;background:var(--vo-bar);border-bottom:1px solid var(--border);font-size:14px}.vo-bar-title{display:flex;flex:1;align-items:center;margin:0;text-transform:none;letter-spacing:normal;padding:0 12px;font-size:14px;font-weight:600;color:var(--text)}.vo-bar-actions{display:flex;flex:0 1 auto;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px;padding:4px 4px 4px 0}.shell.visuobject .vo-bar button.text-button{padding:2px 8px;border-radius:6px}.vo-collapse{padding:0 12px;border:0;background:none;color:var(--muted);font-size:16px;font-weight:700;cursor:pointer}.vo-collapse:hover,.vo-collapse:focus-visible{color:var(--accent)}.vo-tabs{display:flex;flex:1;min-width:0;overflow-x:auto}.vo-tab{display:flex;align-items:stretch;border-right:1px solid var(--border);border-bottom:3px solid transparent}.vo-tab.active{background:var(--panel);border-bottom-color:var(--accent)}.vo-tab [role=tab]{padding:0 4px 0 14px;border:0;background:none;color:var(--text);font:13px ui-monospace,SF Mono,Menlo,Consolas,monospace;white-space:nowrap;cursor:pointer}.vo-tab.active [role=tab]{font-weight:700}.vo-tab [role=tab]:hover{color:var(--accent)}.vo-tab-close{padding:0 10px 0 6px;border:0;background:none;color:var(--muted);font-size:15px;cursor:pointer;visibility:hidden}.vo-tab.active .vo-tab-close,.vo-tab:hover .vo-tab-close{visibility:visible}.vo-tab-close:hover{color:var(--accent)}.vo-tab-close .vo-dot,.vo-tab-close.unsaved .vo-x{display:none}.vo-tab-close.unsaved{visibility:visible;color:var(--text)}.vo-tab-close.unsaved .vo-dot{display:inline;font-size:11px}.vo-tab-close.unsaved:hover .vo-dot{display:none}.vo-tab-close.unsaved:hover .vo-x{display:inline}.vo-no-file{display:flex;align-items:center;padding:0 12px;color:var(--muted)}.vo-editor{flex:1;min-height:0;overflow:auto;font-size:14px}.vo-foot{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;padding:6px 12px;border-top:1px solid var(--border);background:var(--vo-bar)}.vo-hint{color:var(--muted);flex:1 1 260px}.vo-canvas{position:relative;flex:1;min-height:0;overflow:auto;background:radial-gradient(circle,var(--border) 1px,transparent 1px) 0 0 / 20px 20px;outline:none}.vo-frames{position:absolute;inset:0 auto auto 0;z-index:0;pointer-events:none;overflow:visible}.vo-package-frame{fill:#0e7c8609;stroke:var(--muted);stroke-width:1.2}.vo-package.current .vo-package-frame{stroke:var(--accent);fill:var(--accent-faint)}.vo-package-name{font:600 12px ui-monospace,SF Mono,Menlo,Consolas,monospace;fill:var(--muted)}.vo-package.current .vo-package-name{fill:var(--accent)}.vo-lines{position:absolute;inset:0 auto auto 0;z-index:3;pointer-events:none;overflow:visible}.vo-rel{stroke:var(--text);stroke-width:1.4;fill:none}.vo-rel.ghost{stroke:var(--accent);stroke-dasharray:4 4}.vo-hit{stroke:transparent;stroke-width:12;pointer-events:stroke;cursor:pointer}.vo-relation:hover .vo-rel,.vo-relation:hover .vo-diamond{stroke:var(--accent)}.vo-relation.selected .vo-rel,.vo-relation.selected .vo-diamond{stroke:var(--accent);stroke-width:2.4}.vo-relation.selected .vo-label-svg{fill:var(--accent)}.vo-diamond{fill:var(--panel);stroke:var(--text);stroke-width:1.4}.vo-diamond.filled{fill:var(--text)}.vo-relation.selected .vo-diamond.filled{fill:var(--accent)}.vo-label-svg.name{font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-style:italic;fill:var(--text)}.vo-rel.dashed{stroke-dasharray:6 4}.vo-hollow,.vo-open{fill:none;stroke:var(--text);stroke-width:1.4}.vo-label-svg{font:12px ui-monospace,SF Mono,Menlo,Consolas,monospace;fill:var(--muted);paint-order:stroke;stroke:var(--panel);stroke-width:4px}.vo-empty{margin:24px;max-width:40ch;color:var(--muted)}.vo-status{margin:0;color:#b3261e}.vo-status:empty{display:none}.vo-status.hint{color:var(--accent)}.uml-class{position:absolute;left:16px;top:16px;min-width:150px;background:var(--panel);border:1.5px solid var(--text);font:13px/1.5 ui-monospace,SF Mono,Menlo,Consolas,monospace;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.uml-connect{position:absolute;right:-11px;top:50%;width:20px;height:20px;margin-top:-10px;padding:0;border:2px solid var(--panel);border-radius:50%;background:var(--accent);box-shadow:0 1px 4px #00000040;cursor:crosshair;touch-action:none}.uml-connect:after{content:"";position:absolute;top:5px;right:4px;bottom:5px;left:5px;background:#fff;clip-path:polygon(0 35%,55% 35%,55% 0,100% 50%,55% 100%,55% 65%,0 65%)}.uml-class.drop{border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}.vo-relmenu{position:absolute;z-index:10;display:grid;min-width:220px;padding:6px;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #0000002e;font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-relmenu p{margin:2px 8px 6px;color:var(--muted);font-size:12px}.vo-relmenu button{display:flex;align-items:center;gap:10px;padding:6px 8px;border:0;border-radius:6px;background:none;color:var(--text);font:inherit;text-align:left;cursor:pointer}.vo-relmenu button:hover,.vo-relmenu button:focus-visible{background:var(--accent-faint);color:var(--accent);outline:none}.vo-relicon{flex:none}.vo-palette{display:flex;flex-wrap:wrap;align-items:stretch;gap:2px;padding:4px 6px;border-bottom:1px solid var(--border);background:var(--panel)}.vo-palette-sep{width:1px;margin:4px;background:var(--border)}.vo-tool{display:grid;justify-items:center;gap:1px;min-width:44px;padding:3px 3px 2px;border:1px solid transparent;border-radius:7px;background:none;color:var(--text);font:11px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer;touch-action:none;-webkit-user-select:none;user-select:none}.vo-tool:hover{background:var(--accent-faint);color:var(--accent)}.vo-tool[aria-pressed=true]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}.vo-tool[data-tool=class],.vo-tool[data-tool=interface]{cursor:grab}.vo-tool-ghost{position:fixed;z-index:1000;display:grid;justify-items:center;min-width:120px;padding:4px 10px 14px;margin:-14px 0 0 -60px;border:1.5px dashed var(--accent);background:#ffffffe6;font:13px ui-monospace,SF Mono,Menlo,Consolas,monospace;pointer-events:none}.vo-tool-ghost small{color:var(--muted);font-size:11px}.vo-canvas:not([data-tool=select])[data-tool]{cursor:crosshair}.vo-canvas:not([data-tool=select])[data-tool] .uml-class{cursor:crosshair}.vo-canvas:not([data-tool=select])[data-tool] .uml-class:hover,.uml-class.source{border-color:var(--accent)}.uml-class.source{box-shadow:0 0 0 4px var(--accent-soft)}.vo-stage{position:relative;display:flex;flex:1;min-height:0}.vo-stage .vo-canvas{flex:1}.vo-hsplit{flex:0 0 6px;margin:-3px 0;position:relative;z-index:5;cursor:row-resize;touch-action:none}.vo-hsplit:after{content:"";position:absolute;left:0;right:0;top:2px;height:2px;background:transparent}.vo-hsplit:hover:after,.vo-hsplit:focus-visible:after{background:var(--accent)}.vo-hsplit:focus-visible{outline:none}.vo-dock.collapsed+.vo-hsplit,.vo-hsplit:has(+.vo-dock.collapsed){cursor:default;pointer-events:none}.vo-dock{border-top:1px solid var(--border);background:var(--panel)}.vo-dock-bar{min-height:30px}.vo-dock-bar .vo-bar-title{font-size:13px}.vo-dock.collapsed .vo-inspector{display:none}.vo-inspector{display:grid;align-content:start;gap:8px;height:32vh;overflow:auto;padding:8px 12px 10px;font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-inspector-row>label.check,.vo-inspector label.check{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;padding-bottom:6px;color:var(--text);font-size:13px}.vo-inspector input[type=checkbox]{width:auto;margin:0;accent-color:var(--accent)}.vo-inspector fieldset.vo-inspector-ifaces{display:flex;flex-wrap:wrap;gap:4px 14px}.vo-inspector-empty{color:var(--muted)}.vo-inspector-row{display:flex;flex-wrap:wrap;align-items:end;gap:8px 12px}.vo-inspector-row>label{flex:1 1 160px;max-width:260px}.vo-inspector-ends{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:8px}.vo-inspector label{display:grid;gap:3px;color:var(--muted);font-size:12px}.vo-inspector input,.vo-inspector select{box-sizing:border-box;width:100%;min-width:0;padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-inspector input:focus,.vo-inspector select:focus{border-color:var(--accent);outline:2px solid var(--accent-soft)}.vo-inspector fieldset{display:grid;grid-template-columns:minmax(0,1fr) 84px;align-items:start;gap:6px;min-width:0;margin:0;padding:6px 8px 8px;border:1px solid var(--border);border-radius:8px}.vo-inspector fieldset .vo-wide{grid-column:1 / -1}.vo-reading{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px;color:var(--muted)}.vo-reading b{color:var(--text)}.shell.visuobject .vo-reading button.text-button{padding:1px 8px;font-size:12px}.vo-inspector legend{padding:0 4px;color:var(--text);font-weight:600}.vo-inspector small{color:var(--muted);font-size:11px}.vo-inspector p{margin:0}.vo-inspector-kind{font-weight:600;padding-top:4px}.shell.visuobject .vo-inspector button.vo-danger{display:inline-flex;align-items:center;justify-self:start;gap:6px;color:#b3261e}.vo-inspector .vo-danger svg{width:15px;height:15px}.vo-insp-head{position:sticky;top:-8px;z-index:1;margin-top:-8px;padding-top:8px;background:var(--panel);display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 12px;border-bottom:1px solid var(--border)}.vo-insp-head .vo-inspector-kind{padding:0}.vo-insp-tabs{display:flex;gap:2px}.shell.visuobject .vo-insp-tabs button{margin-bottom:-1px;padding:5px 12px;border:1px solid transparent;border-bottom:none;border-radius:6px 6px 0 0;background:none;color:var(--muted);font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer}.shell.visuobject .vo-insp-tabs button[aria-selected=true]{border-color:var(--border);background:var(--panel);color:var(--text);font-weight:600}.vo-members{width:100%;border-collapse:collapse}.vo-members th{padding:0 4px 3px;color:var(--muted);font-size:12px;font-weight:500;text-align:left}.vo-members td{padding:2px 4px;vertical-align:middle}.vo-members td.c{width:52px;text-align:center}.vo-members td:first-child{width:112px}.vo-members td:last-child{width:32px}.vo-members .icon svg{width:15px;height:15px}.vo-doc textarea{box-sizing:border-box;width:100%;max-width:780px;padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;resize:vertical}.vo-insp-sep{align-self:stretch;width:1px;margin:0 4px;background:var(--border)}.vo-insp-label{align-self:center;color:var(--muted);font-size:12px}.uml-class.selected{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);z-index:2}.uml-head{display:grid;justify-items:center;padding:4px 10px;font-weight:700}.uml-head small{font-weight:400;font-size:11px;color:var(--muted)}.uml-class.abstract .uml-name,.uml-member.abstract{font-style:italic}.uml-member.static{text-decoration:underline}.uml-class ul{list-style:none;margin:0;padding:3px 0;border-top:1.5px solid var(--text);min-height:12px}.uml-class.selected ul{border-top-color:var(--accent)}.uml-class li{padding:0 10px;white-space:nowrap}.uml-member.selected{background:var(--accent-soft)}.uml-add{color:var(--accent);font-style:italic;cursor:pointer;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:12px}.uml-add:hover{text-decoration:underline}.uml-input{font:inherit;padding:0 4px;margin:0 -5px;border:1px solid var(--accent);border-radius:4px;outline:none;max-width:340px}.uml-tools{display:flex;flex-wrap:wrap;gap:6px 10px;align-items:center;padding:6px 10px;border-top:1px dashed var(--border);font:12px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:default}.uml-tools label{display:inline-flex;gap:4px;align-items:center}.uml-tools button.icon svg{width:16px;height:16px}.vo-ws{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 10px 4px;font-size:13px}.vo-ws[hidden]{display:none}.vo-ws.ask{margin:8px 10px 4px;padding:10px;border:1px solid var(--accent);border-radius:8px;background:var(--bg, #fff)}.vo-ws.ask p{flex-basis:100%;margin:0}.vo-ws.ask .hint{color:var(--muted);font-size:12px;margin-bottom:4px}.vo-ws-name{display:inline-flex;align-items:center;gap:6px;margin-right:auto;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shell.visuobject .vo-ws button.text-button{padding:2px 8px;border-radius:6px}.shell.visuobject .vo-ws button.text-button.primary{background:var(--accent);border-color:var(--accent);color:#fff}.vo-lines .vo-end-hit{fill:transparent;pointer-events:all;cursor:context-menu}.vo-lines .vo-label-svg.editable{pointer-events:all;cursor:pointer}.vo-lines .vo-label-svg.editable:hover{fill:var(--accent);text-decoration:underline}.vo-lines .vo-label-svg.placeholder{fill:var(--muted);opacity:.6;font-style:italic}.vo-endpop{position:absolute;z-index:12;display:grid;gap:8px;width:min(330px,calc(100% - 16px));box-sizing:border-box;padding:10px 12px;background:var(--panel);border:1px solid var(--accent);border-radius:10px;box-shadow:0 8px 24px #00000029;font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-endpop p{margin:0}.vo-endpop label{display:grid;gap:3px;color:var(--muted);font-size:12px}.vo-endpop input{box-sizing:border-box;min-width:0;padding:4px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-endpop-row{display:flex;flex-wrap:wrap;align-items:center;gap:4px}.vo-endpop-row>span{flex-basis:100%;color:var(--muted);font-size:12px}.vo-endpop-row button{padding:2px 8px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:12px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer}.vo-endpop-row button[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:#fff}.vo-endpop-row input{width:64px}.vo-new{position:relative}.vo-new-menu{position:absolute;top:calc(100% + 4px);left:0;z-index:30;display:grid;min-width:190px;padding:4px;background:var(--panel);border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 24px #00000024}.vo-new-menu[hidden]{display:none}.vo-new-menu button{display:flex;align-items:center;gap:8px;padding:6px 8px;border:0;border-radius:6px;background:none;color:var(--text);font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;text-align:left;cursor:pointer}.vo-new-menu button:hover,.vo-new-menu button:focus-visible{background:var(--accent-soft);outline:none}.vo-badge.folder.source{box-shadow:inset 0 3px #ffffff59,inset -5px -4px #8a6d2b}.confirm-card.vo-wizard{display:grid;gap:10px;width:min(520px,100%);max-width:none;max-height:calc(100vh - 32px);overflow:auto;box-sizing:border-box;font:14px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-wizard h2{margin:0;font-size:17px}.vo-wizard .hint{margin:0;color:var(--muted);font-size:13px}.vo-wizard>label{display:grid;grid-template-columns:130px minmax(0,1fr);align-items:center;gap:8px;color:var(--muted);font-size:13px}.vo-wizard input[type=text],.vo-wizard select{box-sizing:border-box;width:100%;min-width:0;padding:5px 7px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:inherit}.vo-wizard fieldset{margin:0;padding:6px 10px 8px;border:1px solid var(--border);border-radius:8px}.vo-wizard legend{padding:0 4px;color:var(--muted);font-size:13px}.vo-wizard-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px}.vo-wizard-row select,.vo-wizard-row input[type=text]{width:auto;flex:1 1 160px}.vo-wizard-list{display:grid;gap:4px}.vo-wizard .check{display:inline-flex;align-items:center;gap:6px}.vo-wizard code{font-size:12px}.vo-wizard-error{min-height:1em;margin:0;color:#b3261e;font-size:13px}.vo-wizard .group button.primary{background:var(--accent);border-color:var(--accent);color:#fff}@media(max-width:560px){.vo-wizard>label{grid-template-columns:1fr}}.vo-dirty{color:var(--accent)}.vo-tree-tools{display:flex;flex-wrap:wrap;gap:6px;padding:8px 10px 4px}.shell.visuobject .vo-tree-tools button.text-button{padding:2px 8px;border-radius:6px}.vo-tree{flex:1;min-height:0;overflow:auto;padding:6px;font:13px/1.3 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.vo-tree ul{list-style:none;margin:0;padding:0}.vo-row{display:flex;align-items:center;gap:6px;min-height:28px;padding:0 6px 0 calc(4px + var(--depth, 0) * 14px);border-radius:7px;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;outline:none}.vo-row:hover{background:var(--accent-faint)}.vo-row:focus-visible{box-shadow:inset 0 0 0 2px var(--accent-soft)}.vo-row.active .vo-label{font-weight:600}.vo-row.selected{background:var(--accent-soft);color:var(--text)}.vo-twisty,.vo-twisty-space{flex:none;width:18px;height:18px}.vo-twisty{display:grid;place-items:center;padding:0;border:0;border-radius:4px;background:none;color:var(--muted);cursor:pointer}.vo-twisty svg{transition:transform .15s ease}[aria-expanded=true]>.vo-row .vo-twisty svg{transform:rotate(90deg)}.vo-twisty:hover{color:var(--accent)}.vo-label{min-width:0;overflow:hidden;text-overflow:ellipsis}.vo-type{color:var(--muted);font-size:12px;overflow:hidden;text-overflow:ellipsis}.vo-row .uml-input{margin:0;font:inherit}.vo-row-delete{margin-left:auto;visibility:hidden}.vo-tree button.vo-row-delete{width:24px;height:24px}.vo-tree button.vo-row-delete svg{width:14px;height:14px}.vo-row:hover .vo-row-delete,.vo-row.selected .vo-row-delete{visibility:visible}.vo-tree-empty{padding:6px 10px 6px 52px;color:var(--muted);font-size:12px;white-space:normal}.vo-badge{flex:none;display:inline-grid;place-items:center;width:16px;height:16px;border-radius:4px;font:700 10px/1 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#fff}.vo-badge.project{background:var(--accent);border-radius:5px;box-shadow:inset 0 -5px #0000002e}.vo-badge.project.closed{opacity:.55}.vo-badge.folder{width:17px;height:13px;border-radius:2px 4px 3px 3px;background:#e0a63b;box-shadow:inset 0 3px #ffffff59}.vo-badge.package{width:14px;height:14px;border-radius:3px;background:#b07a2a;transform:rotate(45deg) scale(.82)}.vo-badge.package.empty{background:none;border:1.5px solid #b07a2a}.vo-badge.file{background:#e66a2c;border-radius:3px 6px 3px 3px}.vo-badge.type.class{background:#2f7d32;border-radius:50%}.vo-badge.type.class.abstract{background:#6a9c3a;font-style:italic}.vo-badge.type.interface{background:#7b4fb0;border-radius:50%}.vo-badge.field,.vo-badge.method{width:9px;height:9px;margin:0 3px}.vo-badge.field{border-radius:2px}.vo-badge.method{border-radius:50%}.vo-badge.public{background:#2f9e44}.vo-badge.private{background:#d6453d}.vo-badge.protected{background:#e0a63b}.vo-badge.package.field,.vo-badge.package.method{background:#3b82c4;transform:none;border:0}.vo-badge.static{box-shadow:0 0 0 2px var(--panel),0 0 0 3px currentColor;color:var(--muted)}@media(max-width:760px){.vo-columns{grid-template-columns:1fr;grid-auto-rows:auto;overflow:auto}.vo-splitter{display:none}.vo-explorer:not(.collapsed){height:260px}.vo-code:not(.collapsed){height:320px}.vo-diagram:not(.collapsed){min-height:420px}.vo-pane{border-bottom:1px solid var(--border)}.vo-strip{writing-mode:horizontal-tb;padding:10px}}.shell.visuobject .vo-run-group button.vo-run{color:var(--accent);font-weight:600}.vo-console{display:flex;flex-direction:column;height:32vh;min-height:120px;border-top:1px solid var(--border)}.vo-console[hidden],.vo-swing[hidden]{display:none}.vo-console .vo-dock-bar{gap:10px}.vo-console-status{flex:1;color:var(--muted);font-size:12px}.vo-console-status.error{color:#b3261e}.vo-swing{display:flex;height:60%;padding:6px}.vo-console-lines{flex:1;min-height:0;overflow:auto;margin:0;padding:6px 12px;font-size:13px;white-space:pre-wrap}.uml-note{position:absolute;min-width:120px;max-width:260px;padding:8px 22px 8px 10px;background:#fffbe6;border:1.2px solid var(--text);clip-path:polygon(0 0,calc(100% - 14px) 0,100% 14px,100% 100%,0 100%);font:13px/1.45 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#17292e;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none;z-index:1}.uml-note:after{content:"";position:absolute;top:0;right:0;width:14px;height:14px;background:linear-gradient(to bottom left,transparent 50%,#e9dfae 50%);border-left:1.2px solid var(--text);border-bottom:1.2px solid var(--text)}.uml-note.selected{outline:3px solid var(--accent-soft);border-color:var(--accent);clip-path:none}.uml-note .uml-connect{z-index:2}.uml-note-text{white-space:pre-wrap;overflow-wrap:anywhere}.uml-note-text.placeholder{color:#8a8a8a;font-style:italic}.uml-note-edit{box-sizing:border-box;width:220px;border:1px solid var(--accent);background:#fffef5;font:inherit;resize:both}.vo-note-link{stroke-dasharray:5 4}.vo-canvas[hidden],.vo-palette[hidden]{display:none}.vo-diagram-switch{display:flex;gap:2px;padding:2px;border:1px solid var(--border);border-radius:8px;background:var(--panel)}.shell.visuobject .vo-diagram-switch button{padding:3px 10px;border:none;border-radius:6px;background:none;color:var(--muted);font:600 13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif;cursor:pointer}.shell.visuobject .vo-diagram-switch button[aria-selected=true]{background:var(--accent);color:#fff}.vo-obj-palette{align-items:center;gap:8px;padding:6px 10px}.vo-obj-new{display:flex;align-items:center;gap:6px;font-size:13px}.vo-obj-new select{padding:3px 6px;border:1px solid var(--border);border-radius:6px;background:var(--panel);color:var(--text);font:13px system-ui,-apple-system,Segoe UI,Roboto,sans-serif}.uml-object .uml-objname{text-decoration:underline;font-weight:600}.uml-object.unknown{border-style:dashed}.uml-object .uml-member.changed,.vo-objlink.changed{animation:vo-changed 1.2s ease-out}.uml-object .uml-member.changed{background:#fff3b0}@keyframes vo-changed{0%{background:#ffe066}}.vo-obj-values td:first-child{width:auto;white-space:nowrap}.vo-obj-values td:last-child{width:50%}.vo-dbg-controls{display:inline-flex;gap:2px}.vo-dbg-controls[hidden]{display:none}.vo-console-lines .vo-out-err{color:#b3261e}.vo-console-lines .vo-out-in{color:var(--accent);font-weight:600}.vo-console-input{display:flex;align-items:center;gap:6px;padding:4px 12px 8px;color:var(--accent)}.vo-console-input[hidden]{display:none}.vo-console-input input{flex:1;font-size:13px;padding:4px 6px;border:1px solid var(--accent);border-radius:4px}.vo-dbg{display:grid;grid-template-columns:minmax(160px,1fr) minmax(220px,2fr);gap:12px;padding:8px 12px}.vo-dbg h3{margin:0 0 6px;font-size:12px;font-weight:600;color:var(--muted)}.vo-dbg ol{list-style:none;margin:0;padding:0}.vo-dbg-frame{display:block;width:100%;text-align:start;padding:3px 6px;border:0;border-radius:4px;background:none;color:inherit;font:inherit;cursor:pointer}.vo-dbg-frame.on{background:var(--accent-soft)}.vo-dbg-frame small{color:var(--muted)}.vo-dbg-vars tr.changed td{background:#ffd60a59}@media(max-width:760px){.vo-dbg{grid-template-columns:1fr}}.vo-seqcanvas{overflow:auto}.vo-seqcanvas .vo-empty[hidden]{display:none}.vo-seq{display:block;font:12px ui-monospace,SFMono-Regular,Menlo,monospace}.vo-seq-head rect{fill:var(--panel);stroke:var(--text);stroke-width:1.2}.vo-seq-head text{fill:var(--text);text-decoration:underline}.vo-seq-head.static text{text-decoration:none;font-weight:600}.vo-seq-life{stroke:var(--muted);stroke-dasharray:5 4}.vo-seq-bar{fill:var(--panel);stroke:var(--text);stroke-width:1}.vo-seq-bar.running{fill:var(--accent-soft)}.vo-seq-msg{cursor:pointer}.vo-seq-msg line,.vo-seq-msg path{stroke:var(--text);stroke-width:1.2}.vo-seq-msg .head.filled{fill:var(--text)}.vo-seq-msg text{fill:var(--text)}.vo-seq-msg.return line,.vo-seq-msg.create line{stroke-dasharray:6 4}.vo-seq-msg.exception line,.vo-seq-msg.exception text{stroke:#b3261e;fill:#b3261e}.vo-seq-msg.current line,.vo-seq-msg.current path{stroke:#e0a800;stroke-width:2.4}.vo-seq-msg.current .head.filled{fill:#e0a800}.vo-seq-msg.current text{font-weight:700}.vo-seq-msg:hover text{fill:var(--accent)}.vo-seq-more{fill:var(--muted)}.palette-head{display:flex;align-items:center;gap:4px;margin:0 0 4px}.palette-head h2{flex:1;min-width:0;margin:0}.palette-hide{min-height:26px;padding:2px 5px}.app.compact-palette .palette-head{flex-direction:column;gap:2px}.palette-rail{display:none;grid-area:pal;width:auto}.app.palette-hidden .palette,.app.palette-hidden .palette-resizer{display:none}.app.palette-hidden:not(.simulating) .palette-rail{display:flex}@media(max-width:820px){.palette-head{display:none}.app.palette-hidden .palette{display:block}.app.palette-hidden .palette-rail{display:none!important}}.diagram-tools .pseudocode-toggle{gap:4px;margin:0 4px;white-space:nowrap;cursor:pointer}:root.visuflow-theme{--bg: #f3f0fb;--text: #221a35;--muted: #625a75;--border: #ddd6ee;--accent: #6f42c1;--accent-soft: rgba(111, 66, 193, .2);--accent-faint: rgba(111, 66, 193, .08);--accent-glow: rgba(111, 66, 193, .35)}.visuflow-flow{color:var(--accent)}.vf-logo{width:22px;height:22px;background:no-repeat center / contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236f42c1' stroke-width='2'%3E%3Crect x='6' y='1.5' width='12' height='5' rx='2.5'/%3E%3Cpath d='M12 6.5v3M12 9.5l5 4-5 4-5-4z M12 17.5v2'/%3E%3Crect x='7' y='19.5' width='10' height='3' rx='0.5'/%3E%3C/svg%3E")}.shell.visuflow button.text-button{padding:5px 10px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);font:inherit;cursor:pointer}.shell.visuflow button.text-button:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}.shell.visuflow button:disabled{opacity:.45;cursor:default}.vf-export{position:relative}.vf-menu{position:absolute;top:calc(100% + 6px);inset-inline-start:0;z-index:30;display:grid;min-width:190px;padding:4px;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:0 8px 24px #00000026}.vf-menu[hidden]{display:none}.vf-menu button{padding:8px 10px;border:0;border-radius:6px;background:none;color:var(--text);font:inherit;text-align:start;cursor:pointer}.vf-menu button:hover,.vf-menu button:focus-visible{background:var(--accent-faint);color:var(--accent)}.vf-main{display:flex;flex:1;min-height:0;border-top:1px solid var(--border)}.vf-palette{display:flex;flex-direction:column;gap:8px;width:190px;flex-shrink:0;padding:10px;overflow-x:hidden;overflow-y:auto;background:var(--panel);border-inline-end:1px solid var(--border)}.vf-palette h2{margin:0;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}.vf-shapes{display:grid;gap:6px}.vf-shape{display:flex;align-items:center;gap:8px;padding:4px 6px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);font:inherit;font-size:13px;text-align:start;cursor:grab;touch-action:none;-webkit-user-select:none;user-select:none}.vf-shape:hover,.vf-shape:focus-visible{border-color:var(--accent);background:var(--accent-faint)}.vf-shape svg{flex-shrink:0;width:48px;height:27px}.vf-hint{margin:4px 0 0;font-size:12px;line-height:1.4;color:var(--muted)}.vf-stage{display:flex;flex-direction:column;flex:1;min-width:0}.vf-titlebar{padding:8px 12px;background:var(--panel);border-bottom:1px solid var(--border)}.vf-title{width:min(420px,100%);padding:6px 8px;border:1px solid var(--border);border-radius:6px;font:inherit;font-weight:600}.vf-scroll{position:relative;flex:1;overflow:auto;background-color:#fff;background-image:radial-gradient(circle,#d9d4e6 1px,transparent 1.2px);background-size:20px 20px;background-attachment:local}.vf-canvas{display:block;touch-action:none;user-select:none;-webkit-user-select:none}.vf-node{cursor:move}.vf-node.selected>:first-child{stroke:var(--accent);stroke-width:3;filter:drop-shadow(0 0 4px var(--accent-glow))}.vf-node.drop-target>:first-child{stroke:var(--accent);stroke-width:3;stroke-dasharray:6 3}.vf-edge{cursor:pointer}.vf-edge.selected .vf-edge-line{stroke:var(--accent);stroke-width:3}.vf-port{cursor:crosshair}.vf-port-dot{fill:#fff;stroke:var(--accent);stroke-width:2}.vf-port.used .vf-port-dot{fill:var(--accent);opacity:.55}.vf-port:hover .vf-port-dot{fill:var(--accent);opacity:1}.vf-drag-line{stroke:var(--accent);stroke-width:2;stroke-dasharray:6 4;pointer-events:none}.vf-editor{position:absolute;z-index:5;box-sizing:border-box;padding:4px 6px;border:2px solid var(--accent);border-radius:6px;background:#fff;color:var(--text);font:14px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;line-height:16px;text-align:center;resize:none;overflow:hidden}.vf-ghost{position:fixed;z-index:100;pointer-events:none;transform:translate(-50%,-50%) scale(1.6);opacity:.85}.vf-status{margin:0;padding:6px 12px;font-size:12px;color:var(--muted);background:var(--panel);border-top:1px solid var(--border)}@media(max-width:700px){.vf-main{flex-direction:column}.vf-palette{flex-direction:row;width:auto;overflow-x:auto;border-inline-end:0;border-bottom:1px solid var(--border)}.vf-palette h2,.vf-hint{display:none}.vf-shapes{display:flex}.vf-shape{flex-direction:column;gap:2px;font-size:11px}} diff --git a/website/app/assets/it-ClGS2uQV.js b/website/app/assets/it-ClGS2uQV.js new file mode 100644 index 00000000..436c5511 --- /dev/null +++ b/website/app/assets/it-ClGS2uQV.js @@ -0,0 +1,180 @@ +const e=`/* Testi presenti solo nella versione web. Tutto il resto proviene dai Localizable.strings dell’app. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "Diagramma VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Canc"; +"web_key_shift" = "Maiusc"; +"web_export" = "Esporta…"; +"web_export_title" = "Salva come immagine o PDF, oppure stampa"; +"web_export_png" = "Immagine (PNG)"; +"web_export_svg" = "Grafica vettoriale (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "File VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "Esportazione non riuscita: %@"; +"web_print_hint" = "Usa “Esporta… → PDF” per salvare il diagramma e stamparlo da lì."; +"web_delete" = "Elimina"; +"web_language_title" = "Lingua dell’interfaccia"; +"web_simulation_start" = "Avvia simulazione"; +"web_simulation_end" = "Termina simulazione"; +"web_simulation_start_title" = "Esegui il diagramma passo dopo passo"; +"web_simulation_end_title" = "Termina la simulazione e continua a modificare"; +"web_palette_hint" = "Trascina nel diagramma"; +"web_tabs_label" = "Diagrammi"; +"web_status_modified" = "modificato"; +"web_inspector_title" = "Proprietà"; +"web_inspector_help_drop" = "Trascina gli elementi dalla tavolozza su un riquadro: in alto = prima, in basso = dopo, su “ø” = sostituisci. Gli elementi esistenti si possono spostare con il mouse."; +"web_inspector_help_files" = "Puoi anche trascinare file nella finestra."; +"web_case_name" = "Nome del caso"; +"web_case_name_placeholder" = "es. 1, ok, default"; +"web_copied" = "Elemento copiato."; +"web_discard_message_fmt" = "Le modifiche a “%@” andranno perse."; +"web_err_unreadable_fmt" = "“%@” non è un file VisuStruct leggibile (%@)."; +"web_saved_fmt" = "“%@” salvato."; +"web_saved_txt_fmt" = "Salvato come “%@”. Rimuovi l’estensione .txt per usarlo."; +"web_drop_impossible" = "Impossibile rilasciare qui"; +"web_sim_delay" = "Pausa per passo"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Linguaggio"; +"web_codegen_comments" = "Testo del diagramma come commenti"; +"web_codegen_empty_else" = "Genera ramo else vuoto nel codice"; +"web_copied_check" = "Copiato ✓"; +"web_copy_manual" = "Selezionato, premi Ctrl+C per copiare"; +"web_run_stopped_loop" = "Esecuzione interrotta: possibile ciclo infinito."; +"web_run_cancelled" = "Esecuzione annullata."; +"web_run_error" = "Errore durante l’esecuzione."; +"web_run_dropped_fmt" = "… %d righe precedenti nascoste"; +"web_sim_call_arguments_fmt" = "La chiamata non corrisponde all’intestazione di %@. Controlla i valori tra parentesi."; +"web_sim_missing_return_fmt" = "%@ è terminato senza restituire un valore con return."; +"web_sim_file_not_found_fmt" = "Non esiste nessun file chiamato %@."; +"web_sim_end_of_file_fmt" = "Il file %@ non ha più righe."; +"web_sim_null_value_fmt" = "%@ è null."; +"web_sim_written_file_fmt" = "%@ (salvato)"; +"web_site_home" = "Pagina iniziale"; +"web_site_imprint" = "Note legali"; +"web_site_privacy" = "Privacy"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Programmazione"; +"web_live_hide" = "Nascondi programmazione"; +"web_scale_canvas" = "Dimensione testo: diagramma"; +"web_scale_code" = "Dimensione testo: programmazione"; +"web_live_indent" = "Indenta"; +"web_live_indent_title" = "Indenta il codice: quattro spazi per livello (righe selezionate, altrimenti tutto)"; +"web_live_show" = "Mostra programmazione"; +"web_live_resize" = "Modifica la larghezza dell’area codice (doppio clic: ripristina)"; +"web_live_hint" = "Il codice cresce con il tuo diagramma. Grigio = segnaposto: scrivi nell’ispettore e il tuo testo appare qui. Clicca su una riga per selezionarne l’elemento."; +"web_live_ph_selector" = "variabile"; +"web_live_ph_code" = "Il tuo codice"; +"web_live_ph_end" = "fine"; +"web_live_language" = "Linguaggio di programmazione"; +"web_live_java_class" = "Come classe"; +"web_live_java_class_hint" = "Nome della classe = titolo del diagramma"; +"web_live_java_main" = "Con metodo main"; +"web_settings_display" = "Visualizzazione"; +"web_live_swing" = "Java vero (con Swing)"; +"web_live_swing_hint" = "Java vero con finestre (CheerpJ). Scarica circa 40 MB una sola volta, alla prima esecuzione."; +"web_live_swing_windows" = "Finestre Java"; +"web_live_swing_hide" = "Chiudi finestre Java"; +"web_live_swing_loading" = "Caricamento di Java (circa 40 MB la prima volta) …"; +"web_live_swing_compiling" = "Compilazione …"; +"web_live_swing_running" = "Il programma è in esecuzione."; +"web_live_swing_compile_failed" = "Errore di compilazione, vedi sopra."; +"web_live_swing_failed" = "Impossibile caricare Java. Controlla la connessione a internet."; +"web_live_hint_edit" = "Scrivi qui codice Java e il diagramma si costruisce da solo. Oppure lavora nel diagramma e il codice cresce con lui. Grigio = segnaposto, basta scriverci sopra."; +"web_live_edit_label" = "Codice Java"; +"web_parse_line_fmt" = "Riga %d: %@"; +"web_parse_missing" = "Qui manca ancora: %@"; +"web_parse_extra" = "Di troppo: %@"; +"web_parse_unclosed_string" = "Manca il %@ di chiusura."; +"web_parse_else_without_if" = "Questo «else» non ha un «if»."; +"web_parse_case_outside_switch" = "«case» e «default» vanno dentro uno «switch»."; +"web_parse_missing_do_while" = "Dopo «do { … }» manca ancora «while (condizione);»."; +"web_parse_more_methods" = "Per ora qui conta un solo metodo. Crea gli altri sottoprogrammi in schede separate."; +"web_parse_missing_import" = "Manca %@ in cima. Senza questa riga Java non conosce Scanner."; +"web_parse_missing_scanner" = "Manca prima %@ Senza questa riga lo Scanner non esiste."; +"web_parse_unknown_type" = "Java non conosce questo tipo di dato. Intendevi %@?"; +"web_editor_title" = "Diagramma"; +"web_editor_show" = "Mostra diagramma"; +"web_editor_hide" = "Nascondi diagramma"; +"web_keywords_title" = "Parole chiave del codice"; +"web_keywords_hint" = "if, while, for al posto dei nomi degli elementi"; +"web_palette_compact" = "Elementi sempre compatti"; +"web_palette_compact_hint" = "Simbolo con il nome piccolo sotto, altrimenti solo con la colonna stretta"; +"web_about_version_fmt" = "Versione %@"; +"web_about_software" = "Software utilizzato"; +"web_about_software_text" = "L’editor di codice usa CodeMirror e Lezer (licenza MIT). Con il supporto Swing, VisuStruct carica CheerpJ di Leaning Technologies (licenza Community) e javac di OpenJDK."; +"web_about_licenses" = "Testi delle licenze"; +"web_live_run" = "Esegui"; +"web_live_run_title" = "Esegui il programma: output e input compaiono sotto"; +"web_live_run_finished" = "Programma terminato."; +"web_live_run_stopped" = "Fermato."; +"web_console" = "Console"; +"web_console_hide" = "Nascondi console"; +"web_console_resize" = "Ridimensiona la console"; +"web_diagram_tools" = "Strumenti del diagramma"; +"web_files_title" = "File"; +"web_files_show" = "Mostra file"; +"web_files_hide" = "Nascondi file"; +"web_files_resize" = "Ridimensiona file"; +"web_files_new_folder" = "Nuova cartella"; +"web_files_switch" = "Scegli un’altra cartella"; +"web_files_delete" = "Elimina"; +"web_files_in_browser" = "Nella memoria di questo browser"; +"web_files_save_hint_fmt" = "Salvando, il programma va in %@."; +"web_files_empty" = "Ancora niente di salvato. Quando salvi, VisuStruct crea qui una cartella con la data di oggi."; +"web_files_reconnect_hint" = "Dopo il ricaricamento il browser chiede di nuovo se VisuStruct può usare la tua cartella."; +"web_files_reconnect_fmt" = "Apri la cartella «%@»"; +"web_files_connect_hint" = "Scegli una cartella come spazio di lavoro. VisuStruct vi crea una cartella per ogni giorno e salva diagramma e codice."; +"web_files_connect" = "Scegli cartella"; +"web_files_browser_hint" = "Questo browser non può aprire cartelle del dispositivo (per esempio su iPad). I tuoi file restano nella memoria di questo browser."; +"web_files_browser" = "Salva nel browser"; +"web_files_delete_confirm_fmt" = "Eliminare davvero «%@»?"; +"web_files_folder_prompt" = "Nome della nuova cartella:"; +"web_files_default_name" = "Programma"; +"web_files_saved_fmt" = "Salvato: %@"; +"web_files_create" = "Crea"; +"web_learn_ludwig_tip" = "Il consiglio di Ludwig"; +"web_game_title" = "Gioco: Vero o falso?"; +"web_game_intro" = "Ludwig ti mostra dei valori e una condizione. È vera (true) o falsa (false)? Dieci turni, sempre più difficili."; +"web_game_start" = "Inizia il gioco"; +"web_game_round_fmt" = "Turno %@ di %@"; +"web_game_score_fmt" = "Punti: %@"; +"web_game_true" = "vero (true)"; +"web_game_false" = "falso (false)"; +"web_game_right" = "Giusto!"; +"web_game_wrong" = "Non proprio. Ecco il calcolo:"; +"web_game_next" = "Avanti"; +"web_game_finish" = "Risultato"; +"web_game_done_fmt" = "%@ su %@ giuste."; +"web_game_perfect" = "Tutto giusto – Ludwig è davvero colpito!"; +"web_game_good" = "Ottimo! Riguarda gli errori e riprova."; +"web_game_practice" = "La pratica rende perfetti. Rileggi la tabella di verità e gioca un altro turno."; +"web_game_again" = "Gioca ancora"; +"web_game_wrong_short" = "Peccato, è sbagliato."; +"web_game_practice_short" = "La pratica rende perfetti. Rileggi le spiegazioni e gioca un altro turno."; +"web_game_clicks" = "Clic:"; +"web_game_nobody" = "Nessuno ascolta: non succede nulla."; +"web_game_event_fmt" = "Clic su «%@»: l'ascoltatore lo sente ed esegue il suo codice."; +"web_game_try" = "Ora prova tu i pulsanti della finestra."; +"web_game_time_fmt" = "Ancora %@ s"; +"web_game_defused" = "✂️ Disinnescata! Hai trovato l’errore."; +"web_game_boom_time" = "💥 Bum! Il tempo è scaduto."; +"web_game_boom_wrong" = "💥 Bum! Era la riga sbagliata."; +"web_game_fix" = "La riga corretta:"; +"web_game_order_hint" = "Tocca i passaggi nell’ordine giusto."; +"web_debug_step" = "Passo singolo"; +"web_debug_step_title" = "Passo singolo: esegui un’istruzione e fermati di nuovo"; +"web_debug_continue" = "Continua fino al prossimo punto di interruzione"; +"web_debug_paused_fmt" = "Fermo prima della riga %d."; +"web_debug_gutter_title" = "Clicca sul numero di riga per mettere o togliere un punto di interruzione"; +"web_swap_to_code" = "Programmazione grande"; +"web_swap_to_editor" = "Diagramma grande"; +"web_editor_resize" = "Modifica la larghezza del diagramma"; +"web_palette_resize" = "Modifica la larghezza degli elementi"; +"web_palette_hide" = "Nascondi elementi"; +"web_palette_show" = "Mostra elementi"; +"web_code_scopes" = "Blocchi di codice colorati"; +"web_code_scopes_hint" = "Classe, metodo, ciclo, selezione in riquadri propri"; +"web_pseudocode" = "Pseudocodice"; +`;export{e as default}; diff --git a/website/app/assets/ja-JQ8MwNFB.js b/website/app/assets/ja-JQ8MwNFB.js new file mode 100644 index 00000000..7c5d2739 --- /dev/null +++ b/website/app/assets/ja-JQ8MwNFB.js @@ -0,0 +1,180 @@ +const e=`/* Web 版にのみ存在するテキスト。その他はすべてアプリの Localizable.strings から取得されます。 */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct 構造図"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Delete"; +"web_key_shift" = "Shift"; +"web_export" = "エクスポート…"; +"web_export_title" = "画像または PDF として保存、または印刷"; +"web_export_png" = "画像(PNG)"; +"web_export_svg" = "ベクター画像(SVG)"; +"web_export_pdf" = "PDF(A4)"; +"web_export_visustruct" = "VisuStruct ファイル(.visustruct)"; +"web_export_failed_fmt" = "エクスポートに失敗しました:%@"; +"web_print_hint" = "「エクスポート… → PDF」で図を保存し、そこから印刷してください。"; +"web_delete" = "削除"; +"web_language_title" = "表示言語"; +"web_simulation_start" = "シミュレーション開始"; +"web_simulation_end" = "シミュレーション終了"; +"web_simulation_start_title" = "構造図をステップごとに実行"; +"web_simulation_end_title" = "シミュレーションを終了して編集を続ける"; +"web_palette_hint" = "構造図にドラッグ"; +"web_tabs_label" = "図"; +"web_status_modified" = "変更あり"; +"web_inspector_title" = "プロパティ"; +"web_inspector_help_drop" = "パレットの要素をタイルにドラッグ:上 = 前に、下 = 後に、「ø」の上 = 置き換え。既存の要素はマウスで移動できます。"; +"web_inspector_help_files" = "ファイルをウインドウにドロップすることもできます。"; +"web_case_name" = "ケース名"; +"web_case_name_placeholder" = "例:1, ok, default"; +"web_copied" = "要素をコピーしました。"; +"web_discard_message_fmt" = "「%@」への変更は失われます。"; +"web_err_unreadable_fmt" = "「%@」は読み込める VisuStruct ファイルではありません(%@)。"; +"web_saved_fmt" = "「%@」を保存しました。"; +"web_saved_txt_fmt" = "「%@」として保存しました。使用するには拡張子 .txt を削除してください。"; +"web_drop_impossible" = "ここにはドロップできません"; +"web_sim_delay" = "ステップごとの待ち時間"; +"web_sim_delay_value_fmt" = "%@ 秒"; +"web_codegen_language" = "言語"; +"web_codegen_comments" = "図のテキストをコメントとして出力"; +"web_codegen_empty_else" = "空の else 分岐もコードに出力"; +"web_copied_check" = "コピーしました ✓"; +"web_copy_manual" = "選択済み。Ctrl+C でコピーしてください"; +"web_run_stopped_loop" = "実行を停止しました:無限ループの可能性があります。"; +"web_run_cancelled" = "実行を中止しました。"; +"web_run_error" = "実行中にエラーが発生しました。"; +"web_run_dropped_fmt" = "… 以前の %d 行は非表示"; +"web_sim_call_arguments_fmt" = "呼び出しが %@ の見出しと一致しません。かっこ内の値を確認してください。"; +"web_sim_missing_return_fmt" = "%@ は return で値を返さずに終了しました。"; +"web_sim_file_not_found_fmt" = "%@ という名前のファイルはありません。"; +"web_sim_end_of_file_fmt" = "ファイル %@ にはもう行がありません。"; +"web_sim_null_value_fmt" = "%@ は null です。"; +"web_sim_written_file_fmt" = "%@(保存済み)"; +"web_site_home" = "ホームページ"; +"web_site_imprint" = "運営者情報"; +"web_site_privacy" = "プライバシー"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "プログラミング"; +"web_live_hide" = "プログラミングを隠す"; +"web_scale_canvas" = "文字サイズ: 構造化チャート"; +"web_scale_code" = "文字サイズ: プログラミング"; +"web_live_indent" = "インデント"; +"web_live_indent_title" = "コードをインデント: 1 レベルにつき空白 4 つ(選択した行、なければ全体)"; +"web_live_show" = "プログラミングを表示"; +"web_live_resize" = "コード領域の幅を変更(ダブルクリック:リセット)"; +"web_live_hint" = "コードは図と一緒に育ちます。灰色=プレースホルダー:インスペクタに入力するとここに表示されます。行をクリックすると要素を選択します。"; +"web_live_ph_selector" = "変数"; +"web_live_ph_code" = "ここにコード"; +"web_live_ph_end" = "終了"; +"web_live_language" = "プログラミング言語"; +"web_live_java_class" = "クラスとして"; +"web_live_java_class_hint" = "クラス名 = 図のタイトル"; +"web_live_java_main" = "main メソッド付き"; +"web_settings_display" = "表示"; +"web_live_swing" = "本物の Java(Swing 対応)"; +"web_live_swing_hint" = "ウィンドウ付きの本物の Java(CheerpJ)。初回実行時に一度だけ約 40 MB をダウンロードします。"; +"web_live_swing_windows" = "Java ウィンドウ"; +"web_live_swing_hide" = "Java ウィンドウを閉じる"; +"web_live_swing_loading" = "Java を読み込み中(初回は約 40 MB)…"; +"web_live_swing_compiling" = "コンパイル中…"; +"web_live_swing_running" = "プログラム実行中。"; +"web_live_swing_compile_failed" = "コンパイルエラー。上を見てください。"; +"web_live_swing_failed" = "Java を読み込めませんでした。インターネット接続を確認してください。"; +"web_live_hint_edit" = "ここに Java コードを入力すると、図が一緒にできあがります。図で作業すると、コードも一緒に育ちます。灰色=プレースホルダー、そのまま上書きできます。"; +"web_live_edit_label" = "Java コード"; +"web_parse_line_fmt" = "%d 行目: %@"; +"web_parse_missing" = "ここにまだ足りません: %@"; +"web_parse_extra" = "多すぎます: %@"; +"web_parse_unclosed_string" = "閉じる %@ がありません。"; +"web_parse_else_without_if" = "この「else」に対応する「if」がありません。"; +"web_parse_case_outside_switch" = "「case」と「default」は「switch」の中に書きます。"; +"web_parse_missing_do_while" = "「do { … }」の後に「while (条件);」が必要です。"; +"web_parse_more_methods" = "今はここでメソッドを 1 つだけ使います。ほかのサブプログラムは別のタブに作ってください。"; +"web_parse_missing_import" = "先頭に %@ がありません。この行がないと Java は Scanner を知りません。"; +"web_parse_missing_scanner" = "先に %@ がありません。この行がないと Scanner はありません。"; +"web_parse_unknown_type" = "Java はこのデータ型を知りません。%@ のことですか?"; +"web_editor_title" = "構造図"; +"web_editor_show" = "構造図を表示"; +"web_editor_hide" = "構造図を隠す"; +"web_keywords_title" = "コードのキーワード"; +"web_keywords_hint" = "要素名の代わりに if, while, for"; +"web_palette_compact" = "要素を常にコンパクト表示"; +"web_palette_compact_hint" = "記号の下に小さく名前を表示。オフの場合は列が狭いときのみ"; +"web_about_version_fmt" = "バージョン %@"; +"web_about_software" = "使用しているソフトウェア"; +"web_about_software_text" = "コードエディターは CodeMirror と Lezer(MIT ライセンス)を使用しています。Swing サポートを有効にすると、VisuStruct は Leaning Technologies の CheerpJ(Community ライセンス)と OpenJDK の javac を読み込みます。"; +"web_about_licenses" = "ライセンス文"; +"web_live_run" = "実行"; +"web_live_run_title" = "プログラムを実行:出力と入力は下に表示されます"; +"web_live_run_finished" = "プログラムが終了しました。"; +"web_live_run_stopped" = "停止しました。"; +"web_console" = "コンソール"; +"web_console_hide" = "コンソールを隠す"; +"web_console_resize" = "コンソールの高さを変更"; +"web_diagram_tools" = "図のツール"; +"web_files_title" = "ファイル"; +"web_files_show" = "ファイルを表示"; +"web_files_hide" = "ファイルを隠す"; +"web_files_resize" = "ファイルの幅を変更"; +"web_files_new_folder" = "新しいフォルダ"; +"web_files_switch" = "別のフォルダを選ぶ"; +"web_files_delete" = "削除"; +"web_files_in_browser" = "このブラウザのストレージ"; +"web_files_save_hint_fmt" = "保存すると、プログラムは %@ に入ります。"; +"web_files_empty" = "まだ何も保存されていません。保存すると、VisuStruct がここに今日の日付のフォルダを作ります。"; +"web_files_reconnect_hint" = "再読み込み後、VisuStruct がフォルダを使ってよいか、ブラウザがもう一度たずねます。"; +"web_files_reconnect_fmt" = "フォルダ「%@」を開く"; +"web_files_connect_hint" = "作業フォルダを選んでください。VisuStruct が日付ごとのフォルダを作り、図とコードを保存します。"; +"web_files_connect" = "フォルダを選ぶ"; +"web_files_browser_hint" = "このブラウザは端末のフォルダを開けません(例:iPad)。ファイルはこのブラウザのストレージに残ります。"; +"web_files_browser" = "ブラウザに保存"; +"web_files_delete_confirm_fmt" = "「%@」を削除しますか?"; +"web_files_folder_prompt" = "新しいフォルダの名前:"; +"web_files_default_name" = "プログラム"; +"web_files_saved_fmt" = "保存しました:%@"; +"web_files_create" = "作成"; +"web_learn_ludwig_tip" = "ルートヴィヒのヒント"; +"web_game_title" = "ゲーム:真か偽か?"; +"web_game_intro" = "ルートヴィヒが値と条件を見せます。条件は真(true)?それとも偽(false)?10ラウンド、だんだん難しくなります。"; +"web_game_start" = "ゲームを始める"; +"web_game_round_fmt" = "ラウンド %@ / %@"; +"web_game_score_fmt" = "ポイント:%@"; +"web_game_true" = "真(true)"; +"web_game_false" = "偽(false)"; +"web_game_right" = "正解!"; +"web_game_wrong" = "残念。計算はこうなります:"; +"web_game_next" = "次へ"; +"web_game_finish" = "結果"; +"web_game_done_fmt" = "%@ / %@ 正解。"; +"web_game_perfect" = "全問正解――ルートヴィヒも感心しています!"; +"web_game_good" = "すごい!間違えたところを見直して、もう一度やってみよう。"; +"web_game_practice" = "練習あるのみ。上の真理値表をもう一度読んで、もう一回挑戦しよう。"; +"web_game_again" = "もう一度"; +"web_game_wrong_short" = "残念、不正解です。"; +"web_game_practice_short" = "習うより慣れよ。説明をもう一度読んで、もう一回遊んでみよう。"; +"web_game_clicks" = "クリック:"; +"web_game_nobody" = "だれも聞いていません。何も起こりません。"; +"web_game_event_fmt" = "「%@」をクリック: リスナーが気づいて自分のコードを実行します。"; +"web_game_try" = "ウィンドウのボタンを自分で試してみよう。"; +"web_game_time_fmt" = "残り %@ 秒"; +"web_game_defused" = "✂️ 解除成功!間違いを見つけました。"; +"web_game_boom_time" = "💥 ドカン!時間切れです。"; +"web_game_boom_wrong" = "💥 ドカン!その行ではありません。"; +"web_game_fix" = "正しい行:"; +"web_game_order_hint" = "正しい順番でステップをタップしよう。"; +"web_debug_step" = "ステップ実行"; +"web_debug_step_title" = "ステップ実行:命令を1つ実行して再び止まる"; +"web_debug_continue" = "次のブレークポイントまで続行"; +"web_debug_paused_fmt" = "%d 行目の前で一時停止中。"; +"web_debug_gutter_title" = "行番号をクリックするとブレークポイントを設定・解除できます"; +"web_swap_to_code" = "プログラミングを大きく"; +"web_swap_to_editor" = "構造図を大きく"; +"web_editor_resize" = "構造図の幅を変更"; +"web_palette_resize" = "要素の幅を変更"; +"web_palette_hide" = "要素を隠す"; +"web_palette_show" = "要素を表示"; +"web_code_scopes" = "コードブロックを色分け"; +"web_code_scopes_hint" = "クラス、メソッド、ループ、分岐をそれぞれの枠で表示"; +"web_pseudocode" = "疑似コード"; +`;export{e as default}; diff --git a/website/app/assets/kino-saal-BOvcmdzb.svg b/website/app/assets/kino-saal-BOvcmdzb.svg new file mode 100644 index 00000000..65dc50de --- /dev/null +++ b/website/app/assets/kino-saal-BOvcmdzb.svg @@ -0,0 +1,32 @@ + + + +Ecrã +Lugar (segundo índice) +0 +1 +2 +3 +4 +Fila(primeiroíndice) +0 +false +false +true +false +false +1 +false +true +true +false +false +2 +false +false +false +false +false +Tracejado: lugares[1][2], fila 1, lugar 2 +vendido = truelivre = false + diff --git a/website/app/assets/kino-saal-C8zaJk4X.svg b/website/app/assets/kino-saal-C8zaJk4X.svg new file mode 100644 index 00000000..4e49fc22 --- /dev/null +++ b/website/app/assets/kino-saal-C8zaJk4X.svg @@ -0,0 +1,32 @@ + + + +Screen +Seat (second index) +0 +1 +2 +3 +4 +Row(firstindex) +0 +false +false +true +false +false +1 +false +true +true +false +false +2 +false +false +false +false +false +Dashed: seats[1][2], row 1, seat 2 +sold = truefree = false + diff --git a/website/app/assets/kino-saal-CYMOok4_.svg b/website/app/assets/kino-saal-CYMOok4_.svg new file mode 100644 index 00000000..18c5a30a --- /dev/null +++ b/website/app/assets/kino-saal-CYMOok4_.svg @@ -0,0 +1,32 @@ + + + +Leinwand +Platz (zweiter Index) +0 +1 +2 +3 +4 +Reihe(ersterIndex) +0 +false +false +true +false +false +1 +false +true +true +false +false +2 +false +false +false +false +false +Gestrichelt: sitze[1][2], Reihe 1, Platz 2 +verkauft = truefrei = false + diff --git a/website/app/assets/kino-schleifen-Ci9yPnbo.svg b/website/app/assets/kino-schleifen-Ci9yPnbo.svg new file mode 100644 index 00000000..c9788f21 --- /dev/null +++ b/website/app/assets/kino-schleifen-Ci9yPnbo.svg @@ -0,0 +1,49 @@ + + + +ciclo exterior: fila = 0, 1, 2 +ciclo interior: lugar = 0 … 4 +lugares[fila][lugar]ver +lugar +0 +1 +2 +3 +4 +fila0 + +1 + +2 + +3 + +4 + +5 + +fila1 + +6 + +7 + +8 + +9 + +10 + +fila2 + +11 + +12 + +13 + +14 + +15 +Lá dentro, lugar percorre tudo; só depois fila avança um. + diff --git a/website/app/assets/kino-schleifen-D7sfo9iK.svg b/website/app/assets/kino-schleifen-D7sfo9iK.svg new file mode 100644 index 00000000..2698fc0a --- /dev/null +++ b/website/app/assets/kino-schleifen-D7sfo9iK.svg @@ -0,0 +1,49 @@ + + + +outer loop: row = 0, 1, 2 +inner loop: seat = 0 … 4 +seats[row][seat]look at +seat +0 +1 +2 +3 +4 +row0 + +1 + +2 + +3 + +4 + +5 + +row1 + +6 + +7 + +8 + +9 + +10 + +row2 + +11 + +12 + +13 + +14 + +15 +Inside, seat runs through, only then row moves on by one. + diff --git a/website/app/assets/kino-schleifen-DrTQV7dq.svg b/website/app/assets/kino-schleifen-DrTQV7dq.svg new file mode 100644 index 00000000..486b7ca5 --- /dev/null +++ b/website/app/assets/kino-schleifen-DrTQV7dq.svg @@ -0,0 +1,49 @@ + + + +äußere Schleife: reihe = 0, 1, 2 +innere Schleife: platz = 0 … 4 +sitze[reihe][platz]ansehen +platz +0 +1 +2 +3 +4 +reihe0 + +1 + +2 + +3 + +4 + +5 + +reihe1 + +6 + +7 + +8 + +9 + +10 + +reihe2 + +11 + +12 + +13 + +14 + +15 +Innen läuft platz durch, erst dann geht reihe eins weiter. + diff --git a/website/app/assets/ko-tfdKG8Fb.js b/website/app/assets/ko-tfdKG8Fb.js new file mode 100644 index 00000000..6753303e --- /dev/null +++ b/website/app/assets/ko-tfdKG8Fb.js @@ -0,0 +1,180 @@ +const e=`/* 웹 버전에만 있는 텍스트입니다. 나머지는 모두 앱의 Localizable.strings에서 가져옵니다. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct 구조도"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "내보내기…"; +"web_export_title" = "이미지 또는 PDF로 저장하거나 인쇄"; +"web_export_png" = "이미지(PNG)"; +"web_export_svg" = "벡터 그래픽(SVG)"; +"web_export_pdf" = "PDF(A4)"; +"web_export_visustruct" = "VisuStruct 파일(.visustruct)"; +"web_export_failed_fmt" = "내보내기 실패: %@"; +"web_print_hint" = "“내보내기… → PDF”로 다이어그램을 저장한 뒤 인쇄하세요."; +"web_delete" = "삭제"; +"web_language_title" = "인터페이스 언어"; +"web_simulation_start" = "시뮬레이션 시작"; +"web_simulation_end" = "시뮬레이션 종료"; +"web_simulation_start_title" = "구조도를 단계별로 실행"; +"web_simulation_end_title" = "시뮬레이션을 끝내고 계속 편집"; +"web_palette_hint" = "구조도로 드래그하세요"; +"web_tabs_label" = "다이어그램"; +"web_status_modified" = "수정됨"; +"web_inspector_title" = "속성"; +"web_inspector_help_drop" = "팔레트의 요소를 타일로 드래그하세요: 위쪽 = 앞에, 아래쪽 = 뒤에, “ø” 위 = 바꾸기. 기존 요소는 마우스로 옮길 수 있습니다."; +"web_inspector_help_files" = "파일을 창에 끌어다 놓을 수도 있습니다."; +"web_case_name" = "케이스 이름"; +"web_case_name_placeholder" = "예: 1, ok, default"; +"web_copied" = "요소를 복사했습니다."; +"web_discard_message_fmt" = "“%@”의 변경 사항이 사라집니다."; +"web_err_unreadable_fmt" = "“%@”은(는) 읽을 수 있는 VisuStruct 파일이 아닙니다(%@)."; +"web_saved_fmt" = "“%@” 저장됨."; +"web_saved_txt_fmt" = "“%@”(으)로 저장했습니다. 사용하려면 .txt 확장자를 제거하세요."; +"web_drop_impossible" = "여기에 놓을 수 없음"; +"web_sim_delay" = "단계별 대기 시간"; +"web_sim_delay_value_fmt" = "%@초"; +"web_codegen_language" = "언어"; +"web_codegen_comments" = "다이어그램 텍스트를 주석으로"; +"web_codegen_empty_else" = "빈 else 분기도 코드에 출력"; +"web_copied_check" = "복사됨 ✓"; +"web_copy_manual" = "선택됨, Ctrl+C로 복사하세요"; +"web_run_stopped_loop" = "실행 중지: 무한 반복일 수 있습니다."; +"web_run_cancelled" = "실행이 취소되었습니다."; +"web_run_error" = "실행 중 오류가 발생했습니다."; +"web_run_dropped_fmt" = "… 이전 %d줄 숨김"; +"web_sim_call_arguments_fmt" = "호출이 %@의 머리글과 맞지 않습니다. 괄호 안의 값을 확인하세요."; +"web_sim_missing_return_fmt" = "%@이(가) return으로 값을 반환하지 않고 끝났습니다."; +"web_sim_file_not_found_fmt" = "%@(이)라는 파일이 없습니다."; +"web_sim_end_of_file_fmt" = "파일 %@에 더 이상 줄이 없습니다."; +"web_sim_null_value_fmt" = "%@은(는) null입니다."; +"web_sim_written_file_fmt" = "%@ (저장됨)"; +"web_site_home" = "홈페이지"; +"web_site_imprint" = "사이트 정보"; +"web_site_privacy" = "개인정보"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "프로그래밍"; +"web_live_hide" = "프로그래밍 숨기기"; +"web_scale_canvas" = "글자 크기: 구조도"; +"web_scale_code" = "글자 크기: 프로그래밍"; +"web_live_indent" = "들여쓰기"; +"web_live_indent_title" = "코드 들여쓰기: 단계마다 공백 4칸 (선택한 줄, 없으면 전체)"; +"web_live_show" = "프로그래밍 표시"; +"web_live_resize" = "코드 영역 너비 변경(더블클릭: 초기화)"; +"web_live_hint" = "코드는 다이어그램과 함께 자랍니다. 회색 = 자리 표시자: 속성 창에 입력하면 여기에 표시됩니다. 줄을 클릭하면 해당 요소가 선택됩니다."; +"web_live_ph_selector" = "변수"; +"web_live_ph_code" = "코드 작성"; +"web_live_ph_end" = "끝"; +"web_live_language" = "프로그래밍 언어"; +"web_live_java_class" = "클래스로"; +"web_live_java_class_hint" = "클래스 이름 = 순서도 제목"; +"web_live_java_main" = "main 메서드 포함"; +"web_settings_display" = "표시"; +"web_live_swing" = "실제 Java (Swing 포함)"; +"web_live_swing_hint" = "창이 있는 진짜 Java(CheerpJ). 처음 실행할 때 한 번 약 40MB를 내려받습니다."; +"web_live_swing_windows" = "Java 창"; +"web_live_swing_hide" = "Java 창 닫기"; +"web_live_swing_loading" = "Java 불러오는 중(처음에는 약 40MB) …"; +"web_live_swing_compiling" = "컴파일 중 …"; +"web_live_swing_running" = "프로그램 실행 중."; +"web_live_swing_compile_failed" = "컴파일 오류, 위를 보세요."; +"web_live_swing_failed" = "Java를 불러올 수 없습니다. 인터넷 연결을 확인하세요."; +"web_live_hint_edit" = "여기에 Java 코드를 입력하면 순서도가 함께 만들어집니다. 또는 순서도에서 작업하면 코드가 함께 자랍니다. 회색 = 자리표시자, 그대로 덮어쓰면 됩니다."; +"web_live_edit_label" = "Java 코드"; +"web_parse_line_fmt" = "%d행: %@"; +"web_parse_missing" = "여기에 아직 없음: %@"; +"web_parse_extra" = "하나 더 많음: %@"; +"web_parse_unclosed_string" = "닫는 %@가 없습니다."; +"web_parse_else_without_if" = "이 “else”에 맞는 “if”가 없습니다."; +"web_parse_case_outside_switch" = "“case”와 “default”는 “switch” 안에 있어야 합니다."; +"web_parse_missing_do_while" = "“do { … }” 다음에 “while (조건);”이 필요합니다."; +"web_parse_more_methods" = "지금은 메서드 하나만 사용됩니다. 다른 서브프로그램은 별도 탭으로 만드세요."; +"web_parse_missing_import" = "맨 위에 %@ 이(가) 없습니다. 이 줄이 없으면 Java는 Scanner를 모릅니다."; +"web_parse_missing_scanner" = "먼저 %@ 이(가) 없습니다. 이 줄이 없으면 Scanner가 없습니다."; +"web_parse_unknown_type" = "Java는 이 데이터 형식을 알지 못합니다. %@을(를) 의미했나요?"; +"web_editor_title" = "구조도"; +"web_editor_show" = "구조도 표시"; +"web_editor_hide" = "구조도 숨기기"; +"web_keywords_title" = "코드 키워드"; +"web_keywords_hint" = "요소 이름 대신 if, while, for"; +"web_palette_compact" = "요소 항상 간단히 보기"; +"web_palette_compact_hint" = "기호 아래에 작은 이름 표시, 아니면 열이 좁을 때만"; +"web_about_version_fmt" = "버전 %@"; +"web_about_software" = "사용된 소프트웨어"; +"web_about_software_text" = "코드 편집기는 CodeMirror와 Lezer(MIT 라이선스)를 사용합니다. Swing 지원을 켜면 VisuStruct는 Leaning Technologies의 CheerpJ(Community 라이선스)와 OpenJDK의 javac를 불러옵니다."; +"web_about_licenses" = "라이선스 전문"; +"web_live_run" = "실행"; +"web_live_run_title" = "프로그램 실행: 출력과 입력이 아래에 표시됩니다"; +"web_live_run_finished" = "프로그램이 끝났습니다."; +"web_live_run_stopped" = "중지됨."; +"web_console" = "콘솔"; +"web_console_hide" = "콘솔 숨기기"; +"web_console_resize" = "콘솔 크기 조절"; +"web_diagram_tools" = "다이어그램 도구"; +"web_files_title" = "파일"; +"web_files_show" = "파일 보기"; +"web_files_hide" = "파일 숨기기"; +"web_files_resize" = "파일 너비 조절"; +"web_files_new_folder" = "새 폴더"; +"web_files_switch" = "다른 폴더 선택"; +"web_files_delete" = "삭제"; +"web_files_in_browser" = "이 브라우저 저장소"; +"web_files_save_hint_fmt" = "저장하면 프로그램이 %@에 들어갑니다."; +"web_files_empty" = "아직 저장된 것이 없습니다. 저장하면 VisuStruct가 여기에 오늘 날짜 폴더를 만듭니다."; +"web_files_reconnect_hint" = "새로 고침 후 브라우저가 VisuStruct의 폴더 사용 여부를 다시 묻습니다."; +"web_files_reconnect_fmt" = "“%@” 폴더 열기"; +"web_files_connect_hint" = "작업 공간으로 쓸 폴더를 선택하세요. VisuStruct가 날짜별 폴더를 만들고 다이어그램과 코드를 저장합니다."; +"web_files_connect" = "폴더 선택"; +"web_files_browser_hint" = "이 브라우저는 기기의 폴더를 열 수 없습니다 (예: iPad). 파일은 이 브라우저 저장소에 남습니다."; +"web_files_browser" = "브라우저에 저장"; +"web_files_delete_confirm_fmt" = "“%@”을(를) 삭제할까요?"; +"web_files_folder_prompt" = "새 폴더 이름:"; +"web_files_default_name" = "프로그램"; +"web_files_saved_fmt" = "저장됨: %@"; +"web_files_create" = "만들기"; +"web_learn_ludwig_tip" = "루트비히의 팁"; +"web_game_title" = "게임: 참일까 거짓일까?"; +"web_game_intro" = "루트비히가 값과 조건을 보여 줍니다. 조건이 참(true)일까요, 거짓(false)일까요? 10라운드, 점점 어려워집니다."; +"web_game_start" = "게임 시작"; +"web_game_round_fmt" = "라운드 %@ / %@"; +"web_game_score_fmt" = "점수: %@"; +"web_game_true" = "참 (true)"; +"web_game_false" = "거짓 (false)"; +"web_game_right" = "정답!"; +"web_game_wrong" = "아쉽네요. 이렇게 계산합니다:"; +"web_game_next" = "다음"; +"web_game_finish" = "결과"; +"web_game_done_fmt" = "%@ / %@ 정답."; +"web_game_perfect" = "모두 정답 – 루트비히가 감탄했어요!"; +"web_game_good" = "훌륭해요! 틀린 것을 다시 보고 한 번 더 해 보세요."; +"web_game_practice" = "연습이 실력을 만듭니다. 위의 진리표를 다시 읽고 한 번 더 해 보세요."; +"web_game_again" = "다시 하기"; +"web_game_wrong_short" = "아쉽지만 틀렸어요."; +"web_game_practice_short" = "연습이 완벽을 만듭니다. 설명을 다시 읽고 한 판 더 해 보세요."; +"web_game_clicks" = "클릭:"; +"web_game_nobody" = "아무도 듣지 않아요. 아무 일도 일어나지 않습니다."; +"web_game_event_fmt" = "„%@” 클릭: 리스너가 듣고 자기 코드를 실행합니다."; +"web_game_try" = "이제 창의 버튼을 직접 눌러 보세요."; +"web_game_time_fmt" = "%@초 남음"; +"web_game_defused" = "✂️ 해체 성공! 오류를 찾았어요."; +"web_game_boom_time" = "💥 펑! 시간이 다 됐어요."; +"web_game_boom_wrong" = "💥 펑! 틀린 줄이었어요."; +"web_game_fix" = "올바른 줄:"; +"web_game_order_hint" = "올바른 순서대로 단계를 눌러 보세요."; +"web_debug_step" = "한 단계"; +"web_debug_step_title" = "한 단계: 문장 하나를 실행하고 다시 멈춥니다"; +"web_debug_continue" = "다음 중단점까지 계속"; +"web_debug_paused_fmt" = "%d번째 줄 앞에서 멈춤."; +"web_debug_gutter_title" = "줄 번호를 클릭하면 중단점을 설정하거나 지웁니다"; +"web_swap_to_code" = "프로그래밍 크게"; +"web_swap_to_editor" = "구조도 크게"; +"web_editor_resize" = "구조도 너비 변경"; +"web_palette_resize" = "요소 너비 변경"; +"web_palette_hide" = "요소 숨기기"; +"web_palette_show" = "요소 표시"; +"web_code_scopes" = "코드 블록 색상 표시"; +"web_code_scopes_hint" = "클래스, 메서드, 반복, 분기를 각각의 상자로 표시"; +"web_pseudocode" = "의사 코드"; +`;export{e as default}; diff --git a/website/app/assets/l03-lochkarte-BB3rWQOm.svg b/website/app/assets/l03-lochkarte-BB3rWQOm.svg new file mode 100644 index 00000000..8eea3c50 --- /dev/null +++ b/website/app/assets/l03-lochkarte-BB3rWQOm.svg @@ -0,0 +1,998 @@ + + + + +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 +14 +14 +15 +15 +16 +16 +17 +17 +18 +18 +19 +19 +20 +20 +21 +21 +22 +22 +23 +23 +24 +24 +25 +25 +26 +26 +27 +27 +28 +28 +29 +29 +30 +30 +31 +31 +32 +32 +33 +33 +34 +34 +35 +35 +36 +36 +37 +37 +38 +38 +39 +39 +40 +40 +41 +41 +42 +42 +43 +43 +44 +44 +45 +45 +46 +46 +47 +47 +48 +48 +49 +49 +50 +50 +51 +51 +52 +52 +53 +53 +54 +54 +55 +55 +56 +56 +57 +57 +58 +58 +59 +59 +60 +60 +61 +61 +62 +62 +63 +63 +64 +64 +65 +65 +66 +66 +67 +67 +68 +68 +69 +69 +70 +70 +71 +71 +72 +72 +73 +73 +74 +74 +75 +75 +76 +76 +77 +77 +78 +78 +79 +79 +80 +80 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +P + +0 +1 +2 +3 +4 +5 +6 + +8 +9 +R + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +I + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +N + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +T + +1 +2 + +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +* + +0 +1 +2 +3 + +5 +6 +7 + +9 +, + +1 +2 + +4 +5 +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +H + +0 +1 +2 +3 +4 +5 +6 +7 + +9 +E + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +W + +1 +2 +3 +4 +5 + +7 +8 +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +R + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +D + +0 +1 +2 +3 + +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + diff --git a/website/app/assets/l03-lochkarte-BSn6oWaS.svg b/website/app/assets/l03-lochkarte-BSn6oWaS.svg new file mode 100644 index 00000000..1b08640f --- /dev/null +++ b/website/app/assets/l03-lochkarte-BSn6oWaS.svg @@ -0,0 +1,994 @@ + + + + +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 +14 +14 +15 +15 +16 +16 +17 +17 +18 +18 +19 +19 +20 +20 +21 +21 +22 +22 +23 +23 +24 +24 +25 +25 +26 +26 +27 +27 +28 +28 +29 +29 +30 +30 +31 +31 +32 +32 +33 +33 +34 +34 +35 +35 +36 +36 +37 +37 +38 +38 +39 +39 +40 +40 +41 +41 +42 +42 +43 +43 +44 +44 +45 +45 +46 +46 +47 +47 +48 +48 +49 +49 +50 +50 +51 +51 +52 +52 +53 +53 +54 +54 +55 +55 +56 +56 +57 +57 +58 +58 +59 +59 +60 +60 +61 +61 +62 +62 +63 +63 +64 +64 +65 +65 +66 +66 +67 +67 +68 +68 +69 +69 +70 +70 +71 +71 +72 +72 +73 +73 +74 +74 +75 +75 +76 +76 +77 +77 +78 +78 +79 +79 +80 +80 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +P + +0 +1 +2 +3 +4 +5 +6 + +8 +9 +R + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +I + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +N + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +T + +1 +2 + +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +* + +0 +1 +2 +3 + +5 +6 +7 + +9 +, + +1 +2 + +4 +5 +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +A + +0 + +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +M + +0 +1 +2 +3 + +5 +6 +7 +8 +9 +U + +1 +2 +3 + +5 +6 +7 +8 +9 +N + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +D + +0 +1 +2 +3 + +5 +6 +7 +8 +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + diff --git a/website/app/assets/l03-lochkarte-beschriftet-7hmU_7ct.svg b/website/app/assets/l03-lochkarte-beschriftet-7hmU_7ct.svg new file mode 100644 index 00000000..ac9ff74d --- /dev/null +++ b/website/app/assets/l03-lochkarte-beschriftet-7hmU_7ct.svg @@ -0,0 +1,1016 @@ + + + + + + +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 +14 +14 +15 +15 +16 +16 +17 +17 +18 +18 +19 +19 +20 +20 +21 +21 +22 +22 +23 +23 +24 +24 +25 +25 +26 +26 +27 +27 +28 +28 +29 +29 +30 +30 +31 +31 +32 +32 +33 +33 +34 +34 +35 +35 +36 +36 +37 +37 +38 +38 +39 +39 +40 +40 +41 +41 +42 +42 +43 +43 +44 +44 +45 +45 +46 +46 +47 +47 +48 +48 +49 +49 +50 +50 +51 +51 +52 +52 +53 +53 +54 +54 +55 +55 +56 +56 +57 +57 +58 +58 +59 +59 +60 +60 +61 +61 +62 +62 +63 +63 +64 +64 +65 +65 +66 +66 +67 +67 +68 +68 +69 +69 +70 +70 +71 +71 +72 +72 +73 +73 +74 +74 +75 +75 +76 +76 +77 +77 +78 +78 +79 +79 +80 +80 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +P + +0 +1 +2 +3 +4 +5 +6 + +8 +9 +R + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +I + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +N + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +T + +1 +2 + +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +* + +0 +1 +2 +3 + +5 +6 +7 + +9 +, + +1 +2 + +4 +5 +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +H + +0 +1 +2 +3 +4 +5 +6 +7 + +9 +A + +0 + +2 +3 +4 +5 +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +W + +1 +2 +3 +4 +5 + +7 +8 +9 +E + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +T + +1 +2 + +4 +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + + + +Ecke abgeschnitten: +so liegen alle Karten richtig herum + +Aufdruck zum Mitlesen + + + + +Zeilen 12 und 11: Extralöcher für Buchstaben +1 Spalte = 1 Zeichen +hier P: Löcher in 11 und 7 + +gestanztes Loch + + +80 Spalten = höchstens 80 Zeichen pro Zeile + diff --git a/website/app/assets/l03-lochkarte-beschriftet-BjBFZjzb.svg b/website/app/assets/l03-lochkarte-beschriftet-BjBFZjzb.svg new file mode 100644 index 00000000..b5080535 --- /dev/null +++ b/website/app/assets/l03-lochkarte-beschriftet-BjBFZjzb.svg @@ -0,0 +1,1019 @@ + + + + + + +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 +14 +14 +15 +15 +16 +16 +17 +17 +18 +18 +19 +19 +20 +20 +21 +21 +22 +22 +23 +23 +24 +24 +25 +25 +26 +26 +27 +27 +28 +28 +29 +29 +30 +30 +31 +31 +32 +32 +33 +33 +34 +34 +35 +35 +36 +36 +37 +37 +38 +38 +39 +39 +40 +40 +41 +41 +42 +42 +43 +43 +44 +44 +45 +45 +46 +46 +47 +47 +48 +48 +49 +49 +50 +50 +51 +51 +52 +52 +53 +53 +54 +54 +55 +55 +56 +56 +57 +57 +58 +58 +59 +59 +60 +60 +61 +61 +62 +62 +63 +63 +64 +64 +65 +65 +66 +66 +67 +67 +68 +68 +69 +69 +70 +70 +71 +71 +72 +72 +73 +73 +74 +74 +75 +75 +76 +76 +77 +77 +78 +78 +79 +79 +80 +80 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +P + +0 +1 +2 +3 +4 +5 +6 + +8 +9 +R + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +I + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +N + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +T + +1 +2 + +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +* + +0 +1 +2 +3 + +5 +6 +7 + +9 +, + +1 +2 + +4 +5 +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +H + +0 +1 +2 +3 +4 +5 +6 +7 + +9 +E + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +W + +1 +2 +3 +4 +5 + +7 +8 +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +R + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +D + +0 +1 +2 +3 + +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + + + +Cut corner: +so all cards lie the right way round + +Printed text to read along + + + + +Rows 12 and 11: extra holes for letters +1 column = 1 character +here P: holes in 11 and 7 + +punched hole + + +80 columns = at most 80 characters per line + diff --git a/website/app/assets/l03-lochkarte-beschriftet-D1QjqGFo.svg b/website/app/assets/l03-lochkarte-beschriftet-D1QjqGFo.svg new file mode 100644 index 00000000..89cefb22 --- /dev/null +++ b/website/app/assets/l03-lochkarte-beschriftet-D1QjqGFo.svg @@ -0,0 +1,1015 @@ + + + + + + +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 +14 +14 +15 +15 +16 +16 +17 +17 +18 +18 +19 +19 +20 +20 +21 +21 +22 +22 +23 +23 +24 +24 +25 +25 +26 +26 +27 +27 +28 +28 +29 +29 +30 +30 +31 +31 +32 +32 +33 +33 +34 +34 +35 +35 +36 +36 +37 +37 +38 +38 +39 +39 +40 +40 +41 +41 +42 +42 +43 +43 +44 +44 +45 +45 +46 +46 +47 +47 +48 +48 +49 +49 +50 +50 +51 +51 +52 +52 +53 +53 +54 +54 +55 +55 +56 +56 +57 +57 +58 +58 +59 +59 +60 +60 +61 +61 +62 +62 +63 +63 +64 +64 +65 +65 +66 +66 +67 +67 +68 +68 +69 +69 +70 +70 +71 +71 +72 +72 +73 +73 +74 +74 +75 +75 +76 +76 +77 +77 +78 +78 +79 +79 +80 +80 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +P + +0 +1 +2 +3 +4 +5 +6 + +8 +9 +R + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +I + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +N + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +T + +1 +2 + +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +* + +0 +1 +2 +3 + +5 +6 +7 + +9 +, + +1 +2 + +4 +5 +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +A + +0 + +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +M + +0 +1 +2 +3 + +5 +6 +7 +8 +9 +U + +1 +2 +3 + +5 +6 +7 +8 +9 +N + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +D + +0 +1 +2 +3 + +5 +6 +7 +8 +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + + + +Canto cortado: +assim todos os cartões ficam na posição certa + +Texto impresso para ler + + + + +Linhas 12 e 11: furos extra para letras +1 coluna = 1 carácter +aqui P: furos em 11 e 7 + +furo perfurado + + +80 colunas = no máximo 80 caracteres por linha + diff --git a/website/app/assets/l03-lochkarte-gzfFEatc.svg b/website/app/assets/l03-lochkarte-gzfFEatc.svg new file mode 100644 index 00000000..a5cbccfb --- /dev/null +++ b/website/app/assets/l03-lochkarte-gzfFEatc.svg @@ -0,0 +1,995 @@ + + + + +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 +14 +14 +15 +15 +16 +16 +17 +17 +18 +18 +19 +19 +20 +20 +21 +21 +22 +22 +23 +23 +24 +24 +25 +25 +26 +26 +27 +27 +28 +28 +29 +29 +30 +30 +31 +31 +32 +32 +33 +33 +34 +34 +35 +35 +36 +36 +37 +37 +38 +38 +39 +39 +40 +40 +41 +41 +42 +42 +43 +43 +44 +44 +45 +45 +46 +46 +47 +47 +48 +48 +49 +49 +50 +50 +51 +51 +52 +52 +53 +53 +54 +54 +55 +55 +56 +56 +57 +57 +58 +58 +59 +59 +60 +60 +61 +61 +62 +62 +63 +63 +64 +64 +65 +65 +66 +66 +67 +67 +68 +68 +69 +69 +70 +70 +71 +71 +72 +72 +73 +73 +74 +74 +75 +75 +76 +76 +77 +77 +78 +78 +79 +79 +80 +80 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +P + +0 +1 +2 +3 +4 +5 +6 + +8 +9 +R + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +I + +0 +1 +2 +3 +4 +5 +6 +7 +8 + +N + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +T + +1 +2 + +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +* + +0 +1 +2 +3 + +5 +6 +7 + +9 +, + +1 +2 + +4 +5 +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +H + +0 +1 +2 +3 +4 +5 +6 +7 + +9 +A + +0 + +2 +3 +4 +5 +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +O + +0 +1 +2 +3 +4 +5 + +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +W + +1 +2 +3 +4 +5 + +7 +8 +9 +E + +0 +1 +2 +3 +4 + +6 +7 +8 +9 +L + +0 +1 +2 + +4 +5 +6 +7 +8 +9 +T + +1 +2 + +4 +5 +6 +7 +8 +9 +' +0 +1 +2 +3 +4 + +6 +7 + +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + diff --git a/website/app/assets/ludwig-Cus1i402.webp b/website/app/assets/ludwig-Cus1i402.webp new file mode 100644 index 0000000000000000000000000000000000000000..28cfd94a8ff5b61dd4bb30984d3e0ba6887d31f7 GIT binary patch literal 14066 zcmVifZZ zN&g+{5&e7q2U_=_PnTb_2llV||GECyo}e4%o^bx9=v%=*#(!n~tn+X3AD@2v{kQxt z`w#Hm+*sr5XZ%m`9;5#z`>FZ=??2=J<^Os8y!l`LFXhji|C#>Z{~OdJ@}K5k4 z|Nh1QZT{28oAO`oKjHg;|3?1f{-gaL+5V&4H|c-l|LOmk{qX;3 z_7VKE`k(s`?%(MD^Z%3o|Nm$28~?|-FWZm)zUjZQU-(miG^V~&F>6$DTi#!Dd-<2} zlBZXXUteED5c;vyJezCZ`-tlD-gaH|W{=AxqElZW*QA8Zlj(M?0L5Ol8EK1$%T zUx7l1lt8GZ{JVLi8cQy)_z>a5yWn}KJhQ-*#n*D{1e%O?XY$DYI-DrQ#up|=E3S5Bz5AAXk8)654w)Nhoj;UxTWL2aysarcUkN`---G{4{)$^gmw+@z+^gYF zx2%|M`3Ex~oNWBkTa4d@@ceTHPyRTNyD)B%_x$JrL3y0%J%f`~nN zQuM)AD}r&IqH|AV$%f1L;S92)g_ugs>XihCL_acw#o_vdpce!SsjXyrPODJ?7_>qy z_&|}-1{mGe$kA}c@aNa(9pV=WFugwk!fhub$GJUKXQqO%CZIPO71$76K(Ln{wS8Wb zm=klZDu`|CAulw?%b&`CX3o+bE>G)CtKL`V_ZxI!4oUwZc3SSyaQP48srKIQAiab3 zH%gnZ7pgt#1FfkETwqFA%dKKERwYzj#qB!?L3$*}0H?AL?sv7~>}VDM^ky?vRY9w? zzkuVh^r(s0cfKWSzqLZNDgM@?I@K}`Dt;?Ji9&D82s*@4%T@v>zR%JHCp}NrIY=9; zTSkO~vi_Ts@*9(0smQPfaR2_4&G1q|+C96vVVbx6ZiKDZBK?Ww!p|`*nF3fiJ>#DF z+M$qG2v-pJE;f>W2SVJ{f-U@0U08OM96WvI5P_Zr10rn1E1h!gPCR$UkuU#i=310Haj>LDplz#i-IM4trE=<{NFe z!B_m+zzFVg{3X95VWk{=H7+qZPr1obVDIZ%Ej&vwUPs49^CB#1lag6O?CG9q`3NP` z@iTDbt1w@9;R7<{pS^Kn(5=1Xo}J9!^0<$_XlP6oVHbfVh)P6(th=5aZEm3kVkahj z<*Vdh!Y%Uj8}FRI>W_+ml7 zflSBqD4E?N$w>&Sx!RlFoU(o_rfSrPTpxcZS0)d0+GhY}I*oY~89_aMm8JyhAidmm zDcTGb;H^!NLGdzWSd9S#Kmh*!P5DFJPCE2>OJl?Jc1IQK8qQNRRn4IQCerV7O@V`v z;vcjn85;9=16BVmyHZzI%K(WSGJ@8y{Gs4H>L$XqU-Vnso57hCiP9#ha4Yev6I)Hr z0LqyfXpr6GBbW7uZd#W#zkWS&Ufht7UVSu1c&>)28}=!GtB~WkwP_}q@-k!4pI7yr6vI<76~qdDgVI&O;j)SVvGl3*)kE73ka!?5lx1KfrZAZ;2m! zX0d~P;H;Vmdfxy#pV^&m+&uVbWA4h9yw|r@kS~D3rcs8VkPv4y0KIBSLqRFl9U=CR z<^gWUh-RGEPPmUwA%QLa=K0Q77hDbjLtv-?FU;#>bD!*I>nf&0f78!`c1{S|Y9f%g(WXuIGG8f$*S)xx9Kr&Fwz4giyz9mBITTPshirrNa=FgxH6Rx3Hd)FWRkepLSnPkx_B;v%4lHD zO*C-XpL%7WbJLgr2>!-1mB$KkCqbThotOfDKl@a-wG00WsT`?NZD85g+u-w4ZE*o+ zVR=9Y^HCfhwUj8YuC5~(G-R>0gT1PuKEmiJk?&tPel77SdT{E)Z`j4AD(w+Z6`$6e8aaWGyJ?$JZfz9gZJTNXpimEE~iJPgI1$|f^`Sj3TU zDCEPrsY*I1%?(|RRAngq<+GJ`rX6EuhXP~38Gte2d|G<*r*A@|P z65%yXlF*X_3NwMxzg}Z{JxL4W!H9-$SU{Z%|~T%0V7|!1Ew- zDrb(+Go+3eA+5vSpFmLHEm4WM1G}ld`0keDkcA$VuzqGIf*C%PH5uQr1d4Yhd+Bb zzW$mTS3rJJ7rKx=%gOoJV>g*Hxv9z4ffoK(f!$j~1|}}sNCbV}F4ZfSV+zcb;B`!7 zbyL3E0z52axd^Ev_a0)*2d#)wZCP~TQ$nciKNCiC<#dZLf98)7w zR5rROOjzKOa76jlN}S!8PwO%2L%d6UL1{> zRs%TsqyZKOim`I8;yd!S~oucy|i_x^v6U)8YiZoGFW z6svYq!Ir6w8|1WJzteUtmqt-_@Uo*Yl9Ccp(^Pp&KvB-fVFOi98#FN~oMh6; zgug<6cY#;p$x)SR)fzVRh+hrB3V6jJePQk4YKuSb;SA6sqo(w$S?qdp;uW@8z)clI zMb!)OeY)+|nF*{&X0IhUSf7YGfJj%6W&Nt@^PhU~X zQbAO%B<^Nx>hfgDxl67w#?>%7{!lb0x#sfT=BSOI}v zooAmoO}^?LTw+_`*5>dIDRdby9>6j}$6KyfEOvaS{aRN8 z3KHP99tv$egbk+(N-kiPzT44AQotr7Xxj(Tw8ts~mjpyx$~e{+=8D;)Ev_)}P+7=V zOpX|tGYM&6`TA4-&4HD9?g_6VS#~bgV2z(gvGY&ti(x-rtuoRRP3}4-9azQcm zvc}=;n$ssCEv3zDJjC}mG<9tuoFc%ZxA8V%6+Ffx;>+0*tW+445V^YfM-8htUa#RL z03#k_U8sdg@?%X5a14$q){UhiQcliWK{3xaViKClngTHQ^mlAa^eV^Vxpa~SO>V#< z3%@QlDrIHFs8Mw4kEWe3gNm6)^i~Lr*{4{RbbsjnVQ;*g)#`FgDi-MH%+O5HDYY*H zBoEauSJxiy3i8j{XGO}>xw`U1s-mpa$~Fbyyd~v=*UC2|mK`!gpvSzft%e;BOkS{8 z`LY_`f08@6jDxweNdN>cBu%p!e98(N)n5Y)Cz?fDqIxCaT;21gcy0p+&{tGxrHH{l zL>*-ca61rv6?n)SXF|MVfJiP9RKOcVXZDYiG$f_8_{8I0Fms_L4B8e61u&D)4bKH+ z>BuA~$l*ThW`#H$rOvcgqWp=JjUi(F4(nwyb7|;40d)plP#a;WDD59%(a@2pkh7#~ za-YC1ys0+SYQfz;v7o1Huw~gU062{Uhw=U@O{~AgP70;4WB@sT5NL#FgR4VS25#g@w>HbE+79JQ z7aB!nu~EQczdS~4RI;Z4vg*dDQ7ajc0C_Q{N2%6(%&3KLO8@Zmc43e8^fd`@t} zMl$73-7kClpv!z76aFWV5D$)8iRI>uu2dgWv~P>vweUr?*hOSupEQcv*2J{6vN{k8 z*+zMYB}pvvpp2i614!kNjs@Ys?svp!gTC-16HPuOnpLONKUWR-dh>922qe_o@EY0_ zwjWG3=sYYg!*g&w-mZ`oW}+Ry|G0iyJb`w_Q~3yWODr7V%B^7HQM>S5B=CrENxgGc zle^VSh<_JRNoi#kY#cpdX%(E*CUNs2k(wIHNhNRdar8D1^wns#`7}=8X~+lk+`>)A zd-~%?=y`cMz!ZiY{q1N{kYxm+xBj7KEM-)@>s8OD9m`k)5T4-f)W$z7-r%%4O7jf{ zrNQcnPWsxm=IFyAynPy5qzoy#v=e|kf05o2UJvXc`Axkk?3xzH?H-uDe>a5o4!TfU zap6NuB;1i$7$&Cf3l0txC#EZ)f}35;1peFUw6b(WR}nm%%l^xl7L6zl|F$$TI*p0k z2~ya8f2aHJ^a%L^-Xr<6RRcz&GSWUgUOx}r*a+y+V_!=Q*R%2m$?K;b+B4nBY+G_YZ0z-IpmG#9!9PSLi zPIi$i>*??i?PASUR%s^yD!eQmi2nKC5C`kJ>N&`d`G{0BVJkuNCu4zN%^JCco0*iy zX+WO)X-N#7#Q@UekIB)O+fRN_E7UkCPdjUMyJYC@nOYahp8R5+Z!8(LrksGJ6F9dr zf2HH;SS=BPjNm5ni4h|flU0ohj0dxpVGiorUNKI($wz~l*{+F$bkkYeyU^RJ!QA1B zfeb;o_|@+C_tFYYbL0=Y&Q2yQWB|O{4d!CC<|Fj&!Kkkf#=ie z8Ig2WsTFva4p{D}Lk(wvE95YJt~qjVHdGd% zBBXZ`B^#GHpWYmfxg@vvwtXTB5rm;|2K~vy)vTU@`-eOjw%086Dg8h>XEe;(h zgi+)x2?uMK-~W*pz9`|ZSte$7)Ts&;R&8$K`3?t?=-WGT(6Ng zB^=pL-$`Z))=+|1M+@nJI=j`+s~iB($7fX!=T5tJl3)`sOyWOOqh4RZxACXJP!SYf zNI=42+SmLxpa&!sqcSC38NF+9x-!9M@(UxS|ino))skgUGy4b1fbl zjt~%vH-n2@+Um;C+^gDUjw_?T$Rd>{E4W9j3wa8ndB$cI>8NZoQ~%=$ptu{DkY}aw zL^CLFb(yY;<;%)=(v7m3LM_UDp*tkzBipyG3jSW{Xv$&;0n@DEpPn&ot4bgndt2V(4TFvzlEH1yK<#9PbdPQjkkCls3Xua< zOm|qS_X*Z*Sy890k72Dfp+@Bq)PE$`9L=i!Urs5*qmJn8xfKTEqfQoX<(Kp?g`*_s zT+5K*-MbY19UyAa7lr`8;I&sir^Yz>J)Z_FW;clZYQm-hOX<jGaJQo(hCz06XXWIu=o-*;Et_e_X_zKvS*hg&yt4P2u6gMgpOb&$BNY!=w>s-H z;Tg4~&A1~$4z*FuLTV%CLTbOM_Gob6I@UbtQsr1gb>pifB{jAbs*7O4jRN*{W4clC ze)t;o`Q>9@jk0eoxS2VV$zHyD?6Vfg0GJp!o|-tonrO4J$-Za;mV<(vWV)Qi-7XPX zoXKttnAT6iM7LKE?WJHFD7ZfZ>n5ZJfxC$woWUW*nIY`|*p_`$E}H zH|2^0lUEk|fx6W3;jGo3gj1JfqZbcfRrqpAO~l)9V)9!#Jl|=Jc!cn_ogD=secdt( znp$8{jZm2{#y)dRxz_l?8#apJcE9h_d0?XEtAu4k2^V(#|@dxwR7+_D_1T%WCf;4v@9 zT{3LL{^4El^{hr9@yZZDWRrJma1R07V^(-Xtc)58h&haGebj6=01RZAuz!d~V{cOouoM1jALU8R=3qg-2Dx@M<&$zzaewiVfaDGyJF-r_6j1ZPs<8w#CJv04 zPYRH#-^Gpmw?7mR0ktI556|q6M!NM{%^B*ToB&3MU^a#e5Go`w`f?WOq6Csd4>S%1 z))k9(>45Vog6TblT7R@w?$J+3=bUfjqykJpOn4yZ5?-9UvCI2|(14UG>npGv8q?j` zX4)pUBfp93Z21dRD(Gp`M0G$520Z^fHJ>Jh#7dB}@Zdf+(z&hnJSIFH2}5eZ*qxWs z9?5p*5ypAiHb>9!NVPjHUnLFuy!=rW7jovWk;3}^&r-?@JLp zBOm5VoiMJbYS*G$q}pVdWkbJ5VkFITJi6dO%mHvmw)NU$fT3(B&C)^#_&XFddk3N} zHQk_=0V8}uyFmSqx&83M8es29Wl%JoKjqC*fN4zi$VRZf5;l_C;(e7!#FTDrP*jgG zW;PgeOA2L!tiEB2-OwCJ8H(JRKXL%zRfdk*P&fx-8O=}6!!Nnx=0JZh^OWPN0yO*7 z-h7#(C%>bW=2(>xuw>eq=@5Scqf8O2(}`hQv+-j4AL!|a?mH1PG)FB3VMjq{M2+Xp zJPNr-dEQmlWG=cF_U}?JbywT11z$zXfW40?d9g=}ANAI+Oi}$`k>!7tw3qvmmq(pm z4PQ6@^dHcgs+GWv9t{_fh}K$dd7~~v!WQ@!M-g=)AEI;4`z@M39|SrvC~}f#-*W1D z?5(ExA?@YCu1@&ccEPCE0c?I&V?ZDP0>S%xgjT*qaSRUxxM*|jtleM(t57EmiF z`OjZe__J1x^cc_(D#KDPxP2C>-_Ab-8ePA93Sk6(=lJf2%X>zr)lzw}_vk6|nzYKDI&hQF@ z@?#I%EZOoi2AYi$@V#zb0mSt8$C%J25q7!>?xk)0Sqd?HLjuXNKt&pbBcaidkrmKe z&Wf^*9Y}!z@H698ZzhbqnW%(27c6*r+TP9R3kqPgA1CysJ0cI=-~3*vpNp8KSg0rd z!og+_)&&s$NIjItV2L>v?Wq}He>65GVg;m8y6HNxhp_JAghvZ#Mg?z7waMpwF*6BX z@XMW%jp}#l5+?>*j}NJqjhcR~q{`K#?1}fOz-g7lG=e5Zj+|KeecCS>{F`2jzBC$c z*?sw7S+P|e203@sM>hi~;vJ>8oGQ4qdY@Mf=C+AjyI!)-Y)ow8XI8PG5tv_=r9fnZ zKEqdovWcn9gM;Zu^Zp?tvhugY&FEugvAP=&mtf#p0t zi~3gFv5;tVV+Otk_bdG6@-&DOWMHABu^mY2#&OTQTf;oem-#VT$PyswbP}m9bFbY5;QNjbScNh{R71T~gZf3s z0qz#7{L{}oq>UQ`EB7;yyJLePYVzLA+=bj<*4J?uAE=EUrP$z-;dxc4GYgaQmc$h%ujyvyTQ>%D|!8@RZeHyV)j|fMa8LU zg9Z}m2e?Uiakr)9;qtXMa_ks<6BRs>Dd%41NT+=^LLAEoy&Q|Xo9N>2Hu-Fmu3bPjRjWO7-q(SSkRz1g6+flZ`w^Hw09Ed~8 zd2%U!&UY-@AK^1QZ}#gjM9HOzOXW)@?>Hv3UV-oQ27*%`Fgsr3MClA?+IJM5>;moy zFul=i@$nNzKJ~pFp`%PH)|!j$8kXd5cfpQmLJ_I#gAv+*7g&l$rWF9Sl9Ib^?wp{8 z1VzXsH)ylhbp+rxIHz|8EQu`e=SGGr(36P>nz6~isPQms0SjRTCIC1sn)bxt_)g1W zuYk+b;U)9X&f|s!uZSD<$EA~rpfc0VR|l>!3a>{_wXK-J`}~)U&oFtMV&VmW#n#>` zGaThLz5tJpfzAOTk^ILT8}Fln(zrsVK(0vyC5!_wMV`uAHT8mmpeOfx(Ow4U8MiQHC^H^?jTb_Dsv6Gbr~{Y^jL zUmU4f1lgf+%*Px1GOu+hq>dqg$#^!b@^&~?nGa*PG~!g_Nfqfd@!MM=PG3m|M7a@r zy(cW2OSh1{4s?~Q*dsv=9ZRK=%n#EG$o0gc$PAF~)2(MrA4YD;ysK88>b7zparPFS zPystY21W|AshptN+>XMHiJo2k>^97CA@DpXKYQO=k(^Bn{llTP2)b60;-Y8TJdCx zW&^kw-v}8EtzZr!4I|Us&i%|9bB-+0?xeplh+p?ncJbF0@{Fhd@B_Byv>X?EC`hBM z4-j1Rt}PIz#T#ilXPo2ru=hrrJe2kIB4%Nm28UAMF5%nh+sd@kgvx}> zRJ>tP?T^aDP5k4uz54DYD*XbVN>Xh6AMPBRb~Y+99$g*4v2`!NyUa|B8?vmf3(S5*f@7r1fe zi+tK31M!mW|Nfi@vD3E(V><0~7>U>&?@3 z5_m`iO?4&fBzB_{pL?;I6@PwuAXi+8owQT2~CQ7-0RfSv?do43rTE; zX!q|r+1moFIBH1Z=v!GdIZs{Bwl`UjK@PRI+_8!#KJd(;OyIZWF>i1gT*7q2{Mv$W zhH-Ygmd0}nUToS`801{6dbbadWS|fN-F%&qyYp}=LSW~+jF6}rvya}$)xZ1M9@dKc z@ibAs2r4xejRzzB^H^Du3rw&-Kd!;?0{Jn%lglheaB!3Fn&7fkjktQnU=;fFn|JhzHBm?st=lNnfnB5?SM78gju`Ukpf&Ud6zsq} z3Xzu%4uhBvJNKxC3C2Pac2kuWv&xcgTm;8>U+F7Qc9xH9iBZhk4Y{s&J;7j3U%5pf z?N9?GdMl)9Q?iZlSra-05Eax&uRU(%wkn33XY=r>Kdc+HulM|TO6kxi*igrIn;L=e zp5!GeOwKh=#=<6$n>fH?sU&Xj+hUM+A$6M;2Tgq84^w5;mPhLPWeM`#d>2CwC_5Bb4tRsz6n!W5dlP)XQraoF${J^XtAwYxa$i!9@Yg4E?9IEwU1Mm+>@=r zCNV@f{iinplJ3V~D6lEN!jo8T$;2?-Gb#A6gb13?=y=P$AtKc-suM?HRFiZ3qC-D( z&5KL&A^7tu^}X=EGPQBVP(^nu9jU3|@v(0jRZ+ zujzLN#+%;IZw!8}0=1xMj0y2mw~{+S;O^6$)G_Al4@e6=N+v+$|sPd?%MxY)F z52hdA$Hh+TJDv8efc_T}UP%wJSU&8O$FqDH*0!*pn|mU@;$wd1brVIE>`t*eEOtUq z-+zgE(3D5oO*3n3JDVR*zi4B=SzE$G10sfeCqmwi?s=fCidmN&&Ng6pNdq-J2+i3l z-T>c!HCCuj&3i=&lsxU(1=^ic5jvH2xIPD@8YD=+8x{HROStpGOFwSamKzpX(tGZ3 zb*B|HNI85Nej|W1GR9QF#7_uzp5=Z^&b>#DZ>(8<@N>sPJ zB?~mp+J!!TNdnaiD(Z3t=o86Bc&M_Xris>@C?XV1QW123>82Lsg{&09X4rP(w9Av3 zv(;gkUVu0I@(lklrSKrZVQ56n)mYfc9-3x-J$FJu|FF{xTg=aIhCW%&v?uYMD-{Eo z4cjzKk;%+R!o$m^{^$PHcYX_>xCelrGCemgy9qM5*2Kr^fR(~Re zc$*vaY>W`aPu;+KZ`t1Kz_cnH+dH`52e_cwcqFdf6YH4t^mc3yr4V>~Ug+;Y>k*LE zB2ez5goY&eI)r11GA5UmlMf^6*>mYPWoW_}HYe7Kc9R`acGA>?oXO>e>-Jf;Gio)W z9JThUSQ$Y%l;eN1xQfGB60+P|H{7$H;u9OXjt@u{+SVD-RhymL+57R2eA(D2`wNLcjG>(=D5kKL|tuKKtRQMW(R#B5s=ezK3NK_deV~uYiig_ z**=ABMY1C3ZYd7`obY^|q^+1ms2l!r7s)7H!r=)MM>05o3gN%a&}H{4=AF$g=PUZp zqBaUobciyF!-`x7)=Bn-1J=yTLmaFJb+615=_CaV<7v%t%hbS`4fnK{C zn9;_&bNNp*jRY^@HJHj}U>%KS#hVzn&^9Z}_BHG8aYEZsHvt)Z&2qi~t18C|M!Rse zacAosVhuKh?-cE%DdatZG?0s|=_7b;v zrkr6v9&-==5t*TSVM$wJyJTQRy;)1+fp>Cg+cP8WJ%jybcJZeEwMQP4!K~Wc6d)jq z5AV_aIIBt9K|;9Z4QNExqg#}(ixK)wJPQ9Oz%WZQ6c$(n1tV8hYj`H+YsCs|k@*xG z65Fgy3X6H-9iMn|E6F6}Jl`rLnM^79KN-oElCFF*DJD!{J8;1ZiV-OqZBv!=(O@?3RSwBTrymqD5 zIvXkPm6$||zo$^T!C6YYhix7^jqxV(v2{JV+OAH$XzgRASqBew62MvJFF1yMZyd~r z?1vndftcp2S)F#k;=2Sz!$7<$%4g5!4pbP{f>d35W+qIuzc{(SfVBXbCR)+b;RqaAfErT=XN&ZvEmfCC2*$5=RitJ#&!&u{#E1+loWDqM;@e zX^M}J->ap9poO79%fx|_gsOrkJ((rUX1h$MJy((cngd`)A}Hr8aTUV@A06TXE(lx; zZi;?d2lh+e-Ex;%WFwoS(>@SwmAWH&T%vT$B&+(=wcxDnXaTG691YRT+h=Zq+6wI6CB`4ol{YA;+h7GA+f+zU$$KSR25$ixy!Dz6+S{ zQ~8c1Jr2e{m;wV4GBE$c6#*jm%#byCH1LjaxJ$3@0^b)vDZ>I1|GR;*c`H%R$SP-g z1iYMzxQeJm>py2zYrY{^*{cJVi4WF3UHvK9R$fS%nsfQKGU11qUr%L6Zc#bS8qVkx z82F(Sdr`;=OKU$)kPmUx_48te#FU!QR60|%8U7nvaiu2OG%gN$Y+Q>)vo zdH8GS6g~}RugemL^H@E@IC&-YIo6cBYe7oQWq3|!5|0b1E&kAjN2^K>V!BCJo2*3% zz(8jwM_4y0a$<3j$P{?isr+z@w!?IX4N&uvS^+l*lPobo1+w7wcg5TOaj#e8JGmpr z2_4n)(iQf}HKJxJj%C|pru?6kl^ZFF2QO-YF*+H`wx4r;7ynzR2{z*Lp<@*9kHlv` zy+2h8u6Z@~w>iHUFGmOhHPW0y<9_3~>*247D(j6<_69HP7FvW%^+?+-RcA6{D>xy~ z0%~6QxSm7`oR%|Uo5k3ENqP&7JGsNg&4#NwYP^y?1LqCsGgR9oS+da4uxEXfgyi*j z`9{=lCJc>cNypC>-nki_f>RGE#o6ZX%C5%-<9+_ zpIyQ1wgl!ONCmfJDFfXsx9vO6U9NSOt;+^ft7zn5!Th5;)?9VnE)V!zdeCW6;?-FT z6`0()!*fUm6MWF+FhEJ7phQ>UO1wMgpy`6}owmR~62EfXTFhu6x?y)<9!1TdS(N2A zP_WF2V&mmUrq0j}{l$two_~hJ5VxzkSE7cSDgBYYICObSiOQIG$bYc+hyuEnBPU%Z zBD4I*kvbtXTlz-l0mXKz6vp7+^7dxz5CG_y2kb9K00Qv}RBb190$^$9m1X=$=jEFO zYWYx0j!i$`j_G_01c8uY{}Zvx1@tITUng2p?d@G5ztM^NOq$je&RVKL#S=JsFnmOc zdyMHMpUG55K4*DdG+rGO1@c;BpycO9;wvmw>*%u(Rp7jkrC01`S4S-bCS84r2c=1>{L+VBeaAuIStyG5!OUxCAjOg8Aw1p(hSVbLKa$n7?P!BSsSCRuNpd7Or zi$9z=d3xS(W-Xot9|3r~a(roxE~Uy85T$SN57$U-)wzQg-WHUq`-ov}H+Qt4oVdy4 zDRD~Nhi&>ozk--4m_J0ZA?V)*QnJL4&kzJ2L){`i(y~1KFdNxdVe2CxHkjURlFXrE z&Vd9W0p{h{n>_d+KHTE0pSWG|25SK6^}KBZPtt8(p>TyX;lo!i{UF{kbJBLSBmx>R zEy7ypP&;$jPzS6)CAE5JrQKx@tyP$_;Q1tjn-!$p z5)>#QQBIIVe44J~8?_WayGi;*^k>NP_15L8e(jU~0ulSz44p%f09i zw2BYWrh|}msx&N>t59RKk$8JOE&I1#fRpAsi zW)mh+@@jUzM6d=94piGab4J%xZ>JBl0E3Dx)P1Zy(^ePMIl&WB`3zZI}P7X*?~eptr~VjBcGN8ty~ z4NsO##RXO`eL*mwY&^C<@Q-2S`we1)N~i6Hn~KO!pC_Qn0AC_!X-aXtLAI(*@020` z5&>3S1em{U@%(U1%iRE9B?DY!@FF_0K&85AtFzR*hp{99cry-jk>lYzbMevZ7d^h< z?=l^9Kojz~7OymS-}B0tvDu&Q9pDdEY{jUa4vc|pDzln~m-snu2LN~VR6dZW$*&FmH32&OQd^m_RdApszd+)08FDkFaQ7m literal 0 HcmV?d00001 diff --git a/website/app/assets/mvc-klick-BIA_bYzu.svg b/website/app/assets/mvc-klick-BIA_bYzu.svg new file mode 100644 index 00000000..a885cc70 --- /dev/null +++ b/website/app/assets/mvc-klick-BIA_bYzu.svg @@ -0,0 +1,75 @@ + + + + + + + + + View + the display + + Controller + the listener + + Model + Counter + + 0 + 1 + 2 + 3 + + +1 + + value = 0 + value = 1 + value = 2 + value = 3 + + 1 actionPerformed(e) + 1 actionPerformed(e) + + + 2 increase() + 2 increase() + + + 3 getValue() + 3 getValue() + + + 4 update(value) + 4 update(value) + + The model knows neither the view nor the controller. + diff --git a/website/app/assets/mvc-klick-DKonBpbs.svg b/website/app/assets/mvc-klick-DKonBpbs.svg new file mode 100644 index 00000000..08d276a8 --- /dev/null +++ b/website/app/assets/mvc-klick-DKonBpbs.svg @@ -0,0 +1,75 @@ + + + + + + + + + View + o visor + + Controller + o ouvinte + + Model + Contador + + 0 + 1 + 2 + 3 + + +1 + + valor = 0 + valor = 1 + valor = 2 + valor = 3 + + 1 actionPerformed(e) + 1 actionPerformed(e) + + + 2 aumentar() + 2 aumentar() + + + 3 getValor() + 3 getValor() + + + 4 atualizar(valor) + 4 atualizar(valor) + + O model não conhece nem a view nem o controller. + diff --git a/website/app/assets/mvc-klick-KmFKqxH-.svg b/website/app/assets/mvc-klick-KmFKqxH-.svg new file mode 100644 index 00000000..47aa440e --- /dev/null +++ b/website/app/assets/mvc-klick-KmFKqxH-.svg @@ -0,0 +1,75 @@ + + + + + + + + + View + die Anzeige + + Controller + der Zuhörer + + Model + Zaehler + + 0 + 1 + 2 + 3 + + +1 + + wert = 0 + wert = 1 + wert = 2 + wert = 3 + + 1 actionPerformed(e) + 1 actionPerformed(e) + + + 2 erhoehen() + 2 erhoehen() + + + 3 getWert() + 3 getWert() + + + 4 aktualisieren(wert) + 4 aktualisieren(wert) + + Das Model kennt weder die View noch den Controller. + diff --git a/website/app/assets/nb-BpibUAkX.js b/website/app/assets/nb-BpibUAkX.js new file mode 100644 index 00000000..976aa674 --- /dev/null +++ b/website/app/assets/nb-BpibUAkX.js @@ -0,0 +1,180 @@ +const e=`/* Tekster som bare finnes i nettversjonen. Alt annet kommer fra appens Localizable.strings. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct-struktogram"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Eksporter…"; +"web_export_title" = "Lagre som bilde eller PDF, eller skriv ut"; +"web_export_png" = "Bilde (PNG)"; +"web_export_svg" = "Vektorgrafikk (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "VisuStruct-fil (.visustruct)"; +"web_export_failed_fmt" = "Eksporten mislyktes: %@"; +"web_print_hint" = "Bruk «Eksporter… → PDF» for å lagre diagrammet og skrive det ut derfra."; +"web_delete" = "Slett"; +"web_language_title" = "Språk i grensesnittet"; +"web_simulation_start" = "Start simulering"; +"web_simulation_end" = "Avslutt simulering"; +"web_simulation_start_title" = "Kjør struktogrammet trinn for trinn"; +"web_simulation_end_title" = "Avslutt simuleringen og fortsett redigeringen"; +"web_palette_hint" = "Dra inn i struktogrammet"; +"web_tabs_label" = "Diagrammer"; +"web_status_modified" = "endret"; +"web_inspector_title" = "Egenskaper"; +"web_inspector_help_drop" = "Dra elementer fra paletten til en rute: øverst = før, nederst = etter, på «ø» = erstatt. Eksisterende elementer kan flyttes med musen."; +"web_inspector_help_files" = "Du kan også slippe filer i vinduet."; +"web_case_name" = "Navn på case"; +"web_case_name_placeholder" = "f.eks. 1, ok, default"; +"web_copied" = "Element kopiert."; +"web_discard_message_fmt" = "Endringene i «%@» går tapt."; +"web_err_unreadable_fmt" = "«%@» er ikke en lesbar VisuStruct-fil (%@)."; +"web_saved_fmt" = "«%@» lagret."; +"web_saved_txt_fmt" = "Lagret som «%@». Fjern filendelsen .txt for å bruke den."; +"web_drop_impossible" = "Kan ikke slippes her"; +"web_sim_delay" = "Pause per trinn"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Språk"; +"web_codegen_comments" = "Diagramtekst som kommentarer"; +"web_codegen_empty_else" = "Skriv ut tom else-gren i koden"; +"web_copied_check" = "Kopiert ✓"; +"web_copy_manual" = "Markert, trykk Ctrl+C for å kopiere"; +"web_run_stopped_loop" = "Kjøringen stoppet: mulig uendelig løkke."; +"web_run_cancelled" = "Kjøringen avbrutt."; +"web_run_error" = "Feil under kjøring."; +"web_run_dropped_fmt" = "… %d tidligere linjer skjult"; +"web_sim_call_arguments_fmt" = "Kallet passer ikke til hodet i %@. Sjekk verdiene i parentesene."; +"web_sim_missing_return_fmt" = "%@ ble avsluttet uten å returnere en verdi med return."; +"web_sim_file_not_found_fmt" = "Det finnes ingen fil som heter %@."; +"web_sim_end_of_file_fmt" = "Filen %@ har ikke flere linjer."; +"web_sim_null_value_fmt" = "%@ er null."; +"web_sim_written_file_fmt" = "%@ (lagret)"; +"web_site_home" = "Forside"; +"web_site_imprint" = "Kolofon"; +"web_site_privacy" = "Personvern"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Programmering"; +"web_live_hide" = "Skjul programmering"; +"web_scale_canvas" = "Tekststørrelse: strukturdiagram"; +"web_scale_code" = "Tekststørrelse: programmering"; +"web_live_indent" = "Rykk inn"; +"web_live_indent_title" = "Rykk inn koden: fire mellomrom per nivå (merkede linjer, ellers alt)"; +"web_live_show" = "Vis programmering"; +"web_live_resize" = "Endre bredden på kodeområdet (dobbeltklikk: tilbakestill)"; +"web_live_hint" = "Koden vokser med diagrammet ditt. Grått = plassholder: skriv i inspektøren, så vises teksten her. Klikk på en linje for å velge elementet."; +"web_live_ph_selector" = "variabel"; +"web_live_ph_code" = "Din kode"; +"web_live_ph_end" = "slutt"; +"web_live_language" = "Programmeringsspråk"; +"web_live_java_class" = "Som klasse"; +"web_live_java_class_hint" = "Klassenavn = diagrammets tittel"; +"web_live_java_main" = "Med main-metode"; +"web_settings_display" = "Visning"; +"web_live_swing" = "Ekte Java (med Swing)"; +"web_live_swing_hint" = "Ekte Java med vinduer (CheerpJ). Laster ned ca. 40 MB én gang ved første kjøring."; +"web_live_swing_windows" = "Java-vinduer"; +"web_live_swing_hide" = "Lukk Java-vinduer"; +"web_live_swing_loading" = "Java lastes inn (første gang ca. 40 MB) …"; +"web_live_swing_compiling" = "Kompilerer …"; +"web_live_swing_running" = "Programmet kjører."; +"web_live_swing_compile_failed" = "Kompileringsfeil, se over."; +"web_live_swing_failed" = "Java kunne ikke lastes inn. Sjekk internettforbindelsen."; +"web_live_hint_edit" = "Skriv Java-kode her, så bygger diagrammet seg selv. Eller arbeid i diagrammet, så vokser koden med. Grått = plassholder, bare skriv over."; +"web_live_edit_label" = "Java-kode"; +"web_parse_line_fmt" = "Linje %d: %@"; +"web_parse_missing" = "Her mangler fortsatt: %@"; +"web_parse_extra" = "For mye: %@"; +"web_parse_unclosed_string" = "Det avsluttende %@ mangler."; +"web_parse_else_without_if" = "Denne «else» har ingen «if»."; +"web_parse_case_outside_switch" = "«case» og «default» hører hjemme i en «switch»."; +"web_parse_missing_do_while" = "Etter «do { … }» mangler «while (betingelse);»."; +"web_parse_more_methods" = "Foreløpig teller bare én metode her. Lag andre underprogrammer i egne faner."; +"web_parse_missing_import" = "Øverst mangler %@ Uten denne linjen kjenner ikke Java Scanner."; +"web_parse_missing_scanner" = "Før mangler %@ Uten den linjen finnes ikke Scanneren."; +"web_parse_unknown_type" = "Java kjenner ikke denne datatypen. Mente du %@?"; +"web_editor_title" = "Strukturdiagram"; +"web_editor_show" = "Vis strukturdiagram"; +"web_editor_hide" = "Skjul strukturdiagram"; +"web_keywords_title" = "Kode-nøkkelord"; +"web_keywords_hint" = "if, while, for i stedet for elementnavn"; +"web_palette_compact" = "Elementer alltid kompakte"; +"web_palette_compact_hint" = "Symbol med lite navn under, ellers bare når kolonnen er smal"; +"web_about_version_fmt" = "Versjon %@"; +"web_about_software" = "Programvare som brukes"; +"web_about_software_text" = "Kodeeditoren bruker CodeMirror og Lezer (MIT-lisens). Med Swing-støtte laster VisuStruct inn CheerpJ fra Leaning Technologies (Community-lisens) og javac fra OpenJDK."; +"web_about_licenses" = "Lisenstekster"; +"web_live_run" = "Kjør"; +"web_live_run_title" = "Kjør programmet: utdata og inndata vises nedenfor"; +"web_live_run_finished" = "Programmet er ferdig."; +"web_live_run_stopped" = "Stoppet."; +"web_console" = "Konsoll"; +"web_console_hide" = "Skjul konsollen"; +"web_console_resize" = "Endre høyden på konsollen"; +"web_diagram_tools" = "Diagramverktøy"; +"web_files_title" = "Filer"; +"web_files_show" = "Vis filer"; +"web_files_hide" = "Skjul filer"; +"web_files_resize" = "Endre bredden på filer"; +"web_files_new_folder" = "Ny mappe"; +"web_files_switch" = "Velg en annen mappe"; +"web_files_delete" = "Slett"; +"web_files_in_browser" = "I denne nettleserens lagring"; +"web_files_save_hint_fmt" = "Lagring legger programmet i %@."; +"web_files_empty" = "Ingenting lagret ennå. Når du lagrer, lager VisuStruct en mappe med dagens dato her."; +"web_files_reconnect_hint" = "Etter ny innlasting spør nettleseren igjen om VisuStruct kan bruke mappen din."; +"web_files_reconnect_fmt" = "Åpne mappen «%@»"; +"web_files_connect_hint" = "Velg en mappe som arbeidsområde. VisuStruct lager en mappe for hver dag der og lagrer diagram og kode."; +"web_files_connect" = "Velg mappe"; +"web_files_browser_hint" = "Denne nettleseren kan ikke åpne mapper på enheten (f.eks. på iPad). Filene dine blir i nettleserens lagring."; +"web_files_browser" = "Lagre i nettleseren"; +"web_files_delete_confirm_fmt" = "Vil du virkelig slette «%@»?"; +"web_files_folder_prompt" = "Navn på den nye mappen:"; +"web_files_default_name" = "Program"; +"web_files_saved_fmt" = "Lagret: %@"; +"web_files_create" = "Lag"; +"web_learn_ludwig_tip" = "Ludwigs tips"; +"web_game_title" = "Spill: Sant eller usant?"; +"web_game_intro" = "Ludwig viser deg verdier og en betingelse. Er betingelsen sann (true) eller usann (false)? Ti runder, stadig vanskeligere."; +"web_game_start" = "Start spillet"; +"web_game_round_fmt" = "Runde %@ av %@"; +"web_game_score_fmt" = "Poeng: %@"; +"web_game_true" = "sann (true)"; +"web_game_false" = "usann (false)"; +"web_game_right" = "Riktig!"; +"web_game_wrong" = "Ikke helt. Slik regnes det ut:"; +"web_game_next" = "Neste"; +"web_game_finish" = "Resultat"; +"web_game_done_fmt" = "%@ av %@ riktige."; +"web_game_perfect" = "Alt riktig – Ludwig er imponert!"; +"web_game_good" = "Bra! Se på feilene dine og prøv igjen."; +"web_game_practice" = "Øvelse gjør mester. Les sannhetstabellen igjen og spill en runde til."; +"web_game_again" = "Spill igjen"; +"web_game_wrong_short" = "Dessverre feil."; +"web_game_practice_short" = "Øvelse gjør mester. Les forklaringene igjen og spill en runde til."; +"web_game_clicks" = "Klikk:"; +"web_game_nobody" = "Ingen lytter – ingenting skjer."; +"web_game_event_fmt" = "Klikk på «%@»: lytteren hører det og kjører koden sin."; +"web_game_try" = "Prøv nå knappene i vinduet selv."; +"web_game_time_fmt" = "%@ s igjen"; +"web_game_defused" = "✂️ Desarmert! Du fant feilen."; +"web_game_boom_time" = "💥 Bom! Tiden er ute."; +"web_game_boom_wrong" = "💥 Bom! Det var feil linje."; +"web_game_fix" = "Riktig linje:"; +"web_game_order_hint" = "Trykk på trinnene i riktig rekkefølge."; +"web_debug_step" = "Steg"; +"web_debug_step_title" = "Steg: kjør én setning og stopp igjen"; +"web_debug_continue" = "Fortsett til neste stoppunkt"; +"web_debug_paused_fmt" = "Stoppet før linje %d."; +"web_debug_gutter_title" = "Klikk på et linjenummer for å sette eller fjerne et stoppunkt"; +"web_swap_to_code" = "Programmering stor"; +"web_swap_to_editor" = "Struktogram stort"; +"web_editor_resize" = "Endre bredden på struktogrammet"; +"web_palette_resize" = "Endre bredden på elementene"; +"web_palette_hide" = "Skjul elementene"; +"web_palette_show" = "Vis elementene"; +"web_code_scopes" = "Fargede kodeblokker"; +"web_code_scopes_hint" = "Klasse, metode, løkke, forgrening i egne bokser"; +"web_pseudocode" = "Pseudokode"; +`;export{e as default}; diff --git a/website/app/assets/nl-HArZjiga.js b/website/app/assets/nl-HArZjiga.js new file mode 100644 index 00000000..f64e189c --- /dev/null +++ b/website/app/assets/nl-HArZjiga.js @@ -0,0 +1,180 @@ +const e=`/* Teksten die alleen in de webversie bestaan. Al het andere komt uit de Localizable.strings van de app. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct-structogram"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Exporteren…"; +"web_export_title" = "Opslaan als afbeelding of PDF, of afdrukken"; +"web_export_png" = "Afbeelding (PNG)"; +"web_export_svg" = "Vectorafbeelding (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "VisuStruct-bestand (.visustruct)"; +"web_export_failed_fmt" = "Exporteren mislukt: %@"; +"web_print_hint" = "Gebruik “Exporteren… → PDF” om het diagram op te slaan en het daarna af te drukken."; +"web_delete" = "Verwijderen"; +"web_language_title" = "Taal van de interface"; +"web_simulation_start" = "Simulatie starten"; +"web_simulation_end" = "Simulatie beëindigen"; +"web_simulation_start_title" = "Het structogram stap voor stap uitvoeren"; +"web_simulation_end_title" = "Simulatie beëindigen en verder bewerken"; +"web_palette_hint" = "Naar het structogram slepen"; +"web_tabs_label" = "Diagrammen"; +"web_status_modified" = "gewijzigd"; +"web_inspector_title" = "Eigenschappen"; +"web_inspector_help_drop" = "Sleep elementen uit het palet op een tegel: boven = ervoor, onder = erna, op “ø” = vervangen. Bestaande elementen kun je met de muis verplaatsen."; +"web_inspector_help_files" = "Je kunt ook bestanden in het venster neerzetten."; +"web_case_name" = "Naam van de case"; +"web_case_name_placeholder" = "bijv. 1, ok, default"; +"web_copied" = "Element gekopieerd."; +"web_discard_message_fmt" = "De wijzigingen in “%@” gaan verloren."; +"web_err_unreadable_fmt" = "“%@” is geen leesbaar VisuStruct-bestand (%@)."; +"web_saved_fmt" = "“%@” opgeslagen."; +"web_saved_txt_fmt" = "Opgeslagen als “%@”. Verwijder de extensie .txt om het te gebruiken."; +"web_drop_impossible" = "Hier neerzetten is niet mogelijk"; +"web_sim_delay" = "Pauze per stap"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Taal"; +"web_codegen_comments" = "Diagramtekst als commentaar"; +"web_codegen_empty_else" = "Lege else-tak in code genereren"; +"web_copied_check" = "Gekopieerd ✓"; +"web_copy_manual" = "Geselecteerd, druk op Ctrl+C om te kopiëren"; +"web_run_stopped_loop" = "Uitvoering gestopt: mogelijk oneindige lus."; +"web_run_cancelled" = "Uitvoering geannuleerd."; +"web_run_error" = "Fout tijdens het uitvoeren."; +"web_run_dropped_fmt" = "… %d eerdere regels verborgen"; +"web_sim_call_arguments_fmt" = "De aanroep past niet bij de kop van %@. Controleer de waarden tussen de haakjes."; +"web_sim_missing_return_fmt" = "%@ is geëindigd zonder met return een waarde terug te geven."; +"web_sim_file_not_found_fmt" = "Er is geen bestand met de naam %@."; +"web_sim_end_of_file_fmt" = "Het bestand %@ heeft geen regels meer."; +"web_sim_null_value_fmt" = "%@ is null."; +"web_sim_written_file_fmt" = "%@ (opgeslagen)"; +"web_site_home" = "Startpagina"; +"web_site_imprint" = "Colofon"; +"web_site_privacy" = "Privacy"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Programmeren"; +"web_live_hide" = "Programmeren verbergen"; +"web_scale_canvas" = "Tekstgrootte: structuurdiagram"; +"web_scale_code" = "Tekstgrootte: programmeren"; +"web_live_indent" = "Inspringen"; +"web_live_indent_title" = "Code laten inspringen: vier spaties per niveau (geselecteerde regels, anders alles)"; +"web_live_show" = "Programmeren tonen"; +"web_live_resize" = "Breedte van het codegebied wijzigen (dubbelklik: herstellen)"; +"web_live_hint" = "De code groeit mee met je diagram. Grijs = plaatshouder: typ in de inspector en je tekst verschijnt hier. Klik op een regel om het element te selecteren."; +"web_live_ph_selector" = "variabele"; +"web_live_ph_code" = "Jouw code"; +"web_live_ph_end" = "einde"; +"web_live_language" = "Programmeertaal"; +"web_live_java_class" = "Als klasse"; +"web_live_java_class_hint" = "Klassenaam = titel van het diagram"; +"web_live_java_main" = "Met main-methode"; +"web_settings_display" = "Weergave"; +"web_live_swing" = "Echte Java (met Swing)"; +"web_live_swing_hint" = "Echt Java met vensters (CheerpJ). Downloadt eenmalig ca. 40 MB bij de eerste keer uitvoeren."; +"web_live_swing_windows" = "Java-vensters"; +"web_live_swing_hide" = "Java-vensters sluiten"; +"web_live_swing_loading" = "Java wordt geladen (de eerste keer ca. 40 MB) …"; +"web_live_swing_compiling" = "Compileren …"; +"web_live_swing_running" = "Programma draait."; +"web_live_swing_compile_failed" = "Compileerfout, zie hierboven."; +"web_live_swing_failed" = "Java kon niet worden geladen. Controleer de internetverbinding."; +"web_live_hint_edit" = "Typ hier Java-code en het diagram bouwt zichzelf op. Of werk in het diagram en de code groeit mee. Grijs = tijdelijke tekst, typ er gewoon overheen."; +"web_live_edit_label" = "Java-code"; +"web_parse_line_fmt" = "Regel %d: %@"; +"web_parse_missing" = "Hier ontbreekt nog: %@"; +"web_parse_extra" = "Te veel: %@"; +"web_parse_unclosed_string" = "De afsluitende %@ ontbreekt."; +"web_parse_else_without_if" = "Bij deze “else” hoort geen “if”."; +"web_parse_case_outside_switch" = "“case” en “default” horen in een “switch”."; +"web_parse_missing_do_while" = "Na “do { … }” ontbreekt nog “while (voorwaarde);”."; +"web_parse_more_methods" = "Voorlopig telt hier maar één methode. Maak andere subprogramma’s in aparte tabbladen."; +"web_parse_missing_import" = "Bovenaan ontbreekt %@ Zonder deze regel kent Java Scanner niet."; +"web_parse_missing_scanner" = "Eerst ontbreekt %@ Zonder deze regel bestaat de Scanner niet."; +"web_parse_unknown_type" = "Java kent dit gegevenstype niet. Bedoelde je %@?"; +"web_editor_title" = "Diagram"; +"web_editor_show" = "Diagram tonen"; +"web_editor_hide" = "Diagram verbergen"; +"web_keywords_title" = "Code-sleutelwoorden"; +"web_keywords_hint" = "if, while, for in plaats van elementnamen"; +"web_palette_compact" = "Elementen altijd compact"; +"web_palette_compact_hint" = "Symbool met kleine naam eronder, anders alleen bij een smalle kolom"; +"web_about_version_fmt" = "Versie %@"; +"web_about_software" = "Gebruikte software"; +"web_about_software_text" = "De code-editor gebruikt CodeMirror en Lezer (MIT-licentie). Met Swing-ondersteuning laadt VisuStruct CheerpJ van Leaning Technologies (Community-licentie) en javac uit OpenJDK."; +"web_about_licenses" = "Licentieteksten"; +"web_live_run" = "Uitvoeren"; +"web_live_run_title" = "Programma uitvoeren: uitvoer en invoer verschijnen eronder"; +"web_live_run_finished" = "Programma klaar."; +"web_live_run_stopped" = "Gestopt."; +"web_console" = "Console"; +"web_console_hide" = "Console verbergen"; +"web_console_resize" = "Hoogte van de console wijzigen"; +"web_diagram_tools" = "Diagramgereedschap"; +"web_files_title" = "Bestanden"; +"web_files_show" = "Bestanden tonen"; +"web_files_hide" = "Bestanden verbergen"; +"web_files_resize" = "Breedte van bestanden wijzigen"; +"web_files_new_folder" = "Nieuwe map"; +"web_files_switch" = "Andere map kiezen"; +"web_files_delete" = "Verwijderen"; +"web_files_in_browser" = "In de opslag van deze browser"; +"web_files_save_hint_fmt" = "Opslaan zet het programma in %@."; +"web_files_empty" = "Nog niets opgeslagen. Bij het opslaan maakt VisuStruct hier een map met de datum van vandaag."; +"web_files_reconnect_hint" = "Na het herladen vraagt de browser nog eens of VisuStruct je map mag gebruiken."; +"web_files_reconnect_fmt" = "Map „%@” openen"; +"web_files_connect_hint" = "Kies een map als werkruimte. VisuStruct maakt daarin een map voor elke dag en slaat diagram en code op."; +"web_files_connect" = "Map kiezen"; +"web_files_browser_hint" = "Deze browser kan geen mappen op het apparaat openen (bijv. op de iPad). Je bestanden blijven in de opslag van deze browser."; +"web_files_browser" = "Opslaan in de browser"; +"web_files_delete_confirm_fmt" = "„%@” echt verwijderen?"; +"web_files_folder_prompt" = "Naam van de nieuwe map:"; +"web_files_default_name" = "Programma"; +"web_files_saved_fmt" = "Opgeslagen: %@"; +"web_files_create" = "Maken"; +"web_learn_ludwig_tip" = "Ludwigs tip"; +"web_game_title" = "Spel: Waar of onwaar?"; +"web_game_intro" = "Ludwig laat je waarden en een voorwaarde zien. Is de voorwaarde waar (true) of onwaar (false)? Tien rondes, steeds lastiger."; +"web_game_start" = "Spel starten"; +"web_game_round_fmt" = "Ronde %@ van %@"; +"web_game_score_fmt" = "Punten: %@"; +"web_game_true" = "waar (true)"; +"web_game_false" = "onwaar (false)"; +"web_game_right" = "Goed!"; +"web_game_wrong" = "Helaas fout. Zo reken je het uit:"; +"web_game_next" = "Verder"; +"web_game_finish" = "Resultaat"; +"web_game_done_fmt" = "%@ van %@ goed."; +"web_game_perfect" = "Alles goed – Ludwig is diep onder de indruk!"; +"web_game_good" = "Sterk! Bekijk je fouten nog eens en probeer het opnieuw."; +"web_game_practice" = "Oefening baart kunst. Lees de waarheidstabel nog eens en speel nog een ronde."; +"web_game_again" = "Nog een keer"; +"web_game_wrong_short" = "Helaas, fout."; +"web_game_practice_short" = "Oefening baart kunst. Lees de uitleg nog eens en speel nog een ronde."; +"web_game_clicks" = "Klikken:"; +"web_game_nobody" = "Niemand luistert – er gebeurt niets."; +"web_game_event_fmt" = "Klik op ‘%@’: de luisteraar hoort het en voert zijn code uit."; +"web_game_try" = "Probeer de knoppen in het venster nu zelf uit."; +"web_game_time_fmt" = "Nog %@ s"; +"web_game_defused" = "✂️ Onschadelijk gemaakt! Je hebt de fout gevonden."; +"web_game_boom_time" = "💥 Boem! De tijd is om."; +"web_game_boom_wrong" = "💥 Boem! Dat was de verkeerde regel."; +"web_game_fix" = "De juiste regel:"; +"web_game_order_hint" = "Tik de stappen in de juiste volgorde aan."; +"web_debug_step" = "Stap"; +"web_debug_step_title" = "Stap: één opdracht uitvoeren en weer pauzeren"; +"web_debug_continue" = "Doorgaan tot het volgende breekpunt"; +"web_debug_paused_fmt" = "Gepauzeerd vóór regel %d."; +"web_debug_gutter_title" = "Klik op een regelnummer om een breekpunt te plaatsen of te verwijderen"; +"web_swap_to_code" = "Programmeren groot"; +"web_swap_to_editor" = "Structogram groot"; +"web_editor_resize" = "Breedte van het structogram wijzigen"; +"web_palette_resize" = "Breedte van de elementen wijzigen"; +"web_palette_hide" = "Elementen verbergen"; +"web_palette_show" = "Elementen tonen"; +"web_code_scopes" = "Gekleurde codeblokken"; +"web_code_scopes_hint" = "Klasse, methode, lus, keuze in eigen kaders"; +"web_pseudocode" = "Pseudocode"; +`;export{e as default}; diff --git a/website/app/assets/objectApp-Cf8h-zzC.js b/website/app/assets/objectApp-Cf8h-zzC.js new file mode 100644 index 00000000..affe2172 --- /dev/null +++ b/website/app/assets/objectApp-Cf8h-zzC.js @@ -0,0 +1,421 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./projectZip-DZMCzW4J.js","./index-Bmqo_CbG.js","./index-DaVEKYYQ.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 ct}from"./index-Bmqo_CbG.js";function Ys(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 Zs(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=Ys(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=Zs(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 Qs(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 ei=/^[\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 ti={"+":"public ","-":"private ","#":"protected ","~":""};function si(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?"":ti[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(;na.slice(0,e)+s+a.slice(t);function ni(a,e){const[t,s]=mt(a,e.from,e.to),i=a.slice(0,t).match(/\n\s*\n$/);return Y(a,i?t-i[0].length+1:t,s,"")}function oi(a,e,t){const s=[e,...e.members.filter(i=>i.kind==="constructor")].map(i=>[i.nameFrom,i.nameTo]);for(const[i,n]of s.sort((o,r)=>r[0]-o[0]))a=Y(a,i,n,t);return a}function Ze(a,e,t){const s=a.slice(e.headerFrom,e.headerTo),i=e.nameTo-e.headerFrom,n=s.slice(0,i);let o=s.slice(i).replace(/\s*\bextends\s+[\p{L}_$][\p{L}\p{N}_$<>,\s]*?(?=\s*\bimplements\b|\s*$)/u,"");return t&&(o=` extends ${t}`+o),Y(a,e.headerFrom,e.headerTo,n+o)}function jt(a,e,t){if(e.interfaces.includes(t))return a;const s=a.slice(e.headerFrom,e.headerTo),i=e.kind==="interface"?"extends":"implements",n=new RegExp(`\\b${i}\\s+[\\p{L}_$][\\p{L}\\p{N}_$<>,\\s]*?(?=\\s*$)`,"u"),o=n.test(s)?s.replace(n,r=>`${r.replace(/\s+$/,"")}, ${t}`):`${s.replace(/\s+$/,"")} ${i} ${t}${/\s$/.test(s)?" ":""}`;return Y(a,e.headerFrom,e.headerTo,o)}function St(a,e,t){if(!e.interfaces.includes(t))return a;const s=a.slice(e.headerFrom,e.headerTo),i=e.kind==="interface"?"extends":"implements",n=new RegExp(`\\s*\\b${i}\\s+([\\p{L}_$][\\p{L}\\p{N}_$<>,\\s]*?)(?=\\s*$)`,"u"),o=s.replace(n,(r,c)=>{const l=c.split(",").map(h=>h.trim()).filter(h=>h&&h!==t);return l.length?` ${i} ${l.join(", ")}`:""});return Y(a,e.headerFrom,e.headerTo,o)}function Lt(a,e,t,s){if(e.kind!=="field"||e.shared)return a;const i=a.slice(e.headerFrom,e.headerTo),n=i.lastIndexOf(e.type,e.nameFrom-e.headerFrom);if(n<0)return a;const o=i.slice(0,n)+t+i.slice(n+e.type.length);return Y(a,e.headerFrom,e.to,`${o}${s?` = ${s}`:""};`)}function Et(a,e,t){const s=a.slice(e.headerFrom,e.headerTo),i=t?s.replace(/\bclass\b/,"abstract class"):s.replace(/\babstract\s+/,"");return Y(a,e.headerFrom,e.headerTo,i)}function ai(a,e){const t=a.slice(e.headerFrom,e.nameFrom);return{isPublic:/\bpublic\b/.test(t),isFinal:/\bfinal\b/.test(t)}}function ri(a,e,t){const s=a.slice(e.headerFrom,e.headerTo),i=/\bpublic\s+/.test(s.slice(0,e.nameFrom-e.headerFrom)),n=t?i?s:`public ${s}`:s.replace(/\bpublic\s+/,"");return Y(a,e.headerFrom,e.headerTo,n)}function Ne(a,e,t){const s=a.slice(e.headerFrom,e.headerTo),i=t?/\bfinal\b/.test(s)?s:s.replace(/\babstract\s+/,"").replace(/\bclass\b/,"final class"):s.replace(/\bfinal\s+/,"");return Y(a,e.headerFrom,e.headerTo,i)}function Ee(a,e,t){const s=Ve(t);if(!s)return a;const i=ii(a,e),n=bs(s,e,e.kind==="interface");if(s.kind==="field"){const h=[...e.members].reverse().find(m=>m.kind==="field"),u=h?mt(a,h.from,h.to)[1]:ci(a,e),f=a[u-1]===` +`?"":` +`;return Y(a,u,u,`${f}${i}${n}; +`)}let o;if(e.kind==="interface")o=`${i}${n}; +`;else{const h=s.type??"void",f=!(s.name===e.name)&&h!=="void"?`${i} return ${si(h)}; +`:`${i} // Dein Code +`;o=`${i}${n} { +${f}${i}} +`}const r=Ue(a,e.bodyEnd);if(!/^\s*$/.test(a.slice(r,e.bodyEnd)))return Y(a,e.bodyEnd,e.bodyEnd,` +`+o);const c=a.slice(0,r),l=/\n[ \t]*\n$/.test(c)||/\{[ \t]*\n$/.test(c)?"":` +`;return Y(a,r,r,l+o)}function ci(a,e){const t=a.indexOf("{",e.headerTo)+1,s=/^[ \t]*\n/.exec(a.slice(t));return s?t+s[0].length:t}function Qe(a,e,t,s){const i=Ve(s);if(!i)return a;if(t.kind==="field"!==(i.kind==="field")){const l=xe(a,t),h=oe(l).find(u=>u.name===e.name);return h?Ee(l,h,s):l}if(t.shared)return Y(a,t.nameFrom,t.nameTo,i.name);i.visibility??(i.visibility=t.visibility),(i.kind==="field"||t.kind!=="constructor")&&(i.type??(i.type=t.type));const o=bs(i,e,t.isAbstract),r=a.slice(t.headerFrom,t.headerTo),c=/\bfinal\s+/.test(r)&&!/\bfinal\b/.test(o)?o.replace(/^((?:public|private|protected)\s+)?/,"$1final "):o;return Y(a,t.headerFrom,t.headerTo,c)}function xe(a,e){if(e.shared)return a;const[t,s]=mt(a,e.from,e.to);return Y(a,t,s,"")}const Z="src";function we(a){const e=a.indexOf(":");return e<0?{root:Z,rest:a}:{root:a.slice(0,e),rest:a.slice(e+1)}}const qe=(a,e)=>a===Z?e:`${a}:${e}`,re=(a,e)=>qe(a,e),X=a=>we(a).rest,U=a=>we(a).root,D=a=>{const{root:e,rest:t}=we(a);return qe(e,t.includes("/")?t.slice(0,t.lastIndexOf("/")).replace(/\//g,"."):"")},Q=a=>{const e=we(a).rest;return e.slice(e.lastIndexOf("/")+1)},le=(a,e)=>{const{root:t,rest:s}=we(a);return qe(t,s?`${s.replace(/\./g,"/")}/${e}`:e)},li=a=>{const{root:e,rest:t}=we(a);return`${e}/${t}`},hi=/^[\p{L}\p{N}_$-][\p{L}\p{N}_$.-]*$/u,Je=a=>hi.test(a)&&!a.includes("..");function ue(a){const e=new Set([Z,...a.sourceFolders??[]]);for(const t of a.files)e.add(U(t.path));for(const t of a.packages)e.add(U(t));return[...e].sort((t,s)=>t===Z?-1:s===Z?1:t.localeCompare(s))}const di=/^[a-z_$][\p{L}\p{N}_$]*(\.[a-z_$][\p{L}\p{N}_$]*)*$/u,Mt=a=>di.test(a);function ce(a,e){const t=new Set(a.packages);for(const i of a.files)t.add(D(i.path));const s=ue(a);return[...t].filter(i=>X(i)!==""||a.files.some(n=>D(n.path)===i)).filter(i=>e===void 0||U(i)===e).sort((i,n)=>{const o=s.indexOf(U(i))-s.indexOf(U(n));if(o)return o;const[r,c]=[X(i),X(n)];return r===""?1:c===""?-1:r.localeCompare(c)})}function ui(a,e){return a.files.filter(t=>D(t.path)===e).sort((t,s)=>t.path.localeCompare(s.path))}function bt(a,e){const t=X(e),i=/^(\s*(?:\/\/[^\n]*\n|\/\*[\s\S]*?\*\/\s*)*)package\s+[\w.]+\s*;[ \t]*\n?/.exec(a);return i?t?`${i[1]}package ${t}; +`+a.slice(i[0].length):i[1]+a.slice(i[0].length).replace(/^\n/,""):t?`package ${t}; + +${a.replace(/^\n+/,"")}`:a}function pi(a){var e;return((e=/^\s*(?:(?:\/\/[^\n]*|\/\*[\s\S]*?\*\/)\s*)*package\s+([\w.]+)\s*;/.exec(a))==null?void 0:e[1])??""}function Ct(a){return a.files.flatMap(e=>oe(e.text).map(t=>({...t,path:e.path,pkg:X(D(e.path)),root:U(e.path)})))}function $e(a,e,t){return{...a,files:a.files.map(s=>s.path===e?{...s,text:t}:s)}}function et(a,e,t){return{...a,files:[...a.files.filter(s=>s.path!==e),{path:e,text:t}]}}function Tt(a,e){const t=D(e);return{...a,files:a.files.filter(s=>s.path!==e),packages:t&&!a.packages.includes(t)?[...a.packages,t]:a.packages}}function Oe(a,e,t){const s=D(t);return{...a,files:a.files.map(i=>i.path===e?{path:t,text:D(e)===s?i.text:bt(i.text,s)}:i)}}function fi(a,e){return a.packages.includes(e)?a:{...a,packages:[...a.packages,e]}}function mi(a,e,t){const s=i=>i===e?t:i.startsWith(e+".")?t+i.slice(e.length):i;return{...a,packages:[...new Set(a.packages.map(s))],files:a.files.map(i=>{const n=D(i.path),o=s(n);return o===n?i:{path:le(o,Q(i.path)),text:bt(i.text,o)}})}}function bi(a,e){return ue(a).includes(e)?a:{...a,sourceFolders:[...a.sourceFolders??[],e]}}function vi(a,e,t){const s=i=>U(i)===e?qe(t,X(i)):i;return{...a,sourceFolders:(a.sourceFolders??[]).map(i=>i===e?t:i).filter(i=>i!==Z),packages:a.packages.map(s),files:a.files.map(i=>U(i.path)===e?{...i,path:qe(t,we(i.path).rest)}:i)}}function gi(a,e){return e===Z?a:{...a,sourceFolders:(a.sourceFolders??[]).filter(t=>t!==e),packages:a.packages.filter(t=>U(t)!==e),files:a.files.filter(t=>U(t.path)!==e)}}function yi(a,e){return{...a,packages:a.packages.filter(t=>t!==e),files:a.files.filter(t=>D(t.path)!==e)}}function wi(a,e,t){return bt(`public ${t} ${e} { +} +`,a)}function At(a,e){var s,i;const t=[];for(const n of e){const o=n.text.replace(/\r\n/g,` +`),r=pi(o),c=(s=/\bpublic\s+(?:abstract\s+|final\s+)*(?:class|interface|enum)\s+(\w+)/.exec(o))==null?void 0:s[1],l=/\.java$/i.test(n.name)?Q(n.name):`${c??((i=oe(o)[0])==null?void 0:i.name)??"Main"}.java`;t.push({path:le(r,l),text:o})}return{name:a,files:t,packages:[]}}function Pe(a){return JSON.stringify({format:"visuobject",version:1,...a})}function qt(a){try{const e=JSON.parse(a);if(!Array.isArray(e.files))return;const t=e.files.filter(c=>typeof(c==null?void 0:c.path)=="string"&&typeof(c==null?void 0:c.text)=="string"),s={name:typeof e.name=="string"&&e.name?e.name:"Projekt",files:t,packages:Array.isArray(e.packages)?e.packages.filter(c=>typeof c=="string"):[]},i=Array.isArray(e.sourceFolders)?e.sourceFolders.filter(c=>typeof c=="string"&&Je(c)&&c!==Z):[];i.length&&(s.sourceFolders=i);const n=ys(e.uml);n&&(s.uml=n);const o=vs(e.notes);o&&(s.notes=o);const r=gs(e.objects);return r&&(s.objects=r),s}catch{return}}function vs(a){if(!Array.isArray(a))return;const e=[];for(const t of a){if(!t||typeof t.id!="string"||typeof t.text!="string"||typeof t.x!="number"||typeof t.y!="number")continue;const s=Array.isArray(t.attach)?t.attach.filter(i=>typeof i=="string"):[];e.push({id:t.id,text:t.text,x:t.x,y:t.y,...s.length?{attach:s}:{}})}return e.length?e:void 0}function gs(a){if(!Array.isArray(a))return;const e=[];for(const t of a){if(!t||typeof t.id!="string"||typeof t.name!="string"||typeof t.cls!="string"||typeof t.x!="number"||typeof t.y!="number")continue;const s={};if(t.values&&typeof t.values=="object")for(const[i,n]of Object.entries(t.values))typeof n=="string"&&(s[i]=n);e.push({id:t.id,name:t.name,cls:t.cls,x:t.x,y:t.y,values:s})}return e.length?e:void 0}function ys(a){if(!a||typeof a!="object"||Array.isArray(a))return;const e={};for(const[t,s]of Object.entries(a))s&&typeof s=="object"&&!Array.isArray(s)&&(e[t]=s);return Object.keys(e).length?e:void 0}function Ft(){return{name:"Zoo",packages:[],uml:{"Besitzer.hunde":{kind:"aggregation",name:"führt aus",reading:"forward",sourceMultiplicity:"1"}},files:[{path:"tiere/Tier.java",text:`package tiere; + +public class Tier { + private String name; + private int alter; + + public Tier(String name, int alter) { + this.name = name; + this.alter = alter; + } + + public String getName() { + return name; + } + + public void lautGeben() { + System.out.println("..."); + } +} +`},{path:"tiere/Hund.java",text:`package tiere; + +public class Hund extends Tier { + private String rasse; + + public Hund(String name, int alter, String rasse) { + super(name, alter); + this.rasse = rasse; + } + + public void lautGeben() { + System.out.println("Wuff"); + } +} +`},{path:"personen/Besitzer.java",text:`package personen; + +import java.util.ArrayList; +import tiere.Hund; + +public class Besitzer { + private String name; + private ArrayList hunde = new ArrayList<>(); + + public void gassiGehen() { + for (Hund h : hunde) { + h.lautGeben(); + } + } +} +`}]}}const $i=a=>a.replace(/\/\*[\s\S]*?\*\/|\/\/[^\n]*|"(?:\\.|[^"\\\n])*"|'(?:\\.|[^'\\\n])*'/g,e=>" ".repeat(e.length));function _i(a,e){const t=a.map(i=>i.name),s=new Map;for(const i of a){const n=e(i);if(!n)continue;const o=$i(n),r=new Set([i.superclass,...i.interfaces,...i.members.filter(c=>c.kind==="field"&&!c.isStatic).map(c=>Fe(c.type).name)]);for(const c of i.members){if(c.kind==="field")continue;const l=o.slice(c.from,c.to);for(const h of t){if(h===i.name||r.has(h)||!new RegExp(`\\b${h}\\b`).test(l))continue;const f=new RegExp(`\\bnew\\s+${h}\\s*[(<\\[{]`).test(l)?"create":"use",m=`${i.name}>${h}`,g=s.get(m)??{from:i.name,to:h,kind:f,methods:[]};f==="create"&&(g.kind="create");const _=c.kind==="constructor"?`${c.name}()`:`${c.name}()`;g.methods.includes(_)||g.methods.push(_),s.set(m,g)}}}return[...s.values()]}const Nt=["1","0..1","0..*","1..*","*"];function Me(a){const e=a.trim().split("..").pop().trim();return e==="*"||e==="n"||/^\d+$/.test(e)&&Number(e)>1}const V=(a,e)=>`${a}.${e}`;function Ot(a){return Qs(a).filter(e=>e.kind!=="association")}function Pt(a,e={}){const t=new Set(a.map(c=>c.name)),s=[];for(const c of a)for(const l of c.members){if(l.kind!=="field"||l.isStatic)continue;const h=Fe(l.type);t.has(h.name)&&h.name!==c.name&&s.push({cls:c,field:l,target:h.name,many:h.many})}const i=new Set,n=[],o=(c,l)=>c&&Me(c)===l?c:l?"0..*":"1",r=c=>{const l=e[V(c.cls.name,c.field.name)];return!!l&&(l.kind!==void 0||l.name!==void 0||l.reading!==void 0||l.navigable!==void 0||l.targetEnd!==void 0||l.sourceEnd!==void 0)};for(const c of s){if(i.has(c))continue;i.add(c);const l=s.filter(_=>!i.has(_)&&_.cls.name===c.target&&_.target===c.cls.name);let h=l.length===1&&s.filter(_=>_.cls.name===c.cls.name&&_.target===c.target).length===1?l[0]:void 0;h&&i.add(h);let u=c;h&&!r(c)&&r(h)&&([u,h]=[h,c]);const f=V(u.cls.name,u.field.name),m=e[f]??{},g=h?e[V(h.cls.name,h.field.name)]??{}:{};n.push({key:f,from:u.cls.name,to:u.target,kind:m.kind??"association",name:m.name,reading:m.reading??(m.name?"forward":void 0),navTo:m.targetEnd??(m.navigable===!1?"unspecified":"navigable"),navFrom:h?"navigable":m.sourceEnd??"unspecified",role:u.field.name,multiplicity:o(m.multiplicity,u.many),sourceRole:h?h.field.name:m.sourceRole,sourceMultiplicity:h?o(g.multiplicity,h.many):m.sourceMultiplicity,field:u.field,back:h&&{key:V(h.cls.name,h.field.name),field:h.field}})}return n}function xi(a,e,t){const s=e.charAt(0).toLowerCase()+e.slice(1)+(t?"Liste":"");let i=s;for(let n=2;a.members.some(o=>o.name===i);n++)i=s+n;return i}function It(a,e){return e?{type:`ArrayList<${a}>`,init:"new ArrayList<>()"}:{type:a}}function tt(a,e){if(!e.includes("."))return a;const t=e.replace(/\./g,"\\."),s=e.slice(0,e.lastIndexOf("."));if(new RegExp(`^\\s*import\\s+(${t}|${s.replace(/\./g,"\\.")}\\.\\*)\\s*;`,"m").test(a))return a;const i=[...a.matchAll(/^[ \t]*import\s+[\w.*]+\s*;[ \t]*\n/gm)];if(i.length){const o=i[i.length-1],r=o.index+o[0].length;return a.slice(0,r)+`import ${e}; +`+a.slice(r)}const n=/^\s*package\s+[\w.]+\s*;[ \t]*\n/.exec(a);return n?a.slice(0,n[0].length)+` +import ${e}; +`+a.slice(n[0].length).replace(/^(?!\n)/,` +`):`import ${e}; + +${a}`}function ki(a,e,t){const s={...a[e],...t};for(const n of Object.keys(s))(s[n]===void 0||s[n]==="")&&delete s[n];s.kind==="association"&&delete s.kind,delete s.navigable,s.targetEnd==="navigable"&&delete s.targetEnd,s.sourceEnd==="unspecified"&&delete s.sourceEnd;const i={...a};return Object.keys(s).length?i[e]=s:delete i[e],i}function ke(a,e,t){if(!a[e]||e===t)return a;const s={...a,[t]:a[e]};return delete s[e],s}function ji(a,e){const t=new Map(a.map(o=>[o.name,o])),s=[],i=new Set;for(let o=t.get(e);o&&!i.has(o.name);o=o.superclass?t.get(o.superclass):void 0)i.add(o.name),s.unshift(o);const n=[];for(const o of s)for(const r of o.members){if(r.kind!=="field"||r.isStatic||n.some(l=>l.name===r.name))continue;const c=Fe(r.type);n.push({name:r.name,type:r.type,many:c.many,...t.has(c.name)?{target:c.name}:{}})}return n}function Si(a){return/^(int|long|short|byte)$/.test(a)?"0":/^(double|float)$/.test(a)?"0.0":a==="boolean"?"false":a==="char"?"''":"null"}function Ce(a){var s;const e=(a??"").trim();return!e||e==="null"?[]:(((s=/^\[(.*)\]$/s.exec(e))==null?void 0:s[1])??e).split(",").map(i=>i.trim()).filter(i=>/^[\p{L}_$][\p{L}\p{N}_$]*$/u.test(i)&&i!=="null")}function Li(a,e,t){if(!a.many)return t;const s=Ce(e);return`[${(s.includes(t)?s:[...s,t]).join(", ")}]`}function Dt(a,e,t){const s=new Map(a.map(o=>[o.name,o])),i=new Set,n=o=>{if(!o||i.has(o))return!1;if(o===t)return!0;i.add(o);const r=s.get(o);return!!r&&(n(r.superclass)||r.interfaces.some(n))};return n(e)}function Ei(a,e){const t=a.charAt(0).toLowerCase()+a.slice(1);for(let s=1;;s++)if(!e.includes(`${t}${s}`))return`${t}${s}`}const N=a=>a.replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]),Mi=/^[\p{L}_$][\p{L}\p{N}_$]*$/u;class Ci{constructor(e){E(this,"selected");E(this,"live");E(this,"suppressClick",!1);E(this,"lastClick",{id:"",time:0});this.host=e,e.canvas.addEventListener("pointerdown",t=>this.onPointerDown(t)),e.canvas.addEventListener("click",t=>this.onClick(t))}get objects(){var e;return((e=this.live)==null?void 0:e.objects)??this.host.objects()}find(e){return e?this.objects.find(t=>t.id===e):void 0}change(e,t){this.host.setObjects(this.host.objects().map(s=>s.id===e?{...s,...t}:s))}fields(e){return ji(this.host.classes(),e.cls)}valueOf(e,t){return e.values[t.name]??Si(t.type)}render(){const{canvas:e}=this.host;for(const t of e.querySelectorAll(".uml-object, .vo-empty"))t.remove();if(this.objects.length===0){const t=document.createElement("p");t.className="vo-empty",t.textContent=d(this.host.classes().some(s=>s.kind==="class"&&!s.isAbstract)?"web_visuobject_obj_empty":"web_visuobject_obj_no_classes"),e.append(t)}for(const t of this.objects)e.append(this.box(t));this.drawLinks(),this.renderInspector()}box(e){const t=document.createElement("div"),s=this.selected===e.id&&!this.live,i=this.host.classes().some(o=>o.name===e.cls);t.className=`uml-class uml-object${s?" selected":""}${i?"":" unknown"}`,t.dataset.obj=e.id,t.style.left=`${e.x}px`,t.style.top=`${e.y}px`;const n=this.fields(e).map(o=>{var c;return`
  • ${N(o.name)} = ${N(this.valueOf(e,o))}
  • `}).join("");return t.innerHTML=`${s?``:""} +
    ${N(e.name)} : ${N(e.cls)}
    +
      ${n}
    `,t}drawLinks(){var l;const{canvas:e,lines:t}=this.host,s=new Map;for(const h of e.querySelectorAll(".uml-object"))s.set(h.dataset.obj,h);let i=0,n=0;for(const h of s.values())i=Math.max(i,h.offsetLeft+h.offsetWidth+40),n=Math.max(n,h.offsetTop+h.offsetHeight+40);t.setAttribute("width",String(i)),t.setAttribute("height",String(n));const o=h=>({x:h.offsetLeft,y:h.offsetTop,w:h.offsetWidth,h:h.offsetHeight}),r=[],c=new Map;for(const h of this.objects){const u=s.get(h.id);if(u){for(const f of this.fields(h))if(f.target)for(const m of Ce(this.valueOf(h,f))){const g=this.objects.find(W=>W.name===m),_=g&&s.get(g.id);if(!_||_===u)continue;const y=[h.id,g.id].sort().join("|"),w=c.get(y)??0;c.set(y,w+1);const $=o(u),p=o(_),v={x:$.x+$.w/2,y:$.y+$.h/2},x={x:p.x+p.w/2,y:p.y+p.h/2},L=Math.hypot(x.x-v.x,x.y-v.y)||1,S=-(x.y-v.y)/L*w*14,k=(x.x-v.x)/L*w*14,j=Rt($,{x:v.x+S,y:v.y+k},{x:x.x+S,y:x.y+k}),M=Rt(p,{x:x.x+S,y:x.y+k},{x:v.x+S,y:v.y+k}),A=(j.x-M.x)/(Math.hypot(j.x-M.x,j.y-M.y)||1),R=(j.y-M.y)/(Math.hypot(j.x-M.x,j.y-M.y)||1),C={x:M.x+A*22-R*10,y:M.y+R*22+A*10},F=(l=this.live)==null?void 0:l.changed.has(`${h.id}.${f.name}`);r.push(``),r.push(`${N(f.name)}`)}}}t.innerHTML=r.join("")}renderInspector(){const{inspector:e}=this.host;if(this.live)return this.renderDebugger(this.live);const t=this.find(this.selected);if(!t){delete e.dataset.rel,e.innerHTML=`

    ${N(d("web_visuobject_obj_hint"))}

    `;return}e.dataset.rel=`obj:${t.id}`;const s=this.host.classes().filter(r=>r.kind==="class"),i=this.objects.filter(r=>r.id!==t.id),n=r=>{const c=this.valueOf(t,r);if(r.target&&!r.many){const l=i.filter(h=>Dt(this.host.classes(),h.cls,r.target));return``}return``},o=this.fields(t).map(r=>`${N(r.name)} : ${N(r.type)}${n(r)}`).join("");e.innerHTML=` +
    + + +
    + + ${o||``}
    ${N(d("web_visuobject_obj_attribute"))}${N(d("web_visuobject_obj_value"))}
    ${N(d("web_visuobject_insp_no_fields"))}
    +
    `,e.querySelector("[data-field=name]").addEventListener("change",r=>{const c=r.target.value.trim();if(!Mi.test(c))return this.host.message(d("web_visuobject_obj_bad_name",c));if(i.some(h=>h.name===c))return this.host.message(d("web_visuobject_obj_name_taken",c));this.host.message("");const l=t.name;this.host.setObjects(this.host.objects().map(h=>{const u=Object.fromEntries(Object.entries(h.values).map(([f,m])=>[f,Ce(m).includes(l)?m.replace(new RegExp(`(^|[\\s,\\[])${l}(?=$|[\\s,\\]])`,"gu"),`$1${c}`):m]));return h.id===t.id?{...h,name:c,values:u}:{...h,values:u}}))}),e.querySelector("[data-field=cls]").addEventListener("change",r=>this.change(t.id,{cls:r.target.value}));for(const r of e.querySelectorAll("[data-objval]"))r.addEventListener("change",()=>this.change(t.id,{values:{...t.values,[r.dataset.objval]:r.value.trim()}}));e.querySelector("[data-obj-delete]").addEventListener("click",()=>this.remove(t.id))}renderDebugger(e){const{inspector:t}=this.host;delete t.dataset.rel;const s=e.frames[e.frame],i=e.frames.map((o,r)=>`
  • `).join(""),n=((s==null?void 0:s.vars)??[]).map(o=>`${N(o.name)}${N(o.type)}${N(o.value)}`).join("");t.innerHTML=` +
    +

    ${N(d("web_visuobject_dbg_stack"))}

      ${i||`
    1. ${N(d("web_visuobject_obj_live_hint"))}
    2. `}
    +

    ${N(d("web_visuobject_dbg_vars"))}

    + + ${n||``}
    ${N(d("web_visuobject_dbg_var_name"))}${N(d("web_visuobject_dbg_var_type"))}${N(d("web_visuobject_obj_value"))}
    ${N(d("web_visuobject_dbg_no_vars"))}
    +
    +
    `;for(const o of t.querySelectorAll("[data-frame]"))o.addEventListener("click",()=>e.onFrame(Number(o.dataset.frame)))}add(e){const t=this.host.objects(),s=Ei(e,t.map(r=>r.name)),i=[...this.host.canvas.querySelectorAll(".uml-object")].map(r=>({x:r.offsetLeft,y:r.offsetTop,w:r.offsetWidth,h:r.offsetHeight}));let n={x:24,y:24};e:for(let r=24;r<4e3;r+=40)for(let c=24;cc+200+40<=l.x||l.x+l.w+40<=c||r+110+30<=l.y||l.y+l.h+30<=r)){n={x:c,y:r};break e}const o=`o${Date.now().toString(36)}`;this.selected=o,this.host.setObjects([...t,{id:o,name:s,cls:e,x:n.x,y:n.y,values:{}}])}remove(e){const t=this.host.objects().find(s=>s.id===e);t&&(this.selected=void 0,this.host.setObjects(this.host.objects().filter(s=>s.id!==e).map(s=>({...s,values:Object.fromEntries(Object.entries(s.values).map(([i,n])=>{const o=Ce(n);return o.includes(t.name)?[i,/^\[/.test(n.trim())?`[${o.filter(r=>r!==t.name).join(", ")}]`:"null"]:[i,n]}))}))))}onKey(e){return this.live||!this.selected?!1:e.key==="Delete"||e.key==="Backspace"?(e.preventDefault(),this.remove(this.selected),!0):!1}select(e){this.selected=e,this.render(),this.host.canvas.focus({preventScroll:!0})}onPointerDown(e){if(e.button!==0)return;const t=e.target,s=t.closest("[data-obj-connect]"),i=t.closest(".uml-object");if(s&&i&&!this.live)return this.startLink(e,i);i&&this.drag(e,i)}onClick(e){var o;if(this.suppressClick){this.suppressClick=!1;return}if(this.live)return;const t=e.target.closest(".uml-object"),s=t==null?void 0:t.dataset.obj,i=Date.now(),n=!!s&&this.lastClick.id===s&&i-this.lastClick.time<450;this.lastClick={id:s??"",time:n?0:i},this.select(s),n&&((o=this.host.inspector.querySelector("[data-field=name]"))==null||o.select())}drag(e,t){const s=this.find(t.dataset.obj);if(!s)return;const i={x:e.clientX,y:e.clientY};let n=!1,o={x:s.x,y:s.y};const r=l=>{const h=l.clientX-i.x,u=l.clientY-i.y;!n&&Math.hypot(h,u)<4||(n=!0,o={x:Math.max(0,Math.round(s.x+h)),y:Math.max(0,Math.round(s.y+u))},t.style.left=`${o.x}px`,t.style.top=`${o.y}px`,this.drawLinks())},c=()=>{if(window.removeEventListener("pointermove",r),window.removeEventListener("pointerup",c),!!n){if(this.suppressClick=!0,this.live)return Object.assign(s,o),this.live.move(s.id,o);this.selected=s.id,this.change(s.id,o)}};window.addEventListener("pointermove",r),window.addEventListener("pointerup",c)}startLink(e,t){e.preventDefault();const s=this.find(t.dataset.obj);if(!s)return;const{canvas:i,lines:n}=this.host,o=document.createElementNS("http://www.w3.org/2000/svg","line");o.setAttribute("class","vo-rel ghost"),n.append(o);const r={x:t.offsetLeft+t.offsetWidth,y:t.offsetTop+t.offsetHeight/2},c=u=>{var m;const f=(m=document.elementFromPoint(u.clientX,u.clientY))==null?void 0:m.closest(".uml-object");return f&&f!==t?f:void 0},l=u=>{var m;const f=i.getBoundingClientRect();o.setAttribute("x1",String(r.x)),o.setAttribute("y1",String(r.y)),o.setAttribute("x2",String(u.clientX-f.left+i.scrollLeft)),o.setAttribute("y2",String(u.clientY-f.top+i.scrollTop));for(const g of i.querySelectorAll(".uml-object.drop"))g.classList.remove("drop");(m=c(u))==null||m.classList.add("drop")},h=u=>{window.removeEventListener("pointermove",l),window.removeEventListener("pointerup",h),o.remove();const f=c(u);f==null||f.classList.remove("drop"),this.suppressClick=!0;const m=f&&this.find(f.dataset.obj);if(!m)return;const g=this.host.classes(),_=this.fields(s).filter(w=>w.target&&Dt(g,m.cls,w.target)),y=_.find(w=>!w.many&&Ce(this.valueOf(s,w)).length===0)??_.find(w=>w.many)??_[0];if(!y)return this.host.message(d("web_visuobject_obj_no_ref",s.cls,m.cls));this.host.message(""),this.change(s.id,{values:{...s.values,[y.name]:Li(y,this.valueOf(s,y),m.name)}})};window.addEventListener("pointermove",l),window.addEventListener("pointerup",h)}}function Rt(a,e,t){const s=t.x-e.x,i=t.y-e.y,n=s===0?1/0:a.w/2/Math.abs(s),o=i===0?1/0:a.h/2/Math.abs(i),r=Math.min(n,o,1);return{x:Math.round(e.x+s*r),y:Math.round(e.y+i*r)}}const je=a=>a.replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]),Ie=180,Ht=30,De=12,ae=30,Re=34,ee=10,st=a=>a.length*7+16;function Ti(a,e){var w;const t=new Map(a.participants.map(($,p)=>[$.key,p])),s=$=>Ht+(t.get($)??0)*Ie+Ie/2,i=new Map,n=[],o=[],r=[],c=[],l=(w=a.participants[0])!=null&&w.isStatic?a.participants[0].key:"",h=$=>c.filter(p=>p.key===$).length+($===l?1:0),u=($,p)=>s($)-ee/2+Math.max(0,p-1)*6;let f=De+ae+24;a.events.forEach(($,p)=>{const v=p===e?" current":"";if($.k==="return"){const C=c.pop();if(!C)return;if($.hidden){o.push(``);return}const F=u(C.key,C.level),W=h(C.caller),G=C.caller===C.key?u(C.caller,W)+ee:W?u(C.caller,W)+(s(C.caller)`),C.caller!==C.key&&n.push(`${zt(G,f,G${je($.label)}`:""}`),f+=Re;return}const x=h($.from),L=$.from===$.to;$.k==="create"&&(f+=ae/2+8,i.set($.to,f));const S=h($.to)+1,k=x?u($.from,x)+(s($.to)>=s($.from)?ee:0):s($.from);if(L){const C=k,F=u($.to,S)+ee;n.push(`${Wt(F,f+4,-1)}${je($.label)}`),c.push({key:$.to,caller:$.from,y:f+4-6,level:S}),f+=Re;return}const j=s($.to)>s($.from),M=$.k==="create"?s($.to)+(j?-st(Bt(a,$.to))/2:st(Bt(a,$.to))/2):u($.to,S)+(j?0:ee),A=$.k==="create"?" create":"",R=$.k==="create"?`«create» ${$.label}`:$.label;n.push(`${$.k==="create"?zt(M,f,j?1:-1):Wt(M,f,j?1:-1)}${$.k==="create"?`${je(R)}`:`${je(R)}`}`),c.push({key:$.to,caller:$.from,y:$.k==="create"?f+ae/2:f,level:S}),f+=$.k==="create"?Re+ae/2:Re});for(const $ of c)o.push(``);const m=f+10,g=a.participants[0];g!=null&&g.isStatic&&o.unshift(``);for(const $ of a.participants){const p=s($.key),v=i.get($.key),x=v!==void 0?v-ae/2:De,L=Math.min(Ie-12,st($.label));r.push(`${je($.label)}`)}const _=Ht*2+a.participants.length*Ie,y=m+20;return{svg:`${r.join("")}${o.join("")}${n.join("")}`,width:_,height:y}}function Bt(a,e){var t;return((t=a.participants.find(s=>s.key===e))==null?void 0:t.label)??""}function Wt(a,e,t){return``}function zt(a,e,t){return``}class Ke extends Error{constructor(e,t){super(e),this.pos=t}}const Ai=[">>>=","<<=",">>=",">>>","...","->","::","++","--","&&","||","==","!=","<=",">=","+=","-=","*=","/=","%=","&=","|=","^=","<<"];function vt(a,e){const t=[];let s=0,i=0;for(;s=a.length)throw new Ke(n==='"'?"string":"char",{file:e,line:i});t.push({t:n==='"'?"str":"char",v:r,line:i}),s=o+1}else{const o=Ai.find(r=>a.startsWith(r,s))??n;t.push({t:"op",v:o,line:i}),s+=o.length}}return t.push({t:"eof",v:"",line:i}),t}const qi=new Set(["public","private","protected","static","final","abstract","synchronized","transient","volatile","native","strictfp","default"]),Fi=new Set(["int","long","short","byte","double","float","boolean","char","void","var"]),Ae=class Ae{constructor(e,t){E(this,"i",0);this.toks=e,this.file=t}get tok(){return this.toks[this.i]}peek(e=1){return this.toks[Math.min(this.i+e,this.toks.length-1)]}pos(e=this.tok){return{file:this.file,line:e.line}}is(e,t=this.tok){return(t.t==="op"||t.t==="id")&&t.v===e}eat(e){return this.is(e)?(this.i++,!0):!1}expect(e){this.eat(e)||this.fail(`expected:${e}`)}fail(e){throw new Ke(e,this.pos())}ident(){return this.tok.t!=="id"&&this.fail("identifier"),this.toks[this.i++].v}unit(){const e=[];for(this.eat("package")&&this.skipTo(";");this.is("import");)this.skipTo(";");for(;this.tok.t!=="eof";)this.eat(";")||e.push(this.classDecl());return e}skipTo(e){for(;this.tok.t!=="eof"&&!this.is(e);)this.i++;this.expect(e)}mods(){const e=new Set;for(;;)if(this.tok.t==="op"&&this.tok.v==="@")this.i++,this.ident(),this.is("(")&&this.skipParens();else if(this.tok.t==="id"&&qi.has(this.tok.v)&&!(this.tok.v==="default"&&this.is(":",this.peek())))e.add(this.toks[this.i++].v);else return e}skipParens(){let e=0;do this.is("(")?e++:this.is(")")&&e--,this.i++;while(e>0&&this.tok.t!=="eof")}classDecl(){const e=this.mods(),t=this.pos(),s=this.eat("class")?"class":this.eat("interface")?"interface":this.eat("enum")?"enum":this.fail("class"),i=this.ident();this.is("<")&&this.typeArgs();const n={...t,name:i,kind:s,interfaces:[],isAbstract:e.has("abstract")||s==="interface",fields:[],methods:[],enumConstants:[]};if(this.eat("extends")){const o=[this.type().name];for(;this.eat(",");)o.push(this.type().name);s==="interface"?n.interfaces=o:n.superclass=o[0]}if(this.eat("implements"))for(n.interfaces.push(this.type().name);this.eat(",");)n.interfaces.push(this.type().name);if(this.expect("{"),s==="enum"){for(;this.tok.t==="id"&&(n.enumConstants.push(this.ident()),this.is("(")&&this.skipParens(),!!this.eat(",")););this.eat(";")}for(;!this.eat("}");)this.tok.t==="eof"&&this.fail("expected:}"),!this.eat(";")&&this.member(n);return n}member(e){const t=this.tok,s=this.mods();(this.is("class")||this.is("interface")||this.is("enum"))&&this.fail("innerClass"),this.is("{")&&this.fail("initializer"),this.is("<")&&this.typeArgs();const i=this.pos(t);if(this.tok.t==="id"&&this.tok.v===e.name&&this.is("(",this.peek())){this.i++;const l=this.params();this.eat("throws")&&this.skipThrows();const h=this.block();e.methods.push({...i,name:e.name,params:l,isStatic:!1,isAbstract:!1,isConstructor:!0,body:h,endLine:this.toks[this.i-1].line});return}const n=this.type(),o=this.ident();if(this.is("(")){const l=this.params();for(;this.eat("[");)this.expect("]");this.eat("throws")&&this.skipThrows();const h=s.has("abstract")||e.kind==="interface"&&!this.is("{"),u=this.is("{")?this.block():(this.expect(";"),void 0);e.methods.push({...i,name:o,returns:n,params:l,isStatic:s.has("static"),isAbstract:h,isConstructor:!1,body:u,endLine:this.toks[this.i-1].line});return}let r=!0,c=o;for(;;){r||(c=this.ident()),r=!1;let l=0;for(;this.eat("[");)this.expect("]"),l++;const h=l?{...n,dims:n.dims+l}:n,u=this.eat("=")?this.is("{")?this.arrayInit():this.expr():void 0;if(e.fields.push({...i,name:c,type:h,isStatic:s.has("static")||e.kind==="interface",init:u}),!this.eat(","))break}this.expect(";")}skipThrows(){for(this.type();this.eat(",");)this.type()}params(){this.expect("(");const e=[];if(!this.eat(")")){do{this.mods();let t=this.type();this.eat("...")&&(t={...t,dims:t.dims+1});const s=this.ident();for(;this.eat("[");)this.expect("]"),t={...t,dims:t.dims+1};e.push({name:s,type:t})}while(this.eat(","));this.expect(")")}return e}typeArgs(){this.expect("<");const e=[];if(this.eat(">"))return e;do this.eat("?")?this.eat("extends")||this.eat("super")?e.push(this.type()):e.push({name:"Object",dims:0,args:[]}):e.push(this.type());while(this.eat(","));return this.is(">>")?this.toks[this.i]={...this.tok,v:">"}:this.is(">>>")?this.toks[this.i]={...this.tok,v:">>"}:this.expect(">"),e}type(){let e=this.ident(),t=[];for(this.is("<")&&(t=this.typeArgs());this.is(".")&&this.peek().t==="id";)this.i++,e=this.ident(),this.is("<")&&(t=this.typeArgs());let s=0;for(;this.is("[")&&this.is("]",this.peek());)this.i+=2,s++;return{name:e,dims:s,args:t}}looksLikeDecl(){const e=this.i;try{if(this.mods(),this.tok.t!=="id")return!1;const t=this.tok.v;return["return","new","throw","this","super","true","false","null"].includes(t)?!1:(this.type(),this.tok.t==="id"&&(this.is("=",this.peek())||this.is(";",this.peek())||this.is(",",this.peek())||this.is(":",this.peek())||this.is("[",this.peek())))}catch{return!1}finally{this.i=e}}block(){const e=this.pos();this.expect("{");const t=[];for(;!this.eat("}");)this.tok.t==="eof"&&this.fail("expected:}"),t.push(this.stmt());return{...e,k:"block",body:t}}localDecl(){const e=this.pos();this.mods();const t=this.type(),s=[];do{const i=this.ident();let n=0;for(;this.eat("[");)this.expect("]"),n++;const o=this.eat("=")?this.is("{")?this.arrayInit():this.expr():void 0;s.push({name:i,dims:n,init:o})}while(this.eat(","));return{...e,k:"local",type:t,vars:s}}stmt(){const e=this.pos(),t=this.tok.t==="id"||this.tok.t==="op"?this.tok.v:"";if(t==="{")return this.block();if(this.eat(";"))return{...e,k:"empty"};if(this.eat("if")){this.expect("(");const i=this.expr();this.expect(")");const n=this.stmt();return{...e,k:"if",test:i,then:n,else:this.eat("else")?this.stmt():void 0}}if(this.eat("while")){this.expect("(");const i=this.expr();return this.expect(")"),{...e,k:"while",test:i,body:this.stmt()}}if(this.eat("do")){const i=this.stmt();this.expect("while"),this.expect("(");const n=this.expr();return this.expect(")"),this.expect(";"),{...e,k:"do",body:i,test:n}}if(this.eat("for")){this.expect("(");const i=this.i;try{this.mods();const c=this.type(),l=this.ident();if(this.eat(":")){const h=this.expr();return this.expect(")"),{...e,k:"foreach",type:c,name:l,iter:h,body:this.stmt()}}}catch{}this.i=i;const n=[];if(!this.is(";"))if(this.looksLikeDecl())n.push(this.localDecl());else do{const c=this.pos();n.push({...c,k:"expr",expr:this.expr()})}while(this.eat(","));this.expect(";");const o=this.is(";")?void 0:this.expr();this.expect(";");const r=[];if(!this.is(")"))do r.push(this.expr());while(this.eat(","));return this.expect(")"),{...e,k:"for",init:n,test:o,update:r,body:this.stmt()}}if(this.eat("switch")){this.expect("(");const i=this.expr();this.expect(")"),this.expect("{");const n=[];for(;!this.eat("}");){let o;if(this.eat("default"))o="default";else for(this.expect("case"),o=[this.expr()];this.eat(",");)o.push(this.expr());if(this.eat("->")){const c=this.is("{")?[this.block()]:[this.stmt()];n.push({labels:o,body:c,arrow:!0});continue}this.expect(":");const r=[];for(;!this.is("case")&&!this.is("default")&&!this.is("}");)r.push(this.stmt());n.push({labels:o,body:r,arrow:!1})}return{...e,k:"switch",expr:i,cases:n}}if(this.eat("break"))return this.tok.t==="id"&&this.i++,this.expect(";"),{...e,k:"break"};if(this.eat("continue"))return this.tok.t==="id"&&this.i++,this.expect(";"),{...e,k:"continue"};if(this.eat("return")){const i=this.is(";")?void 0:this.expr();return this.expect(";"),{...e,k:"return",value:i}}if(this.eat("throw")){const i=this.expr();return this.expect(";"),{...e,k:"throw",value:i}}if(this.eat("try")){this.is("(")&&this.fail("tryResources");const i=this.block(),n=[];for(;this.eat("catch");){this.expect("("),this.mods();const r=[this.type()];for(;this.eat("|");)r.push(this.type());const c=this.ident();this.expect(")"),n.push({types:r,name:c,body:this.block()})}const o=this.eat("finally")?this.block():void 0;return{...e,k:"try",body:i,catches:n,finally:o}}if((t==="this"||t==="super")&&this.is("(",this.peek())){this.i++;const i=this.args();return this.expect(";"),{...e,k:"ctorCall",isSuper:t==="super",args:i}}if((t==="class"||t==="interface")&&this.fail("innerClass"),this.looksLikeDecl()){const i=this.localDecl();return this.expect(";"),i}const s=this.expr();return this.expect(";"),{...e,k:"expr",expr:s}}args(){this.expect("(");const e=[];if(!this.eat(")")){do e.push(this.expr());while(this.eat(","));this.expect(")")}return e}arrayInit(){const e=this.pos();this.expect("{");const t=[];for(;!this.eat("}");)if(t.push(this.is("{")?this.arrayInit():this.expr()),!this.eat(",")){this.expect("}");break}return{...e,k:"arrayInit",items:t}}expr(){return this.assign()}assign(){const e=this.cond(),t=this.tok.v;if(this.tok.t==="op"&&["=","+=","-=","*=","/=","%=","&=","|=","^=","<<=",">>=",">>>="].includes(t)){const s=this.pos();return this.i++,e.k!=="name"&&e.k!=="field"&&e.k!=="index"&&this.fail("assignTarget"),{...s,k:"assign",op:t,target:e,value:this.assign()}}return e}cond(){const e=this.binary(0);if(this.is("?")){const t=this.pos();this.i++;const s=this.assign();return this.expect(":"),{...t,k:"cond",test:e,then:s,else:this.assign()}}return e}binary(e){if(e>=Ae.levels.length)return this.unary();let t=this.binary(e+1);for(;;){const s=this.tok.v;if(!(this.tok.t==="op"||s==="instanceof")||!Ae.levels[e].includes(s))return t;const i=this.pos();if(this.i++,s==="instanceof"){t={...i,k:"instanceof",expr:t,type:this.type()},this.tok.t==="id"&&this.i++;continue}t={...i,k:"binary",op:s,left:t,right:this.binary(e+1)}}}unary(){const e=this.pos();if(this.is("++")||this.is("--")){const t=this.toks[this.i++].v;return{...e,k:"incdec",op:t,prefix:!0,target:this.unary()}}if(this.is("!")||this.is("-")||this.is("+")||this.is("~")){const t=this.toks[this.i++].v;return{...e,k:"unary",op:t,expr:this.unary()}}if(this.is("(")&&this.peek().t==="id"){const t=this.i;this.i++;try{const s=this.type();if(this.eat(")")){const i=Fi.has(s.name),n=this.tok;if((i?!(n.t==="op"&&["+","-","*","/",")",";",",",".","==","<",">"].includes(n.v)&&!["(","-","+","!","~"].includes(n.v))||n.t!=="op"||["(","-","!","~"].includes(n.v):n.t!=="op"||n.v==="(")&&(i||/^[A-Z]/.test(s.name)))return{...e,k:"cast",type:s,expr:this.unary()}}}catch{}this.i=t}return this.postfix(this.primary())}postfix(e){for(;;){const t=this.pos();if(this.eat(".")){this.eat("new")&&this.fail("innerClass");const s=this.ident();this.is("(")?e={...t,k:"call",target:e,name:s,args:this.args(),isSuper:e.k==="super"}:e={...t,k:"field",target:e,name:s}}else if(this.is("[")){this.i++;const s=this.expr();this.expect("]"),e={...t,k:"index",target:e,index:s}}else if(this.is("++")||this.is("--")){const s=this.toks[this.i++].v;e={...t,k:"incdec",op:s,prefix:!1,target:e}}else if(this.is("::")||this.is("->"))this.fail("lambda");else return e}}primary(){const e=this.tok,t=this.pos();if(e.t==="num"){this.i++;const i=e.v.replace(/_/g,"");return/^0[xX]/.test(i)?{...t,k:"lit",value:{t:"int",v:parseInt(i.replace(/[lL]$/,""),16)}}:/[.eEfFdD]/.test(i)&&!/^0[xX]/.test(i)?{...t,k:"lit",value:{t:"double",v:parseFloat(i.replace(/[fFdD]$/,""))}}:{...t,k:"lit",value:{t:"int",v:parseInt(i.replace(/[lL]$/,""),10)}}}if(e.t==="str")return this.i++,{...t,k:"lit",value:{t:"string",v:e.v}};if(e.t==="char")return this.i++,{...t,k:"lit",value:{t:"char",v:e.v.charCodeAt(0)||0}};if(this.eat("(")){const i=this.expr();return this.expect(")"),i}if(e.t!=="id"&&this.fail("expression"),this.eat("true"))return{...t,k:"lit",value:{t:"bool",v:!0}};if(this.eat("false"))return{...t,k:"lit",value:{t:"bool",v:!1}};if(this.eat("null"))return{...t,k:"lit",value:{t:"null",v:null}};if(this.eat("this"))return{...t,k:"this"};if(this.eat("super"))return{...t,k:"super"};if(this.eat("new")){const i=this.ident();let n=[];this.is("<")&&(n=this.typeArgs());const o={name:i,dims:0,args:n};if(this.is("[")){const c=[];let l=0;for(;this.eat("[");){if(this.eat("]")){l++;continue}c.push(this.expr()),this.expect("]"),l++}const h=this.is("{")?this.arrayInit():void 0;return{...t,k:"newArray",type:{...o,dims:l},sizes:c,init:h}}const r=this.args();return this.is("{")&&this.fail("anonymousClass"),{...t,k:"new",type:o,args:r}}const s=this.ident();return this.is("(")?{...t,k:"call",name:s,args:this.args()}:{...t,k:"name",name:s}}};E(Ae,"levels",[["||"],["&&"],["|"],["^"],["&"],["==","!="],["<",">","<=",">=","instanceof"],["<<",">>",">>>"],["+","-"],["*","/","%"]]);let ht=Ae;const Ni=["Scanner","Random","ArrayList","List","LinkedList","HashMap","Map","TreeMap","LinkedHashMap","Collection","Collections","Arrays","Iterator","Objects"];function Oi(a,e,t){var n,o;const s=vt(a,e),i=[];for(let r=0;rl.v).join("")),r=c}for(let r=0;r0&&!i.has(s[n-1].v))continue;const l=Ps(o.v);if(l)return{type:l,pos:{file:e,line:o.line}}}}function Ii(a,e){return new ht(vt(a,e),e).unit()}class O{constructor(e){this.v=e}}class H{constructor(e){this.code=e}}class I{constructor(e,t){E(this,"fields",new Map);E(this,"native",{});this.cls=e,this.id=t}}class B{constructor(e,t,s){this.elem=e,this.items=t,this.id=s}}class K{constructor(e){E(this,"items",[]);this.id=e}}class be{constructor(e){E(this,"entries",new Map);this.id=e}}class de{constructor(e,t){E(this,"buf","");this.kind=e,this.id=t}}class Se{constructor(e){this.name=e}}const Di={k:"break"},Ri={k:"continue"};class q extends Error{constructor(e,t,s){super(`${e}: ${t}`),this.code=e,this.detail=t,this.pos=s}}class Le extends Error{constructor(e){super(e.cls.name),this.obj=e}}const ve=(a,e=0)=>({name:a,dims:e,args:[]}),ws=new Set(["int","long","short","byte","Integer","Long","Short","Byte"]),$s=new Set(["double","float","Double","Float"]),Vt=new Set(["ArrayList","List","LinkedList","Collection","Iterable"]),Hi=new Set(["HashMap","Map","TreeMap","LinkedHashMap"]),Bi=[["Throwable","Object","java.lang"],["Exception","Throwable","java.lang"],["Error","Throwable","java.lang"],["StackOverflowError","Error","java.lang"],["RuntimeException","Exception","java.lang"],["IOException","Exception","java.io"],["InterruptedException","Exception","java.lang"],["ArithmeticException","RuntimeException","java.lang"],["NullPointerException","RuntimeException","java.lang"],["ClassCastException","RuntimeException","java.lang"],["IllegalArgumentException","RuntimeException","java.lang"],["NumberFormatException","IllegalArgumentException","java.lang"],["IllegalStateException","RuntimeException","java.lang"],["UnsupportedOperationException","RuntimeException","java.lang"],["IndexOutOfBoundsException","RuntimeException","java.lang"],["ArrayIndexOutOfBoundsException","IndexOutOfBoundsException","java.lang"],["StringIndexOutOfBoundsException","IndexOutOfBoundsException","java.lang"],["NegativeArraySizeException","RuntimeException","java.lang"],["NoSuchElementException","RuntimeException","java.util"],["InputMismatchException","NoSuchElementException","java.util"],["ConcurrentModificationException","RuntimeException","java.util"]],Wi=new Set(["Math","System","Integer","Double","String","Character","Boolean","Long","Float","Arrays","Collections","Thread","Objects","List"]);function Ut(a){if(Number.isNaN(a))return"NaN";if(!Number.isFinite(a))return a>0?"Infinity":"-Infinity";if(a===0)return Object.is(a,-0)?"-0.0":"0.0";const e=Math.abs(a);if(e>=.001&&e<1e7){const i=String(a);return i.includes(".")||i.includes("e")?i:`${i}.0`}const[t,s]=a.toExponential().split("e");return`${t.includes(".")?t:`${t}.0`}E${Number(s)}`}const _e=a=>(460141958+a*165902235>>>0).toString(16);function zi(a){let e=0;for(let t=0;ttypeof a=="number"?a:a instanceof O?a.v:a instanceof H?a.code:NaN,ne=a=>typeof a=="number"||a instanceof O||a instanceof H,He=a=>a>=-2147483648&&a<=2147483647;function te(a,e){if(!e||e.dims||a===null||a===void 0)return a;const t=e.name;if($s.has(t))return ne(a)?new O(T(a)):a;if(ws.has(t)){if(a instanceof H)return a.code;if(a instanceof O){if(Number.isNaN(a.v))return 0;const s=Math.trunc(a.v);return t==="int"||t==="Integer"?Math.max(-2147483648,Math.min(2147483647,s)):s}return typeof a=="number"&&(t==="byte"||t==="Byte")?a<<24>>24:typeof a=="number"&&(t==="short"||t==="Short")?a<<16>>16:a}return(t==="char"||t==="Character")&&(typeof a=="number"||a instanceof O)?new H(Math.trunc(T(a))&65535):a}function it(a){return a.dims?null:a.name==="int"||a.name==="long"||a.name==="short"||a.name==="byte"?0:a.name==="double"||a.name==="float"?new O(0):a.name==="boolean"?!1:a.name==="char"?new H(0):null}const dt=a=>`${a.name}${a.args.length?`<${a.args.map(dt).join(", ")}>`:""}${"[]".repeat(a.dims)}`;class Vi{constructor(e,t){E(this,"classes",new Map);E(this,"frames",[]);E(this,"nextId",1);E(this,"quiet",0);E(this,"gen");E(this,"send");E(this,"mode","run");E(this,"startDepth",0);E(this,"prevKey","");E(this,"pauseRequested",!1);E(this,"names",new Map);E(this,"tempNames",new Map);E(this,"seq",[]);E(this,"seqParticipants",new Map);E(this,"seqLimit",3e3);E(this,"stdin",new de("in",0));E(this,"finished",!1);this.io=t;const s={name:"Object",interfaces:[],statics:new Map,staticTypes:new Map,builtin:!0,javaName:"java.lang.Object"};this.classes.set("Object",s);for(const[o,r,c]of Bi)this.classes.set(o,{name:o,sup:this.classes.get(r),interfaces:[],statics:new Map,staticTypes:new Map,builtin:!0,javaName:`${c}.${o}`});const i=[];for(const o of e)try{i.push(...Ii(o.source,o.path))}catch(r){throw r instanceof Ke?new q("syntax",r.message,r.pos):r}for(const o of i)this.classes.set(o.name,{name:o.name,decl:o,interfaces:o.interfaces,statics:new Map,staticTypes:new Map});const n=new Set(i.map(o=>o.name));for(const o of e){const r=Oi(o.source,o.path,n);if(r)throw new q("import",r.line,r.pos);const c=Pi(o.source,o.path,n);if(c)throw new q("typename",c.type,c.pos)}for(const o of i){const r=this.classes.get(o.name),c=o.superclass??(o.kind==="class"?"Object":void 0);if(c&&(r.sup=this.classes.get(c),!r.sup))throw new q("symbol",c,o)}}start(e){const t=[...this.classes.values()].filter(i=>{var n;return(n=i.decl)==null?void 0:n.methods.some(Kt)}),s=t.find(i=>i.name===e)??t[0];if(!s)throw new q("nomain","");this.gen=this.program(s),this.finished=!1}go(e){this.mode=e,this.startDepth=this.frames.length,this.pauseRequested=!1}pause(){this.pauseRequested=!0}input(e){this.send=e}run(e,t=5e3){var s;if(!this.gen||this.finished)return{k:"done"};for(let i=0;i` at ${s}`)].join(` +`)}stack(){return this.nameObjects(),[...this.frames].reverse().map(e=>{const t=[];e.self&&t.push({name:"this",type:e.self.cls.name,value:this.show(e.self),ref:e.self.id});for(const s of e.scopes)for(const[i,n]of s)t.push({name:i,type:dt(n.type),value:this.show(n.v),...n.v instanceof I?{ref:n.v.id}:{}});return{title:e.title,pos:e.pos,vars:t}})}heap(){return this.nameObjects().map(e=>({id:e.id,name:this.names.get(e.id)??this.tempNames.get(e.id),cls:e.cls.name,fields:[...e.fields].map(([t,s])=>({name:t,type:dt(this.fieldType(e.cls,t)??ve("Object")),value:this.show(s)}))}))}fieldType(e,t){var s;for(let i=e;i;i=i.sup){const n=(s=i.decl)==null?void 0:s.fields.find(o=>o.name===t&&!o.isStatic);if(n)return n.type}}nameObjects(){const e=[],t=new Set,s=new Set(this.names.values());this.tempNames.clear();const i=(r,c,l)=>{if(this.names.has(r.id))return;const h=/^[\p{L}_$][\p{L}\p{N}_$]*$/u.test(c);let u=h?c:r.cls.name.charAt(0).toLowerCase()+r.cls.name.slice(1);if(s.has(u)){let f=2;for(;s.has(`${u}${f}`);)f++;u=`${u}${f}`}s.add(u),(h&&l?this.names:this.tempNames).set(r.id,u)},n=[],o=(r,c,l)=>{if(r instanceof I){if(r.cls.builtin||r.native.enumName!==void 0||t.has(r.id))return;t.add(r.id),i(r,c,l),e.push(r);for(const[h,u]of r.fields)n.push([u,h])}else if(r instanceof B||r instanceof K)for(const h of r.items)h instanceof I&&n.push([h,""]);else if(r instanceof be)for(const[h,u]of r.entries.values())n.push([h,""],[u,""])};for(const r of this.frames){r.self&&n.push([r.self,""]);for(const c of r.scopes)for(const[l,h]of c)n.push([h.v,l,!0])}for(const r of this.classes.values())for(const[c,l]of r.statics)n.push([l,c,!0]);for(let r=0;ru===c&&f!=="")||o(c,l,!!h)}return e.sort((r,c)=>r.id-c.id)}show(e){return e===void 0?"?":e===null?"null":typeof e=="string"?JSON.stringify(e):typeof e=="number"||typeof e=="boolean"?String(e):e instanceof O?Ut(e.v):e instanceof H?e.code?`'${String.fromCharCode(e.code)}'`:"''":e instanceof I?e.native.enumName!==void 0?e.native.enumName:e.cls.builtin?e.cls.name:this.names.get(e.id)??this.tempNames.get(e.id)??`${e.cls.name}@${_e(e.id)}`:e instanceof B||e instanceof K?`[${e.items.slice(0,30).map(s=>this.show(s)).join(", ")}${e.items.length>30?", …":""}]`:e instanceof be?`{${[...e.entries.values()].map(([t,s])=>`${this.show(t)}=${this.show(s)}`).join(", ")}}`:e instanceof de?e.kind==="StringBuilder"?JSON.stringify(e.buf):e.kind:e.name}seqKey(e){return e instanceof I?`o${e.id}`:`c${e.name}`}record(e,t,s){if(this.quiet||this.seq.length>=this.seqLimit)return!1;const i=this.frames.at(-1),n=i?this.seqKey(i.self??i.cls):"",o=this.seqKey(t);return this.seqParticipants.has(o)||this.seqParticipants.set(o,t instanceof I?{key:o,cls:t.cls.name,id:t.id}:{key:o,cls:t.name}),this.nameObjects(),this.seq.push({k:e,from:n,to:o,label:s(),pos:(i==null?void 0:i.pos)??{file:"",line:0}}),!0}recordReturn(e,t,s=!1){var i;this.seq.length>=this.seqLimit+1e3||this.seq.push({k:"return",from:"",to:"",label:t?"⚡":e,pos:((i=this.frames.at(-1))==null?void 0:i.pos)??{file:"",line:0},...s&&!t?{hidden:s}:{}})}sequence(){return this.nameObjects(),{participants:[...this.seqParticipants.values()].map(t=>({key:t.key,cls:t.cls,label:t.id===void 0?t.cls:`${this.names.get(t.id)??this.tempNames.get(t.id)??""} : ${t.cls}`,isStatic:t.id===void 0})),events:[...this.seq],truncated:this.seq.length>=this.seqLimit}}get frame(){return this.frames[this.frames.length-1]}*step(e){const t={file:e.file,line:e.line};this.frames.length&&(this.frame.pos=t),this.quiet||(yield{k:"step",pos:t,depth:this.frames.length})}*program(e){this.quiet++;try{for(const s of this.classes.values())yield*this.initStatics(s)}finally{this.quiet--}const t=e.decl.methods.find(Kt);this.seqParticipants.set(`c${e.name}`,{key:`c${e.name}`,cls:e.name}),yield*this.invoke(t,e,void 0,[new B(ve("String"),[],this.id())])}id(){return this.nextId++}*initStatics(e){const t=e.decl;if(!t)return;t.kind==="enum"&&t.enumConstants.forEach((i,n)=>{const o=new I(e,this.id());o.native={enumName:i,ordinal:n},e.statics.set(i,o),e.staticTypes.set(i,ve(e.name))});for(const i of t.fields)i.isStatic&&(e.statics.set(i.name,it(i.type)),e.staticTypes.set(i.name,i.type));const s={cls:e,scopes:[new Map],pos:t,title:`${e.name} (static)`};this.frames.push(s);try{for(const i of t.fields)i.isStatic&&i.init&&e.statics.set(i.name,te(yield*this.initValue(i.init,i.type),i.type))}finally{this.frames.pop()}}*initValue(e,t){return e.k==="arrayInit"?yield*this.arrayFrom(e,t):yield*this.eval(e)}*arrayFrom(e,t){const s={...t,dims:t.dims-1},i=[];for(const n of e.items)i.push(te(n.k==="arrayInit"?yield*this.arrayFrom(n,s):yield*this.eval(n),s));return new B(s,i,this.id())}*invoke(e,t,s,i){if(!e.body)throw new q("unsupported",`abstract ${e.name}`,e);if(this.frames.length>900)throw new Le(this.exception("StackOverflowError"));const n=new Map;e.params.forEach((l,h)=>n.set(l.name,{v:te(i[h],l.type),type:l.type}));const o=e.isConstructor?`new ${t.name}()`:`${t.name}.${e.name}()`,r=this.frames.length>0&&this.record("call",s||t,()=>`${e.name}(${i.map(l=>this.show(l)).join(", ")})`);this.frames.push({cls:t,method:e,self:s,scopes:[n],pos:e,title:o});let c=!1;try{const l=yield*this.execBody(e.body.body);let h;return(l==null?void 0:l.k)==="return"?h=te(l.v,e.returns):yield*this.step({file:e.file,line:e.endLine}),c=!0,this.frames.pop(),r&&this.recordReturn(e.returns&&e.returns.name!=="void"?this.show(h):"",!1),h}finally{c||(this.frames.pop(),r&&this.recordReturn("",!0))}}*execBody(e){for(const t of e){const s=yield*this.exec(t);if(s)return s}}*construct(e,t,s){var c,l;if((c=e.decl)!=null&&c.isAbstract)throw new q("type",`abstract ${e.name}`,s);const i=new I(e,this.id()),n=[];for(let h=e;h;h=h.sup)n.unshift(h);for(const h of n)for(const u of((l=h.decl)==null?void 0:l.fields)??[])u.isStatic||i.fields.set(u.name,it(u.type));const o=this.record("create",i,()=>`new ${e.name}(${t.map(h=>this.show(h)).join(", ")})`);let r=!1;try{yield*this.runCtor(e,i,t,s),r=!0}finally{o&&this.recordReturn("",!r,!0)}return i}*runCtor(e,t,s,i){if(e.builtin){s.length&&(t.native.message=typeof s[0]=="string"||s[0]===null?s[0]:yield*this.str(s[0])),t.native.trace=this.trace();return}const n=e.decl,o=n.methods.filter(l=>l.isConstructor);if(!o.length){if(s.length)throw new q("symbol",`${e.name}(${s.length})`,i);e.sup&&(yield*this.runCtor(e.sup,t,[],i)),this.frames.push({cls:e,self:t,scopes:[new Map],pos:n,title:`new ${e.name}()`});try{yield*this.fieldInits(e,t)}finally{this.frames.pop()}return}const r=this.pick(o,s);if(!r)throw new q("symbol",`${e.name}(${s.length})`,i);const c=new Map;r.params.forEach((l,h)=>c.set(l.name,{v:te(s[h],l.type),type:l.type})),this.frames.push({cls:e,method:r,self:t,scopes:[c],pos:r,title:`new ${e.name}()`});try{let l=r.body.body;const h=l[0];if((h==null?void 0:h.k)==="ctorCall"){yield*this.step(h);const f=[];for(const m of h.args)f.push(yield*this.eval(m));l=l.slice(1),h.isSuper?(e.sup&&(yield*this.runCtor(e.sup,t,f,h)),yield*this.fieldInits(e,t)):yield*this.runCtor(e,t,f,h)}else e.sup&&(yield*this.runCtor(e.sup,t,[],r)),yield*this.fieldInits(e,t);const u=yield*this.execBody(l);(u==null?void 0:u.k)!=="return"&&(yield*this.step({file:r.file,line:r.endLine}))}finally{this.frames.pop()}}*fieldInits(e,t){var s;for(const i of((s=e.decl)==null?void 0:s.fields)??[])!i.isStatic&&i.init&&(yield*this.step(i),t.fields.set(i.name,te(yield*this.initValue(i.init,i.type),i.type)))}pick(e,t){let s,i=-1;for(const n of e){if(n.params.length!==t.length)continue;let o=0;for(let r=0;r=0;r++){const c=this.fits(t[r],n.params[r].type);o=c<0?-1:o+c}o>i&&(s=n,i=o)}return s}fits(e,t){const s=t.name;return t.dims?e===null?1:e instanceof B?2:-1:ws.has(s)?typeof e=="number"?2:e instanceof H?1:-1:$s.has(s)?e instanceof O?2:ne(e)?1:-1:s==="char"||s==="Character"?e instanceof H?2:-1:s==="boolean"||s==="Boolean"?typeof e=="boolean"?2:-1:s==="String"?typeof e=="string"?2:e===null?1:-1:s==="Object"?0:Vt.has(s)?e instanceof K?2:e===null?1:-1:Hi.has(s)?e instanceof be?2:e===null?1:-1:this.classes.get(s)?e===null?1:e instanceof I&&this.isA(e.cls,s)?e.cls.name===s?2:1:-1:0}isA(e,t){const s=new Set,i=n=>!n||s.has(n.name)?!1:n.name===t?!0:(s.add(n.name),i(n.sup)||n.interfaces.some(o=>i(this.classes.get(o))));return t==="Object"||i(e)}findMethod(e,t,s,i=!0){var r,c;const n=new Set,o=[];for(let l=e;l;l=l.sup){const h=this.pick(((r=l.decl)==null?void 0:r.methods.filter(u=>u.name===t&&!u.isConstructor&&(!i||u.body)))??[],s);if(h)return{m:h,owner:l};for(const u of l.interfaces)o.push(this.classes.get(u))}for(;o.length;){const l=o.shift();if(!l||n.has(l.name))continue;n.add(l.name);const h=this.pick(((c=l.decl)==null?void 0:c.methods.filter(u=>u.name===t&&(!i||u.body)))??[],s);if(h)return{m:h,owner:l};for(const u of l.interfaces)o.push(this.classes.get(u))}}trace(){return[...this.frames].reverse().map(e=>{const t=e.method?e.method.isConstructor?"":e.method.name:"";return`${e.cls.name}.${t}(${e.pos.file.split("/").pop()}:${e.pos.line+1})`})}exception(e,t){const s=new I(this.classes.get(e),this.id());return s.native={message:t??null,trace:this.trace()},s}fail(e,t){throw new Le(this.exception(e,t))}throwableText(e){const t=e.native.message,s=e.cls.javaName??e.cls.name;return t==null?s:`${s}: ${t}`}*exec(e){switch(e.k){case"block":{this.frame.scopes.push(new Map);try{return yield*this.execBody(e.body)}finally{this.frame.scopes.pop()}}case"empty":return;case"local":yield*this.step(e),yield*this.declare(e);return;case"expr":yield*this.step(e),yield*this.eval(e.expr);return;case"if":return yield*this.step(e),(yield*this.test(e.test))?yield*this.exec(e.then):e.else?yield*this.exec(e.else):void 0;case"while":for(;;){if(yield*this.step(e),!(yield*this.test(e.test)))return;const t=yield*this.exec(e.body);if((t==null?void 0:t.k)==="break")return;if((t==null?void 0:t.k)==="return")return t}case"do":for(;;){const t=yield*this.exec(e.body);if((t==null?void 0:t.k)==="break")return;if((t==null?void 0:t.k)==="return")return t;if(yield*this.step(e.test),!(yield*this.test(e.test)))return}case"for":{this.frame.scopes.push(new Map);try{yield*this.step(e);for(const t of e.init)t.k==="local"?yield*this.declare(t):t.k==="expr"&&(yield*this.eval(t.expr));for(;;){if(e.test&&!(yield*this.test(e.test)))return;const t=yield*this.exec(e.body);if((t==null?void 0:t.k)==="break")return;if((t==null?void 0:t.k)==="return")return t;yield*this.step(e);for(const s of e.update)yield*this.eval(s)}}finally{this.frame.scopes.pop()}}case"foreach":{yield*this.step(e);const t=yield*this.eval(e.iter);t===null&&this.fail("NullPointerException");const s=t instanceof B||t instanceof K?[...t.items]:t instanceof be?[...t.entries.values()].map(i=>i[0]):void 0;if(!s)throw new q("type","for-each",e);for(let i=0;i0&&(yield*this.step(e)),t instanceof K&&t.items.length!==s.length&&this.fail("ConcurrentModificationException"),this.frame.scopes.push(new Map([[e.name,{v:te(s[i],e.type),type:e.type}]]));try{const n=yield*this.exec(e.body);if((n==null?void 0:n.k)==="break")return;if((n==null?void 0:n.k)==="return")return n}finally{this.frame.scopes.pop()}}return}case"switch":{yield*this.step(e);const t=yield*this.eval(e.expr);let s=-1;for(let i=0;ii.labels==="default")),s<0)return;this.frame.scopes.push(new Map);try{for(let i=s;in.types.some(o=>this.isA(s.obj.cls,o.name)));if(!i)throw s;this.frame.scopes.push(new Map([[i.name,{v:s.obj,type:i.types[0]}]]));try{t=yield*this.exec(i.body)}finally{this.frame.scopes.pop()}}}finally{if(e.finally){const s=yield*this.exec(e.finally);if(s)return s}}return t}case"ctorCall":throw new q("syntax","ctorCall",e)}}*declare(e){for(const t of e.vars){const s=t.dims?{...e.type,dims:e.type.dims+t.dims}:e.type,i=t.init?te(yield*this.initValue(t.init,s),s):void 0;this.frame.scopes[this.frame.scopes.length-1].set(t.name,{v:i,type:s})}}*test(e){const t=yield*this.eval(e);if(typeof t!="boolean")throw new q("type","boolean",e);return t}lookupVar(e){const t=this.frame.scopes;for(let s=t.length-1;s>=0;s--){const i=t[s].get(e);if(i)return i}}staticOwner(e,t){const s=new Set,i=n=>{if(!(!n||s.has(n.name)))return s.add(n.name),n.statics.has(t)?n:i(n.sup)??n.interfaces.map(o=>i(this.classes.get(o))).find(Boolean)};return i(e)}*place(e){if(e.k==="name"){const s=this.lookupVar(e.name);if(s)return{get:()=>s.v,set:o=>s.v=o,type:s.type};const i=this.frame.self;if(i!=null&&i.fields.has(e.name))return{get:()=>i.fields.get(e.name),set:o=>i.fields.set(e.name,o),type:this.fieldType(i.cls,e.name)};const n=this.staticOwner(this.frame.cls,e.name);if(n)return{get:()=>n.statics.get(e.name),set:o=>n.statics.set(e.name,o),type:n.staticTypes.get(e.name)};if(this.classes.has(e.name)||Wi.has(e.name))return{get:()=>new Se(e.name),set:()=>{}};throw new q("symbol",e.name,e)}if(e.k==="field"){const s=yield*this.eval(e.target);if(s instanceof I&&s.fields.has(e.name))return{get:()=>s.fields.get(e.name),set:o=>s.fields.set(e.name,o),type:this.fieldType(s.cls,e.name)};const i=s instanceof Se?this.staticOwner(this.classes.get(s.name),e.name):s instanceof I?this.staticOwner(s.cls,e.name):void 0;if(i)return{get:()=>i.statics.get(e.name),set:o=>i.statics.set(e.name,o),type:i.staticTypes.get(e.name)};const n=this.builtinField(s,e.name,e);return{get:()=>n,set:()=>{throw new q("type",e.name,e)}}}if(e.k==="index"){const s=yield*this.eval(e.target),i=T(yield*this.eval(e.index));if(s===null&&this.fail("NullPointerException"),!(s instanceof B))throw new q("type","[]",e);return(i<0||i>=s.items.length)&&this.fail("ArrayIndexOutOfBoundsException",`Index ${i} out of bounds for length ${s.items.length}`),{get:()=>s.items[i],set:n=>s.items[i]=n,type:s.elem}}const t=yield*this.eval(e);return{get:()=>t,set:()=>{throw new q("syntax","assignTarget",e)}}}builtinField(e,t,s){if(e===null&&this.fail("NullPointerException",`Cannot read field "${t}" because value is null`),e instanceof B&&t==="length")return e.items.length;if(e instanceof Se)switch(`${e.name}.${t}`){case"System.out":return new de("out",0);case"System.err":return new de("err",0);case"System.in":return this.stdin;case"Math.PI":return new O(Math.PI);case"Math.E":return new O(Math.E);case"Integer.MAX_VALUE":return 2147483647;case"Integer.MIN_VALUE":return-2147483648;case"Long.MAX_VALUE":return Number.MAX_SAFE_INTEGER;case"Double.MAX_VALUE":return new O(Number.MAX_VALUE);case"Double.MIN_VALUE":return new O(Number.MIN_VALUE)}throw new q("symbol",t,s)}*eval(e){switch(e.k){case"lit":{const{t,v:s}=e.value;return t==="double"?new O(s):t==="char"?new H(s):s}case"name":{const t=this.lookupVar(e.name);if(t){if(t.v===void 0)throw new q("type",`uninit:${e.name}`,e);return t.v}return(yield*this.place(e)).get()}case"this":if(!this.frame.self)throw new q("type","static:this",e);return this.frame.self;case"super":if(!this.frame.self)throw new q("type","static:super",e);return this.frame.self;case"field":case"index":return(yield*this.place(e)).get();case"assign":{const t=yield*this.place(e.target);let s;if(e.op==="=")s=e.value.k==="arrayInit"&&t.type?yield*this.arrayFrom(e.value,t.type):yield*this.eval(e.value);else{const i=t.get();s=yield*this.binary(e.op.slice(0,-1),i,yield*this.eval(e.value),e)}return s=te(s,t.type),t.set(s),s}case"incdec":{const t=yield*this.place(e.target),s=t.get();ne(s)||this.fail("NullPointerException");const i=e.op==="++"?1:-1,n=s instanceof O?new O(s.v+i):s instanceof H?new H(s.code+i&65535):He(T(s))?T(s)+i|0:T(s)+i;return t.set(te(n,t.type)),e.prefix?n:s}case"unary":{const t=yield*this.eval(e.expr);return e.op==="!"?!t:e.op==="-"?t instanceof O?new O(-t.v):He(T(t))?-T(t)|0:-T(t):e.op==="~"?~T(t):t instanceof H?t.code:t}case"binary":{if(e.op==="&&")return(yield*this.test(e.left))&&(yield*this.test(e.right));if(e.op==="||")return(yield*this.test(e.left))||(yield*this.test(e.right));const t=yield*this.eval(e.left),s=yield*this.eval(e.right);return yield*this.binary(e.op,t,s,e)}case"cond":return(yield*this.test(e.test))?yield*this.eval(e.then):yield*this.eval(e.else);case"cast":{const t=yield*this.eval(e.expr),s=e.type.name;return t instanceof I&&this.classes.has(s)&&!this.isA(t.cls,s)&&this.fail("ClassCastException",`class ${t.cls.name} cannot be cast to class ${s}`),te(t,e.type)}case"instanceof":{const t=yield*this.eval(e.expr);if(t===null)return!1;const s=e.type.name;return t instanceof I?this.isA(t.cls,s):typeof t=="string"?s==="String"||s==="Object"||s==="CharSequence":t instanceof K&&Vt.has(s)||s==="Object"}case"new":return yield*this.create(e);case"newArray":{if(e.init&&e.init.k==="arrayInit")return yield*this.arrayFrom(e.init,e.type);const t=[];for(const i of e.sizes)t.push(T(yield*this.eval(i)));const s=(i,n)=>{const o=t[i];o<0&&this.fail("NegativeArraySizeException",String(o));const r={...n,dims:n.dims-1},c=Array.from({length:o},()=>i+1":return n>o;case"<=":return n<=o;case">=":return n>=o;case"&":return n&o;case"|":return n|o;case"^":return n^o;case"<<":return n<>":return n>>o;case">>>":return n>>>o}throw new q("unsupported",e,i)}same(e,t){return ne(e)&&ne(t)?T(e)===T(t):e===t}*str(e){if(e==null)return"null";if(typeof e=="string")return e;if(typeof e=="number"||typeof e=="boolean")return String(e);if(e instanceof O)return Ut(e.v);if(e instanceof H)return String.fromCharCode(e.code);if(e instanceof I){const t=this.findMethod(e.cls,"toString",[]);return t?yield*this.str(yield*this.invoke(t.m,t.owner,e,[])):e.native.enumName!==void 0?e.native.enumName:e.cls.builtin?this.throwableText(e):`${e.cls.name}@${_e(e.id)}`}if(e instanceof K){const t=[];for(const s of e.items)t.push(s===e?"(this Collection)":yield*this.str(s));return`[${t.join(", ")}]`}if(e instanceof be){const t=[];for(const[s,i]of e.entries.values())t.push(`${yield*this.str(s)}=${yield*this.str(i)}`);return`{${t.join(", ")}}`}return e instanceof B?`[${e.elem.dims?"[L":{int:"I",double:"D",char:"C",boolean:"Z",long:"J"}[e.elem.name]??`L${e.elem.name};`}@${_e(e.id)}`:e instanceof de?e.kind==="StringBuilder"?e.buf:`java.util.${e.kind}@${_e(e.id)}`:`class ${e.name}`}*equalsVal(e,t){if(e instanceof I&&!e.cls.builtin){const s=this.findMethod(e.cls,"equals",[t]);if(s)return(yield*this.invoke(s.m,s.owner,e,[t]))===!0}return typeof e=="string"||e===null?e===t:this.same(e,t)&&e instanceof O==t instanceof O}*create(e){const t=[];for(const n of e.args)t.push(yield*this.eval(n));const s=e.type.name,i=this.classes.get(s);if(i)return yield*this.construct(i,t,e);if(s==="ArrayList"||s==="LinkedList"){const n=new K(this.id());return t[0]instanceof K&&(n.items=[...t[0].items]),n}if(s==="HashMap"||s==="TreeMap"||s==="LinkedHashMap")return new be(this.id());if(s==="Scanner")return new de("Scanner",this.id());if(s==="Random")return new de("Random",this.id());if(s==="StringBuilder"){const n=new de("StringBuilder",this.id());return typeof t[0]=="string"&&(n.buf=t[0]),n}if(s==="String")return t.length?yield*this.str(t[0]instanceof B?t[0].items.map(n=>n instanceof H?String.fromCharCode(n.code):"").join(""):t[0]):"";if(s==="Object")return new I(this.classes.get("Object"),this.id());throw new q("unsupported",`new ${s}`,e)}*call(e){var n,o;const t=()=>this.evalArgs(e.args);if(!e.target){const r=yield*t(),c=this.frame.self,l=this.findMethod((c==null?void 0:c.cls)??this.frame.cls,e.name,r)??(c?this.findMethod(this.frame.cls,e.name,r):void 0);if(!l)throw new q("symbol",`${e.name}()`,e);if(!l.m.isStatic&&!c)throw new q("type",`static:${e.name}`,e);return yield*this.invoke(l.m,l.owner,l.m.isStatic?void 0:c,r)}if(e.target.k==="super"){const r=yield*t(),c=this.findMethod(this.frame.cls.sup,e.name,r);return c?yield*this.invoke(c.m,c.owner,this.frame.self,r):yield*this.objectMethod(this.frame.self,e.name,r,e,!0)}const s=yield*this.eval(e.target),i=yield*t();if(s==null&&this.fail("NullPointerException",`Cannot invoke "${e.name}()" because value is null`),typeof s=="string")return yield*this.stringMethod(s,e.name,i,e);if(s instanceof I){const r=this.findMethod(s.cls,e.name,i);return r?yield*this.invoke(r.m,r.owner,r.m.isStatic?void 0:s,i):yield*this.objectMethod(s,e.name,i,e)}if(s instanceof K)return yield*this.listMethod(s,e.name,i,e);if(s instanceof be)return yield*this.mapMethod(s,e.name,i,e);if(s instanceof de)return yield*this.nativeMethod(s,e.name,i,e);if(s instanceof Se){const r=this.classes.get(s.name);if(r&&!r.builtin){if(((n=r.decl)==null?void 0:n.kind)==="enum"&&e.name==="values")return new B(ve(r.name),r.decl.enumConstants.map(l=>r.statics.get(l)),this.id());if(((o=r.decl)==null?void 0:o.kind)==="enum"&&e.name==="valueOf"){const l=r.statics.get(String(i[0]));return l instanceof I||this.fail("IllegalArgumentException",`No enum constant ${r.name}.${i[0]}`),l}const c=this.findMethod(r,e.name,i);if(!c)throw new q("symbol",`${s.name}.${e.name}()`,e);return yield*this.invoke(c.m,c.owner,void 0,i)}return yield*this.staticBuiltin(s.name,e.name,i,e)}if(s instanceof B){if(e.name==="clone")return new B(s.elem,[...s.items],this.id());if(e.name==="length")throw new q("symbol","length()",e)}if(ne(s)||typeof s=="boolean"){if(e.name==="equals")return yield*this.equalsVal(s,i[0]);if(e.name==="toString")return yield*this.str(s);if(e.name==="compareTo")return Math.sign(T(s)-T(i[0]));if(e.name==="intValue")return Math.trunc(T(s));if(e.name==="doubleValue")return new O(T(s))}throw new q("symbol",`${e.name}()`,e)}*evalArgs(e){const t=[];for(const s of e)t.push(yield*this.eval(s));return t}*objectMethod(e,t,s,i,n=!1){switch(t){case"toString":return n?e.cls.builtin||this.isA(e.cls,"Throwable")?this.throwableText(e):`${e.cls.name}@${_e(e.id)}`:yield*this.str(e);case"equals":return e===s[0];case"hashCode":return parseInt(_e(e.id),16)|0;case"getClass":return new Se(e.cls.name);case"getMessage":case"getLocalizedMessage":return e.native.message??null;case"printStackTrace":this.io.out(`${this.throwableText(e)} +${(e.native.trace??[]).map(o=>` at ${o} +`).join("")}`,!0);return;case"name":if(e.native.enumName!==void 0)return e.native.enumName;break;case"ordinal":if(e.native.ordinal!==void 0)return e.native.ordinal;break;case"compareTo":if(e.native.ordinal!==void 0&&s[0]instanceof I)return e.native.ordinal-(s[0].native.ordinal??0);break}throw new q("symbol",`${e.cls.name}.${t}()`,i)}index(e,t,s,i=!1){const n=T(e);return n>=0&&(i?n<=t:n{const l=T(r);return l>=0&&(c?l<=e.length:l1?n(s[1],!0):e.length;return c1?T(s[1]):0);case"lastIndexOf":return e.lastIndexOf(o);case"contains":return e.includes(o);case"startsWith":return e.startsWith(o);case"endsWith":return e.endsWith(o);case"isEmpty":return e.length===0;case"isBlank":return e.trim().length===0;case"toUpperCase":return e.toUpperCase();case"toLowerCase":return e.toLowerCase();case"trim":case"strip":return e.trim();case"concat":return e+o;case"replace":{const r=typeof s[1]=="string"?s[1]:s[1]instanceof H?String.fromCharCode(s[1].code):yield*this.str(s[1]);return e.split(o).join(r)}case"replaceAll":return e.replace(new RegExp(o,"g"),String(s[1]));case"matches":return new RegExp(`^(?:${o})$`).test(e);case"split":return new B(ve("String"),(e===""?[""]:e.split(new RegExp(o))).filter((r,c,l)=>r!==""||cnew H(r.charCodeAt(0))),this.id());case"repeat":return e.repeat(T(s[0]));case"hashCode":return zi(e);case"toString":case"intern":return e}throw new q("unsupported",`String.${t}()`,i)}*listMethod(e,t,s,i){switch(t){case"add":return s.length===2?e.items.splice(this.index(s[0],e.items.length,i,!0),0,s[1]):e.items.push(s[0]),s.length===2?void 0:!0;case"addAll":return s[0]instanceof K&&e.items.push(...s[0].items),!0;case"get":return e.items[this.index(s[0],e.items.length,i)];case"set":{const n=this.index(s[0],e.items.length,i),o=e.items[n];return e.items[n]=s[1],o}case"size":return e.items.length;case"isEmpty":return e.items.length===0;case"clear":e.items=[];return;case"remove":{if(typeof s[0]=="number")return e.items.splice(this.index(s[0],e.items.length,i),1)[0];for(let n=0;nt==="keySet"?h[0]:h[1]),l}case"toString":return yield*this.str(e)}throw new q("unsupported",`HashMap.${t}()`,i)}*nativeMethod(e,t,s,i){if(e.kind==="out"||e.kind==="err"){const n=e.kind==="err";if(t==="println")this.io.out(`${s.length?yield*this.str(s[0]):""} +`,n);else if(t==="print")this.io.out(yield*this.str(s[0]),n);else if(t==="printf"||t==="format")this.io.out(yield*this.format(String(s[0]),s.slice(1)),n);else{if(t==="flush")return;throw new q("unsupported",`System.out.${t}()`,i)}return}if(e.kind==="Scanner")return yield*this.scan(t,i);if(e.kind==="Random"){if(t==="nextInt"){if(!s.length)return Math.random()*4294967296-2147483648|0;const n=s.length>1?T(s[0]):0,o=s.length>1?T(s[1]):T(s[0]);return o<=n&&this.fail("IllegalArgumentException","bound must be positive"),n+Math.floor(Math.random()*(o-n))}if(t==="nextDouble")return new O(Math.random());if(t==="nextBoolean")return Math.random()<.5}if(e.kind==="StringBuilder")switch(t){case"append":return e.buf+=yield*this.str(s[0]),e;case"toString":return e.buf;case"length":return e.buf.length;case"reverse":return e.buf=[...e.buf].reverse().join(""),e;case"charAt":return new H(e.buf.charCodeAt(T(s[0])));case"insert":return e.buf=e.buf.slice(0,T(s[0]))+(yield*this.str(s[1]))+e.buf.slice(T(s[0])),e;case"setLength":e.buf=e.buf.slice(0,T(s[0]));return;case"deleteCharAt":return e.buf=e.buf.slice(0,T(s[0]))+e.buf.slice(T(s[0])+1),e}if(t!=="close")throw new q("unsupported",`${e.kind}.${t}()`,i)}*scan(e,t){const s=this.stdin,i=function*(){const o=yield{k:"input"};return o==null?!1:(s.buf+=`${o} +`,!0)},n=function*(o,r){for(;;){const c=/^\s*(\S+)/.exec(s.buf);if(c&&(c[0].length=t.length&&this.fail("IllegalArgumentException",`Format specifier '${r[0]}'`);const m=t[s++];switch(u.toLowerCase()){case"d":m instanceof O&&this.fail("IllegalArgumentException","d != java.lang.Double"),f=String(Math.trunc(T(m))),c.includes(",")&&(f=f.replace(/\B(?=(\d{3})+(?!\d))/g,"."));break;case"f":if(f=T(m).toFixed(h?Number(h):6),c.includes(",")){const[g,_]=f.split(".");f=g.replace(/\B(?=(\d{3})+(?!\d))/g,".")+(_?`,${_}`:"")}else f=f.replace(".",",");break;case"e":f=T(m).toExponential(h?Number(h):6).replace(".",",");break;case"x":f=(T(m)>>>0).toString(16);break;case"c":f=m instanceof H?String.fromCharCode(m.code):String.fromCharCode(T(m));break;case"b":f=String(m!==null&&m!==!1);break;default:f=yield*this.str(m),h&&(f=f.slice(0,Number(h)))}c.includes("+")&&/^\d/.test(f)&&/[df]/i.test(u)&&(f=`+${f}`),u===u.toUpperCase()&&u!=="%"&&(f=f.toUpperCase())}if(l&&f.length0&&(yield*this.compare(t[i-1],t[i]))>0;i--)[t[i-1],t[i]]=[t[i],t[i-1]];return t}*compare(e,t){if(ne(e)&&ne(t))return T(e)-T(t);if(typeof e=="string"&&typeof t=="string")return et?1:0;if(e instanceof I){const s=this.findMethod(e.cls,"compareTo",[t]);if(s)return T(yield*this.invoke(s.m,s.owner,e,[t]));if(e.native.ordinal!==void 0&&t instanceof I)return e.native.ordinal-(t.native.ordinal??0)}this.fail("ClassCastException","not Comparable")}*staticBuiltin(e,t,s,i){const n=T(s[0]),o=r=>new O(r);switch(`${e}.${t}`){case"Math.abs":return s[0]instanceof O?o(Math.abs(n)):Math.abs(n);case"Math.max":case"Math.min":{const r=t==="max"?Math.max(n,T(s[1])):Math.min(n,T(s[1]));return s[0]instanceof O||s[1]instanceof O?o(r):r}case"Math.pow":return o(Math.pow(n,T(s[1])));case"Math.sqrt":return o(Math.sqrt(n));case"Math.cbrt":return o(Math.cbrt(n));case"Math.random":return o(Math.random());case"Math.round":return Math.floor(n+.5);case"Math.floor":return o(Math.floor(n));case"Math.ceil":return o(Math.ceil(n));case"Math.sin":case"Math.cos":case"Math.tan":case"Math.log":case"Math.log10":case"Math.exp":return o(Math[t](n));case"Math.toRadians":return o(n*Math.PI/180);case"Math.toDegrees":return o(n*180/Math.PI);case"Math.floorMod":return(n%T(s[1])+T(s[1]))%T(s[1]);case"Integer.parseInt":case"Integer.valueOf":case"Long.parseLong":{if(typeof s[0]=="number")return s[0];const r=String(s[0]);return/^[+-]?\d+$/.test(r)||this.fail("NumberFormatException",`For input string: "${r}"`),parseInt(r,10)}case"Double.parseDouble":case"Double.valueOf":{if(ne(s[0]))return o(n);const r=String(s[0]).trim();return/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?[dDfF]?$/.test(r)||this.fail("NumberFormatException",`For input string: "${r}"`),o(parseFloat(r))}case"Boolean.parseBoolean":return String(s[0]).toLowerCase()==="true";case"Integer.toString":case"Double.toString":case"String.valueOf":case"Objects.toString":return s[0]instanceof B&&s[0].elem.name==="char"?s[0].items.map(r=>String.fromCharCode(T(r))).join(""):yield*this.str(s[0]);case"Integer.compare":case"Double.compare":return Math.sign(n-T(s[1]));case"Integer.toBinaryString":return(n>>>0).toString(2);case"Integer.toHexString":return(n>>>0).toString(16);case"Integer.sum":return n+T(s[1])|0;case"Objects.equals":return s[0]===null?s[1]===null:yield*this.equalsVal(s[0],s[1]);case"String.format":return yield*this.format(String(s[0]),s.slice(1));case"String.join":{const r=[],c=s[1]instanceof K||s[1]instanceof B?s[1].items:s.slice(1);for(const l of c)r.push(yield*this.str(l));return r.join(String(s[0]))}case"Character.isDigit":return new RegExp("\\p{Nd}","u").test(String.fromCharCode(n));case"Character.isLetter":return new RegExp("\\p{L}","u").test(String.fromCharCode(n));case"Character.isLetterOrDigit":return/[\p{L}\p{Nd}]/u.test(String.fromCharCode(n));case"Character.isUpperCase":return new RegExp("\\p{Lu}","u").test(String.fromCharCode(n));case"Character.isLowerCase":return new RegExp("\\p{Ll}","u").test(String.fromCharCode(n));case"Character.isWhitespace":return/\s/.test(String.fromCharCode(n));case"Character.toUpperCase":return new H(String.fromCharCode(n).toUpperCase().charCodeAt(0));case"Character.toLowerCase":return new H(String.fromCharCode(n).toLowerCase().charCodeAt(0));case"Character.getNumericValue":return parseInt(String.fromCharCode(n),36);case"Arrays.toString":{if(s[0]===null)return"null";const r=s[0],c=[];for(const l of r.items)c.push(yield*this.str(l));return`[${c.join(", ")}]`}case"Arrays.sort":case"Collections.sort":{const r=s[0];r.items=yield*this.sorted(r.items);return}case"Arrays.fill":s[0].items.fill(te(s[1],s[0].elem));return;case"Arrays.asList":case"List.of":{const r=new K(this.id());return r.items=s.length===1&&s[0]instanceof B?[...s[0].items]:s,r}case"Collections.reverse":s[0].items.reverse();return;case"Collections.shuffle":s[0].items.sort(()=>Math.random()-.5);return;case"Collections.max":case"Collections.min":{const r=s[0].items;r.length||this.fail("NoSuchElementException");const c=yield*this.sorted(r);return t==="max"?c[c.length-1]:c[0]}case"Thread.sleep":yield{k:"sleep",ms:n};return;case"System.currentTimeMillis":return Date.now();case"System.nanoTime":return Math.round(performance.now()*1e6);case"System.exit":throw new Jt}throw new q("unsupported",`${e}.${t}()`,i)}}class Jt extends Error{}function Kt(a){return a.name==="main"&&a.isStatic&&a.params.length===1&&a.params[0].type.name==="String"&&a.params[0].type.dims===1}function Ui(a){return{name:a.name,kind:a.kind==="field"?"field":"method",params:a.params.length>0,returns:a.type,description:a.kind==="field"?"":a.params.map(e=>`${e.name}: ${e.type}`).join(", ")}}function Ji(a,e,t="de"){const s=new Map(a.map(r=>[r.name,r])),i=(r,c)=>{const l=new Set;for(let h=r?s.get(r):void 0;h&&!l.has(h.name);h=h.superclass?s.get(h.superclass):void 0){if(h.name===c)return!0;l.add(h.name)}return!1},n=(r,c,l)=>r.visibility==="+"?!0:r.visibility==="-"?!l&&e.cls===c.name:c.pkg===e.pkg?!0:r.visibility==="#"&&i(e.cls,c.name),o=(r,c)=>{if(!s.get(r))return;const h=[],u=new Set,f=new Set,m=(g,_)=>{if(u.has(g))return;u.add(g);const y=s.get(g);if(!y){if(!c)for(const w of Is(g,t))f.has(w.name)||(f.add(w.name),h.push(w));return}for(const w of y.members){if(w.kind==="constructor"||w.isStatic!==c||!n(w,y,_))continue;const $=`${w.kind}:${w.name}:${w.params.map(p=>p.type).join(",")}`;f.has($)||(f.add($),h.push(Ui(w)))}y.superclass&&m(y.superclass,!0);for(const w of y.interfaces)m(w,!0)};return m(r,!1),h};return{members:r=>o(r,!1),statics:r=>o(r,!0),thisType:e.cls}}const Xt=["fields","refs","ctors","methods"],Ki=[{fields:"Attribute",refs:"Referenzattribute",ctors:"Konstruktor",methods:"Methoden"},{fields:"Attributes",refs:"Reference attributes",ctors:"Constructor",methods:"Methods"},{fields:"Atributos",refs:"Atributos de referência",ctors:"Construtor",methods:"Métodos"}],Te=a=>a.trim().toLowerCase().replace(/[:.]$/,""),Xi=new Set(Ki.flatMap(a=>Object.values(a)).flatMap(a=>[Te(a),Te(a)+"en",Te(a)+"s",Te(a)+"es"])),ut=a=>{const e=/^\s*\/\/\s*(.+?)\s*$/.exec(a);return!!e&&Xi.has(Te(e[1]))};function Yi(a,e){return a.kind==="constructor"?"ctors":a.kind==="method"?"methods":e.has(Fe(a.type).name)?"refs":"fields"}const Be=(a,e)=>a.lastIndexOf(` +`,e-1)+1,Yt=(a,e)=>{const t=a.indexOf(` +`,e);return t<0?a.length:t+1};function _s(a,e){const t=a.indexOf("{",e.headerTo);return a.slice(t+1,e.bodyEnd).split(` +`).some(ut)}function pt(a,e,t,s){if(e.kind!=="class")return a;const i=a.indexOf("{",e.headerTo);if(i<0||i>e.bodyEnd||oe(a).some(_=>_.from>i&&_.fromo||!/^\s*$/.test(a.slice(i+1,n))||!/^\s*$/.test(a.slice(o,e.bodyEnd)))return a;const r=/^[ \t]*/.exec(a.slice(Be(a,e.from)))[0]+" ",c=new Map(Xt.map(_=>[_,[]])),l=[],h=new Set;for(const _ of e.members){if(h.has(_.from))continue;h.add(_.from);let y=Be(a,_.from);if(!/^\s*$/.test(a.slice(y,_.from)))return a;const w=Yt(a,_.to);if(!/^\s*$/.test(a.slice(_.to,w)))return a;for(;!(y<=n);){const $=Be(a,y-1),p=a.slice($,y);if(ut(p)||!/^\s*(\/\/|\/\*|\*|@)/.test(p))break;y=$}l.push([y,w]),c.get(Yi(_,t)).push(a.slice(y,w).replace(/\s+$/,""))}l.sort((_,y)=>_[0]-y[0]);let u="",f=n;for(const[_,y]of[...l,[o,o]])_>f&&(u+=a.slice(f,_)),f=Math.max(f,y);const m=u.split(` +`).filter(_=>!ut(_)).join(` +`).trim(),g=Xt.map(_=>{const y=c.get(_),w=_==="fields"||_==="refs"?` +`:` + +`;return`${r}// ${s[_]}`+(y.length?` +`+y.join(w):"")});return m&&g.push(r+m),a.slice(0,n)+g.join(` + +`)+` +`+a.slice(o)}function Gi(a,e,t,s){const i=oe(a).find(n=>n.name===e);return i&&_s(a,i)?pt(a,i,t,s):a}const Gt="visuobject.layout",Zi="visuobject.explorer",nt="40px",fe={explorer:260,split:45},xs=(a,e,t,s)=>Number.isFinite(a)?Math.min(t,Math.max(e,Math.round(a))):s,Zt=a=>xs(a,180,480,fe.explorer),Qt=a=>xs(a,20,80,fe.split);class Qi{constructor(e,t){E(this,"collapsed",new Set);E(this,"explorer",fe.explorer);E(this,"split",fe.split);this.root=e,this.changed=t;try{const n=JSON.parse(localStorage.getItem(Gt)??"null");if(n){for(const o of n.collapsed??[])(o==="explorer"||o==="code"||o==="diagram")&&this.collapsed.add(o);this.explorer=Zt(Number(n.explorer??fe.explorer)),this.split=Qt(Number(n.split??fe.split))}else localStorage.getItem(Zi)==="0"&&this.collapsed.add("explorer")}catch{}for(const n of e.querySelectorAll("[data-collapse]"))n.addEventListener("click",()=>this.toggle(n.dataset.collapse,!0));for(const n of e.querySelectorAll("[data-expand]"))n.addEventListener("click",()=>this.toggle(n.dataset.expand,!1));const s=e.querySelector(".vo-splitter[data-split=explorer]"),i=e.querySelector(".vo-splitter[data-split=code]");this.splitter(s,{at:n=>n.clientX-e.getBoundingClientRect().left,get:()=>this.explorer,set:n=>this.explorer=Zt(n),reset:fe.explorer,step:20}),this.splitter(i,{at:n=>{const o=e.querySelector("[data-pane=code]").getBoundingClientRect(),r=e.querySelector("[data-pane=diagram]").getBoundingClientRect();return(n.clientX-o.left)/(r.right-o.left)*100},get:()=>this.split,set:n=>this.split=Qt(n),reset:fe.split,step:5}),this.apply()}isCollapsed(e){return this.collapsed.has(e)}toggle(e,t=!this.collapsed.has(e)){var i,n;if(t&&!this.collapsed.has(e)&&this.collapsed.size>=2)return;t?this.collapsed.add(e):this.collapsed.delete(e),this.apply();const s=this.root.querySelector(`[data-pane=${e}]`);t?(i=s.querySelector(".vo-strip"))==null||i.focus():(n=s.querySelector("[data-collapse]"))==null||n.focus()}apply(){const e=this.collapsed,t=e.has("code")&&e.has("diagram"),s=e.has("explorer")?nt:t?"1fr":`${this.explorer}px`,i=e.has("code")?nt:`minmax(0, ${this.split}fr)`,n=e.has("diagram")?nt:`minmax(0, ${100-this.split}fr)`;this.root.style.setProperty("--vo-cols",`${s} 1px ${i} 1px ${n}`);for(const c of this.root.querySelectorAll("[data-pane]"))c.classList.toggle("collapsed",e.has(c.dataset.pane));const o=this.root.querySelector(".vo-splitter[data-split=explorer]"),r=this.root.querySelector(".vo-splitter[data-split=code]");o.classList.toggle("fixed",e.has("explorer")||t),r.classList.toggle("fixed",e.has("code")||e.has("diagram")),o.setAttribute("aria-valuenow",String(this.explorer)),r.setAttribute("aria-valuenow",String(this.split));try{localStorage.setItem(Gt,JSON.stringify({collapsed:[...e],explorer:this.explorer,split:this.split}))}catch{}this.changed()}splitter(e,t){e.addEventListener("pointerdown",s=>{if(e.classList.contains("fixed"))return;s.preventDefault(),e.setPointerCapture(s.pointerId),this.root.classList.add("vo-resizing");const i=o=>{t.set(t.at(o)),this.apply()},n=()=>{this.root.classList.remove("vo-resizing"),e.removeEventListener("pointermove",i),e.removeEventListener("pointerup",n),e.removeEventListener("pointercancel",n)};e.addEventListener("pointermove",i),e.addEventListener("pointerup",n),e.addEventListener("pointercancel",n)}),e.addEventListener("dblclick",()=>{t.set(t.reset),this.apply()}),e.addEventListener("keydown",s=>{const i=s.key==="ArrowLeft"?-t.step:s.key==="ArrowRight"?t.step:0;i&&(s.preventDefault(),t.set(t.get()+i),this.apply())})}}const en=a=>a==="boolean"?"false":/^(int|long|short|byte|double|float)$/.test(a)?"0":a==="char"?"'\\0'":"null",es=a=>a.map(e=>`${e.type} ${e.name}`).join(", ");function tn(a){const e=new Map,t=(s,i)=>{for(const n of s.members)if(n.kind==="method"&&!n.isStatic&&(i||n.isAbstract)){const o=`${n.name}(${n.params.map(r=>r.type).join(",")})`;e.has(o)||e.set(o,{name:n.name,type:n.type||"void",params:n.params,visibility:i||n.visibility==="+"?"public":n.visibility==="#"?"protected":""})}};a.superclass&&t(a.superclass,!1);for(const s of a.interfaces)t(s,!0);return[...e.values()]}function sn(a){const e=[];a.pkg&&e.push(`package ${a.pkg};`,"");const t=[a.superclass,...a.interfaces].filter(r=>!!r&&!!r.pkg&&r.pkg!==a.pkg).map(r=>`import ${r.pkg}.${r.name};`);t.length&&e.push(...[...new Set(t)].sort(),""),a.comment&&(e.push("/**",` * ${a.name}`," *"),e.push(` * @author ${a.author.trim()||"…"}`," */"));const s=[a.isPublic?"public":"",a.kind==="class"&&a.isAbstract?"abstract":"",a.kind==="class"&&a.isFinal?"final":""].filter(Boolean).join(" "),i=a.interfaces.map(r=>r.name),n=a.kind==="class"?`${s?s+" ":""}class ${a.name}${a.superclass?` extends ${a.superclass.name}`:""}${i.length?` implements ${i.join(", ")}`:""}`:`${s?s+" ":""}interface ${a.name}${i.length?` extends ${i.join(", ")}`:""}`;e.push(`${n} {`);const o=[];if(a.kind==="class"){if(a.constructors&&a.superclass){const r=a.superclass.members.filter(c=>c.kind==="constructor");for(const c of r.length?r:[{params:[]}])o.push([` public ${a.name}(${es(c.params)}) {`,` super(${c.params.map(l=>l.name).join(", ")});`," }"])}else a.constructors&&o.push([` public ${a.name}() {`," }"]);if(a.inherited&&!a.isAbstract)for(const r of tn(a))o.push([" @Override",` ${r.visibility?r.visibility+" ":""}${r.type} ${r.name}(${es(r.params)}) {`,...r.type==="void"?[]:[` return ${en(r.type)};`]," }"]);a.main&&o.push([" public static void main(String[] args) {"," }"])}return o.length&&e.push("",o.map(r=>r.join(` +`)).join(` + +`)),e.push("}",""),e.join(` +`)}const P=a=>a.replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]),ks="visuobject.author";function nn(){try{return localStorage.getItem(ks)??""}catch{return""}}function on(a,e){return new Promise(t=>{const s=document.createElement("div");s.className="confirm vo-wizard-back";const i=a==="class"||a==="interface",n=``,o=``,r=e.classes,c=r.filter(k=>k.kind==="class").map(k=>``).join(""),l=r.filter(k=>k.kind==="interface"),h=l.length?`
    ${P(d(a==="class"?"web_visuobject_new_interfaces":"web_visuobject_new_extends_interfaces"))}${l.map(k=>``).join("")}
    `:"",u=(k,j,M=!1)=>``,f=i?`${n}${o} + +
    ${P(d("web_visuobject_new_modifiers"))} + + ${a==="class"?`${u("abstract","abstract")}${u("final","final")}`:""} +
    + ${a==="class"?``:""} + ${h} + ${a==="class"?`
    ${P(d("web_visuobject_new_stubs"))} + ${u("main","public static void main(String[] args)")} + ${u("constructors",P(d("web_visuobject_new_stub_constructors")))} + ${u("inherited",P(d("web_visuobject_new_stub_inherited")),!0)} +
    `:""} +
    ${P(d("web_visuobject_new_comment_legend"))} + ${u("comment",P(d("web_visuobject_new_comment")))} + +
    `:`${a==="package"?n:""}`;s.innerHTML=``;const m=s.querySelector("form"),g=k=>m.querySelector(`[name="${k}"]`),_=g("name"),y=g("root"),w=g("pkg"),$=m.querySelector(".vo-wizard-error");_.value=e.suggest(a);const p=()=>{if(!w)return;const k=e.packagesIn((y==null?void 0:y.value)??e.root),j=k.includes("")?k:[...k,""],M=w.value||e.pkg;w.innerHTML=j.map(A=>``).join("")};p(),y==null||y.addEventListener("change",p);const v=g("abstract"),x=g("final");v==null||v.addEventListener("change",()=>v.checked&&x&&(x.checked=!1)),x==null||x.addEventListener("change",()=>x.checked&&v&&(v.checked=!1));const L=()=>{const k=e.check(a,_.value.trim(),(y==null?void 0:y.value)??e.root,(w==null?void 0:w.value)??e.pkg);return $.textContent=k??"",!k};_.addEventListener("input",L),w==null||w.addEventListener("change",L);const S=k=>{s.remove(),t(k)};m.addEventListener("submit",k=>{var G;if(k.preventDefault(),!L())return _.focus();const j=_.value.trim(),M=(y==null?void 0:y.value)??e.root,A=(w==null?void 0:w.value)??"";if(!i)return S({kind:a,name:j,root:M,pkg:A});const R=g("author").value;try{localStorage.setItem(ks,R)}catch{}const C=z=>{var he;return!!((he=g(z))!=null&&he.checked)},F=z=>e.classes.find(he=>he.name===z),W=(G=g("superclass"))==null?void 0:G.value;S({kind:a,name:j,root:M,pkg:A,options:{kind:a,pkg:A,name:j,isPublic:g("visibility").value==="public",isAbstract:C("abstract"),isFinal:C("final"),superclass:W?F(W):void 0,interfaces:[...m.querySelectorAll("[name=iface]:checked")].map(z=>F(z.value)).filter(z=>!!z),main:C("main"),constructors:C("constructors"),inherited:C("inherited"),comment:C("comment"),author:R}})}),s.addEventListener("click",k=>{const j=k.target;(j===s||j.closest("[data-cancel]"))&&S(void 0)}),s.addEventListener("keydown",k=>{k.stopPropagation(),k.key==="Escape"&&S(void 0)}),document.body.append(s),_.focus(),_.select()})}const me=(a,e,t,s)=>a.slice(0,e)+s+a.slice(t),js={"+":"public ","-":"private ","#":"protected ","~":""},Ss=(a,e)=>a.lastIndexOf(` +`,e-1)+1;function Ls(a,e){const t=e.members[0];if(t){const s=Ss(a,t.from),i=/^[ \t]*/.exec(a.slice(s))[0];if(s+i.length===t.from)return i}return" "}function Es(a,e,t){return/^(\s*@[\w.]+(\([^)]*\))?\s*)*/.exec(a.slice(e,t))[0]}function Ms(a,e){var n;const t=a.slice(e.headerFrom,e.nameFrom),s=a.slice(e.nameTo,e.to),i=e.shared?"":((n=/^\s*=\s*([\s\S]*?)\s*;?\s*$/.exec(s))==null?void 0:n[1])??"";return{visibility:e.visibility,name:e.name,type:e.type,isStatic:e.isStatic,isFinal:/\bfinal\b/.test(t),init:i}}function an(a){return`${js[a.visibility]}${a.isStatic?"static ":""}${a.isFinal?"final ":""}${a.type} ${a.name}${a.init.trim()?` = ${a.init.trim()}`:""};`}function rn(a,e,t){if(e.shared)return t.name&&t.name!==e.name?me(a,e.nameFrom,e.nameTo,t.name):a;const s={...Ms(a,e),...t};return me(a,e.from,e.to,Es(a,e.from,e.to)+an(s))}function cn(a){return{visibility:a.visibility,name:a.name,type:a.type,params:a.params,isStatic:a.isStatic,isAbstract:a.isAbstract}}function ln(a){const e=[];for(const t of a.split(",").map(s=>s.trim()).filter(Boolean)){const s=/^([\p{L}_$][\p{L}\p{N}_$]*)\s*:\s*(.+)$/u.exec(t),i=/^(.+?)\s+([\p{L}_$][\p{L}\p{N}_$]*)$/u.exec(t);if(s)e.push({name:s[1],type:s[2].replace(/\s+/g,"")});else if(i)e.push({name:i[2],type:i[1].replace(/\s+/g,"")});else return}return e}const hn=a=>a.map(e=>`${e.name}: ${e.type}`).join(", ");function dn(a,e,t,s){const i={...cn(t),...s},n=e.kind==="interface",o=t.kind==="constructor",c=`${n?"":js[i.visibility]}${i.isStatic&&!o?"static ":""}${i.isAbstract&&!n&&!o?"abstract ":""}`,l=i.params.map($=>`${$.type} ${$.name}`).join(", "),h=o?`${c}${t.name}(${l})`:`${c}${i.type||"void"} ${i.name}(${l})`,u=Es(a,t.headerFrom,t.headerTo);let f=me(a,t.headerFrom,t.headerTo,u+h);const m=u.length+h.length-(t.headerTo-t.headerFrom),g=t.headerTo+m,_=t.to+m,y=f.slice(g,_),w=!(i.isAbstract||n&&!i.isStatic);if(!w&&/^\s*(throws[^{;]*)?\{/.test(y))f=me(f,g,_,";");else if(w&&/^\s*;/.test(y)){const $=Ls(a,e),p=i.type&&i.type!=="void"&&!o?`${$} return ${i.type==="boolean"?"false":/^(int|long|short|byte|double|float|char)$/.test(i.type)?"0":"null"}; +`:"";f=me(f,g,_,` { +${p}${$}}`)}return f}function un(a,e){const t=a.slice(0,e.headerFrom),s=/\/\*\*([\s\S]*?)\*\/\s*$/.exec(t);return s?s[1].split(` +`).map(i=>i.replace(/^\s*\*\s?/,"")).join(` +`).trim():""}function pn(a,e,t){const s=a.slice(0,e.headerFrom),i=/\/\*\*[\s\S]*?\*\/\s*$/.exec(s),n=/[ \t]*$/.exec(s)[0],o=t.trim()?`/** +${t.trim().split(` +`).map(r=>` * ${r}`.trimEnd()).join(` +`)} + */ +${n}`:"";return i?me(a,i.index,e.headerFrom,o):me(a,e.headerFrom,e.headerFrom,o)}function gt(a,e,t){const s=Ls(a,e),i=t.split(` +`).map(h=>h&&s+h).join(` +`),n=Ss(a,e.bodyEnd),o=/^\s*$/.test(a.slice(n,e.bodyEnd)),r=o?n:e.bodyEnd,c=o?"":` +`,l=e.members.length?` +`:"";return me(a,r,r,`${c}${l}${i} +`)}const yt=a=>a.members.filter(e=>e.kind==="field"&&!e.isStatic),ts=a=>a.charAt(0).toUpperCase()+a.slice(1);function fn(a,e){const t=yt(e),s=t.map(n=>`${n.type} ${n.name}`).join(", "),i=t.map(n=>` this.${n.name} = ${n.name};`).join(` +`);return gt(a,e,`public ${e.name}(${s}) { +${i}${i?` +`:""}}`)}function mn(a,e){const t=new Set(e.members.filter(i=>i.kind==="method").map(i=>i.name)),s=[];for(const i of yt(e)){const n=/\bfinal\b/.test(a.slice(i.headerFrom,i.nameFrom)),o=`${i.type==="boolean"?"is":"get"}${ts(i.name)}`,r=`set${ts(i.name)}`;t.has(o)||s.push(`public ${i.type} ${o}() { + return ${i.name}; +}`),!n&&!t.has(r)&&s.push(`public void ${r}(${i.type} ${i.name}) { + this.${i.name} = ${i.name}; +}`)}return s.length?gt(a,e,s.join(` + +`)):a}function bn(a,e){if(e.members.some(i=>i.kind==="method"&&i.name==="toString"&&i.params.length===0))return a;const t=yt(e).map((i,n)=>`"${n?", ":""}${i.name}=" + ${i.name}`),s=t.length?`"${e.name} [" + ${t.join(" + ")} + "]"`:`"${e.name} []"`;return gt(a,e,`@Override +public String toString() { + return ${s}; +}`)}const ss="VisuObject-Workspace",Xe="visuobject.json",ge=a=>a.replace(/[\\/:*?"<>|]/g,"_").trim()||"Projekt";async function vn(a,e){try{return await a.dir(e)}catch{return}}async function is(a){const e=[];for(const t of await a.list()){if(t.kind!=="directory")continue;const s=await a.dir(t.name);(await s.has("src")||await s.has(Xe))&&e.push(t.name)}return e.sort((t,s)=>t.localeCompare(s))}function Cs(a){const e=[...a.matchAll(/]*>/g)].map(t=>t[0]).filter(t=>/\bkind\s*=\s*"src"/.test(t)&&!/\bcombineaccessrules\b/.test(t)).map(t=>{var s;return((s=/\bpath\s*=\s*"([^"]+)"/.exec(t))==null?void 0:s[1])??""}).filter(t=>t&&!t.startsWith("/")&&!t.includes(":")&&t.split("/").every(Je));return e.length?[...new Set(e)]:[Z]}function gn(a,e){const t=e.map(i=>` +`).join("");return a.replace(/[ \t]*]*\bkind\s*=\s*"src"[^>]*\/>[ \t]*\n?/g,i=>/\bcombineaccessrules\b/.test(i)?i:"").replace(/(]*>[ \t]*\n?)/,`$1${t}`)}async function yn(a,e){const t=await a.dir(e),s={name:e,files:[],packages:[]},i=await t.has(".classpath")?Cs(await t.read(".classpath")):[Z],n=async(c,l,h)=>{const u=await c.list(),f=re(l,h);h&&!u.some(m=>m.kind==="file"&&/\.java$/i.test(m.name))&&s.packages.push(f);for(const m of u)m.kind==="directory"?await n(await c.dir(m.name),l,h?`${h}.${m.name}`:m.name):/\.java$/i.test(m.name)&&s.files.push({path:le(f,m.name),text:await c.read(m.name)})};for(const c of i){let l=t;for(const h of c.split("/"))l=l&&await vn(l,h);l&&await n(l,c,"")}const o=i.filter(c=>c!==Z);o.length&&(s.sourceFolders=o),s.packages=s.packages.filter(c=>!s.packages.some(l=>l.startsWith(c+"."))&&!s.files.some(l=>D(l.path).startsWith(c+"."))),s.files.sort((c,l)=>c.path.localeCompare(l.path));let r={};if(await t.has(Xe))try{const c=JSON.parse(await t.read(Xe)),l=ys(c.uml);l&&(s.uml=l);const h=vs(c.notes);h&&(s.notes=h);const u=gs(c.objects);if(u&&(s.objects=u),c.positions&&typeof c.positions=="object")for(const[f,m]of Object.entries(c.positions))typeof(m==null?void 0:m.x)=="number"&&typeof(m==null?void 0:m.y)=="number"&&(r[f]={x:m.x,y:m.y})}catch{r={}}return{project:s,positions:r}}const wn=a=>` + + ${a.replace(/[&<>]/g,e=>({"&":"&","<":"<",">":">"})[e])} + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + +`,$n=` + + + + +`;async function _n(a,e,t,s){var c,l;const i=await a.dir(e,!0),n=ue(t),o=await i.has(".classpath")?await i.read(".classpath"):void 0;for(const h of o?Cs(o):[])!n.includes(h)&&!h.includes("/")&&await i.has(h)&&await i.remove(h);for(const h of n){let u=i;for(const y of h.split("/"))u=await u.dir(y,!0);const f=t.files.filter(y=>U(y.path)===h),m=new Set(f.map(y=>y.path.slice(y.path.indexOf(":")+1))),g=new Set;for(const y of ce(t,h)){const w=y.slice(y.indexOf(":")+1);if(!w)continue;const $=w.split(".");for(let p=1;p<=$.length;p++)g.add($.slice(0,p).join("/"))}const _=async(y,w)=>{for(const $ of await y.list()){const p=w?`${w}/${$.name}`:$.name;$.kind==="directory"?g.has(p)?await _(await y.dir($.name),p):n.some(v=>`${h}/${p}`===v||v.startsWith(`${h}/${p}/`))||await y.remove($.name):/\.java$/i.test($.name)&&!m.has(p)&&await y.remove($.name)}};await _(u,"");for(const y of ce(t,h)){const w=y.slice(y.indexOf(":")+1);let $=u;for(const p of w?w.split("."):[])$=await $.dir(p,!0);for(const p of f.filter(v=>D(v.path)===y)){const v=p.path.slice(p.path.lastIndexOf("/")+1).slice(p.path.includes("/")?0:p.path.indexOf(":")+1);(!await $.has(v)||await $.read(v)!==p.text)&&await $.write(v,p.text)}}}await i.write(Xe,JSON.stringify({format:"visuobject",version:1,uml:t.uml??{},...(c=t.notes)!=null&&c.length?{notes:t.notes}:{},...(l=t.objects)!=null&&l.length?{objects:t.objects}:{},positions:s},null,2)+` +`),await i.has(".project")||await i.write(".project",wn(t.name));const r=gn(o??$n,n);r!==o&&await i.write(".classpath",r)}function ns(a,e){const t=new Set(e.map(i=>i.toLowerCase()));let s=a;for(let i=2;t.has(s.toLowerCase());i++)s=a+i;return s}const os="visuobject.project",xn="visuobject.code",ot="visuobject.active",as="visuobject.positions",rs="visuobject.tree",cs="visuobject.tabs",We="visuobject.wsProject",ls="visuobject.inspector",at="visuobject.inspectorHeight",rt="visuobject.noWorkspace",hs="visuobject.diagram",ds="visuobject.breakpoints",us="visuobject-workspace",kn=80,b=a=>a.replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]),pe=/^[\p{L}_$][\p{L}\p{N}_$]*$/u;function se(a){try{return localStorage.getItem(a)}catch{return null}}function J(a,e){try{localStorage.setItem(a,e)}catch{}}function jn(){const a=ct(),e=a==="pt-PT"?"pt":a==="de"?"de":"en";return`${/\/app\/(index\.html)?$/.test(location.pathname)?"../":"https://visustruct.org/"}${e}/visuobject.html`}function Sn(a,e,t){const s=URL.createObjectURL(new Blob([e],{type:t})),i=document.createElement("a");i.href=s,i.download=a,i.click(),setTimeout(()=>URL.revokeObjectURL(s),1e3)}const Ln='';class En{constructor(e){E(this,"shell");E(this,"editor");E(this,"canvas");E(this,"lines");E(this,"frames");E(this,"status");E(this,"tree");E(this,"tabs");E(this,"openTabs",[]);E(this,"project");E(this,"active");E(this,"currentPackage");E(this,"classes",[]);E(this,"positions",new Map);E(this,"selection");E(this,"relSelection");E(this,"inspector");E(this,"tool","select");E(this,"pendingFrom");E(this,"suppressClick",!1);E(this,"treeSelection");E(this,"open",new Map);E(this,"history",[]);E(this,"future",[]);E(this,"lastTyping",0);E(this,"editing",!1);E(this,"objectDiagram");E(this,"diagramMode",["object","sequence"].find(e=>e===se(hs))??"class");E(this,"sequence");E(this,"noteSelection");E(this,"workspace");E(this,"pendingFolder");E(this,"projects",[]);E(this,"folder");E(this,"saved");E(this,"savedFiles",new Map);E(this,"wsBox");E(this,"breakpoints",new Map);E(this,"dbg");E(this,"renameTimer");E(this,"treeClick",{node:"",time:0});E(this,"drag");E(this,"lastClick",{spot:"",time:0});E(this,"endPop");E(this,"classTab","class");var i;document.documentElement.classList.add("visuobject-theme"),history.replaceState(history.state,"",`${location.pathname}?visuobject${location.hash}`);try{const n=JSON.parse(se(as)??"{}");for(const[c,l]of Object.entries(n))Number.isFinite(l==null?void 0:l.x)&&Number.isFinite(l==null?void 0:l.y)&&this.positions.set(c,l);const o=JSON.parse(se(rs)??"{}");for(const[c,l]of Object.entries(o))this.open.set(c,!!l);const r=JSON.parse(se(ds)??"{}");for(const[c,l]of Object.entries(r))Array.isArray(l)&&this.breakpoints.set(c,new Set(l.filter(Number.isInteger)))}catch{}const t=se(xn);this.project=qt(se(os)??"")??(t!==null?At("Projekt",[{name:"",text:t}]):Ft());const s=se(ot);this.active=this.project.files.some(n=>n.path===s)?s:(i=this.project.files[0])==null?void 0:i.path;try{const n=JSON.parse(se(cs)??"[]");Array.isArray(n)&&(this.openTabs=n.filter(o=>typeof o=="string"&&this.project.files.some(r=>r.path===o)))}catch{}this.shell=document.createElement("div"),this.shell.className="shell visuobject",e.replaceWith(this.shell),this.build(),new Qi(this.shell.querySelector(".vo-columns"),()=>this.drawLines()),this.showActive(),this.refresh(),window.addEventListener("keydown",n=>this.onKey(n)),window.addEventListener("resize",()=>this.drawLines()),window.addEventListener("beforeunload",n=>{this.isDirty()&&n.preventDefault()}),this.restoreWorkspace()}build(){const e=(p,v,x,L=v)=>``;this.shell.innerHTML=` +
    + VisuObject ${b(d("web_visuobject_subtitle"))} +
    + ${e("new",d("toolbar_new"),ie.newFile,d("web_visuobject_new_tip"))} + ${e("open",d("menu_open"),ie.open,d("web_visuobject_open_tip"))} + ${e("save",d("menu_save"),ie.save,d("web_visuobject_save_tip"))} + ${e("undo",d("toolbar_undo"),ie.undo)} + ${e("redo",d("toolbar_redo"),ie.redo)} + +
    +
    + + + + +
    +
    + + +
    +
    +
    +
    + +
    +

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

    + +
    + +
    +
    + + +
    +
    +
    +
    + +
    + +
    +
    + +
    +
    + +
    + +
    + +
    +
    + + + +
    +
    + +
    + +
    + + +
    +
    + + +
    + +
    +
    +

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

    + +
    +
    +
    +

    ${b(d("web_visuobject_edit_hint"))}
    +
    +
    `,this.canvas=this.shell.querySelector(".vo-canvas:not(.vo-objcanvas):not(.vo-seqcanvas)"),this.shell.querySelector(".vo-seqcanvas").addEventListener("click",p=>{var L,S,k;const v=(L=p.target.closest("[data-ev]"))==null?void 0:L.dataset.ev,x=v!==void 0?(k=(S=this.sequence)==null?void 0:S.events[Number(v)])==null?void 0:k.pos:void 0;x!=null&&x.file&&this.showLine(x.file,x.line)});const t=this.shell.querySelector(".vo-objcanvas");this.objectDiagram=new Ci({canvas:t,lines:t.querySelector(".vo-objlines"),inspector:this.shell.querySelector(".vo-inspector"),classes:()=>this.classes,objects:()=>this.project.objects??[],setObjects:p=>this.setProject({...this.project,objects:p.length?p:void 0}),message:p=>this.message(p)});for(const p of this.shell.querySelectorAll("[data-diagram]"))p.addEventListener("click",()=>this.setDiagramMode(p.dataset.diagram));this.shell.querySelector("[data-obj-add]").addEventListener("click",()=>{const p=this.shell.querySelector("[data-obj-class]").value;p&&this.objectDiagram.add(p)}),this.lines=this.canvas.querySelector(".vo-lines"),this.frames=this.canvas.querySelector(".vo-frames"),this.status=this.shell.querySelector(".vo-status"),this.inspector=this.shell.querySelector(".vo-inspector");const s=this.shell.querySelector(".vo-dock"),i=s.querySelector("[data-inspector=toggle]"),n=(p,v=!0)=>{s.classList.toggle("collapsed",!p),i.textContent=p?"–":"+",i.setAttribute("aria-expanded",String(p));const x=d(p?"web_visuobject_inspector_hide":"web_visuobject_inspector_show");i.setAttribute("aria-label",x),i.dataset.tip=x,J(ls,p?"1":"0"),v&&this.drawLines()};i.addEventListener("click",()=>n(s.classList.contains("collapsed"))),s.querySelector(".vo-dock-bar").addEventListener("dblclick",()=>n(s.classList.contains("collapsed"))),n(se(ls)!=="0",!1);const o=this.shell.querySelector(".vo-hsplit"),r=this.shell.querySelector("[data-pane=diagram]"),c=p=>{if(p===void 0)this.inspector.style.removeProperty("height"),this.inspector.style.removeProperty("max-height"),J(at,"");else{const v=Math.max(120,r.clientHeight-200),x=Math.round(Math.min(v,Math.max(60,p)));this.inspector.style.height=`${x}px`,this.inspector.style.maxHeight="none",J(at,String(x))}this.drawLines()},l=Number(se(at));l>0&&(this.inspector.style.height=`${l}px`,this.inspector.style.maxHeight="none"),o.addEventListener("pointerdown",p=>{if(s.classList.contains("collapsed"))return;p.preventDefault(),o.setPointerCapture(p.pointerId);const v=p.clientY,x=this.inspector.offsetHeight,L=k=>c(x-(k.clientY-v)),S=()=>{o.removeEventListener("pointermove",L),o.removeEventListener("pointerup",S),o.removeEventListener("pointercancel",S)};o.addEventListener("pointermove",L),o.addEventListener("pointerup",S),o.addEventListener("pointercancel",S)}),o.addEventListener("dblclick",()=>c(void 0)),o.addEventListener("keydown",p=>{const v=p.key==="ArrowUp"?20:p.key==="ArrowDown"?-20:0;v&&(p.preventDefault(),c(this.inspector.offsetHeight+v))}),this.tree=this.shell.querySelector(".vo-tree"),this.tabs=this.shell.querySelector(".vo-tabs"),this.wsBox=this.shell.querySelector(".vo-ws"),this.wsBox.addEventListener("click",p=>void this.onWorkspaceClick(p)),this.editor=new Hs(this.shell.querySelector(".vo-editor"),{onChange:()=>this.typed(),onCaret:()=>this.caretMoved(),onUndo:p=>this.undo(p),words:()=>({condition:d("canvas_stub_condition"),selector:d("web_live_ph_selector"),code:d("web_live_ph_code"),start:d("inspector_for_init"),step:d("inspector_for_step"),branch:d("element_verzweigung"),branchElse:d("element_verzweigung"),switchCase:d("element_fallauswahl"),forLoop:d("element_forSchleife"),whileLoop:d("element_whileSchleife"),doLoop:d("element_doUntilSchleife"),output:d("inspector_io_mode_output"),input:d("inspector_io_mode_input")}),breakpointLine:p=>p,onBreakpoints:()=>this.saveBreakpoints(),ownTypes:p=>this.ownTypesAt(p)},d("web_visuobject_code"));const h=(p,v)=>this.shell.querySelector(`[data-action=${p}]`).addEventListener("click",v);h("new",()=>void this.newProject({name:d("web_visuobject_project_name"),files:[],packages:[]})),h("example",()=>void this.newProject(Ft(),"tiere/Tier.java")),h("open",()=>this.openFiles()),h("save",()=>void this.save()),h("undo",()=>this.undo(!1)),h("redo",()=>this.undo(!0));const u=this.shell.querySelector("[data-action=new-menu]"),f=this.shell.querySelector(".vo-new-menu"),m=p=>{var v;f.hidden=!p,u.setAttribute("aria-expanded",String(p)),p&&((v=f.querySelector("button"))==null||v.focus())};u.addEventListener("click",()=>m(f.hidden)),f.addEventListener("click",p=>{var x;const v=(x=p.target.closest("[data-new]"))==null?void 0:x.dataset.new;v&&(m(!1),this.newFromWizard(v))}),f.addEventListener("keydown",p=>{var L;const v=[...f.querySelectorAll("button")],x=v.indexOf(document.activeElement);p.key==="Escape"?(m(!1),u.focus()):(p.key==="ArrowDown"||p.key==="ArrowUp")&&(p.preventDefault(),(L=v[(x+(p.key==="ArrowDown"?1:v.length-1))%v.length])==null||L.focus())}),document.addEventListener("pointerdown",p=>{!f.hidden&&!p.target.closest(".vo-new")&&m(!1)}),h("layout",()=>{this.positions.clear(),this.savePositions(),this.render()});const g=this.shell.querySelector("[data-action=settings]"),_=this.shell.querySelector(".settings-menu");g.addEventListener("click",()=>{_.hidden=!_.hidden,g.setAttribute("aria-expanded",String(!_.hidden))}),document.addEventListener("pointerdown",p=>{!_.hidden&&!p.target.closest(".settings")&&(_.hidden=!0)});for(const p of _.querySelectorAll("[data-world]"))p.addEventListener("click",()=>this.chooseWorld(p.dataset.world));const y=_.querySelector("[data-action=code-scopes]");y.checked=Bs(),y.addEventListener("change",()=>Ws(y.checked)),this.shell.querySelector("[data-action=run]").addEventListener("click",()=>void this.runProgram()),this.shell.querySelector("[data-action=stop]").addEventListener("click",()=>this.dbg?this.stopDebug("web_visuobject_stopped"):void this.stopProgram()),this.shell.querySelector("[data-action=debug]").addEventListener("click",()=>void this.startDebug());for(const p of this.shell.querySelectorAll("[data-dbg]"))p.addEventListener("click",()=>this.debugCommand(p.dataset.dbg));const w=this.shell.querySelector(".vo-console-input");w.addEventListener("submit",p=>{p.preventDefault();const v=w.querySelector("input");this.debugInput(v.value),v.value=""}),window.addEventListener("keydown",p=>{const v={F5:"into",F6:"over",F7:"out",F8:"continue"}[p.key];!v||!this.dbg||(p.preventDefault(),this.debugCommand(v))});const $=this.shell.querySelector(".vo-console");$.querySelector("[data-console=clear]").addEventListener("click",()=>$.querySelector(".vo-console-lines").replaceChildren()),$.querySelector("[data-console=hide]").addEventListener("click",()=>$.hidden=!0),this.canvas.addEventListener("pointerdown",p=>this.onPointerDown(p)),this.canvas.addEventListener("click",p=>this.onClick(p)),this.canvas.addEventListener("contextmenu",p=>{const v=p.target.closest("[data-end]");v&&(p.preventDefault(),this.relSelection!==v.dataset.rel&&this.selectRelation(v.dataset.rel),this.openEnd(v.dataset.rel,v.dataset.end,p))}),this.tree.addEventListener("click",p=>this.onTreeClick(p)),this.tabs.addEventListener("click",p=>this.onTabClick(p));for(const p of this.shell.querySelectorAll(".vo-tool"))p.addEventListener("pointerdown",v=>this.onToolDown(v,p.dataset.tool));this.tree.addEventListener("keydown",p=>this.onTreeKey(p))}mainClass(){const e=this.classes.filter(s=>s.members.some(i=>i.kind==="method"&&i.name==="main"&&i.isStatic)),t=e.find(s=>s.path===this.active)??e[0];return t&&(t.pkg?`${t.pkg}.${t.name}`:t.name)}async runProgram(){const e=this.shell.querySelector(".vo-console"),t=e.querySelector(".vo-console-lines"),s=e.querySelector(".vo-console-status"),i=e.querySelector(".vo-swing"),n=this.shell.querySelector("[data-action=run]"),o=this.shell.querySelector("[data-action=stop]");e.hidden=!1;const r=(l,h=!1,...u)=>{s.textContent=d(l,...u),s.classList.toggle("error",h)},c=this.mainClass();if(!c)return r("web_visuobject_no_main",!0);this.workspace&&await this.writeCurrent(),await Ye().catch(()=>{}),t.replaceChildren();for(const l of document.querySelectorAll("#console"))l.removeAttribute("id");t.id="console",i.hidden=!0,n.disabled=!0,o.disabled=!1;try{r("web_live_swing_loading"),await zs(i.querySelector(".livecode-swing-display")),r("web_live_swing_compiling");const l=this.project.files.map(u=>({pkg:X(D(u.path)),name:Q(u.path).replace(/\.java$/i,""),text:u.text})),{result:h}=await Vs(l,c,()=>{i.hidden=!1,r("web_visuobject_running_fmt",!1,c)});r({"compile-error":"web_live_swing_compile_failed",windows:"web_live_swing_running",finished:"web_live_run_finished"}[h],h==="compile-error"),i.hidden=h!=="windows",o.disabled=h!=="windows"}catch{r("web_live_swing_failed",!0),o.disabled=!0}n.disabled=!1}async stopProgram(){await Ye().catch(()=>{});const e=this.shell.querySelector(".vo-console");e.querySelector(".vo-swing").hidden=!0;const t=e.querySelector(".vo-console-status");t.textContent=d("web_visuobject_stopped"),t.classList.remove("error"),this.shell.querySelector("[data-action=stop]").disabled=!0}saveBreakpoints(){if(!this.active)return;const e=this.editor.breakpoints;e.size?this.breakpoints.set(this.active,e):this.breakpoints.delete(this.active);const t=new Set(this.project.files.map(s=>s.path));J(ds,JSON.stringify(Object.fromEntries([...this.breakpoints].filter(([s])=>t.has(s)).map(([s,i])=>[s,[...i]]))))}consolePane(){const e=this.shell.querySelector(".vo-console");return{pane:e,lines:e.querySelector(".vo-console-lines"),status:e.querySelector(".vo-console-status"),input:e.querySelector(".vo-console-input")}}debugStatus(e,t=!1){const{status:s}=this.consolePane();s.textContent=e,s.classList.toggle("error",t)}consoleWrite(e,t="out"){const{lines:s}=this.consolePane(),i=s.lastElementChild;if((i==null?void 0:i.dataset.kind)===t)i.textContent+=e;else{const n=document.createElement("span");n.dataset.kind=t,n.className=`vo-out-${t}`,n.textContent=e,s.append(n)}s.scrollTop=s.scrollHeight}async startDebug(){this.dbg&&this.stopDebug();const{pane:e,lines:t,input:s}=this.consolePane();e.hidden=!1,e.querySelector(".vo-swing").hidden=!0,await Ye().catch(()=>{}),this.workspace&&await this.writeCurrent(),t.replaceChildren(),t.removeAttribute("id"),s.hidden=!0;const i=this.mainClass();if(!i)return this.debugStatus(d("web_visuobject_no_main"),!0);let n;try{n=new Vi(this.project.files.map(o=>({path:o.path,source:o.text})),{out:(o,r)=>this.consoleWrite(o,r?"err":"out")}),n.start(i.split(".").pop())}catch(o){if(o instanceof q)return this.debugError(o);throw o}this.dbg={vm:n,state:"running",frames:[],frame:0,places:new Map,values:new Map,vars:new Map},this.shell.querySelector(".vo-dbg-controls").hidden=!1,this.shell.querySelector("[data-action=stop]").disabled=!1,this.shell.querySelector("[data-action=run]").disabled=!0,this.sequence=void 0,this.diagramMode==="class"&&this.setDiagramMode("object"),n.go(this.allBreakpoints().size?"run":"into"),this.debugRun()}allBreakpoints(){const e=new Set;for(const[t,s]of this.breakpoints)for(const i of s)e.add(`${t}:${i}`);return e}debugCommand(e){const t=this.dbg;if(t){if(e==="pause")return t.state!=="running"?void 0:(t.vm.pause(),clearTimeout(t.timer),this.debugRun());t.state==="paused"&&(t.vm.go(e==="continue"?"run":e),this.debugRun())}}debugRun(){const e=this.dbg;if(!e)return;e.state="running",this.showDebugButtons(),this.debugStatus(d("web_visuobject_dbg_running"));const t=this.allBreakpoints(),s=performance.now();for(;;){const i=e.vm.run(t,2e3);if(i.k==="running"){if(performance.now()-s<15)continue;e.timer=window.setTimeout(()=>this.debugRun(),0);return}if(i.k==="sleep"){e.timer=window.setTimeout(()=>this.debugRun(),Math.min(i.ms,1e4));return}if(i.k==="input"){e.state="input",this.showDebugButtons(),this.showDebugState(),this.debugStatus(d("web_visuobject_dbg_waiting"));const{input:n}=this.consolePane();n.hidden=!1,n.querySelector("input").focus();return}if(i.k==="paused"){e.state="paused",e.frame=0,this.showDebugButtons(),this.showDebugState(),this.debugStatus(d("web_visuobject_dbg_paused_fmt",i.pos.file.split("/").pop()??"",String(i.pos.line+1)));return}return i.k==="done"?this.stopDebug("web_live_run_finished"):i.k==="exception"?(this.consoleWrite(`${i.text} +`,"err"),i.pos&&this.showLine(i.pos.file,i.pos.line),this.stopDebug("web_visuobject_dbg_exception",!0)):this.debugError(i.error)}}debugInput(e){const t=this.dbg;!t||t.state!=="input"||(this.consoleWrite(`${e} +`,"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}=Ti(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>kn&&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 Ji([...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-DZMCzW4J.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-DZMCzW4J.js");return{projectToZip:s}},__vite__mapDeps([0,1,2]),import.meta.url),t=e(this.project);Sn(`${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 yn(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 _n(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 on(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(bi(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(fi(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(sn(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"))}

    + ${s("create",d("web_visuobject_ws_create",ss),"text-button primary")} + ${s("open",d("web_visuobject_ws_open"))} + ${s("skip",d("web_visuobject_ws_skip"))}`)}async onWorkspaceClick(e){var s;const t=(s=e.target.closest("[data-ws]"))==null?void 0:s.dataset.ws;if(t){if(t==="zip")return this.downloadZip();if(t==="skip")return J(rt,"1"),this.renderWorkspace();try{if(t==="reopen"&&this.pendingFolder){const n=await _t(this.pendingFolder);n&&await this.useWorkspace(n.root,!0);return}if(this.isDirty()&&!await this.writeCurrent(!1))return;const i=await Xs(t==="create"?ss:void 0,us);J(We,""),await this.useWorkspace(i.root)}catch(i){(i==null?void 0:i.name)!=="AbortError"&&this.message(d("web_visuobject_ws_failed",String((i==null?void 0:i.message)??i)))}}}changeFile(e,t,s){const i=this.project.files.find(n=>n.path===e);i&&(s&&(this.selection=s),this.message(""),this.setProject($e(this.project,e,t(i.text)),e))}uniqueClassName(e){let t=e;for(let s=2;this.findClass(t)||this.project.files.some(i=>Q(i.path)===`${t}.java`);s++)t=e+s;return t}newClass(e,t){const s=this.uniqueClassName(d(e==="class"?"web_visuobject_new_class_name":"web_visuobject_new_interface_name"));t&&this.positions.set(s,{x:Math.max(0,Math.round(t.x)),y:Math.max(0,Math.round(t.y))});const i=this.currentPackage??(this.active?D(this.active):ce(this.project)[0]??""),n=le(i,`${s}.java`);this.selection={cls:s},this.open.set(`pkg:${i}`,!0),this.setProject(et(this.project,n,this.sectioned(wi(i,s,e),s)),n),this.savePositions();const o=this.findClass(s);o&&this.showInCode(o);const r=this.canvas.querySelector(`.uml-class[data-class="${CSS.escape(s)}"]`);r==null||r.scrollIntoView({block:"nearest",inline:"nearest"}),this.startEditing((r==null?void 0:r.querySelector(".uml-name"))??null)}renameClassTo(e,t){if(t===e.name)return;if(!pe.test(t)||this.findClass(t))return this.message(d("web_visuobject_bad_name",t));const s=this.project.files.find(r=>r.path===e.path);let i=$e(this.project,e.path,oi(s.text,e,t)),n=e.path;Q(e.path)===`${e.name}.java`&&(n=le(D(e.path),`${t}.java`),i.files.some(r=>r.path===n)?n=e.path:i=Oe(i,e.path,n));const o=this.positions.get(e.name);o&&this.positions.set(t,o);for(const r of Object.keys(i.uml??{}))r.startsWith(`${e.name}.`)&&(i={...i,uml:ke(i.uml,r,t+r.slice(e.name.length))});this.selection={cls:t},this.message(""),this.setProject(i,n)}deleteClassFromProject(e){const t=this.project.files.find(n=>n.path===e.path),s=ni(t.text,e),i=oe(s).length===0;this.selection=void 0,this.message(""),this.setProject(i?Tt(this.project,e.path):$e(this.project,e.path,s))}commit(e,t){var u,f;const s=t.trim(),i=(u=e.closest("[data-node]"))==null?void 0:u.dataset.node;if(i)return this.commitTree(i,s);const n=e.closest(".uml-class"),o=n&&this.findClass(n.dataset.class);if(!o)return;if(e.classList.contains("uml-name"))return this.renameClassTo(o,s);const r=e.dataset.add;if(r){if(!s)return;const m=Ve(s);if(!m)return this.message(d("web_visuobject_bad_line",s));const g=r==="method"&&m.kind==="field"?`${s}()`:s;this.changeFile(o.path,_=>this.sorted(Ee(_,o,g),o.name),{cls:o.name});return}const c=Number(e.dataset.member),l=o.members[c];if(!l)return;if(!s){this.changeFile(o.path,m=>xe(m,l),{cls:o.name});return}if(s===Ge(l))return;const h=Ve(s);if(!h)return this.message(d("web_visuobject_bad_line",s));if(l.kind==="field"&&h.kind==="field"&&h.name!==l.name&&((f=this.project.uml)!=null&&f[V(o.name,l.name)])){const m=this.project.files.find(g=>g.path===o.path);this.selection={cls:o.name,member:c},this.setProject({...$e(this.project,o.path,Qe(m.text,o,l,s)),uml:ke(this.project.uml,V(o.name,l.name),V(o.name,h.name))},o.path);return}this.changeFile(o.path,m=>Qe(m,o,l,s),{cls:o.name,member:c})}commitTree(e,t){const[s,...i]=e.split(":"),n=i.join(":");if(s==="project"){if(!t||t===this.project.name)return;if(this.projects.some(r=>r!==this.folder&&r.toLowerCase()===ge(t).toLowerCase()))return this.message(d("web_visuobject_ws_taken",t));this.setProject({...this.project,name:t})}else if(s==="root"){if(!t||t===n||n===Z)return;if(!Je(t)||ue(this.project).includes(t))return this.message(d("web_visuobject_bad_folder",t));this.currentPackage&&U(this.currentPackage)===n&&(this.currentPackage=re(t,X(this.currentPackage))),this.treeSelection=`root:${t}`;const o=r=>r&&U(r)===n?`${t}:${r.slice(n.length+1)}`:r;this.openTabs=this.openTabs.map(r=>o(r)),this.setProject(vi(this.project,n,t),o(this.active))}else if(s==="pkg"){const o=re(U(n),t);if(!t||o===n)return;if(!Mt(t)||ce(this.project).includes(o))return this.message(d("web_visuobject_bad_package",t));this.currentPackage===n&&(this.currentPackage=o),this.treeSelection=`pkg:${o}`,this.open.set(`pkg:${o}`,!0),this.setProject(mi(this.project,n,o),this.active&&D(this.active)===n?le(o,Q(this.active)):this.active)}else if(s==="file"){const o=t.replace(/\.java$/i,""),r=this.classes.find(l=>l.path===n&&`${l.name}.java`===Q(n));if(r)return this.renameClassTo(r,o);if(!pe.test(o))return this.message(d("web_visuobject_bad_name",o));const c=le(D(n),`${o}.java`);c!==n&&!this.project.files.some(l=>l.path===c)&&this.setProject(Oe(this.project,n,c),c)}else if(s==="class"){const o=this.findClass(n);o&&this.renameClassTo(o,t)}}startEditing(e){if(!e||this.editing)return;const t=e.classList.contains("uml-name")||e.classList.contains("vo-label"),s=document.createElement("input");s.className="uml-input",s.spellcheck=!1,s.autocapitalize="off",s.setAttribute("autocomplete","off"),s.setAttribute("aria-label",d(t?"web_visuobject_name_label":"web_visuobject_member_label")),e.dataset.add&&(s.placeholder=d(e.dataset.add==="field"?"web_visuobject_field_ph":"web_visuobject_method_ph")),s.value=e.dataset.add?"":e.dataset.value??e.textContent??"",s.size=Math.max(s.value.length,s.placeholder.length,8),e.replaceChildren(s),this.editing=!0;let i=!1;const n=o=>{i||(i=!0,this.editing=!1,o&&this.commit(e,s.value),this.render(),this.renderTree())};s.addEventListener("keydown",o=>{o.stopPropagation(),o.key==="Enter"?n(!0):o.key==="Escape"&&n(!1)}),s.addEventListener("click",o=>o.stopPropagation()),s.addEventListener("input",()=>s.size=Math.max(s.value.length,s.placeholder.length,8)),s.addEventListener("blur",()=>n(!0)),s.focus(),s.select()}onKey(e){if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==="s"){e.preventDefault(),this.save();return}if(e.key==="Escape"&&this.endPop){this.closeEnd();return}if(e.key==="Escape"&&this.tool!=="select"){this.setTool("select");return}if(this.editing||this.editor.hasFocus)return;const t=e.target;if(this.diagramMode==="object"&&!t.closest("input, select, textarea")&&!(e.metaKey||e.ctrlKey)&&this.objectDiagram.onKey(e)||t.closest("input, select, textarea, .vo-tree"))return;if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==="z"){e.preventDefault(),this.undo(e.shiftKey);return}if(!this.canvas.contains(document.activeElement)&&document.activeElement!==document.body)return;if(this.noteSelection&&this.findNote(this.noteSelection)){e.key==="Delete"||e.key==="Backspace"?(e.preventDefault(),this.deleteNote(this.noteSelection)):(e.key==="Enter"||e.key==="F2")&&(e.preventDefault(),this.editNote(this.noteSelection));return}if(this.relSelection&&(e.key==="Delete"||e.key==="Backspace")){e.preventDefault(),this.deleteRelation(this.relSelection);return}const i=this.selection,n=i&&this.findClass(i.cls);if(n){if(e.key==="Delete"||e.key==="Backspace"){e.preventDefault();const o=i.member!==void 0?n.members[i.member]:void 0;o?this.changeFile(n.path,r=>xe(r,o),{cls:n.name}):this.deleteClassFromProject(n)}else if(e.key==="Enter"||e.key==="F2"){e.preventDefault();const o=this.canvas.querySelector(`.uml-class[data-class="${CSS.escape(n.name)}"]`);this.startEditing((o==null?void 0:o.querySelector(i.member!==void 0?`[data-member="${i.member}"]`:".uml-name"))??null)}}}isOpen(e){if(e.startsWith("wsproject:"))return!1;const t=this.open.get(e);return t!==void 0?t:e.startsWith("file:")?e===`file:${this.active}`:!0}toggle(e){this.open.set(e,!this.isOpen(e)),J(rs,JSON.stringify(Object.fromEntries(this.open))),this.renderTree()}renderTree(){var f,m,g,_;const e=(m=(f=document.activeElement)==null?void 0:f.closest("[data-node]"))==null?void 0:m.dataset.node,t=this.treeSelection??(this.selection?`class:${this.selection.cls}`:this.active?`file:${this.active}`:void 0),s=(y,w,$,p,v={})=>{const x=v.children!==void 0,L=x&&this.isOpen(y),S=y===t;return`
  • +
    + ${x?``:''} + ${$}${b(p)}${v.extra??""} + ${v.action?``:""} +
    + ${L&&v.children?`
      ${v.children}
    `:""} +
  • `},i=(y,w,$,p)=>{const v={"+":"public","-":"private","#":"protected","~":"package"}[w.visibility],x=w.params.map(k=>k.type).join(", "),L=w.kind==="field"?w.name:`${w.name}(${x})`,S=w.kind==="constructor"?"":`: ${b(w.type)}`;return s(`member:${y.name}:${$}`,p,``,L,{extra:S,title:Ge(w)})},n=(y,w)=>{const $=y.kind==="interface"?"I":y.isAbstract?"A":"C",p=y.members.map((v,x)=>i(y,v,x,w+1)).join("");return s(`class:${y.name}`,w,``,y.name,{children:p})},o=(y,w)=>{const $=this.classes.filter(p=>p.path===y);return s(`file:${y}`,w,'',Q(y),{children:$.map(p=>n(p,w+1)).join(""),action:!0})},r=y=>ce(this.project,y).map(w=>{const $=ui(this.project,w).map(x=>o(x.path,3)).join(""),p=X(w),v=p||d("web_visuobject_default_package");return s(`pkg:${w}`,2,``,v,{children:$,value:p,action:!0})}).join(""),c=ue(this.project).map(y=>s(`root:${y}`,1,'',y,{children:r(y)||`
  • ${b(d("web_visuobject_tree_empty"))}
  • `,action:y!==Z})).join(""),l=s("project",0,'',this.project.name,{children:c,extra:this.isDirty()?` ●`:""}),u=[...(this.workspace?this.projects.filter(y=>y!==this.folder):[]).map(y=>({name:y,html:s(`wsproject:${y}`,0,'',y,{children:"",title:d("web_visuobject_ws_open_project",y)})})),{name:this.folder??this.project.name,html:l}];u.sort((y,w)=>y.name.localeCompare(w.name)),this.tree.innerHTML=`
      ${u.map(y=>y.html).join("")}
    `,this.tree.querySelector('[tabindex="0"]')||(g=this.tree.querySelector(".vo-row"))==null||g.setAttribute("tabindex","0"),e&&((_=this.tree.querySelector(`[data-node="${CSS.escape(e)}"] > .vo-row`))==null||_.focus({preventScroll:!0}))}onTreeClick(e){if(this.editing)return;const t=e.target,s=t.closest("[data-node]"),i=s==null?void 0:s.dataset.node;if(!s||!i)return;if(t.closest("[data-toggle]"))return i.startsWith("wsproject:")?void this.switchProject(i.slice(10)):this.toggle(i);if(t.closest("[data-delete]"))return this.deleteNode(i);const n=Date.now(),o=this.treeClick.node===i&&n-this.treeClick.time<450;if(this.treeClick={node:i,time:o?0:n},o&&!i.startsWith("member:")&&!i.startsWith("wsproject:")&&i!==`root:${Z}`){this.startEditing(this.tree.querySelector(`[data-node="${CSS.escape(i)}"] > .vo-row .vo-label`));return}this.selectNode(i)}selectNode(e){const[t,...s]=e.split(":"),i=s.join(":");if(this.treeSelection=void 0,t==="wsproject")return void this.switchProject(i);if(t==="pkg")this.currentPackage=i,this.treeSelection=e;else if(t==="file")this.currentPackage=D(i),this.treeSelection=e,this.openFile(i);else if(t==="class"||t==="member"){const[n,o]=i.split(":"),r=this.findClass(n);if(!r)return;const c=o!==void 0?r.members[Number(o)]:void 0;this.selection={cls:r.name,member:o!==void 0?Number(o):void 0},this.currentPackage=D(r.path),this.showInCode(r,c),o!==void 0&&(this.treeSelection=e)}else this.treeSelection=e;this.render(),this.renderTree()}deleteNode(e){const[t,...s]=e.split(":"),i=s.join(":");this.treeSelection=void 0,t==="file"?this.setProject(Tt(this.project,i)):t==="root"?(this.currentPackage&&U(this.currentPackage)===i&&(this.currentPackage=void 0),this.setProject(gi(this.project,i))):t==="pkg"&&(this.currentPackage===i&&(this.currentPackage=void 0),this.setProject(yi(this.project,i)))}onTreeKey(e){var r,c;if(this.editing)return;const t=[...this.tree.querySelectorAll(".vo-row")],s=(r=document.activeElement)==null?void 0:r.closest(".vo-row"),i=s?t.indexOf(s):-1,n=(c=s==null?void 0:s.closest("[data-node]"))==null?void 0:c.dataset.node,o=l=>{const h=t[Math.max(0,Math.min(t.length-1,l))];for(const u of t)u.tabIndex=-1;h.tabIndex=0,h.focus()};if(e.key==="ArrowDown")o(i+1);else if(e.key==="ArrowUp")o(i-1);else if(n&&e.key==="ArrowRight"&&(s!=null&&s.querySelector("[data-toggle]"))&&!this.isOpen(n))this.toggle(n);else if(n&&e.key==="ArrowLeft"&&(s!=null&&s.querySelector("[data-toggle]"))&&this.isOpen(n))this.toggle(n);else if(n&&e.key==="Enter")this.selectNode(n);else if(n&&e.key==="F2")this.startEditing(s.querySelector(".vo-label"));else if(n&&(e.key==="Delete"||e.key==="Backspace")&&(s!=null&&s.querySelector("[data-delete]")))this.deleteNode(n);else return;e.preventDefault()}onPointerDown(e){this.closeEnd();const t=e.target;if(this.tool!=="select"&&e.button===0&&!t.closest(".vo-dock, .vo-relmenu, input, select, button:not(.uml-connect)"))return this.suppressClick=!0,this.useTool(e);const s=t.closest("[data-note-connect]");if(s&&e.button===0)return this.startNoteConnect(e,s.closest(".uml-note").dataset.note);const i=t.closest(".uml-note");if(i&&e.button===0&&!t.closest("textarea"))return this.dragNote(e,i);const n=t.closest("[data-connect]");if(n&&e.button===0)return this.startConnect(e,n.closest(".uml-class").dataset.class);if(t.closest("input, select, button, label"))return;const o=t.closest(".uml-class");if(!o||e.button!==0)return;const r=this.positions.get(o.dataset.class)??{x:o.offsetLeft,y:o.offsetTop};this.drag={name:o.dataset.class,box:o,start:{x:e.clientX,y:e.clientY},origin:r,moved:!1};const c=h=>{const u=this.drag;if(!u)return;const f=h.clientX-u.start.x,m=h.clientY-u.start.y;if(!u.moved&&Math.hypot(f,m)<4)return;u.moved=!0;const g={x:Math.max(0,Math.round(u.origin.x+f)),y:Math.max(0,Math.round(u.origin.y+m))};this.positions.set(u.name,g),u.box.style.left=`${g.x}px`,u.box.style.top=`${g.y}px`,this.drawLines()},l=()=>{var h;window.removeEventListener("pointermove",c),window.removeEventListener("pointerup",l),(h=this.drag)!=null&&h.moved&&this.savePositions(),setTimeout(()=>this.drag=void 0,0)};window.addEventListener("pointermove",c),window.addEventListener("pointerup",l)}onClick(e){var _,y;if(this.suppressClick){this.suppressClick=!1;return}if((_=this.drag)!=null&&_.moved||this.editing)return;const t=e.target;if(t.closest("input, select, label, textarea"))return;const s=t.closest(".uml-note");if(s){const w=s.dataset.note,$=Date.now(),p=this.lastClick.spot===`note|${w}`&&$-this.lastClick.time<450;return this.lastClick={spot:`note|${w}`,time:p?0:$},p?this.editNote(w):this.selectNote(w)}this.noteSelection=void 0;const i=t.closest("[data-class-action]"),n=t.closest(".uml-class"),o=n&&this.findClass(n.dataset.class);if(i&&o){i.dataset.classAction==="delete"&&this.deleteClassFromProject(o);return}const r=t.closest("[data-add]");if(r){this.startEditing(r);return}const c=(y=t.closest("[data-rel]"))==null?void 0:y.dataset.rel,l=t.closest("[data-end]");if(c&&!o&&l&&this.relSelection===c){this.openEnd(c,l.dataset.end,e,l.dataset.part);return}if(c&&!o){this.selectRelation(c);return}if(!o){this.relSelection=void 0,this.selection=void 0,this.render(),this.renderTree();return}const h=t.closest("[data-member]"),u=h?Number(h.dataset.member):void 0,f=`${o.name}|${u??(t.closest(".uml-name")?"name":"")}`,m=Date.now(),g=f===this.lastClick.spot&&m-this.lastClick.time<450&&!f.endsWith("|");if(this.lastClick={spot:f,time:g?0:m},g){const w=this.canvas.querySelector(`.uml-class[data-class="${CSS.escape(o.name)}"]`);this.startEditing((w==null?void 0:w.querySelector(u!==void 0?`[data-member="${u}"]`:".uml-name"))??null);return}this.selection={cls:o.name,member:u},this.relSelection=void 0,this.treeSelection=void 0,this.currentPackage=D(o.path),this.showInCode(o,u!==void 0?o.members[u]:void 0),this.render(),this.renderTree(),this.canvas.focus({preventScroll:!0})}setDiagramMode(e){this.diagramMode=e,J(hs,e),this.setTool("select"),this.render()}showDiagramMode(){const e=this.diagramMode==="object",t=this.diagramMode==="class";for(const s of this.shell.querySelectorAll("[data-diagram]"))s.setAttribute("aria-selected",String(s.dataset.diagram===this.diagramMode));if(this.shell.querySelector(".vo-palette:not(.vo-obj-palette)").hidden=!t,this.shell.querySelector(".vo-obj-palette").hidden=!e,this.canvas.hidden=!t,this.shell.querySelector(".vo-objcanvas").hidden=!e,this.shell.querySelector(".vo-seqcanvas").hidden=this.diagramMode!=="sequence",this.shell.querySelector("[data-action=layout]").hidden=!t,e){const s=this.shell.querySelector("[data-obj-class]"),i=[...new Set(this.classes.filter(o=>o.kind==="class"&&!o.isAbstract).map(o=>o.name))],n=i.includes(s.value)?s.value:i[0];s.innerHTML=i.map(o=>`${b(o)}`).join(""),this.shell.querySelector("[data-obj-add]").disabled=i.length===0}}savePositions(){const e=new Set(this.classes.map(t=>t.name));J(as,JSON.stringify(Object.fromEntries([...this.positions].filter(([t])=>e.has(t)))))}render(){var t;if(this.showDiagramMode(),this.diagramMode==="object")return this.objectDiagram.render();if(this.diagramMode==="sequence")return this.renderSequence();for(const s of this.canvas.querySelectorAll(".uml-class, .uml-note, .vo-empty"))s.remove();for(const s of this.project.notes??[])this.canvas.append(this.noteBox(s));if(this.classes.length===0){const s=document.createElement("p");s.className="vo-empty",s.textContent=d("web_visuobject_empty"),(t=this.project.notes)!=null&&t.length||this.canvas.append(s),this.drawLines();return}const e=new Map;for(const s of this.classes){if(e.has(s.name))continue;const i=this.classBox(s);e.set(s.name,i),this.canvas.append(i)}this.placeNew(e),this.drawLines()}noteBox(e){const t=document.createElement("div"),s=this.noteSelection===e.id;return t.className=`uml-note${s?" selected":""}`,t.dataset.note=e.id,t.style.left=`${e.x}px`,t.style.top=`${e.y}px`,t.innerHTML=`${s?``:""}
    ${b(e.text||d("web_visuobject_note_ph"))}
    `,t}findNote(e){var t;return e?(t=this.project.notes)==null?void 0:t.find(s=>s.id===e):void 0}setNotes(e){this.setProject({...this.project,notes:e.length?e:void 0})}changeNote(e,t){this.setNotes((this.project.notes??[]).map(s=>s.id===e?{...s,...t}:s))}addNote(e){const t=`n${Date.now().toString(36)}`;this.noteSelection=t,this.selection=void 0,this.relSelection=void 0,this.setNotes([...this.project.notes??[],{id:t,text:"",x:Math.max(0,Math.round(e.x)),y:Math.max(0,Math.round(e.y))}]),this.editNote(t)}deleteNote(e){this.noteSelection=void 0,this.setNotes((this.project.notes??[]).filter(t=>t.id!==e))}selectNote(e){this.noteSelection=e,this.selection=void 0,this.relSelection=void 0,this.treeSelection=void 0,this.render(),this.renderTree(),this.canvas.focus({preventScroll:!0})}editNote(e){const t=this.findNote(e),s=this.canvas.querySelector(`.uml-note[data-note="${CSS.escape(e)}"]`);if(!t||!s)return;const i=document.createElement("textarea");i.className="uml-note-edit",i.value=t.text,i.placeholder=d("web_visuobject_note_ph"),i.rows=Math.max(3,t.text.split(` +`).length+1),s.querySelector(".uml-note-text").replaceWith(i),this.editing=!0;let n=!1;const o=r=>{n||(n=!0,this.editing=!1,r&&i.value!==t.text?this.changeNote(e,{text:i.value}):this.render())};i.addEventListener("keydown",r=>{r.stopPropagation(),r.key==="Escape"?o(!1):r.key==="Enter"&&(r.metaKey||r.ctrlKey)&&o(!0)}),i.addEventListener("blur",()=>o(!0)),i.focus()}startNoteConnect(e,t){e.preventDefault();const s=this.canvas.querySelector(`.uml-note[data-note="${CSS.escape(t)}"]`),i=document.createElementNS("http://www.w3.org/2000/svg","line");i.setAttribute("class","vo-rel vo-note-link ghost"),this.lines.append(i);const n={x:s.offsetLeft+s.offsetWidth,y:s.offsetTop+s.offsetHeight/2},o=l=>{var h;return((h=document.elementFromPoint(l.clientX,l.clientY))==null?void 0:h.closest(".uml-class"))??void 0},r=l=>{var u;const h=this.canvas.getBoundingClientRect();i.setAttribute("x1",String(n.x)),i.setAttribute("y1",String(n.y)),i.setAttribute("x2",String(l.clientX-h.left+this.canvas.scrollLeft)),i.setAttribute("y2",String(l.clientY-h.top+this.canvas.scrollTop));for(const f of this.canvas.querySelectorAll(".uml-class.drop"))f.classList.remove("drop");(u=o(l))==null||u.classList.add("drop")},c=l=>{var m;window.removeEventListener("pointermove",r),window.removeEventListener("pointerup",c),i.remove();const h=o(l);h==null||h.classList.remove("drop"),this.suppressClick=!0;const u=this.findNote(t),f=h==null?void 0:h.dataset.class;u&&f&&!((m=u.attach)!=null&&m.includes(f))&&this.changeNote(t,{attach:[...u.attach??[],f]})};window.addEventListener("pointermove",r),window.addEventListener("pointerup",c)}dragNote(e,t){const s=this.findNote(t.dataset.note);if(!s)return;const i={x:e.clientX,y:e.clientY};let n=!1,o={x:s.x,y:s.y};const r=l=>{const h=l.clientX-i.x,u=l.clientY-i.y;!n&&Math.hypot(h,u)<4||(n=!0,o={x:Math.max(0,Math.round(s.x+h)),y:Math.max(0,Math.round(s.y+u))},t.style.left=`${o.x}px`,t.style.top=`${o.y}px`,this.drawLines())},c=()=>{window.removeEventListener("pointermove",r),window.removeEventListener("pointerup",c),n&&(this.suppressClick=!0,this.changeNote(s.id,o))};window.addEventListener("pointermove",r),window.addEventListener("pointerup",c)}noteLinksSVG(e){const t=[];for(const s of this.project.notes??[]){const i=this.canvas.querySelector(`.uml-note[data-note="${CSS.escape(s.id)}"]`);if(i)for(const n of s.attach??[]){const o=e.get(n);if(!o)continue;const r={x:i.offsetLeft,y:i.offsetTop,w:i.offsetWidth,h:i.offsetHeight},c={x:o.offsetLeft,y:o.offsetTop,w:o.offsetWidth,h:o.offsetHeight},l={x:r.x+r.w/2,y:r.y+r.h/2},h={x:c.x+c.w/2,y:c.y+c.h/2},u=ze(r,l,h),f=ze(c,h,l);t.push(``)}}return t.join("")}renderNoteInspector(e){this.inspector.dataset.rel=`note:${e.id}`;const t=[...new Set(this.classes.map(s=>s.name))];this.inspector.innerHTML=` +

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

    + + ${t.length?`
    ${b(d("web_visuobject_note_attached"))}${t.map(s=>{var i;return``}).join("")}
    `:""} +
    `,this.inspector.querySelector("[data-field=note-text]").addEventListener("change",s=>this.changeNote(e.id,{text:s.target.value}));for(const s of this.inspector.querySelectorAll("[data-field=note-attach]"))s.addEventListener("change",()=>{const i=[...this.inspector.querySelectorAll("[data-field=note-attach]")].filter(n=>n.checked).map(n=>n.value);this.changeNote(e.id,{attach:i.length?i:void 0})});this.inspector.querySelector("[data-inspector=delete-note]").addEventListener("click",()=>this.deleteNote(e.id))}classBox(e){var l;const t=((l=this.selection)==null?void 0:l.cls)===e.name?this.selection:void 0,s=document.createElement("div");s.className=`uml-class${t?" selected":""}${e.kind==="interface"?" interface":""}${e.isAbstract?" abstract":""}`,s.dataset.class=e.name;const i=this.positions.get(e.name);i&&(s.style.left=`${i.x}px`,s.style.top=`${i.y}px`);const n=(h,u)=>{const f=Ge(h);return`
  • ${b(f)}
  • `},o=e.members.map((h,u)=>h.kind==="field"?n(h,u):"").join(""),r=e.members.map((h,u)=>h.kind!=="field"?n(h,u):"").join(""),c=h=>t?`
  • ${b(d(h==="field"?"web_visuobject_add_field":"web_visuobject_add_method"))}
  • `:"";return s.innerHTML=` + ${t&&t.member===void 0?``:""} +
    ${e.kind==="interface"?"«interface»":e.isAbstract?"{abstract}":""}${b(e.name)}
    + ${e.kind==="interface"&&!o?"":`
      ${o}${c("field")}
    `} +
      ${r}${c("method")}
    `,s}placeNew(e){var f;if(this.classes.every(m=>this.positions.has(m.name)))return;const t=m=>[m.superclass,...m.interfaces].filter(g=>!!g&&e.has(g)),s=new Map,i=(m,g)=>{if(s.has(m.name))return s.get(m.name);if(g.has(m.name))return 0;g.add(m.name);const _=t(m).map(w=>this.findClass(w)).filter(w=>w.pkg===m.pkg).map(w=>i(w,g)),y=_.length?Math.max(..._)+1:0;return s.set(m.name,y),y};for(const m of this.classes)i(m,new Set);const n=48,o=Math.max(this.canvas.clientWidth,400)-24,r=(m,g,_)=>m.x+m.w+_<=g.x||g.x+g.w+_<=m.x||m.y+m.h+_<=g.y||g.y+g.h+_<=m.y,c=m=>({w:e.get(m.name).offsetWidth,h:e.get(m.name).offsetHeight}),l=(m,g,_)=>{this.positions.set(m.name,{x:g,y:_});const y=e.get(m.name);y.style.left=`${g}px`,y.style.top=`${_}px`},h=m=>{const g=this.classes.filter(w=>w.pkg===m&&e.has(w.name)&&this.positions.has(w.name)).map(w=>({...this.positions.get(w.name),...c(w)}));if(g.length===0)return;const _=Math.min(...g.map(w=>w.x))-16,y=Math.min(...g.map(w=>w.y))-40;return{x:_,y,w:Math.max(...g.map(w=>w.x+w.w))+16-_,h:Math.max(...g.map(w=>w.y+w.h))+16-y}},u=this.diagramPackages().filter(m=>this.classes.some(g=>g.pkg===m&&e.has(g.name)));for(const m of u){const g=this.classes.filter(j=>j.pkg===m&&e.has(j.name)&&!this.positions.has(j.name));if(g.length===0)continue;const _=u.filter(j=>j!==m).map(h).filter(j=>!!j),y=h(m);if(y){for(const j of g){const{w:M,h:A}=c(j),R=this.classes.filter(F=>F.pkg===m&&this.positions.has(F.name)&&e.has(F.name)).map(F=>({...this.positions.get(F.name),...c(F)}));let C;for(let F=y.y+40;!C&&Fr(G,he,n))&&_.every(he=>r(z,he,24))){C={x:W,y:F};break}}C??(C={x:y.x+16,y:y.y+y.h+n}),l(j,C.x,C.y)}continue}const w=[];for(const j of g)(w[f=s.get(j.name)]??(w[f]=[])).push(j);const $=new Map;let p=0,v=0;for(const j of w){if(!j)continue;let M=0,A=0;for(const R of j){const{w:C,h:F}=c(R);$.set(R.name,{x:M,y:p}),M+=C+n*3,A=Math.max(A,F)}v=Math.max(v,M-n*3),p+=A+n*1.5}const x=p-n*1.5,L=v+32,S=x+56;let k;for(let j=4;!k&&j<2e4;j+=20)for(let M=16;M===16||M+L<=o;M+=20)if(_.every(A=>r({x:M,y:j,w:L,h:S},A,32))){k={x:M,y:j};break}k??(k={x:16,y:4});for(const j of g)l(j,k.x+16+$.get(j.name).x,k.y+40+$.get(j.name).y)}this.savePositions()}drawLines(){const e=new Map;for(const l of this.canvas.querySelectorAll(".uml-class"))e.set(l.dataset.class,l);let t=0,s=0;for(const l of e.values())t=Math.max(t,l.offsetLeft+l.offsetWidth+40),s=Math.max(s,l.offsetTop+l.offsetHeight+40);for(const l of[this.lines,this.frames])l.setAttribute("width",String(t)),l.setAttribute("height",String(s));this.frames.innerHTML=this.packageFrames(e);const i=[` + + + `],n=Pt(this.classes,this.project.uml),o=Ot(this.classes),r=new Map,c=(l,h)=>{const u=[l,h].sort().join("|"),f=r.get(u)??0;return r.set(u,f+1),f*16};for(const l of o){const h=e.get(l.from),u=e.get(l.to);h&&u&&h!==u&&i.push(this.generalizationSVG(l,h,u,c(l.from,l.to)))}for(const l of this.shownAssociations(n)){const h=e.get(l.from),u=e.get(l.to);h&&u&&h!==u&&i.push(this.associationSVG(l,h,u,c(l.from,l.to)))}for(const l of this.dependencies()){const h=e.get(l.from),u=e.get(l.to);h&&u&&h!==u&&i.push(this.dependencySVG(l,h,u,c(l.from,l.to)))}i.push(this.noteLinksSVG(e)),this.lines.innerHTML=i.join(""),this.renderInspector()}diagramPackages(){return[...new Set(ce(this.project).map(X))]}packageFrames(e){const t=[];for(const s of this.diagramPackages()){if(!s)continue;const i=this.classes.filter(u=>u.pkg===s).map(u=>e.get(u.name)).filter(u=>!!u);if(i.length===0)continue;const n=Math.min(...i.map(u=>u.offsetLeft))-16,o=Math.min(...i.map(u=>u.offsetTop))-16,r=Math.max(...i.map(u=>u.offsetLeft+u.offsetWidth))+16,c=Math.max(...i.map(u=>u.offsetTop+u.offsetHeight))+16,l=Math.max(70,s.length*7.6+20),h=this.currentPackage!==void 0&&X(this.currentPackage)===s?" current":"";t.push(` + + + ${b(s)} + `)}return t.join("")}segment(e,t,s){const i=_=>({x:_.offsetLeft,y:_.offsetTop,w:_.offsetWidth,h:_.offsetHeight}),n=i(e),o=i(t),r={x:n.x+n.w/2,y:n.y+n.h/2},c={x:o.x+o.w/2,y:o.y+o.h/2},l=Math.hypot(c.x-r.x,c.y-r.y)||1,h=-(c.y-r.y)/l*s,u=(c.x-r.x)/l*s,f=ze(n,{x:r.x+h,y:r.y+u},{x:c.x+h,y:c.y+u}),m=ze(o,{x:c.x+h,y:c.y+u},{x:r.x+h,y:r.y+u}),g=Math.hypot(m.x-f.x,m.y-f.y)||1;return{from:f,to:m,length:g,u:{x:(m.x-f.x)/g,y:(m.y-f.y)/g},n:{x:-(m.y-f.y)/g,y:(m.x-f.x)/g}}}hitLine(e,t,s,i){return`${b(i)}`}dependencies(){return _i(this.classes,e=>{var t;return(t=this.project.files.find(s=>s.path===e.path))==null?void 0:t.text})}findDependency(e){return this.dependencies().find(t=>`dep:${t.from}:${t.to}`===e)}dependencySVG(e,t,s,i){const{from:n,to:o,n:r}=this.segment(t,s,i),c=`dep:${e.from}:${e.to}`,l=this.relSelection===c?" selected":"",h={x:(n.x+o.x)/2+r.x*12,y:(n.y+o.y)/2+r.y*12},u=Math.abs(r.x)<.35?"middle":r.x>0?"start":"end",f=d(`web_visuobject_dep_${e.kind}_text`,e.from,e.to,e.methods.join(", "));return` + + «${e.kind}» + ${this.hitLine(c,n,o,f)} + `}generalizationSVG(e,t,s,i){const{from:n,to:o,u:r}=this.segment(t,s,i),c={x:o.x-r.x*12,y:o.y-r.y*12},l=`gen:${e.kind}:${e.from}:${e.to}`,h=this.relSelection===l?" selected":"",u=d(e.kind==="implements"?"web_visuobject_rel_implements_text":"web_visuobject_rel_extends_text",e.from,e.to);return` + + ${this.hitLine(l,n,o,u)} + `}shownAssociations(e){const t=new Map;for(const s of e){const i=[s.from,s.to].sort().join("|");t.set(i,[...t.get(i)??[],s])}return[...t.values()].map(s=>{const i=l=>(l.name?2:0)+(l.kind!=="association"||l.navTo!=="navigable"||l.navFrom!==(l.back?"navigable":"unspecified")?1:0),n=[...s].sort((l,h)=>i(h)-i(l))[0],o=l=>s.filter(h=>h.from===l).length+s.filter(h=>h.back&&h.to===l).length,r=o(n.from)>1||o(n.to)>1,c=s.some(l=>l.from===n.to);return{...n,navFrom:c&&n.navFrom==="unspecified"?"navigable":n.navFrom,several:r}})}associationSVG(e,t,s,i){const{from:n,to:o,length:r,u:c,n:l}=this.segment(t,s,i),h=`assoc:${e.key}`,u=this.relSelection===h?" selected":"",f=e.kind!=="association",m=f?{x:n.x+c.x*20,y:n.y+c.y*20}:n;let g=``;const _=(p,v)=>{const x={x:p.x+v.x*12,y:p.y+v.y*12},L={x:(v.x+l.x)*5,y:(v.y+l.y)*5},S={x:(v.x-l.x)*5,y:(v.y-l.y)*5};return``};if(e.navTo==="non-navigable"&&(g+=_(o,{x:-c.x,y:-c.y})),e.navFrom==="non-navigable"&&(g+=_(m,c)),f){const p=(v,x)=>`${n.x+c.x*v+l.x*x},${n.y+c.y*v+l.y*x}`;g+=``}const y=(p,v,x,L,S,k)=>{const j=Math.abs(l.x)<.35,M=j?{x:p.x+v.x*8,y:p.y+v.y*8}:{x:p.x+v.x*x,y:p.y+v.y*x},A=(F,W,G)=>{const z=!W;if(z&&(!u||G==="role"))return"";const he=M.x+l.x*F,As=M.y+l.y*F,qs=j?v.x>0?"start":"end":l.x*F>0?"start":"end",Fs=z?d(G==="role"?"web_visuobject_rel_role":"web_visuobject_end_mult_ph"):W;return`${b(Fs)}`},R={x:p.x+v.x*16,y:p.y+v.y*16};return`${b(d("web_visuobject_end_tip"))}`+A(12,S,"mult")+A(-12,k,"role")},w=Math.min(30,r/3);if(g+=y(o,{x:-c.x,y:-c.y},w,"b",e.several?void 0:e.multiplicity),g+=y(n,c,f?Math.min(42,r/3):w,"a",e.several?void 0:e.sourceMultiplicity),e.name){const p=e.reading==="backward"?{x:-c.x,y:-c.y}:c,v=e.reading?Math.abs(p.x)>=Math.abs(p.y)?p.x>0?" ▶":"◀ ":p.y>0?" ▼":" ▲":"",x=v==="◀ "?`◀ ${e.name}`:`${e.name}${v}`,L=this.freeMiddle(n,o,[e.from,e.to]),S={x:L.x+l.x*14,y:L.y+l.y*14},k=Math.abs(l.x)<.35?"middle":l.x>0?"start":"end";g+=`${b(x)}`}const $=d(`web_visuobject_rel_${e.kind}`)+`: ${e.from} – ${e.to}`;return`${g}${this.hitLine(h,n,o,$)}`}freeMiddle(e,t,s){const i=[...this.canvas.querySelectorAll(".uml-class")].filter(h=>!s.includes(h.dataset.class)).map(h=>({x:h.offsetLeft-8,y:h.offsetTop-8,w:h.offsetWidth+16,h:h.offsetHeight+16})),n=Math.hypot(t.x-e.x,t.y-e.y);if(n>120){const h=48/n;[e,t]=[{x:e.x+(t.x-e.x)*h,y:e.y+(t.y-e.y)*h},{x:t.x-(t.x-e.x)*h,y:t.y-(t.y-e.y)*h}]}const o=40;let r={start:0,length:0},c=-1;for(let h=0;h<=o;h++){const u=e.x+(t.x-e.x)*h/o,f=e.y+(t.y-e.y)*h/o,m=i.some(g=>u>=g.x&&u<=g.x+g.w&&f>=g.y&&f<=g.y+g.h);if(!m&&c<0&&(c=h),(m||h===o)&&c>=0){const g=m?h-1:h;g-c>r.length&&(r={start:c,length:g-c}),c=-1}}const l=(r.start+r.length/2)/o;return{x:e.x+(t.x-e.x)*l,y:e.y+(t.y-e.y)*l}}findRelation(e){return e.startsWith("assoc:")?Pt(this.classes,this.project.uml).find(t=>{var s;return`assoc:${t.key}`===e||`assoc:${(s=t.back)==null?void 0:s.key}`===e}):Ot(this.classes).find(t=>`gen:${t.kind}:${t.from}:${t.to}`===e)}selectRelation(e){this.noteSelection=void 0,this.relSelection=e,this.selection=void 0,this.treeSelection=void 0,this.message(""),this.render(),this.renderTree(),this.canvas.focus({preventScroll:!0})}editClass(e,t,s){for(const i of e.files){const n=oe(i.text).find(o=>o.name===t);if(n)return $e(e,i.path,this.sorted(s(i.text,n),t))}return e}sectionLabels(){return{fields:d("web_visuobject_section_fields"),refs:d("web_visuobject_section_refs"),ctors:d("web_visuobject_section_ctors"),methods:d("web_visuobject_section_methods")}}sorted(e,t){return Gi(e,t,new Set(this.classes.map(s=>s.name)),this.sectionLabels())}sectioned(e,t){const s=oe(e).find(i=>i.name===t);return s?pt(e,s,new Set([...this.classes.map(i=>i.name),t]),this.sectionLabels()):e}fieldOf(e,t){return e.members.find(s=>s.kind==="field"&&s.name===t)}importFor(e,t,s){const i=this.findClass(t),n=this.findClass(s);return!i||!n||i.pkg===n.pkg||!n.pkg?e:this.editClass(e,t,o=>tt(o,`${n.pkg}.${n.name}`))}addAssociationField(e,t,s,i,n){const o=Ct(e).find(u=>u.name===t),r=n&&pe.test(n)&&!o.members.some(u=>u.name===n)?n:xi(o,s,i),{type:c,init:l}=It(s,i);let h=this.editClass(e,t,(u,f)=>Ee(u,f,`- ${r}: ${c}`));return l&&(h=this.editClass(h,t,(u,f)=>{const m=this.fieldOf(f,r);return m?Lt(u,m,c,l):u}),h=this.editClass(h,t,u=>tt(u,"java.util.ArrayList"))),{project:this.importFor(h,t,s),field:r}}setUml(e,t,s){return{...e,uml:ki(e.uml??{},t,s)}}createRelation(e,t,s){const i=this.findClass(e),n=this.findClass(t);if(!i||!n)return;let o=this.project,r;if(s==="extends"&&i.kind==="class")o=this.importFor(this.editClass(o,e,(c,l)=>Ze(c,l,t)),e,t),r=`gen:extends:${e}:${t}`;else if(s==="extends"||s==="implements")o=this.importFor(this.editClass(o,e,(c,l)=>jt(c,l,t)),e,t),r=`gen:${i.kind==="interface"?"extends":"implements"}:${e}:${t}`;else{const c=this.addAssociationField(o,e,t,!1),l=V(e,c.field);o=s==="association"?c.project:s==="link"?this.setUml(c.project,l,{targetEnd:"unspecified"}):this.setUml(c.project,l,{kind:s}),r=`assoc:${V(e,c.field)}`}this.relSelection=r,this.selection=void 0,this.message(""),this.setProject(o,i.path),this.canvas.focus({preventScroll:!0})}deleteRelation(e){var i;const t=this.findRelation(e);if(!t)return;let s=this.project;if("key"in t){const n=(r,c,l)=>this.editClass(r,c,(h,u)=>{const f=this.fieldOf(u,l);return f?xe(h,f):h});s=n(s,t.from,t.role),t.back&&(s=n(s,t.to,t.back.field.name));const o={...s.uml??{}};delete o[t.key],t.back&&delete o[t.back.key],s={...s,uml:o}}else t.kind==="extends"&&((i=this.findClass(t.from))==null?void 0:i.kind)==="class"?s=this.editClass(s,t.from,(n,o)=>Ze(n,o,void 0)):s=this.editClass(s,t.from,(n,o)=>St(n,o,t.to));this.relSelection=void 0,this.setProject(s)}changeAssoc(e,t,s){let i=this.project,n=e.key;const o=(l,h,u)=>{if(!pe.test(u))return this.message(d("web_visuobject_bad_name",u)),!1;const f=this.findClass(l);return f&&f.members.some(m=>m.name===u)?(this.message(d("web_visuobject_bad_name",u)),!1):(i=this.editClass(i,l,(m,g)=>{const _=this.fieldOf(g,h);return _?Qe(m,g,_,`${_.visibility} ${u}: ${_.type}`):m}),i={...i,uml:ke(i.uml??{},V(l,h),V(l,u))},!0)},r=(l,h,u,f,m)=>{const g=Me(f);i=this.editClass(i,l,(y,w)=>{const $=this.fieldOf(w,h);if(!$||Me(e.key===m?e.multiplicity:e.sourceMultiplicity??"1")===g)return y;const{type:v,init:x}=It(u,g);return Lt(y,$,v,x)}),g&&(i=this.editClass(i,l,y=>tt(y,"java.util.ArrayList")));const _=g?"0..*":"1";i=this.setUml(i,m,{multiplicity:f===_?void 0:f})};switch(t){case"kind":i=this.setUml(i,n,{kind:s});break;case"name":i=this.setUml(i,n,{name:s.trim()||void 0});break;case"reading":i=this.setUml(i,n,{reading:e.reading==="backward"?void 0:"backward"});break;case"targetEnd":i=this.setUml(i,n,{targetEnd:s,navigable:void 0});break;case"sourceEnd":{if(s==="navigable"&&!e.back){const l=this.addAssociationField(i,e.to,e.from,Me(e.sourceMultiplicity??"1"),e.sourceRole);i=this.setUml(l.project,n,{sourceEnd:void 0,sourceRole:void 0,sourceMultiplicity:void 0}),e.sourceMultiplicity&&e.sourceMultiplicity!==(Me(e.sourceMultiplicity)?"0..*":"1")&&(i=this.setUml(i,V(e.to,l.field),{multiplicity:e.sourceMultiplicity}))}else if(s!=="navigable"){if(e.back){const l=e.back;i=this.editClass(i,e.to,(u,f)=>{const m=this.fieldOf(f,l.field.name);return m?xe(u,m):u});const h={...i.uml??{}};delete h[l.key],i={...i,uml:h},i=this.setUml(i,n,{sourceRole:e.sourceRole,sourceMultiplicity:e.sourceMultiplicity})}i=this.setUml(i,n,{sourceEnd:s})}break}case"role":if(s===e.role||!o(e.from,e.role,s))return;n=V(e.from,s);break;case"multiplicity":if(!s.trim())return;r(e.from,e.role,e.to,s.trim(),n);break;case"sourceRole":if(e.back){if(s===e.back.field.name||!o(e.to,e.back.field.name,s))return}else i=this.setUml(i,n,{sourceRole:s.trim()||void 0});break;case"sourceMultiplicity":if(!s.trim())return;e.back?r(e.to,e.back.field.name,e.from,s.trim(),e.back.key):i=this.setUml(i,n,{sourceMultiplicity:s.trim()});break}this.relSelection=`assoc:${n}`,this.message(""),this.setProject(i);const c=this.findRelation(this.relSelection);c&&"key"in c&&`assoc:${c.key}`!==this.relSelection&&(this.relSelection=`assoc:${c.key}`,this.render())}openEnd(e,t,s,i){this.closeEnd();const n=this.findRelation(e);if(!n||!("key"in n))return;const o=t==="a",r=o?{role:"sourceRole",mult:"sourceMultiplicity",nav:"sourceEnd"}:{role:"role",mult:"multiplicity",nav:"targetEnd"},c=(o?n.sourceRole:n.role)??"",l=(o?n.sourceMultiplicity:n.multiplicity)??"",h=o?n.navFrom:n.navTo,u=o?n.from:n.to,f=document.createElement("div");f.className="vo-endpop",f.setAttribute("role","dialog"),f.setAttribute("aria-label",d(o?"web_visuobject_rel_end_a":"web_visuobject_rel_end_b",u)),f.innerHTML=`

    ${b(d(o?"web_visuobject_rel_end_a":"web_visuobject_rel_end_b",u))}

    + +
    ${b(d("web_visuobject_rel_multiplicity"))}${Nt.map(p=>``).join("")}
    +
    ${b(d("web_visuobject_rel_navigable"))}${["navigable","non-navigable","unspecified"].map(p=>``).join("")}
    `;const m=this.shell.querySelector(".vo-stage"),g=m.getBoundingClientRect();m.append(f);const _=Math.min(Math.max(8,s.clientX-g.left+8),g.width-f.offsetWidth-8),y=Math.min(Math.max(8,s.clientY-g.top+8),g.height-f.offsetHeight-8);f.style.left=`${Math.max(8,_)}px`,f.style.top=`${Math.max(8,y)}px`;const w=(p,v)=>{var S,k;const x=this.findRelation(e);x&&"key"in x&&this.changeAssoc(x,p,v);const L=(k=(S=document.activeElement)==null?void 0:S.dataset)==null?void 0:k.endField;this.relSelection&&this.reopenEnd(this.relSelection,t,f,L)};for(const p of f.querySelectorAll("[data-end-field]"))p.addEventListener("change",()=>w(p.dataset.endField==="role"?r.role:r.mult,p.value.trim())),p.addEventListener("keydown",v=>{v.stopPropagation(),v.key==="Enter"&&p.blur(),v.key==="Escape"&&this.closeEnd()});for(const p of f.querySelectorAll("[data-mult]"))p.addEventListener("click",()=>w(r.mult,p.dataset.mult));for(const p of f.querySelectorAll("[data-nav]"))p.addEventListener("click",()=>w(r.nav,p.dataset.nav));f.addEventListener("pointerdown",p=>p.stopPropagation()),f.addEventListener("click",p=>p.stopPropagation()),this.endPop=f;const $=f.querySelector(`[data-end-field="${i==="mult"?"mult":"role"}"]`);$==null||$.focus(),$==null||$.select()}reopenEnd(e,t,s,i){const n=this.shell.querySelector(".vo-stage").getBoundingClientRect(),o={clientX:n.left+parseFloat(s.style.left)-8,clientY:n.top+parseFloat(s.style.top)-8};this.openEnd(e,t,o,i)}closeEnd(){var e;(e=this.endPop)==null||e.remove(),this.endPop=void 0}renderInspector(){var r,c,l;if(this.diagramMode==="object")return this.objectDiagram.renderInspector();if(this.diagramMode==="sequence")return this.renderSequenceInspector();const e=this.findNote(this.noteSelection);if(e)return this.renderNoteInspector(e);const t=(r=this.relSelection)!=null&&r.startsWith("dep:")?this.findDependency(this.relSelection):void 0;if(t)return this.renderDependency(t);const s=this.relSelection?this.findRelation(this.relSelection):void 0;this.endPop&&(!s||!this.endPop.isConnected)&&this.closeEnd();const i=!s&&this.selection?this.findClass(this.selection.cls):void 0;if(i)return this.renderClassInspector(i);if(!s){delete this.inspector.dataset.rel,this.inspector.innerHTML=`

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

    `;return}const n=this.inspector.contains(document.activeElement)?document.activeElement.dataset.field??document.activeElement.dataset.inspector:void 0;this.inspector.dataset.rel=this.relSelection;const o=``;if("key"in s){const h=($,p,v)=>``,u=["association","aggregation","composition"].map($=>h($,d(`web_visuobject_rel_${$}`).replace(/\s*\(.*\)$/,""),s.kind)).join(""),f=$=>["navigable","non-navigable","unspecified"].map(p=>h(p,d(`web_visuobject_rel_nav_${p}`),$)).join(""),[m,g]=s.reading==="backward"?[s.to,s.from]:[s.from,s.to],_=s.name?`

    ${b(d("web_visuobject_rel_reading"))}: ${b(m)} ▶ ${b(g)}

    `:`

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

    `,y=`${Nt.map($=>``,w=($,p,v,x,L,S,k,j)=>` +
    + ${b($)} + + + + ${b(S)} +
    `;this.inspector.innerHTML=` +
    + + + ${_} + ${o} +
    +
    + ${w(d("web_visuobject_rel_end_a",s.from),"sourceRole",s.sourceRole,"sourceMultiplicity",s.sourceMultiplicity,s.back?d("web_visuobject_rel_role_field",s.to,s.back.field.name):d("web_visuobject_rel_role_only_uml"),"sourceEnd",s.navFrom)} + ${w(d("web_visuobject_rel_end_b",s.to),"role",s.role,"multiplicity",s.multiplicity,d("web_visuobject_rel_role_field",s.from,s.role),"targetEnd",s.navTo)} +
    + ${y}`}else{const h=d(s.kind==="implements"?"web_visuobject_rel_implements_text":"web_visuobject_rel_extends_text",s.from,s.to);this.inspector.innerHTML=`

    ${b(d(s.kind==="implements"?"web_visuobject_rel_implements":"web_visuobject_rel_extends"))}

    ${b(h)}

    ${o}
    `}for(const h of this.inspector.querySelectorAll("[data-field]"))h.addEventListener("change",()=>{const u=this.relSelection&&this.findRelation(this.relSelection);u&&"key"in u&&this.changeAssoc(u,h.dataset.field,h.value)}),h instanceof HTMLInputElement&&h.addEventListener("keydown",u=>u.key==="Enter"&&h.blur());this.inspector.querySelector("[data-inspector=delete]").addEventListener("click",()=>this.deleteRelation(this.relSelection)),n&&((c=this.inspector.querySelector(`[data-field="${n}"], [data-inspector="${n}"]`))==null||c.focus({preventScroll:!0})),(l=this.inspector.querySelector("[data-inspector=flip]"))==null||l.addEventListener("click",()=>{const h=this.relSelection&&this.findRelation(this.relSelection);h&&"key"in h&&this.changeAssoc(h,"reading","")})}renderClassInspector(e){var w,$;const t=document.activeElement,s=this.inspector.contains(t)&&t!=null&&t.dataset.field?`${t.dataset.row??""}|${t.dataset.field}`:void 0,i=((w=this.project.files.find(p=>p.path===e.path))==null?void 0:w.text)??"",n=ai(i,e),o=e.kind==="class",r=(p,v,x)=>``,c=(p,v=!0)=>["+","-","#","~"].filter(x=>v||x!=="~").map(x=>r(x,`${x} ${{"+":"public","-":"private","#":"protected","~":"package"}[x]}`,x===p)).join(""),l=e.members.map((p,v)=>({m:p,i:v})).filter(p=>p.m.kind==="field"),h=e.members.map((p,v)=>({m:p,i:v})).filter(p=>p.m.kind!=="field"),u=(p,v)=>``,f=`${["int","double","boolean","char","long","String",...this.classes.map(p=>p.name),...this.classes.map(p=>`ArrayList<${p.name}>`)].map(p=>``;let m="";if(this.classTab==="class"){const p=this.classes.filter(S=>S.kind==="class"&&S.name!==e.name),v=this.classes.filter(S=>S.kind==="interface"&&S.name!==e.name),x=D(e.path),L=ue(this.project).flatMap(S=>{const k=ce(this.project,S);return k.includes(re(S,""))?k:[...k,re(S,"")]});m=` +
    + + + + ${o?``:""} +
    +
    + ${o?``:""} + ${v.length?`
    ${b(d(o?"web_visuobject_new_interfaces":"web_visuobject_new_extends_interfaces"))}${v.map(S=>``).join("")}
    `:""} +
    + +
    ${o?``:""}
    `}else if(this.classTab==="fields"){const p=l.map(({m:v,i:x})=>{const L=Ms(i,v);return` + + + + + + + + `}).join("");m=`${p||``}
    ${b(d("web_visuobject_insp_visibility"))}${b(d("web_visuobject_new_name"))}${b(d("web_visuobject_insp_type"))}staticfinal${b(d("web_visuobject_insp_init"))}
    ${b(d("web_visuobject_insp_no_fields"))}
    +
    `}else{const p=o,v=h.map(({m:x,i:L})=>{const S=x.kind==="constructor";return` + + + + + + + + `}).join("");m=`${v||``}
    ${b(d("web_visuobject_insp_visibility"))}${b(d("web_visuobject_new_name"))}${b(d("web_visuobject_insp_params"))}${b(d("web_visuobject_insp_return"))}staticabstract
    ${b(d("web_visuobject_insp_no_methods"))}
    +
    + + ${o?`${b(d("web_visuobject_insp_generate"))} + + + `:""} +
    `}this.inspector.dataset.rel=`class:${e.name}`,this.inspector.innerHTML=` +
    +

    ${b(d(o?"web_visuobject_new_class":"web_visuobject_new_interface"))} ${b(e.name)}

    +
    ${u("class",d(o?"web_visuobject_new_class":"web_visuobject_new_interface"))}${u("fields",`${d("web_visuobject_insp_fields")} (${l.length})`)}${u("methods",`${d("web_visuobject_insp_methods")} (${h.length})`)}
    +
    + ${m}${f}`;const g=(p,v)=>{this.message("");let x=this.editClass(this.project,e.name,p);v&&(x=v(x)),this.setProject(x,e.path)},_=(p,v)=>p.members[Number(v.dataset.row)];for(const p of this.inspector.querySelectorAll("[data-class-tab]"))p.addEventListener("click",()=>{this.classTab=p.dataset.classTab,this.renderInspector()});for(const p of this.inspector.querySelectorAll("[data-field]"))p.addEventListener("change",()=>{var S;const v=p.dataset.field,x=p instanceof HTMLInputElement&&p.checked,L=p.value.trim();if(v==="name")L&&L!==e.name&&this.renameClassTo(e,L);else if(v==="package"){const k=le(p.value,Q(e.path));if(k===e.path)return;if(this.project.files.some(j=>j.path===k))return this.message(d("web_visuobject_new_exists",Q(k)));this.openTabs=this.openTabs.map(j=>j===e.path?k:j),this.currentPackage=p.value,this.setProject(Oe(this.project,e.path,k),k)}else if(v==="visibility")g((k,j)=>ri(k,j,p.value==="public"));else if(v==="abstract")g((k,j)=>{const M=x?Ne(k,j,!1):k;return Et(M,oe(M).find(A=>A.name===j.name)??j,x)});else if(v==="final")g((k,j)=>Ne(k,j,x));else if(v==="superclass"){const k=p.value||void 0;g((j,M)=>Ze(j,M,k),j=>k?this.importFor(j,e.name,k):j)}else if(v==="iface"){const k=p.value;g((j,M)=>x?jt(j,M,k):St(j,M,k),j=>x?this.importFor(j,e.name,k):j)}else if(v==="doc")g((k,j)=>pn(k,j,p.value));else if(v.startsWith("f-")){if(v==="f-name"&&!pe.test(L)||v==="f-type"&&!L)return this.message(d("web_visuobject_bad_name",L));const k=v==="f-vis"?{visibility:p.value}:v==="f-name"?{name:L}:v==="f-type"?{type:L}:v==="f-static"?{isStatic:x}:v==="f-final"?{isFinal:x}:{init:p.value},j=(S=e.members[Number(p.dataset.row)])==null?void 0:S.name;g((M,A)=>rn(M,_(A,p),k),M=>{var A;return v==="f-name"&&j&&((A=M.uml)!=null&&A[V(e.name,j)])?{...M,uml:ke(M.uml,V(e.name,j),V(e.name,L))}:M})}else if(v.startsWith("m-")){let k;if(v==="m-params"){const j=ln(p.value);if(!j)return this.message(d("web_visuobject_insp_bad_params",p.value));k={params:j}}else if(v==="m-name"){if(!pe.test(L))return this.message(d("web_visuobject_bad_name",L));k={name:L}}else k=v==="m-vis"?{visibility:p.value}:v==="m-type"?{type:L||"void"}:v==="m-static"?{isStatic:x}:{isAbstract:x};g((j,M)=>{const A=dn(j,M,_(M,p),k);if(v==="m-abstract"&&x&&!M.isAbstract){const R=oe(A).find(C=>C.name===M.name);return R?Et(Ne(A,R,!1),oe(Ne(A,R,!1)).find(C=>C.name===M.name),!0):A}return A})}}),p instanceof HTMLInputElement&&p.type==="text"&&p.addEventListener("keydown",v=>v.key==="Enter"&&p.blur());const y=(p,v)=>{for(const x of this.inspector.querySelectorAll(`[data-inspector="${p}"]`))x.addEventListener("click",()=>v(x))};if(y("delete-class",()=>this.deleteClassFromProject(e)),y("sections",()=>g((p,v)=>pt(p,v,new Set(this.classes.map(x=>x.name)),this.sectionLabels()))),y("delete-member",p=>g((v,x)=>xe(v,_(x,p)))),y("add-field",()=>g((p,v)=>Ee(p,v,`- ${this.freeMember(e,"attribut")}: int`))),y("add-method",()=>g((p,v)=>Ee(p,v,`+ ${this.freeMember(e,"methode")}(): void`))),y("gen-constructor",()=>g((p,v)=>fn(p,v))),y("gen-accessors",()=>g((p,v)=>mn(p,v))),y("gen-tostring",()=>g((p,v)=>bn(p,v))),s){const[p,v]=s.split("|");($=this.inspector.querySelector(p?`[data-row="${p}"][data-field="${v}"]`:`[data-field="${v}"]`))==null||$.focus({preventScroll:!0})}}freeMember(e,t){let s=t;for(let i=2;e.members.some(n=>n.name===s);i++)s=t+i;return s}renderDependency(e){this.closeEnd(),this.inspector.dataset.rel=this.relSelection,this.inspector.innerHTML=`
    +

    ${b(d("web_visuobject_dep_title",e.kind))}

    +

    ${b(d(`web_visuobject_dep_${e.kind}_text`,e.from,e.to,e.methods.join(", ")))}

    +
    +

    ${b(d("web_visuobject_dep_hint",e.from,e.to))}

    +
    `,this.inspector.querySelector("[data-inspector=to-assoc]").addEventListener("click",()=>{var s;const t=this.addAssociationField(this.project,e.from,e.to,!1);this.relSelection=`assoc:${V(e.from,t.field)}`,this.setProject(t.project,(s=this.findClass(e.from))==null?void 0:s.path)})}setTool(e){this.tool=e,this.pendingFrom=void 0;for(const t of this.canvas.querySelectorAll(".uml-class.source"))t.classList.remove("source");for(const t of this.shell.querySelectorAll(".vo-tool"))t.setAttribute("aria-pressed",String(t.dataset.tool===e));this.canvas.dataset.tool=e,this.message(e==="select"?"":d(`web_visuobject_tool_${e}_tip`),!0)}onToolDown(e,t){if(e.button!==0)return;if(t!=="class"&&t!=="interface")return this.setTool(this.tool===t?"select":t);e.preventDefault();const s={x:e.clientX,y:e.clientY};let i;const n=r=>{!i&&Math.hypot(r.clientX-s.x,r.clientY-s.y)<6||(i||(i=document.createElement("div"),i.className=`vo-tool-ghost${t==="interface"?" interface":""}`,i.innerHTML=`${t==="interface"?"«interface»":""}${b(d(t==="class"?"web_visuobject_new_class_name":"web_visuobject_new_interface_name"))}`,document.body.append(i)),i.style.left=`${r.clientX}px`,i.style.top=`${r.clientY}px`)},o=r=>{if(window.removeEventListener("pointermove",n),window.removeEventListener("pointerup",o),!i)return this.setTool(this.tool===t?"select":t);i.remove();const c=this.canvas.getBoundingClientRect();r.clientXc.right||r.clientYc.bottom||(this.setTool("select"),this.newClass(t,{x:r.clientX-c.left+this.canvas.scrollLeft-60,y:r.clientY-c.top+this.canvas.scrollTop-14}))};window.addEventListener("pointermove",n),window.addEventListener("pointerup",o)}useTool(e){e.preventDefault();const t=this.tool,s=this.canvas.getBoundingClientRect(),i={x:e.clientX-s.left+this.canvas.scrollLeft,y:e.clientY-s.top+this.canvas.scrollTop};if(t==="class"||t==="interface"){this.setTool("select"),this.newClass(t,{x:i.x-60,y:i.y-14});return}if(t==="note"){this.setTool("select"),this.addNote({x:i.x-20,y:i.y-14});return}const n=e.target.closest(".uml-class");if(!n){this.pendingFrom&&this.setTool(t);return}const o=n.dataset.class;if(this.pendingFrom&&this.pendingFrom!==o){const r=this.pendingFrom;this.connectWith(r,o,t);return}this.startConnect(e,o,t)}connectWith(e,t,s){const i=this.findClass(e),n=this.findClass(t);if(this.setTool("select"),!(!i||!n)){if(!ps(i,n).includes(s))return this.message(d(`web_visuobject_tool_not_${s}`,e,t));this.createRelation(e,t,s)}}startConnect(e,t,s){e.preventDefault();const i=document.createElementNS("http://www.w3.org/2000/svg","line");i.setAttribute("class","vo-rel ghost"),this.lines.append(i);const n=this.canvas.querySelector(`.uml-class[data-class="${CSS.escape(t)}"]`),o=u=>{const f=this.canvas.getBoundingClientRect();return{x:u.clientX-f.left+this.canvas.scrollLeft,y:u.clientY-f.top+this.canvas.scrollTop}},r={x:n.offsetLeft+n.offsetWidth,y:n.offsetTop+n.offsetHeight/2},c=u=>{var m;const f=(m=document.elementFromPoint(u.clientX,u.clientY))==null?void 0:m.closest(".uml-class");return f&&f.dataset.class!==t?f:void 0},l=u=>{var m;const f=o(u);i.setAttribute("x1",String(r.x)),i.setAttribute("y1",String(r.y)),i.setAttribute("x2",String(f.x)),i.setAttribute("y2",String(f.y));for(const g of this.canvas.querySelectorAll(".uml-class.drop"))g.classList.remove("drop");(m=c(u))==null||m.classList.add("drop")},h=u=>{var m;window.removeEventListener("pointermove",l),window.removeEventListener("pointerup",h),i.remove();const f=c(u);f==null||f.classList.remove("drop"),f&&s?this.connectWith(t,f.dataset.class,s):f?this.showRelationMenu(t,f.dataset.class,o(u)):s&&(this.pendingFrom=t,(m=this.canvas.querySelector(`.uml-class[data-class="${CSS.escape(t)}"]`))==null||m.classList.add("source"),this.message(d("web_visuobject_tool_pick_second",t),!0))};l(e),window.addEventListener("pointermove",l),window.addEventListener("pointerup",h)}showRelationMenu(e,t,s){var u;const i=this.findClass(e),n=this.findClass(t);if(!i||!n)return;const o=ps(i,n).map(f=>[f,f==="association"?"web_visuobject_rel_directed":`web_visuobject_rel_${f}`]);if(o.length===0)return this.message(d("web_visuobject_rel_impossible",e,t));const r=document.createElement("div");r.className="vo-relmenu",r.setAttribute("role","menu"),r.style.left=`${s.x}px`,r.style.top=`${s.y}px`,r.innerHTML=`

    ${b(d("web_visuobject_rel_menu",e,t))}

    `+o.map(([f,m])=>``).join(""),this.canvas.append(r);const c=()=>{r.remove(),document.removeEventListener("pointerdown",l,!0),document.removeEventListener("keydown",h,!0)},l=f=>{r.contains(f.target)||c()},h=f=>{f.key==="Escape"&&(f.stopPropagation(),c())};r.addEventListener("click",f=>{var g;const m=(g=f.target.closest("[data-kind]"))==null?void 0:g.dataset.kind;m&&(c(),this.createRelation(e,t,m))}),document.addEventListener("pointerdown",l,!0),document.addEventListener("keydown",h,!0),(u=r.querySelector("button"))==null||u.focus()}}const Mn=["select","class","interface","note","link","association","aggregation","composition","extends","implements"];function ps(a,e){const t=[];return a.kind==="class"&&t.push("link","association","aggregation","composition"),a.kind===e.kind&&(a.kind==="class"?a.superclass!==e.name:!a.interfaces.includes(e.name))&&t.push("extends"),a.kind==="class"&&e.kind==="interface"&&!a.interfaces.includes(e.name)&&t.push("implements"),t}function Cn(a){return a==="select"?'':a==="class"||a==="interface"?``:a==="note"?'':Ts(a)}function Ts(a){const e=(s,i,n=!1)=>``;return``}function ze(a,e,t){const s=t.x-e.x,i=t.y-e.y,n=s===0?1/0:a.w/2/Math.abs(s),o=i===0?1/0:a.h/2/Math.abs(i),r=Math.min(n,o,1);return{x:Math.round(e.x+s*r),y:Math.round(e.y+i*r)}}const qn=Object.freeze(Object.defineProperty({__proto__:null,ObjectApp:En},Symbol.toStringTag,{value:"Module"}));export{Z as a,le as b,re as c,pi as d,li as e,X as f,qn as g,Je as i,vs as n,gs as o,At as p,U as r,ue as s,ys as u}; diff --git a/website/app/assets/pl-C3HmQqUD.js b/website/app/assets/pl-C3HmQqUD.js new file mode 100644 index 00000000..d2d604d6 --- /dev/null +++ b/website/app/assets/pl-C3HmQqUD.js @@ -0,0 +1,180 @@ +const e=`/* Teksty dostępne tylko w wersji webowej. Wszystko inne pochodzi z plików Localizable.strings aplikacji. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "Diagram VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Eksportuj…"; +"web_export_title" = "Zapisz jako obraz lub PDF albo wydrukuj"; +"web_export_png" = "Obraz (PNG)"; +"web_export_svg" = "Grafika wektorowa (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "Plik VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "Eksport nie powiódł się: %@"; +"web_print_hint" = "Użyj „Eksportuj… → PDF“, aby zapisać diagram i wydrukować go z pliku."; +"web_delete" = "Usuń"; +"web_language_title" = "Język interfejsu"; +"web_simulation_start" = "Uruchom symulację"; +"web_simulation_end" = "Zakończ symulację"; +"web_simulation_start_title" = "Uruchom diagram krok po kroku"; +"web_simulation_end_title" = "Zakończ symulację i wróć do edycji"; +"web_palette_hint" = "Przeciągnij do diagramu"; +"web_tabs_label" = "Diagramy"; +"web_status_modified" = "zmieniony"; +"web_inspector_title" = "Właściwości"; +"web_inspector_help_drop" = "Przeciągnij elementy z palety na kafelek: góra = przed, dół = za, na „ø“ = zastąp. Istniejące elementy można przesuwać myszą."; +"web_inspector_help_files" = "Pliki można też upuścić w oknie."; +"web_case_name" = "Nazwa przypadku"; +"web_case_name_placeholder" = "np. 1, ok, default"; +"web_copied" = "Skopiowano element."; +"web_discard_message_fmt" = "Zmiany w „%@“ zostaną utracone."; +"web_err_unreadable_fmt" = "„%@“ nie jest czytelnym plikiem VisuStruct (%@)."; +"web_saved_fmt" = "Zapisano „%@“."; +"web_saved_txt_fmt" = "Zapisano jako „%@“. Usuń rozszerzenie .txt, aby go użyć."; +"web_drop_impossible" = "Nie można tu upuścić"; +"web_sim_delay" = "Pauza na krok"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Język"; +"web_codegen_comments" = "Tekst diagramu jako komentarze"; +"web_codegen_empty_else" = "Generuj pustą gałąź else w kodzie"; +"web_copied_check" = "Skopiowano ✓"; +"web_copy_manual" = "Zaznaczono, naciśnij Ctrl+C, aby skopiować"; +"web_run_stopped_loop" = "Wykonanie zatrzymane: możliwa pętla nieskończona."; +"web_run_cancelled" = "Wykonanie anulowane."; +"web_run_error" = "Błąd podczas wykonywania."; +"web_run_dropped_fmt" = "… ukryto wcześniejsze wiersze: %d"; +"web_sim_call_arguments_fmt" = "Wywołanie nie pasuje do nagłówka %@. Sprawdź wartości w nawiasach."; +"web_sim_missing_return_fmt" = "%@ zakończył się bez zwrócenia wartości przez return."; +"web_sim_file_not_found_fmt" = "Nie ma pliku o nazwie %@."; +"web_sim_end_of_file_fmt" = "Plik %@ nie ma już więcej wierszy."; +"web_sim_null_value_fmt" = "%@ ma wartość null."; +"web_sim_written_file_fmt" = "%@ (zapisano)"; +"web_site_home" = "Strona główna"; +"web_site_imprint" = "Nota prawna"; +"web_site_privacy" = "Prywatność"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Programowanie"; +"web_live_hide" = "Ukryj programowanie"; +"web_scale_canvas" = "Rozmiar tekstu: diagram"; +"web_scale_code" = "Rozmiar tekstu: programowanie"; +"web_live_indent" = "Wcięcia"; +"web_live_indent_title" = "Popraw wcięcia kodu: cztery spacje na poziom (zaznaczone wiersze, w przeciwnym razie wszystko)"; +"web_live_show" = "Pokaż programowanie"; +"web_live_resize" = "Zmień szerokość obszaru kodu (dwuklik: resetuj)"; +"web_live_hint" = "Kod rośnie razem z diagramem. Szary = symbol zastępczy: wpisz tekst w inspektorze, a pojawi się tutaj. Kliknij wiersz, aby zaznaczyć jego element."; +"web_live_ph_selector" = "zmienna"; +"web_live_ph_code" = "Twój kod"; +"web_live_ph_end" = "koniec"; +"web_live_language" = "Język programowania"; +"web_live_java_class" = "Jako klasa"; +"web_live_java_class_hint" = "Nazwa klasy = tytuł diagramu"; +"web_live_java_main" = "Z metodą main"; +"web_settings_display" = "Wygląd"; +"web_live_swing" = "Prawdziwa Java (ze Swing)"; +"web_live_swing_hint" = "Prawdziwa Java z oknami (CheerpJ). Przy pierwszym uruchomieniu jednorazowo pobiera ok. 40 MB."; +"web_live_swing_windows" = "Okna Java"; +"web_live_swing_hide" = "Zamknij okna Java"; +"web_live_swing_loading" = "Ładowanie Javy (za pierwszym razem ok. 40 MB) …"; +"web_live_swing_compiling" = "Kompilowanie …"; +"web_live_swing_running" = "Program działa."; +"web_live_swing_compile_failed" = "Błąd kompilacji, zobacz powyżej."; +"web_live_swing_failed" = "Nie udało się załadować Javy. Sprawdź połączenie z internetem."; +"web_live_hint_edit" = "Wpisz tu kod Java, a diagram zbuduje się sam. Albo pracuj w diagramie, a kod będzie rósł razem z nim. Szary = symbol zastępczy, po prostu pisz."; +"web_live_edit_label" = "Kod Java"; +"web_parse_line_fmt" = "Wiersz %d: %@"; +"web_parse_missing" = "Tu jeszcze brakuje: %@"; +"web_parse_extra" = "Za dużo: %@"; +"web_parse_unclosed_string" = "Brakuje zamykającego %@."; +"web_parse_else_without_if" = "Ten „else” nie ma pasującego „if”."; +"web_parse_case_outside_switch" = "„case” i „default” należą do „switch”."; +"web_parse_missing_do_while" = "Po „do { … }” brakuje jeszcze „while (warunek);”."; +"web_parse_more_methods" = "Na razie liczy się tu tylko jedna metoda. Utwórz kolejne podprogramy w osobnych kartach."; +"web_parse_missing_import" = "Na samej górze brakuje %@ Bez tej linii Java nie zna klasy Scanner."; +"web_parse_missing_scanner" = "Wcześniej brakuje %@ Bez tej linii Scanner nie istnieje."; +"web_parse_unknown_type" = "Java nie zna tego typu danych. Czy chodziło ci o %@?"; +"web_editor_title" = "Diagram"; +"web_editor_show" = "Pokaż diagram"; +"web_editor_hide" = "Ukryj diagram"; +"web_keywords_title" = "Słowa kluczowe kodu"; +"web_keywords_hint" = "if, while, for zamiast nazw elementów"; +"web_palette_compact" = "Elementy zawsze kompaktowe"; +"web_palette_compact_hint" = "Symbol z małą nazwą pod spodem, w przeciwnym razie tylko przy wąskiej kolumnie"; +"web_about_version_fmt" = "Wersja %@"; +"web_about_software" = "Używane oprogramowanie"; +"web_about_software_text" = "Edytor kodu korzysta z CodeMirror i Lezer (licencja MIT). Z obsługą Swing VisuStruct wczytuje CheerpJ firmy Leaning Technologies (licencja Community) oraz javac z OpenJDK."; +"web_about_licenses" = "Teksty licencji"; +"web_live_run" = "Uruchom"; +"web_live_run_title" = "Uruchom program: wyjście i wejście pojawią się poniżej"; +"web_live_run_finished" = "Program zakończony."; +"web_live_run_stopped" = "Zatrzymano."; +"web_console" = "Konsola"; +"web_console_hide" = "Ukryj konsolę"; +"web_console_resize" = "Zmień wysokość konsoli"; +"web_diagram_tools" = "Narzędzia diagramu"; +"web_files_title" = "Pliki"; +"web_files_show" = "Pokaż pliki"; +"web_files_hide" = "Ukryj pliki"; +"web_files_resize" = "Zmień szerokość plików"; +"web_files_new_folder" = "Nowy folder"; +"web_files_switch" = "Wybierz inny folder"; +"web_files_delete" = "Usuń"; +"web_files_in_browser" = "W pamięci tej przeglądarki"; +"web_files_save_hint_fmt" = "Zapis umieszcza program w %@."; +"web_files_empty" = "Nic jeszcze nie zapisano. Przy zapisie VisuStruct tworzy tu folder z dzisiejszą datą."; +"web_files_reconnect_hint" = "Po przeładowaniu przeglądarka ponownie pyta, czy VisuStruct może używać twojego folderu."; +"web_files_reconnect_fmt" = "Otwórz folder „%@”"; +"web_files_connect_hint" = "Wybierz folder jako obszar roboczy. VisuStruct tworzy w nim folder na każdy dzień oraz zapisuje diagram i kod."; +"web_files_connect" = "Wybierz folder"; +"web_files_browser_hint" = "Ta przeglądarka nie może otwierać folderów na urządzeniu (np. na iPadzie). Twoje pliki pozostają w pamięci tej przeglądarki."; +"web_files_browser" = "Zapisz w przeglądarce"; +"web_files_delete_confirm_fmt" = "Na pewno usunąć „%@”?"; +"web_files_folder_prompt" = "Nazwa nowego folderu:"; +"web_files_default_name" = "Program"; +"web_files_saved_fmt" = "Zapisano: %@"; +"web_files_create" = "Utwórz"; +"web_learn_ludwig_tip" = "Wskazówka Ludwiga"; +"web_game_title" = "Gra: Prawda czy fałsz?"; +"web_game_intro" = "Ludwig pokazuje wartości i warunek. Czy warunek jest prawdziwy (true), czy fałszywy (false)? Dziesięć rund, coraz trudniejszych."; +"web_game_start" = "Zacznij grę"; +"web_game_round_fmt" = "Runda %@ z %@"; +"web_game_score_fmt" = "Punkty: %@"; +"web_game_true" = "prawda (true)"; +"web_game_false" = "fałsz (false)"; +"web_game_right" = "Dobrze!"; +"web_game_wrong" = "Niestety źle. Tak to się liczy:"; +"web_game_next" = "Dalej"; +"web_game_finish" = "Wynik"; +"web_game_done_fmt" = "%@ z %@ dobrze."; +"web_game_perfect" = "Wszystko dobrze – Ludwig jest pod wrażeniem!"; +"web_game_good" = "Świetnie! Przejrzyj błędy i spróbuj jeszcze raz."; +"web_game_practice" = "Trening czyni mistrza. Przeczytaj jeszcze raz tabelę prawdy i zagraj ponownie."; +"web_game_again" = "Zagraj ponownie"; +"web_game_wrong_short" = "Niestety źle."; +"web_game_practice_short" = "Praktyka czyni mistrza. Przeczytaj jeszcze raz wyjaśnienia i zagraj kolejną rundę."; +"web_game_clicks" = "Kliknięcia:"; +"web_game_nobody" = "Nikt nie słucha – nic się nie dzieje."; +"web_game_event_fmt" = "Kliknięcie „%@”: słuchacz to słyszy i wykonuje swój kod."; +"web_game_try" = "Teraz sam wypróbuj przyciski w oknie."; +"web_game_time_fmt" = "Zostało %@ s"; +"web_game_defused" = "✂️ Rozbrojona! Znalazłeś błąd."; +"web_game_boom_time" = "💥 Bum! Czas minął."; +"web_game_boom_wrong" = "💥 Bum! To była zła linia."; +"web_game_fix" = "Poprawna linia:"; +"web_game_order_hint" = "Stuknij kroki we właściwej kolejności."; +"web_debug_step" = "Krok"; +"web_debug_step_title" = "Krok: wykonaj jedną instrukcję i zatrzymaj się ponownie"; +"web_debug_continue" = "Dalej do następnego punktu przerwania"; +"web_debug_paused_fmt" = "Zatrzymano przed wierszem %d."; +"web_debug_gutter_title" = "Kliknij numer wiersza, aby ustawić lub usunąć punkt przerwania"; +"web_swap_to_code" = "Programowanie duże"; +"web_swap_to_editor" = "Diagram duży"; +"web_editor_resize" = "Zmień szerokość diagramu"; +"web_palette_resize" = "Zmień szerokość elementów"; +"web_palette_hide" = "Ukryj elementy"; +"web_palette_show" = "Pokaż elementy"; +"web_code_scopes" = "Kolorowe bloki kodu"; +"web_code_scopes_hint" = "Klasa, metoda, pętla, rozgałęzienie we własnych ramkach"; +"web_pseudocode" = "Pseudokod"; +`;export{e as default}; diff --git a/website/app/assets/projectZip-DZMCzW4J.js b/website/app/assets/projectZip-DZMCzW4J.js new file mode 100644 index 00000000..a21924af --- /dev/null +++ b/website/app/assets/projectZip-DZMCzW4J.js @@ -0,0 +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-Cf8h-zzC.js";import"./index-Bmqo_CbG.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/pt-PT-De0Ipirm.js b/website/app/assets/pt-PT-De0Ipirm.js new file mode 100644 index 00000000..011dcf92 --- /dev/null +++ b/website/app/assets/pt-PT-De0Ipirm.js @@ -0,0 +1,742 @@ +const e=`/* Textos que só existem na versão web. Tudo o resto vem dos Localizable.strings da app. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "Diagrama estruturado VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Exportar…"; +"web_export_title" = "Guardar como imagem ou PDF, ou imprimir"; +"web_export_png" = "Imagem (PNG)"; +"web_export_svg" = "Gráfico vetorial (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "Ficheiro VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "Falha na exportação: %@"; +"web_print_hint" = "Use “Exportar… → PDF” para guardar o diagrama e imprimi-lo a partir daí."; +"web_delete" = "Eliminar"; +"web_language_title" = "Idioma da interface"; +"web_simulation_start" = "Iniciar simulação"; +"web_simulation_end" = "Terminar simulação"; +"web_simulation_start_title" = "Executar o diagrama passo a passo"; +"web_simulation_end_title" = "Terminar a simulação e continuar a editar"; +"web_palette_hint" = "Arrastar para o diagrama"; +"web_tabs_label" = "Diagramas"; +"web_status_modified" = "alterado"; +"web_inspector_title" = "Inspetor de objetos"; +"web_inspector_help_drop" = "Arraste elementos da paleta para um bloco: em cima = antes, em baixo = depois, sobre “ø” = substituir. Os elementos existentes podem ser movidos com o rato."; +"web_inspector_help_files" = "Também pode largar ficheiros na janela."; +"web_case_name" = "Nome do caso"; +"web_case_name_placeholder" = "p. ex. 1, ok, default"; +"web_copied" = "Elemento copiado."; +"web_discard_message_fmt" = "As alterações a “%@” serão perdidas."; +"web_err_unreadable_fmt" = "“%@” não é um ficheiro VisuStruct legível (%@)."; +"web_saved_fmt" = "“%@” guardado."; +"web_saved_txt_fmt" = "Guardado como “%@”. Remova a extensão .txt para o utilizar."; +"web_drop_impossible" = "Não é possível largar aqui"; +"web_sim_delay" = "Pausa por passo"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Linguagem"; +"web_codegen_comments" = "Texto do diagrama como comentários"; +"web_codegen_empty_else" = "Gerar ramo else vazio no código"; +"web_copied_check" = "Copiado ✓"; +"web_copy_manual" = "Selecionado, prima Ctrl+C para copiar"; +"web_run_stopped_loop" = "Execução interrompida: possível ciclo infinito."; +"web_run_cancelled" = "Execução cancelada."; +"web_run_error" = "Erro durante a execução."; +"web_run_dropped_fmt" = "… %d linhas anteriores ocultas"; +"web_learn_title" = "Aprender"; +"web_learn_hide" = "Recolher a área de aprendizagem"; +"web_learn_show" = "Expandir a área de aprendizagem: lições, exercícios e consulta"; +"web_learn_lessons" = "Lições"; +"web_learn_tasks" = "Exercícios"; +"web_learn_reference" = "Consulta"; +"web_learn_intro" = "Aprende passo a passo, com exercícios. O teu progresso fica guardado neste navegador."; +"web_learn_tasks_intro" = "Pequenos projetos sem instruções. Cada um indica a lição que deves terminar primeiro."; +"web_learn_step_of_fmt" = "Passo %d de %d"; +"web_learn_lesson_fmt" = "Lição %d"; +"web_learn_all_lessons" = "Todas as lições"; +"web_learn_all_tasks" = "Todos os exercícios"; +"web_learn_back" = "Voltar"; +"web_learn_next" = "Seguinte"; +"web_learn_finish" = "Terminar a lição"; +"web_learn_done" = "Concluída"; +"web_learn_after_fmt" = "Depois da lição %d: %@"; +"web_learn_level_fmt" = "Dificuldade %d de 3"; +"web_learn_exercise" = "Exercício"; +"web_learn_brag" = "Curiosidades com o Ludwig"; +"web_learn_solved" = "resolvido"; +"web_learn_open_exercise" = "Abrir no editor"; +"web_learn_solve_in_editor" = "Resolve este exercício na área %@."; +"web_learn_solve_in_code" = "Resolve este exercício na área %@."; +"web_learn_solve_in_both" = "Resolve este exercício nas áreas %1$@ e %2$@."; +"web_learn_open_in_editor" = "Abrir no editor"; +"web_learn_graphic_labels" = "👆 Clica na imagem para mostrar ou esconder as legendas"; +"web_learn_check" = "Verificar"; +"web_learn_hint" = "Dica"; +"web_learn_reset" = "Recomeçar"; +"web_learn_reset_confirm" = "Queres mesmo recomeçar?"; +"web_learn_solution" = "Mostrar a solução"; +"web_learn_hint_more" = "Outra dica"; +"web_learn_hint_fmt" = "Dica %d de %d"; +"web_learn_teacher" = "Para professores"; +"web_learn_teacher_intro" = "O código de professor mostra as soluções de todos os exercícios. O navegador memoriza-o."; +"web_learn_teacher_code" = "Código de professor"; +"web_learn_teacher_unlock" = "Desbloquear"; +"web_learn_teacher_wrong" = "O código não está correto."; +"web_learn_teacher_on" = "O modo de professor está ativo: as soluções de todos os exercícios estão visíveis."; +"web_learn_teacher_off" = "Sair do modo de professor"; +"web_learn_open_first" = "Abre primeiro o exercício no editor e constrói lá o teu estrutograma."; +"web_learn_empty" = "O teu estrutograma ainda está vazio. Arrasta primeiro elementos da área «Elementos» para ele."; +"web_learn_passed" = "Muito bem! O teu estrutograma faz exatamente o que deve."; +"web_learn_failed" = "Ainda não está bem. Compara a saída esperada com a tua:"; +"web_learn_missing_fmt" = "O teu estrutograma ainda precisa de: %@"; +"web_learn_input_fmt" = "Entrada: %@"; +"web_learn_no_input" = "Sem entrada"; +"web_learn_expected" = "Esperado"; +"web_learn_actual" = "A tua saída"; +"web_learn_missing_input" = "O teu estrutograma pede mais entradas do que o previsto."; +"web_learn_unused_input" = "O teu estrutograma não pede todas as entradas."; +"web_learn_too_many_steps" = "Parado após 100 000 passos. Há um ciclo que nunca termina?"; +"web_learn_score_fmt" = "%d de %d certas"; +"web_learn_cloze_hint" = "Escreve as palavras que faltam nos espaços e carrega em “Verificar”."; +"web_learn_cloze_score_fmt" = "%d de %d espaços certos"; +"web_learn_cloze_all_right" = "Todos os espaços certos!"; +"web_learn_cloze_solution" = "Mostrar solução"; +"web_learn_cloze_again" = "De novo"; +"web_learn_pap_hint" = "Toca num elemento à direita e depois no seu lugar no fluxograma. Também o podes arrastar. Tocar num lugar ocupado devolve o elemento."; +"web_learn_pap_score_fmt" = "%d de %d elementos certos"; +"web_learn_pap_all_right" = "Tudo certo! O teu fluxograma está pronto."; +"web_learn_pap_missing_fmt" = "Ainda faltam %d elementos."; +"web_learn_pap_empty" = "Lugar vazio"; +"web_learn_pap_yes" = "sim"; +"web_learn_pap_no" = "não"; +"web_learn_pap_legend_oval" = "Início ou fim"; +"web_learn_pap_legend_rect" = "Instrução"; +"web_learn_pap_legend_diamond" = "Decisão: pergunta com sim e não"; +"web_learn_pap_legend_para" = "Entrada ou saída"; +"web_learn_review" = "Rever"; +"web_learn_terms" = "Termos técnicos"; +"web_learn_resize" = "Alterar a largura da área de aprendizagem (duplo clique: repor)"; +"web_learn_competences_intro" = "No fim desta lição consigo …"; +"web_learn_rating_sun" = "consigo com segurança"; +"web_learn_rating_cloud" = "em parte"; +"web_learn_rating_umbrella" = "ainda não"; +"web_learn_review_title" = "A tua lista de verificação em comparação"; +"web_learn_review_hint" = "Aqui a tua autoavaliação e o teste não coincidem. Lê o passo outra vez e volta a avaliar-te na lista de verificação."; +"web_learn_review_match" = "A tua autoavaliação corresponde ao teu teste. Muito bem!"; +"web_learn_review_overrated_fmt" = "Escolheste ☀️, mas a pergunta %@ estava errada."; +"web_learn_review_underrated" = "Todas as perguntas sobre isto estavam certas. Sabes mais do que pensas!"; +"web_learn_review_unrated" = "ainda não avaliado"; +"web_learn_back_to_checklist" = "Voltar à lista de verificação"; +"web_learn_step_fmt" = "Passo %d: %@"; +"web_sim_call_arguments_fmt" = "A chamada não corresponde ao cabeçalho de %@. Verifica os valores entre parênteses."; +"web_sim_missing_return_fmt" = "%@ terminou sem devolver um valor com return."; +"web_sim_file_not_found_fmt" = "Não existe nenhum ficheiro chamado %@."; +"web_sim_end_of_file_fmt" = "O ficheiro %@ não tem mais linhas."; +"web_sim_null_value_fmt" = "%@ é null."; +"web_sim_written_file_fmt" = "%@ (guardado)"; +"web_site_home" = "Página inicial"; +"web_site_imprint" = "Contacto"; +"web_site_privacy" = "Privacidade"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Código"; +"web_live_hide" = "Ocultar código"; +"web_scale_canvas" = "Tamanho do texto: estrutograma"; +"web_scale_code" = "Tamanho do texto: Código"; +"web_live_indent" = "Indentar"; +"web_live_indent_title" = "Indentar o código: quatro espaços por nível (linhas selecionadas, senão tudo)"; +"web_live_show" = "Mostrar código"; +"web_live_resize" = "Alterar a largura da área de código (duplo clique: repor)"; +"web_live_hint" = "O código cresce com o teu diagrama. Cinzento = marcador: escreve no inspetor de objetos e o teu texto aparece aí. Clica numa linha para selecionar o elemento."; +"web_live_ph_selector" = "variável"; +"web_live_ph_code" = "O teu código"; +"web_live_ph_end" = "fim"; +"web_live_language" = "Linguagem de programação"; +"web_live_java_class" = "Como classe"; +"web_live_java_class_hint" = "Nome da classe = título do diagrama"; +"web_live_java_main" = "Com método main"; +"web_settings_display" = "Apresentação"; +"web_live_swing" = "Java verdadeiro (com Swing)"; +"web_live_swing_hint" = "Java verdadeiro com janelas (CheerpJ). Descarrega cerca de 40 MB uma vez, na primeira execução."; +"web_live_swing_windows" = "Janelas Java"; +"web_live_swing_hide" = "Fechar janelas Java"; +"web_live_swing_loading" = "A carregar o Java (cerca de 40 MB na primeira vez) …"; +"web_live_swing_compiling" = "A compilar …"; +"web_live_swing_running" = "O programa está a correr."; +"web_live_swing_compile_failed" = "Erro de compilação, vê acima."; +"web_live_swing_failed" = "Não foi possível carregar o Java. Verifica a ligação à internet."; +"web_live_hint_edit" = "Escreve aqui código Java e o diagrama constrói-se sozinho. Ou trabalha no diagrama e o código cresce com ele. Cinzento = marcador, basta escrever por cima."; +"web_live_edit_label" = "Código Java"; +"web_parse_line_fmt" = "Linha %d: %@"; +"web_parse_missing" = "Ainda falta aqui: %@"; +"web_parse_extra" = "Está a mais: %@"; +"web_parse_unclosed_string" = "Falta aqui o %@ de fecho."; +"web_parse_else_without_if" = "Este “else” não tem um “if” correspondente."; +"web_parse_case_outside_switch" = "“case” e “default” pertencem a um “switch”."; +"web_parse_missing_do_while" = "Depois de “do { … }” ainda falta “while (condição);”."; +"web_parse_more_methods" = "Por agora só conta um método aqui. Cria outros subprogramas em separadores próprios."; +"web_parse_missing_import" = "Falta %@ mesmo no início. Sem esta linha, o Java não conhece o Scanner."; +"web_parse_missing_scanner" = "Falta antes %@ Sem esta linha, o Scanner não existe."; +"web_parse_unknown_type" = "O Java não conhece este tipo de dados. Querias dizer %@?"; +"web_editor_title" = "Diagrama"; +"web_editor_show" = "Mostrar diagrama"; +"web_editor_hide" = "Ocultar diagrama"; +"web_keywords_title" = "Palavras-chave do código"; +"web_keywords_hint" = "if, while, for em vez de Decisão, Ciclo …"; +"web_palette_compact" = "Elementos sempre compactos"; +"web_palette_compact_hint" = "Símbolo com o nome pequeno por baixo; caso contrário, só com a coluna estreita"; +"web_about_version_fmt" = "Versão %@"; +"web_about_software" = "Software utilizado"; +"web_about_software_text" = "O editor de código usa o CodeMirror e o Lezer (licença MIT). Com o suporte para Swing, o VisuStruct carrega o CheerpJ da Leaning Technologies (licença Community) e o javac do OpenJDK."; +"web_about_licenses" = "Textos das licenças"; +"web_live_run" = "Executar"; +"web_live_run_title" = "Executar o programa: as saídas e entradas aparecem em baixo"; +"web_live_run_finished" = "Programa terminado."; +"web_live_run_stopped" = "Parado."; +"web_console" = "Consola"; +"web_console_hide" = "Ocultar consola"; +"web_console_resize" = "Alterar a altura da consola"; +"web_diagram_tools" = "Ferramentas do diagrama"; +"web_files_title" = "Ficheiros"; +"web_files_show" = "Mostrar ficheiros"; +"web_files_hide" = "Ocultar ficheiros"; +"web_files_resize" = "Alterar a largura dos ficheiros"; +"web_files_new_folder" = "Nova pasta"; +"web_files_switch" = "Escolher outra pasta"; +"web_files_delete" = "Eliminar"; +"web_files_in_browser" = "No armazenamento deste navegador"; +"web_files_save_hint_fmt" = "Guardar coloca o programa em %@."; +"web_files_empty" = "Ainda nada guardado. Ao guardar, o VisuStruct cria aqui uma pasta com a data de hoje."; +"web_files_reconnect_hint" = "Depois de recarregar, o navegador pergunta outra vez se o VisuStruct pode usar a tua pasta."; +"web_files_reconnect_fmt" = "Abrir a pasta “%@”"; +"web_files_connect_hint" = "Escolhe uma pasta como área de trabalho, de preferência uma pasta nova “VisuStruct-Ficheiros” nos teus Documentos. O VisuStruct cria lá uma pasta para cada dia e guarda o diagrama e o código."; +"web_files_connect" = "Escolher pasta"; +"web_files_browser_hint" = "Este navegador não consegue abrir pastas no dispositivo (por exemplo no iPad). Os teus ficheiros ficam no armazenamento deste navegador."; +"web_files_browser" = "Guardar no navegador"; +"web_files_delete_confirm_fmt" = "Eliminar mesmo “%@”?"; +"web_files_folder_prompt" = "Nome da nova pasta:"; +"web_files_default_name" = "Programa"; +"web_files_saved_fmt" = "Guardado: %@"; +"web_files_create" = "Criar"; +"web_learn_ludwig_tip" = "Dica do Ludwig"; +"web_game_title" = "Jogo: Verdadeiro ou falso?"; +"web_game_intro" = "O Ludwig mostra-te valores e uma condição. A condição é verdadeira (true) ou falsa (false)? Dez rondas, cada vez mais difíceis."; +"web_game_start" = "Começar o jogo"; +"web_game_round_fmt" = "Ronda %@ de %@"; +"web_game_score_fmt" = "Pontos: %@"; +"web_game_true" = "verdadeiro (true)"; +"web_game_false" = "falso (false)"; +"web_game_right" = "Certo!"; +"web_game_wrong" = "Não exatamente. É assim que se calcula:"; +"web_game_next" = "Seguinte"; +"web_game_finish" = "Resultado"; +"web_game_done_fmt" = "%@ de %@ certas."; +"web_game_perfect" = "Tudo certo – o Ludwig está mesmo impressionado!"; +"web_game_good" = "Muito bem! Revê os teus erros e tenta outra vez."; +"web_game_practice" = "A prática faz o mestre. Lê outra vez a tabela de verdade acima e joga mais uma ronda."; +"web_game_again" = "Jogar outra vez"; +"web_game_wrong_short" = "Infelizmente errado."; +"web_game_practice_short" = "A prática leva à perfeição. Lê outra vez as explicações e joga mais uma ronda."; +"web_game_clicks" = "Cliques:"; +"web_game_nobody" = "Ninguém está a ouvir – não acontece nada."; +"web_game_event_fmt" = "Clique em “%@”: o ouvinte ouve e executa o seu código."; +"web_game_try" = "Agora experimenta tu os botões da janela."; +"web_game_time_fmt" = "Faltam %@ s"; +"web_game_defused" = "✂️ Desativada! Encontraste o erro."; +"web_game_boom_time" = "💥 Bum! O tempo acabou."; +"web_game_boom_wrong" = "💥 Bum! Era a linha errada."; +"web_game_fix" = "A linha correta:"; +"web_game_order_hint" = "Toca nos passos pela ordem certa."; +"web_debug_step" = "Passo a passo"; +"web_debug_step_title" = "Passo a passo: executar uma instrução e parar outra vez"; +"web_debug_continue" = "Continuar até ao próximo ponto de paragem"; +"web_debug_paused_fmt" = "Parado antes da linha %d."; +"web_debug_gutter_title" = "Clica num número de linha para pôr ou tirar um ponto de paragem"; + +/* Lernbereich: Caesar-Scheibe */ +"web_learn_caesar_title" = "Disco de César"; +"web_learn_caesar_hint" = "Roda o disco interior ou toca em −1 e +1. Por fora está o texto simples, por dentro o texto cifrado."; +"web_learn_caesar_key_fmt" = "Chave %d"; +"web_learn_caesar_plain" = "Texto simples"; +"web_learn_caesar_secret" = "Texto cifrado"; +"web_learn_caesar_encrypt" = "Cifrar"; +"web_learn_caesar_decrypt" = "Decifrar"; +"web_learn_caesar_back" = "Rodar o disco uma letra para trás"; +"web_learn_caesar_forward" = "Rodar o disco uma letra para a frente"; +"web_learn_rescue_station_fmt" = "Estação %@ de %@: %@"; +"web_learn_rescue_number" = "O teu número"; +"web_learn_rescue_not_number" = "Escreve um número inteiro."; +"web_learn_rescue_wrong" = "Ainda não. Lê o código outra vez, carácter a carácter."; +"web_learn_rescue_letter_moved" = "A letra vai para as palavras cruzadas."; +"web_learn_rescue_alphabet" = "O teu número transforma-se numa letra:"; +"web_learn_rescue_to_crossword" = "Para as palavras cruzadas"; +"web_learn_rescue_crossword" = "As palavras cruzadas"; +"web_learn_rescue_across" = "→ Horizontais"; +"web_learn_rescue_down" = "↓ Verticais"; +"web_learn_rescue_cell_fmt" = "Quadrado linha %@, coluna %@"; +"web_learn_rescue_keyword" = "Palavra secreta:"; +"web_learn_rescue_cw_wrong" = "Os quadrados marcados a vermelho ainda não estão certos."; +"web_learn_rescue_cw_done" = "Resolvido! Os quadrados amarelos formam a palavra secreta."; +"web_learn_rescue_to_gate" = "Para o portão"; +"web_learn_rescue_gate" = "O portão"; +"web_learn_rescue_word" = "Palavra secreta"; +"web_learn_rescue_open" = "Abrir o portão"; +"web_learn_rescue_gate_case" = "Quase! O equals distingue maiúsculas de minúsculas. Escreve a palavra exatamente como nas palavras cruzadas."; +"web_learn_rescue_gate_wrong" = "O portão continua fechado. Olha outra vez para os quadrados amarelos."; +"web_learn_rescue_freed" = "🎉 O portão está aberto!"; + +/* VisuBot (mBot2-Modus), nur de/en/pt */ +"web_visubot_world_title" = "Com o que queres trabalhar?"; +"web_visubot_world_visustruct_hint" = "VisuStruct: estrutogramas e Java com o curso completo. Podes mudar a qualquer momento na roda dentada."; +"web_visubot_world_visubot_hint" = "VisuBot: programar o robô mBot2, com lições e tarefas próprias. Podes mudar a qualquer momento na roda dentada."; +"web_visubot_connect" = "Ligar o mBot2 real"; +"web_visubot_upload_button" = "Transferir"; +"web_visubot_upload_title" = "Transferir o programa para o mBot2"; +"web_visubot_upload_step1" = "Liga o mBot2 com o cabo USB e acende-o. Só funciona no Chrome ou no Edge."; +"web_visubot_upload_step2" = "Clica em “Transferir agora” e escolhe “USB Serial”. O mBot2 guarda o teu programa e reinicia."; +"web_visubot_upload_step3" = "Desliga o cabo e põe o mBot2 na partida. Quando carregas no botão A, o programa arranca. Fica guardado, mesmo depois de desligar."; +"web_visubot_upload_start" = "Transferir agora"; +"web_visubot_upload_busy" = "A transferir … não desligues o cabo."; +"web_visubot_upload_done" = "Pronto! Desliga o cabo, põe o mBot2 na partida e carrega no botão A."; +"web_visubot_upload_failed" = "A transferência não funcionou. Reinicia o mBot2 e tenta outra vez."; +"web_visubot_upload_label" = "A = Início"; +"web_visubot_upload_error_input" = "O teu programa pede uma entrada. O mBot2 não tem teclado, por isso não funciona."; +"web_visubot_upload_error_files" = "O teu programa trabalha com ficheiros. Isso não funciona no mBot2."; +"web_visubot_upload_error_empty" = "O teu programa ainda está vazio."; +"web_visubot_disconnect" = "Desligar"; +"web_visubot_connecting" = "A ligar … (o CyberPi reinicia brevemente)"; +"web_visubot_connected" = "O mBot2 real conduz também"; +"web_visubot_no_serial" = "mBot2 real: só no Chrome ou Edge num computador."; +"web_visubot_link_error" = "Ligação perdida"; +"web_visubot_world" = "Mundo VisuBot"; +"web_visubot_no_3d" = "A vista 3D não consegue arrancar neste navegador."; +"web_visubot_distance" = "Distância"; +"web_visubot_line" = "Linha"; +"web_visubot_bumps" = "bateu na parede"; +"web_visubot_el_forward" = "andar para a frente"; +"web_visubot_el_backward" = "andar para trás"; +"web_visubot_el_right" = "rodar à direita"; +"web_visubot_el_left" = "rodar à esquerda"; +"web_visubot_el_led" = "LEDs ligados"; +"web_visubot_el_tone" = "tocar um som"; +"web_visubot_drive" = "Percurso"; +"web_visubot_depth_fmt" = "Os ciclos têm de estar encaixados %d vezes."; +"web_visubot_tap_part" = "Roda o mBot2 com o rato ou o dedo. Toca numa peça para ver o nome."; +"web_visubot_quiz_right" = "Certo!"; +"web_visubot_quiz_wrong_fmt" = "Isso é: %@. Tenta outra vez."; +"web_visubot_part_cyberpi" = "CyberPi"; +"web_visubot_part_screen" = "Ecrã"; +"web_visubot_part_joystick" = "Joystick"; +"web_visubot_part_buttons" = "Botões A, B e Home"; +"web_visubot_part_leds" = "LEDs RGB"; +"web_visubot_part_lightSensor" = "Sensor de luz"; +"web_visubot_part_microphone" = "Microfone"; +"web_visubot_part_shield" = "Shield do mBot2 com bateria"; +"web_visubot_part_powerSwitch" = "Interruptor"; +"web_visubot_part_motors" = "Motores com encoder"; +"web_visubot_part_wheels" = "Rodas"; +"web_visubot_part_ultrasonic" = "Sensor ultrassónico"; +"web_visubot_part_lineSensor" = "Sensor de linha (quad RGB)"; +"web_visubot_part_caster" = "Roda livre"; +"web_visubot_part_chassis" = "Chassi"; +"web_visubot_world_fmt" = "Mundo %d"; +"web_visubot_goal_reached" = "Objetivo alcançado"; +"web_visubot_goal_missed" = "Objetivo não alcançado"; +"web_visubot_commands" = "Comandos do mBot2"; +"web_visubot_sensors" = "Sensores do mBot2"; +"web_visubot_sensor_distance" = "Distância"; +"web_visubot_sensor_line" = "Linha"; +"web_visubot_el_led_off" = "LEDs desligados"; +"web_visubot_el_led_color" = "cor do LED"; +"web_visubot_el_wait" = "esperar um pouco"; +"web_visubot_el_emotion" = "mostrar um sentimento"; +"web_visubot_el_text" = "mostrar texto"; +"web_visubot_sensor_color" = "A cor é vermelha?"; +"web_visubot_sensor_button_a" = "Botão A premido?"; +"web_visubot_sensor_button_b" = "Botão B premido?"; +"web_visubot_sensor_joy_up" = "Joystick para cima?"; +"web_visubot_sensor_joy_down" = "Joystick para baixo?"; +"web_visubot_sensor_joy_left" = "Joystick para a esquerda?"; +"web_visubot_sensor_joy_right" = "Joystick para a direita?"; +"web_visubot_sensor_brightness" = "Luminosidade"; +"web_visubot_sensor_loudness" = "Volume do som"; +"web_visubot_sensor_pitch" = "Inclinação frente/trás"; +"web_visubot_sensor_roll" = "Inclinação lateral"; +"web_visubot_sensor_shake" = "Abanado?"; +"web_visubot_el_drive" = "rodas separadas"; +"web_visubot_el_stop" = "parar"; +"web_visubot_el_timer" = "cronómetro a 0"; +"web_visubot_sensor_line_left" = "Linha à esquerda?"; +"web_visubot_sensor_line_right" = "Linha à direita?"; +"web_visubot_sensor_timer" = "Cronómetro (s)"; +"web_visubot_sensor_battery" = "Bateria (%)"; +"web_visubot_actions" = "Comandos"; +"web_visubot_led_on" = "LEDs ligados"; +"web_visubot_led_off" = "LEDs desligados"; +"web_visubot_tone_yes" = "som"; +"web_visubot_tone_no" = "sem som"; +"web_visubot_controls" = "Experimentar os sensores"; +"web_visubot_controls_hint" = "Sem um mBot2 real: define aqui o que os sensores medem. Botões, joystick e abanar duram um segundo."; +"web_visubot_shake" = "abanar"; +"web_visubot_check" = "Testar o mBot2"; +"web_visubot_check_hint" = "Experimenta cada atuador uma vez. Os valores dos sensores atualizam-se em direto: põe a mão à frente do sensor ultrassónico, carrega nos botões, inclina ou abana o mBot2. Levanta-o para testar as rodas."; +"web_visubot_check_forward" = "Rodas 1 s para a frente"; +"web_visubot_check_spin" = "Rodar no lugar 1 s"; + +/* Start: Ordner für Lernstand und Programme */ +"web_learn_start_title" = "Onde guardas o teu trabalho?"; +"web_learn_start_hint" = "O teu progresso e os teus programas ficam numa pasta no teu dispositivo. O progresso fica no ficheiro learnProgress.json."; +"web_learn_start_continue_fmt" = "Continuar com “%@”"; +"web_learn_start_open" = "Abrir pasta existente"; +"web_learn_start_create_fmt" = "Criar nova pasta “%@”"; +"web_learn_start_create_hint" = "Depois escolhes onde fica, por exemplo em “Documentos”."; +"web_learn_start_folder" = "VisuStruct-Ficheiros"; +"web_learn_start_without" = "Continuar sem pasta"; +"web_learn_start_without_hint" = "Assim o teu progresso perde-se ao fechar a página."; +"web_visubot_preview_title" = "mBot2 ao vivo"; +"web_visubot_preview_hint" = "Mostra logo para onde o teu programa leva o mBot2."; +"web_visubot_preview_sim_title" = "Simulação"; +"web_visubot_preview_sim_hint" = "O mBot2 anda aqui enquanto a simulação corre."; +"web_visubot_world_in_preview" = "O mBot2 anda na janela «Simulação»."; +"web_visubot_preview_play" = "Reproduzir o percurso"; +"web_visubot_preview_stop" = "Parar"; +"web_visubot_preview_hide" = "Recolher mBot2 ao vivo"; +"web_visubot_preview_show" = "Mostrar mBot2 ao vivo"; +"web_visubot_preview_resize" = "Alterar o tamanho de mBot2 ao vivo"; +"web_visubot_preview_stack" = "Por baixo do código na área Código"; +"web_visubot_preview_side" = "Como coluna própria"; +"web_visubot_preview_distance_fmt" = "Percurso: %d cm"; +"web_visubot_preview_input" = "precisa de uma entrada, inicia a simulação para isso"; +"web_visubot_preview_limit" = "demora muito (ciclo infinito?), mostra-se o início"; +"web_visubot_group_drive" = "Andar e rodar"; +"web_visubot_group_wheels" = "Rodas separadas"; +"web_visubot_group_output" = "Luz, som e ecrã"; +"web_visubot_group_emotion" = "Emoções"; +"web_visubot_group_wait" = "Esperar e cronómetro"; +"web_visubot_group_distance" = "Distância"; +"web_visubot_group_line" = "Linha"; +"web_visubot_group_color" = "Cores"; +"web_visubot_group_buttons" = "Botões e joystick"; +"web_visubot_group_light" = "Luz e volume"; +"web_visubot_group_tilt" = "Inclinação e abanar"; +"web_visubot_group_timer" = "Cronómetro e bateria"; +"web_swap_to_code" = "Código grande, diagrama estreito"; +"web_swap_to_editor" = "Diagrama grande, código estreito"; +"web_editor_resize" = "Alterar a largura do diagrama"; +"web_palette_resize" = "Alterar a largura dos elementos (duplo clique: repor)"; +"web_palette_hide" = "Ocultar elementos"; +"web_palette_show" = "Mostrar elementos"; + +/* VisuObject */ +"web_visuobject_world_hint" = "VisuObject: programar classes em Java e vê-las ou desenhá-las como diagrama de classes (a partir do 12.º ano). Podes mudar a qualquer momento na roda dentada."; +"web_visuobject_subtitle" = "Diagrama de classes"; +"web_visuobject_code" = "Código Java"; +"web_visuobject_diagram" = "Diagrama de classes"; +"web_visuobject_add_interface" = "Interface"; +"web_visuobject_add_interface_tip" = "Nova interface no diagrama e no código"; +"web_visuobject_layout" = "Reorganizar"; +"web_visuobject_layout_tip" = "Organizar todas as classes automaticamente: superclasses em cima"; +"web_visuobject_add_field" = "novo atributo …"; +"web_visuobject_add_method" = "novo método …"; +"web_visuobject_delete_class" = "Apagar classe"; +"web_visuobject_new_class_name" = "NovaClasse"; +"web_visuobject_new_interface_name" = "NovaInterface"; +"web_visuobject_example" = "Exemplo"; +"web_visuobject_example_tip" = "Carregar o projeto de exemplo Zoo: Tier e Hund no package tiere, Besitzer em personen"; +"web_visuobject_new_tip" = "Novo: projeto vazio (Anular recupera o anterior)"; +"web_visuobject_empty" = "Ainda não há nenhuma classe. Clica em «+ Classe» à esquerda ou escreve, por exemplo, «public class Cao { }» num ficheiro."; +"web_visuobject_edit_hint" = "Duplo clique para alterar. Escreve como em UML: «- nome: String» ou «+ ladrar(): void». Deixar vazio apaga."; +"web_visuobject_member_label" = "Atributo ou método em notação UML"; +"web_visuobject_name_label" = "Nome da classe"; +"web_visuobject_bad_name" = "«%@» não é um nome válido ou já existe."; +"web_visuobject_bad_line" = "Não percebo «%@». Exemplo: - nome: String ou + ladrar(): void"; +"web_visuobject_open_failed" = "Não foi possível ler o ficheiro."; +"web_visuobject_field_ph" = "- nome: String"; +"web_visuobject_seq_diagram" = "Diagrama de sequência"; +"web_visuobject_seq_empty" = "O diagrama de sequência surge ao depurar: clica em “Depurar” em cima e percorre o programa passo a passo."; +"web_visuobject_seq_no_calls" = "Ainda não há chamadas dos teus métodos."; +"web_visuobject_seq_truncated" = "… encurtado: a partir daqui há chamadas demais."; +"web_visuobject_seq_hint" = "Cada seta é uma chamada de um dos teus métodos; a seta tracejada traz o valor de retorno. Clica numa seta para ver a linha no código."; +"web_visuobject_dbg" = "Depurar"; +"web_visuobject_dbg_tip" = "Executar o programa passo a passo. Ponto de paragem: clica no número da linha. O diagrama de objetos mostra os objetos na memória."; +"web_visuobject_dbg_continue" = "Continuar"; +"web_visuobject_dbg_continue_tip" = "Continuar até ao próximo ponto de paragem (F8)"; +"web_visuobject_dbg_pause" = "Pausa"; +"web_visuobject_dbg_pause_tip" = "Pausar o programa"; +"web_visuobject_dbg_over" = "Passo"; +"web_visuobject_dbg_over_tip" = "Próxima linha; os métodos correm até ao fim (F6)"; +"web_visuobject_dbg_into" = "Entrar"; +"web_visuobject_dbg_into_tip" = "Entrar no método chamado (F5)"; +"web_visuobject_dbg_out" = "Sair"; +"web_visuobject_dbg_out_tip" = "Terminar o método e voltar a quem o chamou (F7)"; +"web_visuobject_dbg_input" = "Entrada para o Scanner, depois Enter"; +"web_visuobject_dbg_running" = "Depurador: o programa está a correr …"; +"web_visuobject_dbg_waiting" = "Depurador: o programa espera pela tua entrada."; +"web_visuobject_dbg_paused_fmt" = "Depurador: parado em %1$@, linha %2$@"; +"web_visuobject_dbg_exception" = "O programa terminou com uma exceção."; +"web_visuobject_dbg_code_changed" = "Código alterado: depurador terminado."; +"web_visuobject_dbg_line_fmt" = "%1$@:%2$@"; +"web_visuobject_dbg_stack" = "Pilha de chamadas"; +"web_visuobject_dbg_vars" = "Variáveis"; +"web_visuobject_dbg_var_name" = "Nome"; +"web_visuobject_dbg_var_type" = "Tipo"; +"web_visuobject_dbg_no_vars" = "Sem variáveis"; +"web_visuobject_dbg_err_syntax" = "%1$@, linha %2$@: o depurador não entende isto (%3$@). ▶ Executar mostra a mensagem do Java."; +"web_visuobject_dbg_err_symbol" = "%1$@, linha %2$@: %3$@ é desconhecido."; +"web_visuobject_dbg_err_import" = "%1$@, linha %2$@: falta %3$@ mesmo no início. Sem esta linha, o Java não conhece a classe."; +"web_visuobject_dbg_err_typename" = "%1$@, linha %2$@: o Java não conhece este tipo de dados. Querias dizer %3$@?"; +"web_visuobject_dbg_err_unsupported" = "%1$@, linha %2$@: o depurador ainda não consegue %3$@. ▶ Executar corre o programa em Java real."; +"web_visuobject_dbg_err_type" = "%1$@, linha %2$@: algo não encaixa aqui (%3$@)."; +"web_visuobject_obj_diagram" = "Diagrama de objetos"; +"web_visuobject_obj_new" = "Novo objeto da classe"; +"web_visuobject_obj_add" = "Objeto"; +"web_visuobject_obj_empty" = "Ainda sem objetos. Escolhe uma classe em cima e clica em “+ Objeto”."; +"web_visuobject_obj_no_classes" = "Cria primeiro uma classe (não abstrata) no diagrama de classes."; +"web_visuobject_obj_hint" = "Clica num objeto para mudar aqui o nome, a classe e os valores. Arrasta a pega até outro objeto para os ligar através de um atributo de referência."; +"web_visuobject_obj_live_hint" = "Ao vivo do depurador: é assim que os objetos estão agora na memória."; +"web_visuobject_obj_link" = "Arrastar até outro objeto: definir referência"; +"web_visuobject_obj_name" = "Nome"; +"web_visuobject_obj_class" = "Classe"; +"web_visuobject_obj_attribute" = "Atributo"; +"web_visuobject_obj_value" = "Valor"; +"web_visuobject_obj_delete" = "Apagar objeto"; +"web_visuobject_obj_bad_name" = "“%@” não é um nome válido para um objeto."; +"web_visuobject_obj_name_taken" = "Já existe um objeto “%@”."; +"web_visuobject_obj_no_ref" = "%1$@ não tem nenhum atributo que possa apontar para %2$@."; +"web_visuobject_tool_note" = "Nota"; +"web_visuobject_tool_note_tip" = "Nota: clica no diagrama de classes e escreve o texto. Arrasta a pega até uma classe para uma linha tracejada."; +"web_visuobject_note_ph" = "Nota …"; +"web_visuobject_note_text" = "Texto"; +"web_visuobject_note_attached" = "Ligada a"; +"web_visuobject_note_attach" = "Arrastar até uma classe: linha tracejada"; +"web_visuobject_note_delete" = "Apagar nota"; +"web_visuobject_run" = "Executar"; +"web_visuobject_run_tip" = "Executar o programa com Java verdadeiro: todas as classes são compiladas, é iniciada a classe com main (de preferência a aberta)."; +"web_visuobject_stop" = "Parar"; +"web_visuobject_stop_tip" = "Terminar o programa e fechar as suas janelas"; +"web_visuobject_stopped" = "Programa terminado."; +"web_visuobject_no_main" = "Nenhuma classe com public static void main(String[] args) encontrada."; +"web_visuobject_running_fmt" = "%@ está a correr …"; +"web_visuobject_console_clear" = "Limpar"; +"web_visuobject_section_fields" = "Atributos"; +"web_visuobject_section_refs" = "Atributos de referência"; +"web_visuobject_section_ctors" = "Construtor"; +"web_visuobject_section_methods" = "Métodos"; +"web_visuobject_insp_sections" = "Inserir comentários de secção"; +"web_visuobject_insp_sort" = "Ordenar por secções"; +"web_visuobject_insp_sections_tip" = "Escreve // Atributos, // Atributos de referência, // Construtor e // Métodos na classe e ordena tudo por baixo. O que for criado no diagrama de classes vai logo para o sítio certo."; +"web_visuobject_insp_doc" = "Descrição (Javadoc)"; +"web_visuobject_insp_doc_ph" = "Para que serve a classe? Fica no código como comentário Javadoc por cima da classe."; +"web_visuobject_insp_visibility" = "Visibilidade"; +"web_visuobject_insp_type" = "Tipo"; +"web_visuobject_insp_init" = "Valor inicial"; +"web_visuobject_insp_no_fields" = "Ainda sem atributos."; +"web_visuobject_insp_add_field" = "Atributo"; +"web_visuobject_insp_params" = "Parâmetros"; +"web_visuobject_insp_return" = "Tipo de retorno"; +"web_visuobject_insp_constructor" = "Construtor"; +"web_visuobject_insp_no_methods" = "Ainda sem métodos."; +"web_visuobject_insp_add_method" = "Método"; +"web_visuobject_insp_generate" = "Gerar:"; +"web_visuobject_insp_gen_constructor" = "Construtor a partir dos atributos"; +"web_visuobject_insp_gen_constructor_tip" = "Como no Eclipse “Generate Constructor using Fields”: um construtor que define todos os atributos (exceto static)."; +"web_visuobject_insp_gen_accessors" = "Getters e setters"; +"web_visuobject_insp_gen_accessors_tip" = "Como no Eclipse “Generate Getters and Setters”: get…/set… para cada atributo (atributos final só com getter)."; +"web_visuobject_insp_bad_params" = "Escreve os parâmetros assim: nome: Tipo, segundo: int (lido “%@”)."; +"web_visuobject_insp_fields" = "Atributos"; +"web_visuobject_insp_methods" = "Métodos"; +"web_visuobject_inspector_resize" = "Redimensionar: arrasta a fronteira entre o diagrama de classes e o inspetor para cima ou para baixo (duplo clique = padrão)"; +"web_visuobject_dep_title" = "Dependência «%@»"; +"web_visuobject_dep_create_text" = "%1$@ cria um objeto da classe %2$@ em %3$@ (new)."; +"web_visuobject_dep_use_text" = "%1$@ usa a classe %2$@ em %3$@."; +"web_visuobject_dep_hint" = "Isto não é uma associação: %@ não guarda o objeto %@ num atributo, ele só existe dentro do método. Por isso a linha é tracejada."; +"web_visuobject_dep_to_assoc" = "Guardar como atributo (associação a %@)"; +"web_visuobject_end_mult_ph" = "mult."; +"web_visuobject_end_tip" = "Clique (linha selecionada) ou clique direito: papel, multiplicidade e navegabilidade nesta extremidade"; +"web_visuobject_end_role_ph" = "p. ex. osMeusGatos"; +"web_visuobject_new_menu" = "Novo"; +"web_visuobject_new_menu_tip" = "Criar um novo projeto, source folder, package, classe ou interface"; +"web_visuobject_new_project" = "Projeto Java"; +"web_visuobject_new_folder" = "Source folder"; +"web_visuobject_new_package" = "Package"; +"web_visuobject_new_class" = "Classe"; +"web_visuobject_new_interface" = "Interface"; +"web_visuobject_new_project_title" = "Novo projeto Java"; +"web_visuobject_new_project_hint" = "No workspace cada projeto tem uma pasta própria com src."; +"web_visuobject_new_folder_title" = "Novo source folder"; +"web_visuobject_new_folder_hint" = "Outra pasta para código ao lado de src, por exemplo test para classes de teste."; +"web_visuobject_new_package_title" = "Novo package"; +"web_visuobject_new_package_hint" = "Os nomes de package escrevem-se em minúsculas, partes com ponto: animais ou escola.secretaria."; +"web_visuobject_new_class_title" = "Nova classe Java"; +"web_visuobject_new_class_hint" = "Os nomes de classe começam com maiúscula, por exemplo Cao ou ContaBancaria."; +"web_visuobject_new_interface_title" = "Nova interface Java"; +"web_visuobject_new_interface_hint" = "Uma interface define métodos que as classes implementam depois."; +"web_visuobject_new_root" = "Source folder"; +"web_visuobject_new_name" = "Nome"; +"web_visuobject_new_modifiers" = "Modificadores"; +"web_visuobject_new_package_private" = "package (sem modificador)"; +"web_visuobject_new_superclass" = "Superclasse"; +"web_visuobject_new_interfaces" = "Interfaces (implements)"; +"web_visuobject_new_extends_interfaces" = "Estende interfaces (extends)"; +"web_visuobject_new_stubs" = "Que esqueletos de métodos criar?"; +"web_visuobject_new_stub_constructors" = "Construtores da superclasse"; +"web_visuobject_new_stub_inherited" = "Métodos abstratos herdados"; +"web_visuobject_new_comment_legend" = "Comentário"; +"web_visuobject_new_comment" = "Comentário Javadoc com @author"; +"web_visuobject_new_author" = "O teu nome"; +"web_visuobject_new_finish" = "Concluir"; +"web_visuobject_new_name_missing" = "Escreve um nome."; +"web_visuobject_new_exists" = "“%@” já existe no projeto."; +"web_visuobject_new_upper" = "Em Java, os nomes de classe começam com maiúscula."; +"web_visuobject_bad_folder" = "“%@” não é um nome de pasta válido ou já existe."; +"web_visuobject_inspector_hide" = "Recolher o inspetor de objetos"; +"web_visuobject_inspector_show" = "Expandir o inspetor de objetos"; +"web_visuobject_inspector_empty" = "Clica numa relação (linha) no diagrama para a editares aqui."; +"web_visuobject_rel_end_a" = "Extremidade A: %@ (a linha começa aqui)"; +"web_visuobject_rel_end_b" = "Extremidade B: %@ (a linha acaba aqui)"; +"web_visuobject_ws_title" = "Pasta do workspace no teu computador"; +"web_visuobject_ws_question" = "Onde guardas os teus projetos?"; +"web_visuobject_ws_hint" = "Como no Eclipse: uma pasta de workspace no teu computador, com uma pasta por projeto com src e os ficheiros .java."; +"web_visuobject_ws_create" = "Criar a pasta “%@”"; +"web_visuobject_ws_open" = "Abrir um workspace existente"; +"web_visuobject_ws_skip" = "Sem pasta (só no browser)"; +"web_visuobject_ws_choose" = "Escolher workspace"; +"web_visuobject_ws_reopen" = "Abrir o workspace “%@”"; +"web_visuobject_ws_switch" = "Mudar"; +"web_visuobject_ws_zip" = "ZIP"; +"web_visuobject_ws_zip_tip" = "Descarregar o projeto como .zip, por exemplo para o entregar"; +"web_visuobject_ws_saved" = "Guardado em %@/%@"; +"web_visuobject_ws_created" = "Novo projeto “%@” no workspace"; +"web_visuobject_ws_failed" = "Não foi possível guardar no workspace: %@"; +"web_visuobject_ws_taken" = "O workspace já tem um projeto “%@”."; +"web_visuobject_ws_open_project" = "Abrir o projeto %@"; +"web_visuobject_save_ws_tip" = "Guardar no workspace (Ctrl+S)"; +"web_visuobject_unsaved" = "não guardado"; +"web_visuobject_rel_nav_navigable" = "navegável (seta)"; +"web_visuobject_rel_nav_non-navigable" = "não navegável (cruz ×)"; +"web_visuobject_rel_nav_unspecified" = "não especificado (aberto)"; +"web_visuobject_rel_reading_flip" = "inverter"; +"web_visuobject_rel_reading_auto" = "Com um nome, a relação lê-se no sentido em que arrastaste."; +"web_visuobject_tools" = "Ferramentas"; +"web_visuobject_tool_select" = "Seleção"; +"web_visuobject_tool_select_tip" = "Selecionar e mover"; +"web_visuobject_tool_class" = "Classe"; +"web_visuobject_tool_class_tip" = "Classe: arrasta para a área ou escolhe e clica na área"; +"web_visuobject_tool_interface" = "Interface"; +"web_visuobject_tool_interface_tip" = "Interface: arrasta para a área ou escolhe e clica na área"; +"web_visuobject_tool_link" = "Associação"; +"web_visuobject_tool_link_tip" = "Associação sem navegação: desenha uma linha simples entre duas classes"; +"web_visuobject_rel_link" = "Associação (sem navegação)"; +"web_visuobject_tool_not_link" = "%@ é uma interface e não pode ter atributos. Arrasta a relação a partir de uma classe."; +"web_visuobject_tool_association" = "Dirigida"; +"web_visuobject_tool_association_tip" = "Associação dirigida: arrasta da classe que conhece a outra para a outra (seta)"; +"web_visuobject_tool_aggregation" = "Agregação"; +"web_visuobject_tool_aggregation_tip" = "Agregação: arrasta do todo para a parte (tem, as partes continuam a existir)"; +"web_visuobject_tool_composition" = "Composição"; +"web_visuobject_tool_composition_tip" = "Composição: arrasta do todo para a parte (é composto por, as partes pertencem-lhe)"; +"web_visuobject_tool_extends" = "Herança"; +"web_visuobject_tool_extends_tip" = "Herança: arrasta da subclasse para a superclasse (extends)"; +"web_visuobject_tool_implements" = "Realização"; +"web_visuobject_tool_implements_tip" = "Realização: arrasta da classe para a interface (implements)"; +"web_visuobject_tool_pick_second" = "Agora clica na segunda classe (a partir de %@). Esc cancela."; +"web_visuobject_tool_not_association" = "%@ é uma interface e não pode ter atributos. Arrasta a relação a partir de uma classe."; +"web_visuobject_tool_not_aggregation" = "%@ é uma interface e não pode ter atributos. Arrasta a relação a partir de uma classe."; +"web_visuobject_tool_not_composition" = "%@ é uma interface e não pode ter atributos. Arrasta a relação a partir de uma classe."; +"web_visuobject_tool_not_extends" = "%@ não pode herdar de %@: classes herdam de classes, interfaces de interfaces. Para uma interface usa a realização."; +"web_visuobject_tool_not_implements" = "%@ não pode implementar %@: só uma classe implementa uma interface."; +"web_visuobject_inspector" = "Inspetor de objetos"; +"web_visuobject_connect" = "Arrastar: relação com outra classe"; +"web_visuobject_rel_association" = "Associação"; +"web_visuobject_rel_directed" = "Associação dirigida"; +"web_visuobject_rel_aggregation" = "Agregação (tem, as partes continuam a existir)"; +"web_visuobject_rel_composition" = "Composição (é composto por, as partes pertencem-lhe)"; +"web_visuobject_rel_extends" = "Herança (extends)"; +"web_visuobject_rel_implements" = "Realização (implements)"; +"web_visuobject_rel_extends_text" = "%@ herda de %@ (extends no código)."; +"web_visuobject_rel_implements_text" = "%@ implementa a interface %@ (implements no código)."; +"web_visuobject_rel_kind" = "Tipo"; +"web_visuobject_rel_name" = "Nome da relação"; +"web_visuobject_rel_name_ph" = "por exemplo, possui"; +"web_visuobject_rel_reading" = "Sentido de leitura"; +"web_visuobject_rel_navigable" = "Navegabilidade"; +"web_visuobject_rel_role" = "Papel"; +"web_visuobject_rel_multiplicity" = "Multiplicidade"; +"web_visuobject_rel_role_field" = "= atributo %@.%@ no código"; +"web_visuobject_rel_role_only_uml" = "só no diagrama (sem atributo enquanto a seta só aponta num sentido)"; +"web_visuobject_rel_delete" = "Eliminar a relação"; +"web_visuobject_rel_impossible" = "Não há uma relação adequada de %@ para %@."; +"web_visuobject_rel_menu" = "%@ → %@"; +"web_visuobject_resize" = "Arrastar para mudar a largura (duplo clique: padrão)"; +"web_visuobject_pane_show" = "Expandir a área"; +"web_visuobject_pane_hide" = "Recolher a área"; +"web_visuobject_close_tab" = "Fechar %@"; +"web_visuobject_collapse" = "Recolher"; +"web_visuobject_expand" = "Expandir"; +"web_visuobject_tree_empty" = "Ainda vazio. Cria um package ou uma classe com «+ Novo»."; +"web_visuobject_delete" = "Eliminar"; +"web_visuobject_default_package" = "(package predefinido)"; +"web_visuobject_bad_package" = "«%@» não é um nome de package válido ou já existe. Os nomes de package escrevem-se em minúsculas, por exemplo animais."; +"web_visuobject_new_package_name" = "novopackage"; +"web_visuobject_no_file" = "Nenhum ficheiro aberto"; +"web_visuobject_project_name" = "MeuProjeto"; +"web_visuobject_explorer_show" = "Mostrar o Package Explorer"; +"web_visuobject_explorer_hide" = "Recolher o Package Explorer"; +"web_visuobject_explorer" = "Package Explorer"; +"web_visuobject_save_tip" = "Guardar o projeto como .zip: NomeDoProjeto/src/package/Classe.java"; +"web_visuobject_open_tip" = "Abrir um projeto (.zip como do Eclipse ou BlueJ) ou juntar ficheiros .java ao projeto"; +"web_visuobject_method_ph" = "+ ladrar(): void"; +"web_code_scopes" = "Blocos coloridos"; +"web_code_scopes_hint" = "Código e diagrama: ciclo rosa, decisão azul, método amarelo, classe verde"; +"web_pseudocode" = "Pseudocódigo"; + +/* VisuFlow (desenhar fluxogramas) */ +"web_visuflow_subtitle" = "Desenhar fluxogramas"; +"web_visuflow_world_hint" = "VisuFlow: desenhar livremente um fluxograma e exportá-lo como imagem ou PDF. Podes mudar a qualquer momento na roda dentada."; +"web_visuflow_palette" = "Símbolos"; +"web_visuflow_palette_hint" = "Toca num símbolo para o juntar abaixo do selecionado, ligado por uma seta. Também o podes arrastar para a área."; +"web_visuflow_shape_start" = "Início"; +"web_visuflow_shape_ende" = "Fim"; +"web_visuflow_shape_anweisung" = "Instrução"; +"web_visuflow_shape_ein" = "Entrada/Saída"; +"web_visuflow_shape_verzweigung" = "Decisão"; +"web_visuflow_shape_unterprogramm" = "Subprograma"; +"web_visuflow_shape_start_tip" = "Oval: aqui começa o fluxo"; +"web_visuflow_shape_ende_tip" = "Oval: aqui termina o fluxo"; +"web_visuflow_shape_anweisung_tip" = "Retângulo: uma instrução, por exemplo «Ferver água»"; +"web_visuflow_shape_ein_tip" = "Paralelogramo: entrada ou saída, por exemplo «Entrada: número»"; +"web_visuflow_shape_verzweigung_tip" = "Losango: uma pergunta com as saídas sim e não"; +"web_visuflow_shape_unterprogramm_tip" = "Retângulo com duas barras: chama um subprograma"; +"web_visuflow_text_start" = "Início"; +"web_visuflow_text_ende" = "Fim"; +"web_visuflow_text_anweisung" = "Instrução"; +"web_visuflow_text_ein" = "Entrada: número"; +"web_visuflow_text_verzweigung" = "Condição?"; +"web_visuflow_text_unterprogramm" = "Subprograma"; +"web_visuflow_new_tip" = "Novo: fluxograma vazio com Início (Anular recupera o anterior)"; +"web_visuflow_open_tip" = "Abrir um ficheiro de fluxograma (.visuflow)"; +"web_visuflow_save_tip" = "Guardar o fluxograma como ficheiro (.visuflow)"; +"web_visuflow_delete" = "Apagar"; +"web_visuflow_delete_tip" = "Apagar o símbolo ou a seta selecionada (Del)"; +"web_visuflow_swap" = "trocar sim/não"; +"web_visuflow_swap_tip" = "Losango: «sim» e «não» trocam de lado"; +"web_visuflow_example" = "Exemplo"; +"web_visuflow_example_tip" = "Carregar o exemplo «Fazer chá» da lição 1 (Anular recupera o fluxograma anterior)"; +"web_visuflow_example_title" = "Fazer chá"; +"web_visuflow_example_water" = "Ferver água"; +"web_visuflow_example_bag" = "Saqueta de chá na chávena"; +"web_visuflow_example_hot" = "O chá ainda está quente demais?"; +"web_visuflow_example_wait" = "Esperar"; +"web_visuflow_example_drink" = "Beber o chá"; +"web_visuflow_title_label" = "Título do fluxograma"; +"web_visuflow_title_ph" = "Título do fluxograma"; +"web_visuflow_canvas_label" = "Área do fluxograma"; +"web_visuflow_open_error" = "Este ficheiro não é um fluxograma VisuFlow."; +"web_visuflow_saved" = "Guardado como %@"; +"web_visuflow_status_empty" = "Arrasta um símbolo da barra para a área ou toca nele."; +"web_visuflow_status_idle" = "Toca num símbolo para o selecionar. Arrasta a partir do ponto na saída para desenhar uma seta até ao próximo símbolo."; +"web_visuflow_status_node" = "Arrasta para mover o símbolo, toca outra vez para mudar o texto. Arrasta uma seta a partir do ponto na saída."; +"web_visuflow_status_edge" = "Seta selecionada. Apagar remove-a."; +"web_visuflow_status_connect" = "Larga sobre o símbolo para onde a seta vai."; +"web_visuflow_edit_label" = "Texto no símbolo"; +`;export{e as default}; diff --git a/website/app/assets/robot3d-DZxNwb67.js b/website/app/assets/robot3d-DZxNwb67.js new file mode 100644 index 00000000..7e616487 --- /dev/null +++ b/website/app/assets/robot3d-DZxNwb67.js @@ -0,0 +1,3955 @@ +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-Bmqo_CbG.js";/** + * @license + * Copyright 2010-2025 Three.js Authors + * SPDX-License-Identifier: MIT + */const Na="181",yi={ROTATE:0,DOLLY:1,PAN:2},vi={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},vl=0,co=1,Ml=2,bc=1,Ec=2,_n=3,Fn=0,Le=1,Mn=2,yn=0,bi=1,lo=2,ho=3,uo=4,Sl=5,Yn=100,yl=101,bl=102,El=103,Tl=104,Al=200,wl=201,Rl=202,Cl=203,Gr=204,kr=205,Pl=206,Dl=207,Ll=208,Il=209,Ul=210,Nl=211,Fl=212,Ol=213,Bl=214,Hr=0,Wr=1,Xr=2,Ti=3,qr=4,Yr=5,Zr=6,Kr=7,Fa=0,zl=1,Vl=2,Un=0,Gl=1,kl=2,Hl=3,Tc=4,Wl=5,Xl=6,ql=7,Ac=300,Ai=301,wi=302,jr=303,Jr=304,Js=306,$r=1e3,Sn=1001,Qr=1002,He=1003,Yl=1004,us=1005,Ye=1006,ir=1007,Kn=1008,hn=1009,wc=1010,Rc=1011,Qi=1012,Oa=1013,jn=1014,on=1015,Di=1016,Ba=1017,za=1018,ts=1020,Cc=35902,Pc=35899,Dc=1021,Lc=1022,tn=1023,es=1026,ns=1027,Va=1028,Ga=1029,ka=1030,Ha=1031,Wa=1033,Bs=33776,zs=33777,Vs=33778,Gs=33779,ta=35840,ea=35841,na=35842,ia=35843,sa=36196,ra=37492,aa=37496,oa=37808,ca=37809,la=37810,ha=37811,ua=37812,fa=37813,da=37814,pa=37815,ma=37816,xa=37817,ga=37818,_a=37819,va=37820,Ma=37821,Sa=36492,ya=36494,ba=36495,Ea=36283,Ta=36284,Aa=36285,wa=36286,Zl=3200,Kl=3201,Xa=0,jl=1,Ln="",De="srgb",Ri="srgb-linear",Ws="linear",ne="srgb",ii=7680,fo=519,Jl=512,$l=513,Ql=514,Ic=515,th=516,eh=517,nh=518,ih=519,po=35044,mo="300 es",cn=2e3,Xs=2001;function Uc(i){for(let t=i.length-1;t>=0;--t)if(i[t]>=65535)return!0;return!1}function qs(i){return document.createElementNS("http://www.w3.org/1999/xhtml",i)}function sh(){const i=qs("canvas");return i.style.display="block",i}const xo={};function go(...i){const t="THREE."+i.shift();console.log(t,...i)}function Bt(...i){const t="THREE."+i.shift();console.warn(t,...i)}function de(...i){const t="THREE."+i.shift();console.error(t,...i)}function is(...i){const t=i.join(" ");t in xo||(xo[t]=!0,Bt(...i))}function rh(i,t,e){return new Promise(function(n,s){function r(){switch(i.clientWaitSync(t,i.SYNC_FLUSH_COMMANDS_BIT,0)){case i.WAIT_FAILED:s();break;case i.TIMEOUT_EXPIRED:setTimeout(r,e);break;default:n()}}setTimeout(r,e)})}class ti{addEventListener(t,e){this._listeners===void 0&&(this._listeners={});const n=this._listeners;n[t]===void 0&&(n[t]=[]),n[t].indexOf(e)===-1&&n[t].push(e)}hasEventListener(t,e){const n=this._listeners;return n===void 0?!1:n[t]!==void 0&&n[t].indexOf(e)!==-1}removeEventListener(t,e){const n=this._listeners;if(n===void 0)return;const s=n[t];if(s!==void 0){const r=s.indexOf(e);r!==-1&&s.splice(r,1)}}dispatchEvent(t){const e=this._listeners;if(e===void 0)return;const n=e[t.type];if(n!==void 0){t.target=this;const s=n.slice(0);for(let r=0,a=s.length;r>8&255]+Ae[i>>16&255]+Ae[i>>24&255]+"-"+Ae[t&255]+Ae[t>>8&255]+"-"+Ae[t>>16&15|64]+Ae[t>>24&255]+"-"+Ae[e&63|128]+Ae[e>>8&255]+"-"+Ae[e>>16&255]+Ae[e>>24&255]+Ae[n&255]+Ae[n>>8&255]+Ae[n>>16&255]+Ae[n>>24&255]).toLowerCase()}function Xt(i,t,e){return Math.max(t,Math.min(e,i))}function ah(i,t){return(i%t+t)%t}function sr(i,t,e){return(1-e)*i+e*t}function Fi(i,t){switch(t.constructor){case Float32Array:return i;case Uint32Array:return i/4294967295;case Uint16Array:return i/65535;case Uint8Array:return i/255;case Int32Array:return Math.max(i/2147483647,-1);case Int16Array:return Math.max(i/32767,-1);case Int8Array:return Math.max(i/127,-1);default:throw new Error("Invalid component type.")}}function Fe(i,t){switch(t.constructor){case Float32Array:return i;case Uint32Array:return Math.round(i*4294967295);case Uint16Array:return Math.round(i*65535);case Uint8Array:return Math.round(i*255);case Int32Array:return Math.round(i*2147483647);case Int16Array:return Math.round(i*32767);case Int8Array:return Math.round(i*127);default:throw new Error("Invalid component type.")}}const oh={DEG2RAD:ks};class at{constructor(t=0,e=0){at.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,n=this.y,s=t.elements;return this.x=s[0]*e+s[3]*n+s[6],this.y=s[1]*e+s[4]*n+s[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Xt(this.x,t.x,e.x),this.y=Xt(this.y,t.y,e.y),this}clampScalar(t,e){return this.x=Xt(this.x,t,e),this.y=Xt(this.y,t,e),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Xt(n,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(e===0)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Xt(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const n=Math.cos(e),s=Math.sin(e),r=this.x-t.x,a=this.y-t.y;return this.x=r*n-a*s+t.x,this.y=r*s+a*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Jn{constructor(t=0,e=0,n=0,s=1){this.isQuaternion=!0,this._x=t,this._y=e,this._z=n,this._w=s}static slerpFlat(t,e,n,s,r,a,o){let l=n[s+0],c=n[s+1],h=n[s+2],u=n[s+3],d=r[a+0],p=r[a+1],x=r[a+2],_=r[a+3];if(o<=0){t[e+0]=l,t[e+1]=c,t[e+2]=h,t[e+3]=u;return}if(o>=1){t[e+0]=d,t[e+1]=p,t[e+2]=x,t[e+3]=_;return}if(u!==_||l!==d||c!==p||h!==x){let m=l*d+c*p+h*x+u*_;m<0&&(d=-d,p=-p,x=-x,_=-_,m=-m);let f=1-o;if(m<.9995){const b=Math.acos(m),S=Math.sin(b);f=Math.sin(f*b)/S,o=Math.sin(o*b)/S,l=l*f+d*o,c=c*f+p*o,h=h*f+x*o,u=u*f+_*o}else{l=l*f+d*o,c=c*f+p*o,h=h*f+x*o,u=u*f+_*o;const b=1/Math.sqrt(l*l+c*c+h*h+u*u);l*=b,c*=b,h*=b,u*=b}}t[e]=l,t[e+1]=c,t[e+2]=h,t[e+3]=u}static multiplyQuaternionsFlat(t,e,n,s,r,a){const o=n[s],l=n[s+1],c=n[s+2],h=n[s+3],u=r[a],d=r[a+1],p=r[a+2],x=r[a+3];return t[e]=o*x+h*u+l*p-c*d,t[e+1]=l*x+h*d+c*u-o*p,t[e+2]=c*x+h*p+o*d-l*u,t[e+3]=h*x-o*u-l*d-c*p,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,n,s){return this._x=t,this._y=e,this._z=n,this._w=s,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e=!0){const n=t._x,s=t._y,r=t._z,a=t._order,o=Math.cos,l=Math.sin,c=o(n/2),h=o(s/2),u=o(r/2),d=l(n/2),p=l(s/2),x=l(r/2);switch(a){case"XYZ":this._x=d*h*u+c*p*x,this._y=c*p*u-d*h*x,this._z=c*h*x+d*p*u,this._w=c*h*u-d*p*x;break;case"YXZ":this._x=d*h*u+c*p*x,this._y=c*p*u-d*h*x,this._z=c*h*x-d*p*u,this._w=c*h*u+d*p*x;break;case"ZXY":this._x=d*h*u-c*p*x,this._y=c*p*u+d*h*x,this._z=c*h*x+d*p*u,this._w=c*h*u-d*p*x;break;case"ZYX":this._x=d*h*u-c*p*x,this._y=c*p*u+d*h*x,this._z=c*h*x-d*p*u,this._w=c*h*u+d*p*x;break;case"YZX":this._x=d*h*u+c*p*x,this._y=c*p*u+d*h*x,this._z=c*h*x-d*p*u,this._w=c*h*u-d*p*x;break;case"XZY":this._x=d*h*u-c*p*x,this._y=c*p*u-d*h*x,this._z=c*h*x+d*p*u,this._w=c*h*u+d*p*x;break;default:Bt("Quaternion: .setFromEuler() encountered an unknown order: "+a)}return e===!0&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,s=Math.sin(n);return this._x=t.x*s,this._y=t.y*s,this._z=t.z*s,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],s=e[4],r=e[8],a=e[1],o=e[5],l=e[9],c=e[2],h=e[6],u=e[10],d=n+o+u;if(d>0){const p=.5/Math.sqrt(d+1);this._w=.25/p,this._x=(h-l)*p,this._y=(r-c)*p,this._z=(a-s)*p}else if(n>o&&n>u){const p=2*Math.sqrt(1+n-o-u);this._w=(h-l)/p,this._x=.25*p,this._y=(s+a)/p,this._z=(r+c)/p}else if(o>u){const p=2*Math.sqrt(1+o-n-u);this._w=(r-c)/p,this._x=(s+a)/p,this._y=.25*p,this._z=(l+h)/p}else{const p=2*Math.sqrt(1+u-n-o);this._w=(a-s)/p,this._x=(r+c)/p,this._y=(l+h)/p,this._z=.25*p}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return n<1e-8?(n=0,Math.abs(t.x)>Math.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Xt(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(n===0)return this;const s=Math.min(1,e/n);return this.slerp(t,s),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return t===0?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const n=t._x,s=t._y,r=t._z,a=t._w,o=e._x,l=e._y,c=e._z,h=e._w;return this._x=n*h+a*o+s*c-r*l,this._y=s*h+a*l+r*o-n*c,this._z=r*h+a*c+n*l-s*o,this._w=a*h-n*o-s*l-r*c,this._onChangeCallback(),this}slerp(t,e){if(e<=0)return this;if(e>=1)return this.copy(t);let n=t._x,s=t._y,r=t._z,a=t._w,o=this.dot(t);o<0&&(n=-n,s=-s,r=-r,a=-a,o=-o);let l=1-e;if(o<.9995){const c=Math.acos(o),h=Math.sin(c);l=Math.sin(l*c)/h,e=Math.sin(e*c)/h,this._x=this._x*l+n*e,this._y=this._y*l+s*e,this._z=this._z*l+r*e,this._w=this._w*l+a*e,this._onChangeCallback()}else this._x=this._x*l+n*e,this._y=this._y*l+s*e,this._z=this._z*l+r*e,this._w=this._w*l+a*e,this.normalize();return this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=2*Math.PI*Math.random(),e=2*Math.PI*Math.random(),n=Math.random(),s=Math.sqrt(1-n),r=Math.sqrt(n);return this.set(s*Math.sin(t),s*Math.cos(t),r*Math.sin(e),r*Math.cos(e))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class D{constructor(t=0,e=0,n=0){D.prototype.isVector3=!0,this.x=t,this.y=e,this.z=n}set(t,e,n){return n===void 0&&(n=this.z),this.x=t,this.y=e,this.z=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(_o.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(_o.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,s=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*s,this.y=r[1]*e+r[4]*n+r[7]*s,this.z=r[2]*e+r[5]*n+r[8]*s,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,s=this.z,r=t.elements,a=1/(r[3]*e+r[7]*n+r[11]*s+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*s+r[12])*a,this.y=(r[1]*e+r[5]*n+r[9]*s+r[13])*a,this.z=(r[2]*e+r[6]*n+r[10]*s+r[14])*a,this}applyQuaternion(t){const e=this.x,n=this.y,s=this.z,r=t.x,a=t.y,o=t.z,l=t.w,c=2*(a*s-o*n),h=2*(o*e-r*s),u=2*(r*n-a*e);return this.x=e+l*c+a*u-o*h,this.y=n+l*h+o*c-r*u,this.z=s+l*u+r*h-a*c,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,n=this.y,s=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*s,this.y=r[1]*e+r[5]*n+r[9]*s,this.z=r[2]*e+r[6]*n+r[10]*s,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Xt(this.x,t.x,e.x),this.y=Xt(this.y,t.y,e.y),this.z=Xt(this.z,t.z,e.z),this}clampScalar(t,e){return this.x=Xt(this.x,t,e),this.y=Xt(this.y,t,e),this.z=Xt(this.z,t,e),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Xt(n,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,s=t.y,r=t.z,a=e.x,o=e.y,l=e.z;return this.x=s*l-r*o,this.y=r*a-n*l,this.z=n*o-s*a,this}projectOnVector(t){const e=t.lengthSq();if(e===0)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return rr.copy(this).projectOnVector(t),this.sub(rr)}reflect(t){return this.sub(rr.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(e===0)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Xt(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,s=this.z-t.z;return e*e+n*n+s*s}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,n){const s=Math.sin(e)*t;return this.x=s*Math.sin(n),this.y=Math.cos(e)*t,this.z=s*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),s=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=s,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,e*4)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,e*3)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=Math.random()*Math.PI*2,e=Math.random()*2-1,n=Math.sqrt(1-e*e);return this.x=n*Math.cos(t),this.y=e,this.z=n*Math.sin(t),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const rr=new D,_o=new Jn;class Ht{constructor(t,e,n,s,r,a,o,l,c){Ht.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],t!==void 0&&this.set(t,e,n,s,r,a,o,l,c)}set(t,e,n,s,r,a,o,l,c){const h=this.elements;return h[0]=t,h[1]=s,h[2]=o,h[3]=e,h[4]=r,h[5]=l,h[6]=n,h[7]=a,h[8]=c,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,s=e.elements,r=this.elements,a=n[0],o=n[3],l=n[6],c=n[1],h=n[4],u=n[7],d=n[2],p=n[5],x=n[8],_=s[0],m=s[3],f=s[6],b=s[1],S=s[4],T=s[7],R=s[2],w=s[5],L=s[8];return r[0]=a*_+o*b+l*R,r[3]=a*m+o*S+l*w,r[6]=a*f+o*T+l*L,r[1]=c*_+h*b+u*R,r[4]=c*m+h*S+u*w,r[7]=c*f+h*T+u*L,r[2]=d*_+p*b+x*R,r[5]=d*m+p*S+x*w,r[8]=d*f+p*T+x*L,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[1],s=t[2],r=t[3],a=t[4],o=t[5],l=t[6],c=t[7],h=t[8];return e*a*h-e*o*c-n*r*h+n*o*l+s*r*c-s*a*l}invert(){const t=this.elements,e=t[0],n=t[1],s=t[2],r=t[3],a=t[4],o=t[5],l=t[6],c=t[7],h=t[8],u=h*a-o*c,d=o*l-h*r,p=c*r-a*l,x=e*u+n*d+s*p;if(x===0)return this.set(0,0,0,0,0,0,0,0,0);const _=1/x;return t[0]=u*_,t[1]=(s*c-h*n)*_,t[2]=(o*n-s*a)*_,t[3]=d*_,t[4]=(h*e-s*l)*_,t[5]=(s*r-o*e)*_,t[6]=p*_,t[7]=(n*l-c*e)*_,t[8]=(a*e-n*r)*_,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,n,s,r,a,o){const l=Math.cos(r),c=Math.sin(r);return this.set(n*l,n*c,-n*(l*a+c*o)+a+t,-s*c,s*l,-s*(-c*a+l*o)+o+e,0,0,1),this}scale(t,e){return this.premultiply(ar.makeScale(t,e)),this}rotate(t){return this.premultiply(ar.makeRotation(-t)),this}translate(t,e){return this.premultiply(ar.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,n,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,n=t.elements;for(let s=0;s<9;s++)if(e[s]!==n[s])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return new this.constructor().fromArray(this.elements)}}const ar=new Ht,vo=new Ht().set(.4123908,.3575843,.1804808,.212639,.7151687,.0721923,.0193308,.1191948,.9505322),Mo=new Ht().set(3.2409699,-1.5373832,-.4986108,-.9692436,1.8759675,.0415551,.0556301,-.203977,1.0569715);function ch(){const i={enabled:!0,workingColorSpace:Ri,spaces:{},convert:function(s,r,a){return this.enabled===!1||r===a||!r||!a||(this.spaces[r].transfer===ne&&(s.r=bn(s.r),s.g=bn(s.g),s.b=bn(s.b)),this.spaces[r].primaries!==this.spaces[a].primaries&&(s.applyMatrix3(this.spaces[r].toXYZ),s.applyMatrix3(this.spaces[a].fromXYZ)),this.spaces[a].transfer===ne&&(s.r=Ei(s.r),s.g=Ei(s.g),s.b=Ei(s.b))),s},workingToColorSpace:function(s,r){return this.convert(s,this.workingColorSpace,r)},colorSpaceToWorking:function(s,r){return this.convert(s,r,this.workingColorSpace)},getPrimaries:function(s){return this.spaces[s].primaries},getTransfer:function(s){return s===Ln?Ws:this.spaces[s].transfer},getToneMappingMode:function(s){return this.spaces[s].outputColorSpaceConfig.toneMappingMode||"standard"},getLuminanceCoefficients:function(s,r=this.workingColorSpace){return s.fromArray(this.spaces[r].luminanceCoefficients)},define:function(s){Object.assign(this.spaces,s)},_getMatrix:function(s,r,a){return s.copy(this.spaces[r].toXYZ).multiply(this.spaces[a].fromXYZ)},_getDrawingBufferColorSpace:function(s){return this.spaces[s].outputColorSpaceConfig.drawingBufferColorSpace},_getUnpackColorSpace:function(s=this.workingColorSpace){return this.spaces[s].workingColorSpaceConfig.unpackColorSpace},fromWorkingColorSpace:function(s,r){return is("ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace()."),i.workingToColorSpace(s,r)},toWorkingColorSpace:function(s,r){return is("ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking()."),i.colorSpaceToWorking(s,r)}},t=[.64,.33,.3,.6,.15,.06],e=[.2126,.7152,.0722],n=[.3127,.329];return i.define({[Ri]:{primaries:t,whitePoint:n,transfer:Ws,toXYZ:vo,fromXYZ:Mo,luminanceCoefficients:e,workingColorSpaceConfig:{unpackColorSpace:De},outputColorSpaceConfig:{drawingBufferColorSpace:De}},[De]:{primaries:t,whitePoint:n,transfer:ne,toXYZ:vo,fromXYZ:Mo,luminanceCoefficients:e,outputColorSpaceConfig:{drawingBufferColorSpace:De}}}),i}const $t=ch();function bn(i){return i<.04045?i*.0773993808:Math.pow(i*.9478672986+.0521327014,2.4)}function Ei(i){return i<.0031308?i*12.92:1.055*Math.pow(i,.41666)-.055}let si;class lh{static getDataURL(t,e="image/png"){if(/^data:/i.test(t.src)||typeof HTMLCanvasElement>"u")return t.src;let n;if(t instanceof HTMLCanvasElement)n=t;else{si===void 0&&(si=qs("canvas")),si.width=t.width,si.height=t.height;const s=si.getContext("2d");t instanceof ImageData?s.putImageData(t,0,0):s.drawImage(t,0,0,t.width,t.height),n=si}return n.toDataURL(e)}static sRGBToLinear(t){if(typeof HTMLImageElement<"u"&&t instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&t instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&t instanceof ImageBitmap){const e=qs("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n.drawImage(t,0,0,t.width,t.height);const s=n.getImageData(0,0,t.width,t.height),r=s.data;for(let a=0;a1),this.pmremVersion=0}get width(){return this.source.getSize(cr).x}get height(){return this.source.getSize(cr).y}get depth(){return this.source.getSize(cr).z}get image(){return this.source.data}set image(t=null){this.source.data=t}updateMatrix(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}clone(){return new this.constructor().copy(this)}copy(t){return this.name=t.name,this.source=t.source,this.mipmaps=t.mipmaps.slice(0),this.mapping=t.mapping,this.channel=t.channel,this.wrapS=t.wrapS,this.wrapT=t.wrapT,this.magFilter=t.magFilter,this.minFilter=t.minFilter,this.anisotropy=t.anisotropy,this.format=t.format,this.internalFormat=t.internalFormat,this.type=t.type,this.offset.copy(t.offset),this.repeat.copy(t.repeat),this.center.copy(t.center),this.rotation=t.rotation,this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrix.copy(t.matrix),this.generateMipmaps=t.generateMipmaps,this.premultiplyAlpha=t.premultiplyAlpha,this.flipY=t.flipY,this.unpackAlignment=t.unpackAlignment,this.colorSpace=t.colorSpace,this.renderTarget=t.renderTarget,this.isRenderTargetTexture=t.isRenderTargetTexture,this.isArrayTexture=t.isArrayTexture,this.userData=JSON.parse(JSON.stringify(t.userData)),this.needsUpdate=!0,this}setValues(t){for(const e in t){const n=t[e];if(n===void 0){Bt(`Texture.setValues(): parameter '${e}' has value of undefined.`);continue}const s=this[e];if(s===void 0){Bt(`Texture.setValues(): property '${e}' does not exist.`);continue}s&&n&&s.isVector2&&n.isVector2||s&&n&&s.isVector3&&n.isVector3||s&&n&&s.isMatrix3&&n.isMatrix3?s.copy(n):this[e]=n}}toJSON(t){const e=t===void 0||typeof t=="string";if(!e&&t.textures[this.uuid]!==void 0)return t.textures[this.uuid];const n={metadata:{version:4.7,type:"Texture",generator:"Texture.toJSON"},uuid:this.uuid,name:this.name,image:this.source.toJSON(t).uuid,mapping:this.mapping,channel:this.channel,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,internalFormat:this.internalFormat,type:this.type,colorSpace:this.colorSpace,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,generateMipmaps:this.generateMipmaps,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};return Object.keys(this.userData).length>0&&(n.userData=this.userData),e||(t.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==Ac)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case $r:t.x=t.x-Math.floor(t.x);break;case Sn:t.x=t.x<0?0:1;break;case Qr:Math.abs(Math.floor(t.x)%2)===1?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x);break}if(t.y<0||t.y>1)switch(this.wrapT){case $r:t.y=t.y-Math.floor(t.y);break;case Sn:t.y=t.y<0?0:1;break;case Qr:Math.abs(Math.floor(t.y)%2)===1?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y);break}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){t===!0&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(t){t===!0&&this.pmremVersion++}}Re.DEFAULT_IMAGE=null;Re.DEFAULT_MAPPING=Ac;Re.DEFAULT_ANISOTROPY=1;class se{constructor(t=0,e=0,n=0,s=1){se.prototype.isVector4=!0,this.x=t,this.y=e,this.z=n,this.w=s}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,n,s){return this.x=t,this.y=e,this.z=n,this.w=s,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=t.w!==void 0?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,n=this.y,s=this.z,r=this.w,a=t.elements;return this.x=a[0]*e+a[4]*n+a[8]*s+a[12]*r,this.y=a[1]*e+a[5]*n+a[9]*s+a[13]*r,this.z=a[2]*e+a[6]*n+a[10]*s+a[14]*r,this.w=a[3]*e+a[7]*n+a[11]*s+a[15]*r,this}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this.w/=t.w,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,n,s,r;const l=t.elements,c=l[0],h=l[4],u=l[8],d=l[1],p=l[5],x=l[9],_=l[2],m=l[6],f=l[10];if(Math.abs(h-d)<.01&&Math.abs(u-_)<.01&&Math.abs(x-m)<.01){if(Math.abs(h+d)<.1&&Math.abs(u+_)<.1&&Math.abs(x+m)<.1&&Math.abs(c+p+f-3)<.1)return this.set(1,0,0,0),this;e=Math.PI;const S=(c+1)/2,T=(p+1)/2,R=(f+1)/2,w=(h+d)/4,L=(u+_)/4,F=(x+m)/4;return S>T&&S>R?S<.01?(n=0,s=.707106781,r=.707106781):(n=Math.sqrt(S),s=w/n,r=L/n):T>R?T<.01?(n=.707106781,s=0,r=.707106781):(s=Math.sqrt(T),n=w/s,r=F/s):R<.01?(n=.707106781,s=.707106781,r=0):(r=Math.sqrt(R),n=L/r,s=F/r),this.set(n,s,r,e),this}let b=Math.sqrt((m-x)*(m-x)+(u-_)*(u-_)+(d-h)*(d-h));return Math.abs(b)<.001&&(b=1),this.x=(m-x)/b,this.y=(u-_)/b,this.z=(d-h)/b,this.w=Math.acos((c+p+f-1)/2),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this.w=e[15],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this.w=Math.min(this.w,t.w),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this.w=Math.max(this.w,t.w),this}clamp(t,e){return this.x=Xt(this.x,t.x,e.x),this.y=Xt(this.y,t.y,e.y),this.z=Xt(this.z,t.z,e.z),this.w=Xt(this.w,t.w,e.w),this}clampScalar(t,e){return this.x=Xt(this.x,t,e),this.y=Xt(this.y,t,e),this.z=Xt(this.z,t,e),this.w=Xt(this.w,t,e),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Xt(n,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this.w=Math.trunc(this.w),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z+this.w*t.w}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this.w+=(t.w-this.w)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this.w=t.w+(e.w-t.w)*n,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z&&t.w===this.w}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this.w=t[e+3],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t[e+3]=this.w,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this.w=t.getW(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this.w=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z,yield this.w}}class fh extends ti{constructor(t=1,e=1,n={}){super(),n=Object.assign({generateMipmaps:!1,internalFormat:null,minFilter:Ye,depthBuffer:!0,stencilBuffer:!1,resolveDepthBuffer:!0,resolveStencilBuffer:!0,depthTexture:null,samples:0,count:1,depth:1,multiview:!1},n),this.isRenderTarget=!0,this.width=t,this.height=e,this.depth=n.depth,this.scissor=new se(0,0,t,e),this.scissorTest=!1,this.viewport=new se(0,0,t,e);const s={width:t,height:e,depth:n.depth},r=new Re(s);this.textures=[];const a=n.count;for(let o=0;o1);this.dispose()}this.viewport.set(0,0,t,e),this.scissor.set(0,0,t,e)}clone(){return new this.constructor().copy(this)}copy(t){this.width=t.width,this.height=t.height,this.depth=t.depth,this.scissor.copy(t.scissor),this.scissorTest=t.scissorTest,this.viewport.copy(t.viewport),this.textures.length=0;for(let e=0,n=t.textures.length;e=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y&&t.z>=this.min.z&&t.z<=this.max.z}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return t.max.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y&&t.max.z>=this.min.z&&t.min.z<=this.max.z}intersectsSphere(t){return this.clampPoint(t.center,Ke),Ke.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(Oi),ds.subVectors(this.max,Oi),ri.subVectors(t.a,Oi),ai.subVectors(t.b,Oi),oi.subVectors(t.c,Oi),Tn.subVectors(ai,ri),An.subVectors(oi,ai),Vn.subVectors(ri,oi);let e=[0,-Tn.z,Tn.y,0,-An.z,An.y,0,-Vn.z,Vn.y,Tn.z,0,-Tn.x,An.z,0,-An.x,Vn.z,0,-Vn.x,-Tn.y,Tn.x,0,-An.y,An.x,0,-Vn.y,Vn.x,0];return!lr(e,ri,ai,oi,ds)||(e=[1,0,0,0,1,0,0,0,1],!lr(e,ri,ai,oi,ds))?!1:(ps.crossVectors(Tn,An),e=[ps.x,ps.y,ps.z],lr(e,ri,ai,oi,ds))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Ke).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=this.getSize(Ke).length()*.5),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()?this:(fn[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),fn[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),fn[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),fn[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),fn[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),fn[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),fn[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),fn[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(fn),this)}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}toJSON(){return{min:this.min.toArray(),max:this.max.toArray()}}fromJSON(t){return this.min.fromArray(t.min),this.max.fromArray(t.max),this}}const fn=[new D,new D,new D,new D,new D,new D,new D,new D],Ke=new D,fs=new On,ri=new D,ai=new D,oi=new D,Tn=new D,An=new D,Vn=new D,Oi=new D,ds=new D,ps=new D,Gn=new D;function lr(i,t,e,n,s){for(let r=0,a=i.length-3;r<=a;r+=3){Gn.fromArray(i,r);const o=s.x*Math.abs(Gn.x)+s.y*Math.abs(Gn.y)+s.z*Math.abs(Gn.z),l=t.dot(Gn),c=e.dot(Gn),h=n.dot(Gn);if(Math.max(-Math.max(l,c,h),Math.min(l,c,h))>o)return!1}return!0}const ph=new On,Bi=new D,hr=new D;class Ii{constructor(t=new D,e=-1){this.isSphere=!0,this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;e!==void 0?n.copy(e):ph.setFromPoints(t).getCenter(n);let s=0;for(let r=0,a=t.length;rthis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;Bi.subVectors(t,this.center);const e=Bi.lengthSq();if(e>this.radius*this.radius){const n=Math.sqrt(e),s=(n-this.radius)*.5;this.center.addScaledVector(Bi,s/n),this.radius+=s}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(this.center.equals(t.center)===!0?this.radius=Math.max(this.radius,t.radius):(hr.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(Bi.copy(t.center).add(hr)),this.expandByPoint(Bi.copy(t.center).sub(hr))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return new this.constructor().copy(this)}toJSON(){return{radius:this.radius,center:this.center.toArray()}}fromJSON(t){return this.radius=t.radius,this.center.fromArray(t.center),this}}const dn=new D,ur=new D,ms=new D,wn=new D,fr=new D,xs=new D,dr=new D;class $s{constructor(t=new D,e=new D(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,dn)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=dn.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(dn.copy(this.origin).addScaledVector(this.direction,e),dn.distanceToSquared(t))}distanceSqToSegment(t,e,n,s){ur.copy(t).add(e).multiplyScalar(.5),ms.copy(e).sub(t).normalize(),wn.copy(this.origin).sub(ur);const r=t.distanceTo(e)*.5,a=-this.direction.dot(ms),o=wn.dot(this.direction),l=-wn.dot(ms),c=wn.lengthSq(),h=Math.abs(1-a*a);let u,d,p,x;if(h>0)if(u=a*l-o,d=a*o-l,x=r*h,u>=0)if(d>=-x)if(d<=x){const _=1/h;u*=_,d*=_,p=u*(u+a*d+2*o)+d*(a*u+d+2*l)+c}else d=r,u=Math.max(0,-(a*d+o)),p=-u*u+d*(d+2*l)+c;else d=-r,u=Math.max(0,-(a*d+o)),p=-u*u+d*(d+2*l)+c;else d<=-x?(u=Math.max(0,-(-a*r+o)),d=u>0?-r:Math.min(Math.max(-r,-l),r),p=-u*u+d*(d+2*l)+c):d<=x?(u=0,d=Math.min(Math.max(-r,-l),r),p=d*(d+2*l)+c):(u=Math.max(0,-(a*r+o)),d=u>0?r:Math.min(Math.max(-r,-l),r),p=-u*u+d*(d+2*l)+c);else d=a>0?-r:r,u=Math.max(0,-(a*d+o)),p=-u*u+d*(d+2*l)+c;return n&&n.copy(this.origin).addScaledVector(this.direction,u),s&&s.copy(ur).addScaledVector(ms,d),p}intersectSphere(t,e){dn.subVectors(t.center,this.origin);const n=dn.dot(this.direction),s=dn.dot(dn)-n*n,r=t.radius*t.radius;if(s>r)return null;const a=Math.sqrt(r-s),o=n-a,l=n+a;return l<0?null:o<0?this.at(l,e):this.at(o,e)}intersectsSphere(t){return t.radius<0?!1:this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(e===0)return t.distanceToPoint(this.origin)===0?0:null;const n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return n===null?null:this.at(n,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);return e===0||t.normal.dot(this.direction)*e<0}intersectBox(t,e){let n,s,r,a,o,l;const c=1/this.direction.x,h=1/this.direction.y,u=1/this.direction.z,d=this.origin;return c>=0?(n=(t.min.x-d.x)*c,s=(t.max.x-d.x)*c):(n=(t.max.x-d.x)*c,s=(t.min.x-d.x)*c),h>=0?(r=(t.min.y-d.y)*h,a=(t.max.y-d.y)*h):(r=(t.max.y-d.y)*h,a=(t.min.y-d.y)*h),n>a||r>s||((r>n||isNaN(n))&&(n=r),(a=0?(o=(t.min.z-d.z)*u,l=(t.max.z-d.z)*u):(o=(t.max.z-d.z)*u,l=(t.min.z-d.z)*u),n>l||o>s)||((o>n||n!==n)&&(n=o),(l=0?n:s,e)}intersectsBox(t){return this.intersectBox(t,dn)!==null}intersectTriangle(t,e,n,s,r){fr.subVectors(e,t),xs.subVectors(n,t),dr.crossVectors(fr,xs);let a=this.direction.dot(dr),o;if(a>0){if(s)return null;o=1}else if(a<0)o=-1,a=-a;else return null;wn.subVectors(this.origin,t);const l=o*this.direction.dot(xs.crossVectors(wn,xs));if(l<0)return null;const c=o*this.direction.dot(fr.cross(wn));if(c<0||l+c>a)return null;const h=-o*wn.dot(dr);return h<0?null:this.at(h/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return new this.constructor().copy(this)}}class re{constructor(t,e,n,s,r,a,o,l,c,h,u,d,p,x,_,m){re.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],t!==void 0&&this.set(t,e,n,s,r,a,o,l,c,h,u,d,p,x,_,m)}set(t,e,n,s,r,a,o,l,c,h,u,d,p,x,_,m){const f=this.elements;return f[0]=t,f[4]=e,f[8]=n,f[12]=s,f[1]=r,f[5]=a,f[9]=o,f[13]=l,f[2]=c,f[6]=h,f[10]=u,f[14]=d,f[3]=p,f[7]=x,f[11]=_,f[15]=m,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return new re().fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,s=1/ci.setFromMatrixColumn(t,0).length(),r=1/ci.setFromMatrixColumn(t,1).length(),a=1/ci.setFromMatrixColumn(t,2).length();return e[0]=n[0]*s,e[1]=n[1]*s,e[2]=n[2]*s,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*a,e[9]=n[9]*a,e[10]=n[10]*a,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,n=t.x,s=t.y,r=t.z,a=Math.cos(n),o=Math.sin(n),l=Math.cos(s),c=Math.sin(s),h=Math.cos(r),u=Math.sin(r);if(t.order==="XYZ"){const d=a*h,p=a*u,x=o*h,_=o*u;e[0]=l*h,e[4]=-l*u,e[8]=c,e[1]=p+x*c,e[5]=d-_*c,e[9]=-o*l,e[2]=_-d*c,e[6]=x+p*c,e[10]=a*l}else if(t.order==="YXZ"){const d=l*h,p=l*u,x=c*h,_=c*u;e[0]=d+_*o,e[4]=x*o-p,e[8]=a*c,e[1]=a*u,e[5]=a*h,e[9]=-o,e[2]=p*o-x,e[6]=_+d*o,e[10]=a*l}else if(t.order==="ZXY"){const d=l*h,p=l*u,x=c*h,_=c*u;e[0]=d-_*o,e[4]=-a*u,e[8]=x+p*o,e[1]=p+x*o,e[5]=a*h,e[9]=_-d*o,e[2]=-a*c,e[6]=o,e[10]=a*l}else if(t.order==="ZYX"){const d=a*h,p=a*u,x=o*h,_=o*u;e[0]=l*h,e[4]=x*c-p,e[8]=d*c+_,e[1]=l*u,e[5]=_*c+d,e[9]=p*c-x,e[2]=-c,e[6]=o*l,e[10]=a*l}else if(t.order==="YZX"){const d=a*l,p=a*c,x=o*l,_=o*c;e[0]=l*h,e[4]=_-d*u,e[8]=x*u+p,e[1]=u,e[5]=a*h,e[9]=-o*h,e[2]=-c*h,e[6]=p*u+x,e[10]=d-_*u}else if(t.order==="XZY"){const d=a*l,p=a*c,x=o*l,_=o*c;e[0]=l*h,e[4]=-u,e[8]=c*h,e[1]=d*u+_,e[5]=a*h,e[9]=p*u-x,e[2]=x*u-p,e[6]=o*h,e[10]=_*u+d}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(mh,t,xh)}lookAt(t,e,n){const s=this.elements;return Ve.subVectors(t,e),Ve.lengthSq()===0&&(Ve.z=1),Ve.normalize(),Rn.crossVectors(n,Ve),Rn.lengthSq()===0&&(Math.abs(n.z)===1?Ve.x+=1e-4:Ve.z+=1e-4,Ve.normalize(),Rn.crossVectors(n,Ve)),Rn.normalize(),gs.crossVectors(Ve,Rn),s[0]=Rn.x,s[4]=gs.x,s[8]=Ve.x,s[1]=Rn.y,s[5]=gs.y,s[9]=Ve.y,s[2]=Rn.z,s[6]=gs.z,s[10]=Ve.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,s=e.elements,r=this.elements,a=n[0],o=n[4],l=n[8],c=n[12],h=n[1],u=n[5],d=n[9],p=n[13],x=n[2],_=n[6],m=n[10],f=n[14],b=n[3],S=n[7],T=n[11],R=n[15],w=s[0],L=s[4],F=s[8],E=s[12],M=s[1],P=s[5],O=s[9],z=s[13],k=s[2],W=s[6],Y=s[10],nt=s[14],X=s[3],rt=s[7],st=s[11],St=s[15];return r[0]=a*w+o*M+l*k+c*X,r[4]=a*L+o*P+l*W+c*rt,r[8]=a*F+o*O+l*Y+c*st,r[12]=a*E+o*z+l*nt+c*St,r[1]=h*w+u*M+d*k+p*X,r[5]=h*L+u*P+d*W+p*rt,r[9]=h*F+u*O+d*Y+p*st,r[13]=h*E+u*z+d*nt+p*St,r[2]=x*w+_*M+m*k+f*X,r[6]=x*L+_*P+m*W+f*rt,r[10]=x*F+_*O+m*Y+f*st,r[14]=x*E+_*z+m*nt+f*St,r[3]=b*w+S*M+T*k+R*X,r[7]=b*L+S*P+T*W+R*rt,r[11]=b*F+S*O+T*Y+R*st,r[15]=b*E+S*z+T*nt+R*St,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[4],s=t[8],r=t[12],a=t[1],o=t[5],l=t[9],c=t[13],h=t[2],u=t[6],d=t[10],p=t[14],x=t[3],_=t[7],m=t[11],f=t[15];return x*(+r*l*u-s*c*u-r*o*d+n*c*d+s*o*p-n*l*p)+_*(+e*l*p-e*c*d+r*a*d-s*a*p+s*c*h-r*l*h)+m*(+e*c*u-e*o*p-r*a*u+n*a*p+r*o*h-n*c*h)+f*(-s*o*h-e*l*u+e*o*d+s*a*u-n*a*d+n*l*h)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,n){const s=this.elements;return t.isVector3?(s[12]=t.x,s[13]=t.y,s[14]=t.z):(s[12]=t,s[13]=e,s[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],s=t[2],r=t[3],a=t[4],o=t[5],l=t[6],c=t[7],h=t[8],u=t[9],d=t[10],p=t[11],x=t[12],_=t[13],m=t[14],f=t[15],b=u*m*c-_*d*c+_*l*p-o*m*p-u*l*f+o*d*f,S=x*d*c-h*m*c-x*l*p+a*m*p+h*l*f-a*d*f,T=h*_*c-x*u*c+x*o*p-a*_*p-h*o*f+a*u*f,R=x*u*l-h*_*l-x*o*d+a*_*d+h*o*m-a*u*m,w=e*b+n*S+s*T+r*R;if(w===0)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const L=1/w;return t[0]=b*L,t[1]=(_*d*r-u*m*r-_*s*p+n*m*p+u*s*f-n*d*f)*L,t[2]=(o*m*r-_*l*r+_*s*c-n*m*c-o*s*f+n*l*f)*L,t[3]=(u*l*r-o*d*r-u*s*c+n*d*c+o*s*p-n*l*p)*L,t[4]=S*L,t[5]=(h*m*r-x*d*r+x*s*p-e*m*p-h*s*f+e*d*f)*L,t[6]=(x*l*r-a*m*r-x*s*c+e*m*c+a*s*f-e*l*f)*L,t[7]=(a*d*r-h*l*r+h*s*c-e*d*c-a*s*p+e*l*p)*L,t[8]=T*L,t[9]=(x*u*r-h*_*r-x*n*p+e*_*p+h*n*f-e*u*f)*L,t[10]=(a*_*r-x*o*r+x*n*c-e*_*c-a*n*f+e*o*f)*L,t[11]=(h*o*r-a*u*r-h*n*c+e*u*c+a*n*p-e*o*p)*L,t[12]=R*L,t[13]=(h*_*s-x*u*s+x*n*d-e*_*d-h*n*m+e*u*m)*L,t[14]=(x*o*s-a*_*s-x*n*l+e*_*l+a*n*m-e*o*m)*L,t[15]=(a*u*s-h*o*s+h*n*l-e*u*l-a*n*d+e*o*d)*L,this}scale(t){const e=this.elements,n=t.x,s=t.y,r=t.z;return e[0]*=n,e[4]*=s,e[8]*=r,e[1]*=n,e[5]*=s,e[9]*=r,e[2]*=n,e[6]*=s,e[10]*=r,e[3]*=n,e[7]*=s,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],s=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,s))}makeTranslation(t,e,n){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),s=Math.sin(e),r=1-n,a=t.x,o=t.y,l=t.z,c=r*a,h=r*o;return this.set(c*a+n,c*o-s*l,c*l+s*o,0,c*o+s*l,h*o+n,h*l-s*a,0,c*l-s*o,h*l+s*a,r*l*l+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,s,r,a){return this.set(1,n,r,0,t,1,a,0,e,s,1,0,0,0,0,1),this}compose(t,e,n){const s=this.elements,r=e._x,a=e._y,o=e._z,l=e._w,c=r+r,h=a+a,u=o+o,d=r*c,p=r*h,x=r*u,_=a*h,m=a*u,f=o*u,b=l*c,S=l*h,T=l*u,R=n.x,w=n.y,L=n.z;return s[0]=(1-(_+f))*R,s[1]=(p+T)*R,s[2]=(x-S)*R,s[3]=0,s[4]=(p-T)*w,s[5]=(1-(d+f))*w,s[6]=(m+b)*w,s[7]=0,s[8]=(x+S)*L,s[9]=(m-b)*L,s[10]=(1-(d+_))*L,s[11]=0,s[12]=t.x,s[13]=t.y,s[14]=t.z,s[15]=1,this}decompose(t,e,n){const s=this.elements;let r=ci.set(s[0],s[1],s[2]).length();const a=ci.set(s[4],s[5],s[6]).length(),o=ci.set(s[8],s[9],s[10]).length();this.determinant()<0&&(r=-r),t.x=s[12],t.y=s[13],t.z=s[14],je.copy(this);const c=1/r,h=1/a,u=1/o;return je.elements[0]*=c,je.elements[1]*=c,je.elements[2]*=c,je.elements[4]*=h,je.elements[5]*=h,je.elements[6]*=h,je.elements[8]*=u,je.elements[9]*=u,je.elements[10]*=u,e.setFromRotationMatrix(je),n.x=r,n.y=a,n.z=o,this}makePerspective(t,e,n,s,r,a,o=cn,l=!1){const c=this.elements,h=2*r/(e-t),u=2*r/(n-s),d=(e+t)/(e-t),p=(n+s)/(n-s);let x,_;if(l)x=r/(a-r),_=a*r/(a-r);else if(o===cn)x=-(a+r)/(a-r),_=-2*a*r/(a-r);else if(o===Xs)x=-a/(a-r),_=-a*r/(a-r);else throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+o);return c[0]=h,c[4]=0,c[8]=d,c[12]=0,c[1]=0,c[5]=u,c[9]=p,c[13]=0,c[2]=0,c[6]=0,c[10]=x,c[14]=_,c[3]=0,c[7]=0,c[11]=-1,c[15]=0,this}makeOrthographic(t,e,n,s,r,a,o=cn,l=!1){const c=this.elements,h=2/(e-t),u=2/(n-s),d=-(e+t)/(e-t),p=-(n+s)/(n-s);let x,_;if(l)x=1/(a-r),_=a/(a-r);else if(o===cn)x=-2/(a-r),_=-(a+r)/(a-r);else if(o===Xs)x=-1/(a-r),_=-r/(a-r);else throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+o);return c[0]=h,c[4]=0,c[8]=0,c[12]=d,c[1]=0,c[5]=u,c[9]=0,c[13]=p,c[2]=0,c[6]=0,c[10]=x,c[14]=_,c[3]=0,c[7]=0,c[11]=0,c[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let s=0;s<16;s++)if(e[s]!==n[s])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}const ci=new D,je=new re,mh=new D(0,0,0),xh=new D(1,1,1),Rn=new D,gs=new D,Ve=new D,So=new re,yo=new Jn;class nn{constructor(t=0,e=0,n=0,s=nn.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=n,this._order=s}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,n,s=this._order){return this._x=t,this._y=e,this._z=n,this._order=s,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,n=!0){const s=t.elements,r=s[0],a=s[4],o=s[8],l=s[1],c=s[5],h=s[9],u=s[2],d=s[6],p=s[10];switch(e){case"XYZ":this._y=Math.asin(Xt(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-h,p),this._z=Math.atan2(-a,r)):(this._x=Math.atan2(d,c),this._z=0);break;case"YXZ":this._x=Math.asin(-Xt(h,-1,1)),Math.abs(h)<.9999999?(this._y=Math.atan2(o,p),this._z=Math.atan2(l,c)):(this._y=Math.atan2(-u,r),this._z=0);break;case"ZXY":this._x=Math.asin(Xt(d,-1,1)),Math.abs(d)<.9999999?(this._y=Math.atan2(-u,p),this._z=Math.atan2(-a,c)):(this._y=0,this._z=Math.atan2(l,r));break;case"ZYX":this._y=Math.asin(-Xt(u,-1,1)),Math.abs(u)<.9999999?(this._x=Math.atan2(d,p),this._z=Math.atan2(l,r)):(this._x=0,this._z=Math.atan2(-a,c));break;case"YZX":this._z=Math.asin(Xt(l,-1,1)),Math.abs(l)<.9999999?(this._x=Math.atan2(-h,c),this._y=Math.atan2(-u,r)):(this._x=0,this._y=Math.atan2(o,p));break;case"XZY":this._z=Math.asin(-Xt(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(d,c),this._y=Math.atan2(o,r)):(this._x=Math.atan2(-h,p),this._y=0);break;default:Bt("Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,n===!0&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return So.makeRotationFromQuaternion(t),this.setFromRotationMatrix(So,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return yo.setFromEuler(this),this.setFromQuaternion(yo,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],t[3]!==void 0&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}nn.DEFAULT_ORDER="XYZ";class Ya{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let e=0;e1){for(let n=0;n0&&(s.userData=this.userData),s.layers=this.layers.mask,s.matrix=this.matrix.toArray(),s.up=this.up.toArray(),this.matrixAutoUpdate===!1&&(s.matrixAutoUpdate=!1),this.isInstancedMesh&&(s.type="InstancedMesh",s.count=this.count,s.instanceMatrix=this.instanceMatrix.toJSON(),this.instanceColor!==null&&(s.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(s.type="BatchedMesh",s.perObjectFrustumCulled=this.perObjectFrustumCulled,s.sortObjects=this.sortObjects,s.drawRanges=this._drawRanges,s.reservedRanges=this._reservedRanges,s.geometryInfo=this._geometryInfo.map(o=>({...o,boundingBox:o.boundingBox?o.boundingBox.toJSON():void 0,boundingSphere:o.boundingSphere?o.boundingSphere.toJSON():void 0})),s.instanceInfo=this._instanceInfo.map(o=>({...o})),s.availableInstanceIds=this._availableInstanceIds.slice(),s.availableGeometryIds=this._availableGeometryIds.slice(),s.nextIndexStart=this._nextIndexStart,s.nextVertexStart=this._nextVertexStart,s.geometryCount=this._geometryCount,s.maxInstanceCount=this._maxInstanceCount,s.maxVertexCount=this._maxVertexCount,s.maxIndexCount=this._maxIndexCount,s.geometryInitialized=this._geometryInitialized,s.matricesTexture=this._matricesTexture.toJSON(t),s.indirectTexture=this._indirectTexture.toJSON(t),this._colorsTexture!==null&&(s.colorsTexture=this._colorsTexture.toJSON(t)),this.boundingSphere!==null&&(s.boundingSphere=this.boundingSphere.toJSON()),this.boundingBox!==null&&(s.boundingBox=this.boundingBox.toJSON()));function r(o,l){return o[l.uuid]===void 0&&(o[l.uuid]=l.toJSON(t)),l.uuid}if(this.isScene)this.background&&(this.background.isColor?s.background=this.background.toJSON():this.background.isTexture&&(s.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&this.environment.isRenderTargetTexture!==!0&&(s.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){s.geometry=r(t.geometries,this.geometry);const o=this.geometry.parameters;if(o!==void 0&&o.shapes!==void 0){const l=o.shapes;if(Array.isArray(l))for(let c=0,h=l.length;c0){s.children=[];for(let o=0;o0){s.animations=[];for(let o=0;o0&&(n.geometries=o),l.length>0&&(n.materials=l),c.length>0&&(n.textures=c),h.length>0&&(n.images=h),u.length>0&&(n.shapes=u),d.length>0&&(n.skeletons=d),p.length>0&&(n.animations=p),x.length>0&&(n.nodes=x)}return n.object=s,n;function a(o){const l=[];for(const c in o){const h=o[c];delete h.metadata,l.push(h)}return l}}clone(t){return new this.constructor().copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.animations=t.animations.slice(),this.userData=JSON.parse(JSON.stringify(t.userData)),e===!0)for(let n=0;n0?s.multiplyScalar(1/Math.sqrt(r)):s.set(0,0,0)}static getBarycoord(t,e,n,s,r){Je.subVectors(s,e),mn.subVectors(n,e),mr.subVectors(t,e);const a=Je.dot(Je),o=Je.dot(mn),l=Je.dot(mr),c=mn.dot(mn),h=mn.dot(mr),u=a*c-o*o;if(u===0)return r.set(0,0,0),null;const d=1/u,p=(c*l-o*h)*d,x=(a*h-o*l)*d;return r.set(1-p-x,x,p)}static containsPoint(t,e,n,s){return this.getBarycoord(t,e,n,s,xn)===null?!1:xn.x>=0&&xn.y>=0&&xn.x+xn.y<=1}static getInterpolation(t,e,n,s,r,a,o,l){return this.getBarycoord(t,e,n,s,xn)===null?(l.x=0,l.y=0,"z"in l&&(l.z=0),"w"in l&&(l.w=0),null):(l.setScalar(0),l.addScaledVector(r,xn.x),l.addScaledVector(a,xn.y),l.addScaledVector(o,xn.z),l)}static getInterpolatedAttribute(t,e,n,s,r,a){return vr.setScalar(0),Mr.setScalar(0),Sr.setScalar(0),vr.fromBufferAttribute(t,e),Mr.fromBufferAttribute(t,n),Sr.fromBufferAttribute(t,s),a.setScalar(0),a.addScaledVector(vr,r.x),a.addScaledVector(Mr,r.y),a.addScaledVector(Sr,r.z),a}static isFrontFacing(t,e,n,s){return Je.subVectors(n,e),mn.subVectors(t,e),Je.cross(mn).dot(s)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,s){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[s]),this}setFromAttributeAndIndices(t,e,n,s){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,s),this}clone(){return new this.constructor().copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return Je.subVectors(this.c,this.b),mn.subVectors(this.a,this.b),Je.cross(mn).length()*.5}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return Qe.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return Qe.getBarycoord(t,this.a,this.b,this.c,e)}getInterpolation(t,e,n,s,r){return Qe.getInterpolation(t,this.a,this.b,this.c,e,n,s,r)}containsPoint(t){return Qe.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return Qe.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,s=this.b,r=this.c;let a,o;ui.subVectors(s,n),fi.subVectors(r,n),xr.subVectors(t,n);const l=ui.dot(xr),c=fi.dot(xr);if(l<=0&&c<=0)return e.copy(n);gr.subVectors(t,s);const h=ui.dot(gr),u=fi.dot(gr);if(h>=0&&u<=h)return e.copy(s);const d=l*u-h*c;if(d<=0&&l>=0&&h<=0)return a=l/(l-h),e.copy(n).addScaledVector(ui,a);_r.subVectors(t,r);const p=ui.dot(_r),x=fi.dot(_r);if(x>=0&&p<=x)return e.copy(r);const _=p*c-l*x;if(_<=0&&c>=0&&x<=0)return o=c/(c-x),e.copy(n).addScaledVector(fi,o);const m=h*x-p*u;if(m<=0&&u-h>=0&&p-x>=0)return Ro.subVectors(r,s),o=(u-h)/(u-h+(p-x)),e.copy(s).addScaledVector(Ro,o);const f=1/(m+_+d);return a=_*f,o=d*f,e.copy(n).addScaledVector(ui,a).addScaledVector(fi,o)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}const Fc={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Cn={h:0,s:0,l:0},vs={h:0,s:0,l:0};function yr(i,t,e){return e<0&&(e+=1),e>1&&(e-=1),e<1/6?i+(t-i)*6*e:e<1/2?t:e<2/3?i+(t-i)*6*(2/3-e):i}class Yt{constructor(t,e,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,n)}set(t,e,n){if(e===void 0&&n===void 0){const s=t;s&&s.isColor?this.copy(s):typeof s=="number"?this.setHex(s):typeof s=="string"&&this.setStyle(s)}else this.setRGB(t,e,n);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=De){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(t&255)/255,$t.colorSpaceToWorking(this,e),this}setRGB(t,e,n,s=$t.workingColorSpace){return this.r=t,this.g=e,this.b=n,$t.colorSpaceToWorking(this,s),this}setHSL(t,e,n,s=$t.workingColorSpace){if(t=ah(t,1),e=Xt(e,0,1),n=Xt(n,0,1),e===0)this.r=this.g=this.b=n;else{const r=n<=.5?n*(1+e):n+e-n*e,a=2*n-r;this.r=yr(a,r,t+1/3),this.g=yr(a,r,t),this.b=yr(a,r,t-1/3)}return $t.colorSpaceToWorking(this,s),this}setStyle(t,e=De){function n(r){r!==void 0&&parseFloat(r)<1&&Bt("Color: Alpha component of "+t+" will be ignored.")}let s;if(s=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const a=s[1],o=s[2];switch(a){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:Bt("Color: Unknown color model "+t)}}else if(s=/^\#([A-Fa-f\d]+)$/.exec(t)){const r=s[1],a=r.length;if(a===3)return this.setRGB(parseInt(r.charAt(0),16)/15,parseInt(r.charAt(1),16)/15,parseInt(r.charAt(2),16)/15,e);if(a===6)return this.setHex(parseInt(r,16),e);Bt("Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=De){const n=Fc[t.toLowerCase()];return n!==void 0?this.setHex(n,e):Bt("Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=bn(t.r),this.g=bn(t.g),this.b=bn(t.b),this}copyLinearToSRGB(t){return this.r=Ei(t.r),this.g=Ei(t.g),this.b=Ei(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=De){return $t.workingToColorSpace(we.copy(this),t),Math.round(Xt(we.r*255,0,255))*65536+Math.round(Xt(we.g*255,0,255))*256+Math.round(Xt(we.b*255,0,255))}getHexString(t=De){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=$t.workingColorSpace){$t.workingToColorSpace(we.copy(this),e);const n=we.r,s=we.g,r=we.b,a=Math.max(n,s,r),o=Math.min(n,s,r);let l,c;const h=(o+a)/2;if(o===a)l=0,c=0;else{const u=a-o;switch(c=h<=.5?u/(a+o):u/(2-a-o),a){case n:l=(s-r)/u+(s0!=t>0&&this.version++,this._alphaTest=t}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(t!==void 0)for(const e in t){const n=t[e];if(n===void 0){Bt(`Material: parameter '${e}' has value of undefined.`);continue}const s=this[e];if(s===void 0){Bt(`Material: '${e}' is not a property of THREE.${this.type}.`);continue}s&&s.isColor?s.set(n):s&&s.isVector3&&n&&n.isVector3?s.copy(n):this[e]=n}}toJSON(t){const e=t===void 0||typeof t=="string";e&&(t={textures:{},images:{}});const n={metadata:{version:4.7,type:"Material",generator:"Material.toJSON"}};n.uuid=this.uuid,n.type=this.type,this.name!==""&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),this.roughness!==void 0&&(n.roughness=this.roughness),this.metalness!==void 0&&(n.metalness=this.metalness),this.sheen!==void 0&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),this.sheenRoughness!==void 0&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity!==void 0&&this.emissiveIntensity!==1&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),this.specularIntensity!==void 0&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),this.shininess!==void 0&&(n.shininess=this.shininess),this.clearcoat!==void 0&&(n.clearcoat=this.clearcoat),this.clearcoatRoughness!==void 0&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),this.sheenColorMap&&this.sheenColorMap.isTexture&&(n.sheenColorMap=this.sheenColorMap.toJSON(t).uuid),this.sheenRoughnessMap&&this.sheenRoughnessMap.isTexture&&(n.sheenRoughnessMap=this.sheenRoughnessMap.toJSON(t).uuid),this.dispersion!==void 0&&(n.dispersion=this.dispersion),this.iridescence!==void 0&&(n.iridescence=this.iridescence),this.iridescenceIOR!==void 0&&(n.iridescenceIOR=this.iridescenceIOR),this.iridescenceThicknessRange!==void 0&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),this.anisotropy!==void 0&&(n.anisotropy=this.anisotropy),this.anisotropyRotation!==void 0&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,this.combine!==void 0&&(n.combine=this.combine)),this.envMapRotation!==void 0&&(n.envMapRotation=this.envMapRotation.toArray()),this.envMapIntensity!==void 0&&(n.envMapIntensity=this.envMapIntensity),this.reflectivity!==void 0&&(n.reflectivity=this.reflectivity),this.refractionRatio!==void 0&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),this.transmission!==void 0&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),this.thickness!==void 0&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),this.attenuationDistance!==void 0&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),this.attenuationColor!==void 0&&(n.attenuationColor=this.attenuationColor.getHex()),this.size!==void 0&&(n.size=this.size),this.shadowSide!==null&&(n.shadowSide=this.shadowSide),this.sizeAttenuation!==void 0&&(n.sizeAttenuation=this.sizeAttenuation),this.blending!==bi&&(n.blending=this.blending),this.side!==Fn&&(n.side=this.side),this.vertexColors===!0&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),this.transparent===!0&&(n.transparent=!0),this.blendSrc!==Gr&&(n.blendSrc=this.blendSrc),this.blendDst!==kr&&(n.blendDst=this.blendDst),this.blendEquation!==Yn&&(n.blendEquation=this.blendEquation),this.blendSrcAlpha!==null&&(n.blendSrcAlpha=this.blendSrcAlpha),this.blendDstAlpha!==null&&(n.blendDstAlpha=this.blendDstAlpha),this.blendEquationAlpha!==null&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),this.blendAlpha!==0&&(n.blendAlpha=this.blendAlpha),this.depthFunc!==Ti&&(n.depthFunc=this.depthFunc),this.depthTest===!1&&(n.depthTest=this.depthTest),this.depthWrite===!1&&(n.depthWrite=this.depthWrite),this.colorWrite===!1&&(n.colorWrite=this.colorWrite),this.stencilWriteMask!==255&&(n.stencilWriteMask=this.stencilWriteMask),this.stencilFunc!==fo&&(n.stencilFunc=this.stencilFunc),this.stencilRef!==0&&(n.stencilRef=this.stencilRef),this.stencilFuncMask!==255&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==ii&&(n.stencilFail=this.stencilFail),this.stencilZFail!==ii&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==ii&&(n.stencilZPass=this.stencilZPass),this.stencilWrite===!0&&(n.stencilWrite=this.stencilWrite),this.rotation!==void 0&&this.rotation!==0&&(n.rotation=this.rotation),this.polygonOffset===!0&&(n.polygonOffset=!0),this.polygonOffsetFactor!==0&&(n.polygonOffsetFactor=this.polygonOffsetFactor),this.polygonOffsetUnits!==0&&(n.polygonOffsetUnits=this.polygonOffsetUnits),this.linewidth!==void 0&&this.linewidth!==1&&(n.linewidth=this.linewidth),this.dashSize!==void 0&&(n.dashSize=this.dashSize),this.gapSize!==void 0&&(n.gapSize=this.gapSize),this.scale!==void 0&&(n.scale=this.scale),this.dithering===!0&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),this.alphaHash===!0&&(n.alphaHash=!0),this.alphaToCoverage===!0&&(n.alphaToCoverage=!0),this.premultipliedAlpha===!0&&(n.premultipliedAlpha=!0),this.forceSinglePass===!0&&(n.forceSinglePass=!0),this.wireframe===!0&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),this.wireframeLinecap!=="round"&&(n.wireframeLinecap=this.wireframeLinecap),this.wireframeLinejoin!=="round"&&(n.wireframeLinejoin=this.wireframeLinejoin),this.flatShading===!0&&(n.flatShading=!0),this.visible===!1&&(n.visible=!1),this.toneMapped===!1&&(n.toneMapped=!1),this.fog===!1&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData);function s(r){const a=[];for(const o in r){const l=r[o];delete l.metadata,a.push(l)}return a}if(e){const r=s(t.textures),a=s(t.images);r.length>0&&(n.textures=r),a.length>0&&(n.images=a)}return n}clone(){return new this.constructor().copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.blendColor.copy(t.blendColor),this.blendAlpha=t.blendAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let n=null;if(e!==null){const s=e.length;n=new Array(s);for(let r=0;r!==s;++r)n[r]=e[r].clone()}return this.clippingPlanes=n,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaHash=t.alphaHash,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){t===!0&&this.version++}}class Ys extends ei{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Yt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new nn,this.combine=Fa,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const ge=new D,Ms=new at;let yh=0;class en{constructor(t,e,n=!1){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,Object.defineProperty(this,"id",{value:yh++}),this.name="",this.array=t,this.itemSize=e,this.count=t!==void 0?t.length/e:0,this.normalized=n,this.usage=po,this.updateRanges=[],this.gpuType=on,this.version=0}onUploadCallback(){}set needsUpdate(t){t===!0&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this.gpuType=t.gpuType,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let s=0,r=this.itemSize;se.count&&Bt("BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry."),e.needsUpdate=!0}return this}computeBoundingBox(){this.boundingBox===null&&(this.boundingBox=new On);const t=this.attributes.position,e=this.morphAttributes.position;if(t&&t.isGLBufferAttribute){de("BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.",this),this.boundingBox.set(new D(-1/0,-1/0,-1/0),new D(1/0,1/0,1/0));return}if(t!==void 0){if(this.boundingBox.setFromBufferAttribute(t),e)for(let n=0,s=e.length;n0&&(t.userData=this.userData),this.parameters!==void 0){const l=this.parameters;for(const c in l)l[c]!==void 0&&(t[c]=l[c]);return t}t.data={attributes:{}};const e=this.index;e!==null&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const n=this.attributes;for(const l in n){const c=n[l];t.data.attributes[l]=c.toJSON(t.data)}const s={};let r=!1;for(const l in this.morphAttributes){const c=this.morphAttributes[l],h=[];for(let u=0,d=c.length;u0&&(s[l]=h,r=!0)}r&&(t.data.morphAttributes=s,t.data.morphTargetsRelative=this.morphTargetsRelative);const a=this.groups;a.length>0&&(t.data.groups=JSON.parse(JSON.stringify(a)));const o=this.boundingSphere;return o!==null&&(t.data.boundingSphere=o.toJSON()),t}clone(){return new this.constructor().copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const n=t.index;n!==null&&this.setIndex(n.clone());const s=t.attributes;for(const c in s){const h=s[c];this.setAttribute(c,h.clone(e))}const r=t.morphAttributes;for(const c in r){const h=[],u=r[c];for(let d=0,p=u.length;d0){const s=e[n[0]];if(s!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let r=0,a=s.length;r(t.far-t.near)**2))&&(Co.copy(r).invert(),kn.copy(t.ray).applyMatrix4(Co),!(n.boundingBox!==null&&kn.intersectsBox(n.boundingBox)===!1)&&this._computeIntersections(t,e,kn)))}_computeIntersections(t,e,n){let s;const r=this.geometry,a=this.material,o=r.index,l=r.attributes.position,c=r.attributes.uv,h=r.attributes.uv1,u=r.attributes.normal,d=r.groups,p=r.drawRange;if(o!==null)if(Array.isArray(a))for(let x=0,_=d.length;x<_;x++){const m=d[x],f=a[m.materialIndex],b=Math.max(m.start,p.start),S=Math.min(o.count,Math.min(m.start+m.count,p.start+p.count));for(let T=b,R=S;Te.far?null:{distance:c,point:As.clone(),object:i}}function ws(i,t,e,n,s,r,a,o,l,c){i.getVertexPosition(o,ys),i.getVertexPosition(l,bs),i.getVertexPosition(c,Es);const h=Eh(i,t,e,n,ys,bs,Es,Do);if(h){const u=new D;Qe.getBarycoord(Do,ys,bs,Es,u),s&&(h.uv=Qe.getInterpolatedAttribute(s,o,l,c,u,new at)),r&&(h.uv1=Qe.getInterpolatedAttribute(r,o,l,c,u,new at)),a&&(h.normal=Qe.getInterpolatedAttribute(a,o,l,c,u,new D),h.normal.dot(n.direction)>0&&h.normal.multiplyScalar(-1));const d={a:o,b:l,c,normal:new D,materialIndex:0};Qe.getNormal(ys,bs,Es,d.normal),h.face=d,h.barycoord=u}return h}class oe extends Ie{constructor(t=1,e=1,n=1,s=1,r=1,a=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:s,heightSegments:r,depthSegments:a};const o=this;s=Math.floor(s),r=Math.floor(r),a=Math.floor(a);const l=[],c=[],h=[],u=[];let d=0,p=0;x("z","y","x",-1,-1,n,e,t,a,r,0),x("z","y","x",1,-1,n,e,-t,a,r,1),x("x","z","y",1,1,t,n,e,s,a,2),x("x","z","y",1,-1,t,n,-e,s,a,3),x("x","y","z",1,-1,t,e,n,s,r,4),x("x","y","z",-1,-1,t,e,-n,s,r,5),this.setIndex(l),this.setAttribute("position",new he(c,3)),this.setAttribute("normal",new he(h,3)),this.setAttribute("uv",new he(u,2));function x(_,m,f,b,S,T,R,w,L,F,E){const M=T/L,P=R/F,O=T/2,z=R/2,k=w/2,W=L+1,Y=F+1;let nt=0,X=0;const rt=new D;for(let st=0;st0?1:-1,h.push(rt.x,rt.y,rt.z),u.push(Gt/L),u.push(1-st/F),nt+=1}}for(let st=0;st0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader,e.lights=this.lights,e.clipping=this.clipping;const n={};for(const s in this.extensions)this.extensions[s]===!0&&(n[s]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}class Vc extends Me{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new re,this.projectionMatrix=new re,this.projectionMatrixInverse=new re,this.coordinateSystem=cn,this._reversedDepth=!1}get reversedDepth(){return this._reversedDepth}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this.coordinateSystem=t.coordinateSystem,this}getWorldDirection(t){return super.getWorldDirection(t).negate()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return new this.constructor().copy(this)}}const Pn=new D,Lo=new at,Io=new at;class ke extends Vc{constructor(t=50,e=1,n=.1,s=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=s,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=t.view===null?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=Ra*2*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(ks*.5*this.fov);return .5*this.getFilmHeight()/t}getEffectiveFOV(){return Ra*2*Math.atan(Math.tan(ks*.5*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(t,e,n){Pn.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),e.set(Pn.x,Pn.y).multiplyScalar(-t/Pn.z),Pn.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Pn.x,Pn.y).multiplyScalar(-t/Pn.z)}getViewSize(t,e){return this.getViewBounds(t,Lo,Io),e.subVectors(Io,Lo)}setViewOffset(t,e,n,s,r,a){this.aspect=t/e,this.view===null&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=s,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){this.view!==null&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(ks*.5*this.fov)/this.zoom,n=2*e,s=this.aspect*n,r=-.5*s;const a=this.view;if(this.view!==null&&this.view.enabled){const l=a.fullWidth,c=a.fullHeight;r+=a.offsetX*s/l,e-=a.offsetY*n/c,s*=a.width/l,n*=a.height/c}const o=this.filmOffset;o!==0&&(r+=t*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+s,e,e-n,t,this.far,this.coordinateSystem,this.reversedDepth),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,this.view!==null&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const pi=-90,mi=1;class Ch extends Me{constructor(t,e,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const s=new ke(pi,mi,t,e);s.layers=this.layers,this.add(s);const r=new ke(pi,mi,t,e);r.layers=this.layers,this.add(r);const a=new ke(pi,mi,t,e);a.layers=this.layers,this.add(a);const o=new ke(pi,mi,t,e);o.layers=this.layers,this.add(o);const l=new ke(pi,mi,t,e);l.layers=this.layers,this.add(l);const c=new ke(pi,mi,t,e);c.layers=this.layers,this.add(c)}updateCoordinateSystem(){const t=this.coordinateSystem,e=this.children.concat(),[n,s,r,a,o,l]=e;for(const c of e)this.remove(c);if(t===cn)n.up.set(0,1,0),n.lookAt(1,0,0),s.up.set(0,1,0),s.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),a.up.set(0,0,1),a.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),l.up.set(0,1,0),l.lookAt(0,0,-1);else if(t===Xs)n.up.set(0,-1,0),n.lookAt(-1,0,0),s.up.set(0,-1,0),s.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),a.up.set(0,0,-1),a.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),l.up.set(0,-1,0),l.lookAt(0,0,-1);else throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+t);for(const c of e)this.add(c),c.updateMatrixWorld()}update(t,e){this.parent===null&&this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:s}=this;this.coordinateSystem!==t.coordinateSystem&&(this.coordinateSystem=t.coordinateSystem,this.updateCoordinateSystem());const[r,a,o,l,c,h]=this.children,u=t.getRenderTarget(),d=t.getActiveCubeFace(),p=t.getActiveMipmapLevel(),x=t.xr.enabled;t.xr.enabled=!1;const _=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0,s),t.render(e,r),t.setRenderTarget(n,1,s),t.render(e,a),t.setRenderTarget(n,2,s),t.render(e,o),t.setRenderTarget(n,3,s),t.render(e,l),t.setRenderTarget(n,4,s),t.render(e,c),n.texture.generateMipmaps=_,t.setRenderTarget(n,5,s),t.render(e,h),t.setRenderTarget(u,d,p),t.xr.enabled=x,n.texture.needsPMREMUpdate=!0}}class Gc extends Re{constructor(t=[],e=Ai,n,s,r,a,o,l,c,h){super(t,e,n,s,r,a,o,l,c,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class Ph extends $n{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const n={width:t,height:t,depth:1},s=[n,n,n,n,n,n];this.texture=new Gc(s),this._setTextureOptions(e),this.texture.isRenderTargetTexture=!0}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:` + + varying vec3 vWorldDirection; + + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); + + } + + void main() { + + vWorldDirection = transformDirection( position, modelMatrix ); + + #include + #include + + } + `,fragmentShader:` + + uniform sampler2D tEquirect; + + varying vec3 vWorldDirection; + + #include + + void main() { + + vec3 direction = normalize( vWorldDirection ); + + vec2 sampleUV = equirectUv( direction ); + + gl_FragColor = texture2D( tEquirect, sampleUV ); + + } + `},s=new oe(5,5,5),r=new En({name:"CubemapFromEquirect",uniforms:Ci(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:Le,blending:yn});r.uniforms.tEquirect.value=e;const a=new Vt(s,r),o=e.minFilter;return e.minFilter===Kn&&(e.minFilter=Ye),new Ch(1,10,this).update(t,a),e.minFilter=o,a.geometry.dispose(),a.material.dispose(),this}clear(t,e=!0,n=!0,s=!0){const r=t.getRenderTarget();for(let a=0;a<6;a++)t.setRenderTarget(this,a),t.clear(e,n,s);t.setRenderTarget(r)}}class ln extends Me{constructor(){super(),this.isGroup=!0,this.type="Group"}}const Dh={type:"move"};class Tr{constructor(){this._targetRay=null,this._grip=null,this._hand=null}getHandSpace(){return this._hand===null&&(this._hand=new ln,this._hand.matrixAutoUpdate=!1,this._hand.visible=!1,this._hand.joints={},this._hand.inputState={pinching:!1}),this._hand}getTargetRaySpace(){return this._targetRay===null&&(this._targetRay=new ln,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1,this._targetRay.hasLinearVelocity=!1,this._targetRay.linearVelocity=new D,this._targetRay.hasAngularVelocity=!1,this._targetRay.angularVelocity=new D),this._targetRay}getGripSpace(){return this._grip===null&&(this._grip=new ln,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1,this._grip.hasLinearVelocity=!1,this._grip.linearVelocity=new D,this._grip.hasAngularVelocity=!1,this._grip.angularVelocity=new D),this._grip}dispatchEvent(t){return this._targetRay!==null&&this._targetRay.dispatchEvent(t),this._grip!==null&&this._grip.dispatchEvent(t),this._hand!==null&&this._hand.dispatchEvent(t),this}connect(t){if(t&&t.hand){const e=this._hand;if(e)for(const n of t.hand.values())this._getHandJoint(e,n)}return this.dispatchEvent({type:"connected",data:t}),this}disconnect(t){return this.dispatchEvent({type:"disconnected",data:t}),this._targetRay!==null&&(this._targetRay.visible=!1),this._grip!==null&&(this._grip.visible=!1),this._hand!==null&&(this._hand.visible=!1),this}update(t,e,n){let s=null,r=null,a=null;const o=this._targetRay,l=this._grip,c=this._hand;if(t&&e.session.visibilityState!=="visible-blurred"){if(c&&t.hand){a=!0;for(const _ of t.hand.values()){const m=e.getJointPose(_,n),f=this._getHandJoint(c,_);m!==null&&(f.matrix.fromArray(m.transform.matrix),f.matrix.decompose(f.position,f.rotation,f.scale),f.matrixWorldNeedsUpdate=!0,f.jointRadius=m.radius),f.visible=m!==null}const h=c.joints["index-finger-tip"],u=c.joints["thumb-tip"],d=h.position.distanceTo(u.position),p=.02,x=.005;c.inputState.pinching&&d>p+x?(c.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!c.inputState.pinching&&d<=p-x&&(c.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else l!==null&&t.gripSpace&&(r=e.getPose(t.gripSpace,n),r!==null&&(l.matrix.fromArray(r.transform.matrix),l.matrix.decompose(l.position,l.rotation,l.scale),l.matrixWorldNeedsUpdate=!0,r.linearVelocity?(l.hasLinearVelocity=!0,l.linearVelocity.copy(r.linearVelocity)):l.hasLinearVelocity=!1,r.angularVelocity?(l.hasAngularVelocity=!0,l.angularVelocity.copy(r.angularVelocity)):l.hasAngularVelocity=!1));o!==null&&(s=e.getPose(t.targetRaySpace,n),s===null&&r!==null&&(s=r),s!==null&&(o.matrix.fromArray(s.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,s.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(s.linearVelocity)):o.hasLinearVelocity=!1,s.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(s.angularVelocity)):o.hasAngularVelocity=!1,this.dispatchEvent(Dh)))}return o!==null&&(o.visible=s!==null),l!==null&&(l.visible=r!==null),c!==null&&(c.visible=a!==null),this}_getHandJoint(t,e){if(t.joints[e.jointName]===void 0){const n=new ln;n.matrixAutoUpdate=!1,n.visible=!1,t.joints[e.jointName]=n,t.add(n)}return t.joints[e.jointName]}}class kc extends Me{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new nn,this.environmentIntensity=1,this.environmentRotation=new nn,this.overrideMaterial=null,typeof __THREE_DEVTOOLS__<"u"&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),t.background!==null&&(this.background=t.background.clone()),t.environment!==null&&(this.environment=t.environment.clone()),t.fog!==null&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,this.backgroundRotation.copy(t.backgroundRotation),this.environmentIntensity=t.environmentIntensity,this.environmentRotation.copy(t.environmentRotation),t.overrideMaterial!==null&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return this.fog!==null&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.object.backgroundBlurriness=this.backgroundBlurriness),this.backgroundIntensity!==1&&(e.object.backgroundIntensity=this.backgroundIntensity),e.object.backgroundRotation=this.backgroundRotation.toArray(),this.environmentIntensity!==1&&(e.object.environmentIntensity=this.environmentIntensity),e.object.environmentRotation=this.environmentRotation.toArray(),e}}class Hc extends Re{constructor(t=null,e=1,n=1,s,r,a,o,l,c=He,h=He,u,d){super(null,a,o,l,c,h,s,r,u,d),this.isDataTexture=!0,this.image={data:t,width:e,height:n},this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}}class Uo extends en{constructor(t,e,n,s=1){super(t,e,n),this.isInstancedBufferAttribute=!0,this.meshPerAttribute=s}copy(t){return super.copy(t),this.meshPerAttribute=t.meshPerAttribute,this}toJSON(){const t=super.toJSON();return t.meshPerAttribute=this.meshPerAttribute,t.isInstancedBufferAttribute=!0,t}}const xi=new re,No=new re,Rs=[],Fo=new On,Lh=new re,Gi=new Vt,ki=new Ii;class Ih extends Vt{constructor(t,e,n){super(t,e),this.isInstancedMesh=!0,this.instanceMatrix=new Uo(new Float32Array(n*16),16),this.instanceColor=null,this.morphTexture=null,this.count=n,this.boundingBox=null,this.boundingSphere=null;for(let s=0;s1?null:e.copy(t.start).addScaledVector(n,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||Nh.getNormalMatrix(t),s=this.coplanarPoint(Ar).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-s.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return new this.constructor().copy(this)}}const Hn=new Ii,Fh=new at(.5,.5),Cs=new D;class Za{constructor(t=new Dn,e=new Dn,n=new Dn,s=new Dn,r=new Dn,a=new Dn){this.planes=[t,e,n,s,r,a]}set(t,e,n,s,r,a){const o=this.planes;return o[0].copy(t),o[1].copy(e),o[2].copy(n),o[3].copy(s),o[4].copy(r),o[5].copy(a),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t,e=cn,n=!1){const s=this.planes,r=t.elements,a=r[0],o=r[1],l=r[2],c=r[3],h=r[4],u=r[5],d=r[6],p=r[7],x=r[8],_=r[9],m=r[10],f=r[11],b=r[12],S=r[13],T=r[14],R=r[15];if(s[0].setComponents(c-a,p-h,f-x,R-b).normalize(),s[1].setComponents(c+a,p+h,f+x,R+b).normalize(),s[2].setComponents(c+o,p+u,f+_,R+S).normalize(),s[3].setComponents(c-o,p-u,f-_,R-S).normalize(),n)s[4].setComponents(l,d,m,T).normalize(),s[5].setComponents(c-l,p-d,f-m,R-T).normalize();else if(s[4].setComponents(c-l,p-d,f-m,R-T).normalize(),e===cn)s[5].setComponents(c+l,p+d,f+m,R+T).normalize();else if(e===Xs)s[5].setComponents(l,d,m,T).normalize();else throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+e);return this}intersectsObject(t){if(t.boundingSphere!==void 0)t.boundingSphere===null&&t.computeBoundingSphere(),Hn.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;e.boundingSphere===null&&e.computeBoundingSphere(),Hn.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(Hn)}intersectsSprite(t){Hn.center.set(0,0,0);const e=Fh.distanceTo(t.center);return Hn.radius=.7071067811865476+e,Hn.applyMatrix4(t.matrixWorld),this.intersectsSphere(Hn)}intersectsSphere(t){const e=this.planes,n=t.center,s=-t.radius;for(let r=0;r<6;r++)if(e[r].distanceToPoint(n)0?t.max.x:t.min.x,Cs.y=s.normal.y>0?t.max.y:t.min.y,Cs.z=s.normal.z>0?t.max.z:t.min.z,s.distanceToPoint(Cs)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return new this.constructor().copy(this)}}class Wc extends ei{constructor(t){super(),this.isLineBasicMaterial=!0,this.type="LineBasicMaterial",this.color=new Yt(16777215),this.map=null,this.linewidth=1,this.linecap="round",this.linejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.linewidth=t.linewidth,this.linecap=t.linecap,this.linejoin=t.linejoin,this.fog=t.fog,this}}const Zs=new D,Ks=new D,Oo=new re,Hi=new $s,Ps=new Ii,wr=new D,Bo=new D;class Oh extends Me{constructor(t=new Ie,e=new Wc){super(),this.isLine=!0,this.type="Line",this.geometry=t,this.material=e,this.morphTargetDictionary=void 0,this.morphTargetInfluences=void 0,this.updateMorphTargets()}copy(t,e){return super.copy(t,e),this.material=Array.isArray(t.material)?t.material.slice():t.material,this.geometry=t.geometry,this}computeLineDistances(){const t=this.geometry;if(t.index===null){const e=t.attributes.position,n=[0];for(let s=1,r=e.count;s0){const s=e[n[0]];if(s!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let r=0,a=s.length;rn)return;wr.applyMatrix4(i.matrixWorld);const c=t.ray.origin.distanceTo(wr);if(!(ct.far))return{distance:c,point:Bo.clone().applyMatrix4(i.matrixWorld),index:a,face:null,faceIndex:null,barycoord:null,object:i}}const zo=new D,Vo=new D;class Bh extends Oh{constructor(t,e){super(t,e),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const t=this.geometry;if(t.index===null){const e=t.attributes.position,n=[];for(let s=0,r=e.count;s0&&S(!0),e>0&&S(!1)),this.setIndex(h),this.setAttribute("position",new he(u,3)),this.setAttribute("normal",new he(d,3)),this.setAttribute("uv",new he(p,2));function b(){const T=new D,R=new D;let w=0;const L=(e-t)/n;for(let F=0;F<=r;F++){const E=[],M=F/r,P=M*(e-t)+t;for(let O=0;O<=s;O++){const z=O/s,k=z*l+o,W=Math.sin(k),Y=Math.cos(k);R.x=P*W,R.y=-M*n+m,R.z=P*Y,u.push(R.x,R.y,R.z),T.set(W,L,Y).normalize(),d.push(T.x,T.y,T.z),p.push(z,1-M),E.push(x++)}_.push(E)}for(let F=0;F0||E!==0)&&(h.push(M,P,z),w+=3),(e>0||E!==r-1)&&(h.push(P,O,z),w+=3)}c.addGroup(f,w,0),f+=w}function S(T){const R=x,w=new at,L=new D;let F=0;const E=T===!0?t:e,M=T===!0?1:-1;for(let O=1;O<=s;O++)u.push(0,m*M,0),d.push(0,M,0),p.push(.5,.5),x++;const P=x;for(let O=0;O<=s;O++){const k=O/s*l+o,W=Math.cos(k),Y=Math.sin(k);L.x=E*Y,L.y=m*M,L.z=E*W,u.push(L.x,L.y,L.z),d.push(0,M,0),w.x=W*.5+.5,w.y=Y*.5*M+.5,p.push(w.x,w.y),x++}for(let O=0;O0)l=s-1;else{l=s;break}if(s=l,n[s]===a)return s/(r-1);const h=n[s],d=n[s+1]-h,p=(a-h)/d;return(s+p)/(r-1)}getTangent(t,e){let s=t-1e-4,r=t+1e-4;s<0&&(s=0),r>1&&(r=1);const a=this.getPoint(s),o=this.getPoint(r),l=e||(a.isVector2?new at:new D);return l.copy(o).sub(a).normalize(),l}getTangentAt(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)}computeFrenetFrames(t,e=!1){const n=new D,s=[],r=[],a=[],o=new D,l=new re;for(let p=0;p<=t;p++){const x=p/t;s[p]=this.getTangentAt(x,new D)}r[0]=new D,a[0]=new D;let c=Number.MAX_VALUE;const h=Math.abs(s[0].x),u=Math.abs(s[0].y),d=Math.abs(s[0].z);h<=c&&(c=h,n.set(1,0,0)),u<=c&&(c=u,n.set(0,1,0)),d<=c&&n.set(0,0,1),o.crossVectors(s[0],n).normalize(),r[0].crossVectors(s[0],o),a[0].crossVectors(s[0],r[0]);for(let p=1;p<=t;p++){if(r[p]=r[p-1].clone(),a[p]=a[p-1].clone(),o.crossVectors(s[p-1],s[p]),o.length()>Number.EPSILON){o.normalize();const x=Math.acos(Xt(s[p-1].dot(s[p]),-1,1));r[p].applyMatrix4(l.makeRotationAxis(o,x))}a[p].crossVectors(s[p],r[p])}if(e===!0){let p=Math.acos(Xt(r[0].dot(r[t]),-1,1));p/=t,s[0].dot(o.crossVectors(r[0],r[t]))>0&&(p=-p);for(let x=1;x<=t;x++)r[x].applyMatrix4(l.makeRotationAxis(s[x],p*x)),a[x].crossVectors(s[x],r[x])}return{tangents:s,normals:r,binormals:a}}clone(){return new this.constructor().copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.7,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class ja extends un{constructor(t=0,e=0,n=1,s=1,r=0,a=Math.PI*2,o=!1,l=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=n,this.yRadius=s,this.aStartAngle=r,this.aEndAngle=a,this.aClockwise=o,this.aRotation=l}getPoint(t,e=new at){const n=e,s=Math.PI*2;let r=this.aEndAngle-this.aStartAngle;const a=Math.abs(r)s;)r-=s;r0?0:(Math.floor(Math.abs(o)/r)+1)*r:l===0&&o===r-1&&(o=r-2,l=1);let c,h;this.closed||o>0?c=s[(o-1)%r]:(Ls.subVectors(s[0],s[1]).add(s[0]),c=Ls);const u=s[o%r],d=s[(o+1)%r];if(this.closed||o+2s.length-2?s.length-1:a+1],u=s[a>s.length-3?s.length-1:a+2];return n.set(Go(o,l.x,c.x,h.x,u.x),Go(o,l.y,c.y,h.y,u.y)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e=n){const a=s[r]-n,o=this.curves[r],l=o.getLength(),c=l===0?0:1-a/l;return o.getPointAt(c,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let n=0,s=this.curves.length;n1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,n=t.curves.length;e0){const u=c.getPoint(0);u.equals(this.currentPoint)||this.lineTo(u.x,u.y)}this.curves.push(c);const h=c.getPoint(1);return this.currentPoint.copy(h),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class js extends rs{constructor(t){super(t),this.uuid=Li(),this.type="Shape",this.holes=[]}getPointsHoles(t){const e=[];for(let n=0,s=this.holes.length;n80*e){o=i[0],l=i[1];let h=o,u=l;for(let d=e;dh&&(h=p),x>u&&(u=x)}c=Math.max(h-o,u-l),c=c!==0?32767/c:0}return as(r,a,e,o,l,c,0),a}function Jc(i,t,e,n,s){let r;if(s===pu(i,t,e,n)>0)for(let a=t;a=t;a-=n)r=ko(a/n|0,i[a],i[a+1],r);return r&&Pi(r,r.next)&&(cs(r),r=r.next),r}function Qn(i,t){if(!i)return i;t||(t=i);let e=i,n;do if(n=!1,!e.steiner&&(Pi(e,e.next)||pe(e.prev,e,e.next)===0)){if(cs(e),e=t=e.prev,e===e.next)break;n=!0}else e=e.next;while(n||e!==t);return t}function as(i,t,e,n,s,r,a){if(!i)return;!a&&r&&cu(i,n,s,r);let o=i;for(;i.prev!==i.next;){const l=i.prev,c=i.next;if(r?tu(i,n,s,r):Qh(i)){t.push(l.i,i.i,c.i),cs(i),i=c.next,o=c.next;continue}if(i=c,i===o){a?a===1?(i=eu(Qn(i),t),as(i,t,e,n,s,r,2)):a===2&&nu(i,t,e,n,s,r):as(Qn(i),t,e,n,s,r,1);break}}}function Qh(i){const t=i.prev,e=i,n=i.next;if(pe(t,e,n)>=0)return!1;const s=t.x,r=e.x,a=n.x,o=t.y,l=e.y,c=n.y,h=Math.min(s,r,a),u=Math.min(o,l,c),d=Math.max(s,r,a),p=Math.max(o,l,c);let x=n.next;for(;x!==t;){if(x.x>=h&&x.x<=d&&x.y>=u&&x.y<=p&&Yi(s,o,r,l,a,c,x.x,x.y)&&pe(x.prev,x,x.next)>=0)return!1;x=x.next}return!0}function tu(i,t,e,n){const s=i.prev,r=i,a=i.next;if(pe(s,r,a)>=0)return!1;const o=s.x,l=r.x,c=a.x,h=s.y,u=r.y,d=a.y,p=Math.min(o,l,c),x=Math.min(h,u,d),_=Math.max(o,l,c),m=Math.max(h,u,d),f=Pa(p,x,t,e,n),b=Pa(_,m,t,e,n);let S=i.prevZ,T=i.nextZ;for(;S&&S.z>=f&&T&&T.z<=b;){if(S.x>=p&&S.x<=_&&S.y>=x&&S.y<=m&&S!==s&&S!==a&&Yi(o,h,l,u,c,d,S.x,S.y)&&pe(S.prev,S,S.next)>=0||(S=S.prevZ,T.x>=p&&T.x<=_&&T.y>=x&&T.y<=m&&T!==s&&T!==a&&Yi(o,h,l,u,c,d,T.x,T.y)&&pe(T.prev,T,T.next)>=0))return!1;T=T.nextZ}for(;S&&S.z>=f;){if(S.x>=p&&S.x<=_&&S.y>=x&&S.y<=m&&S!==s&&S!==a&&Yi(o,h,l,u,c,d,S.x,S.y)&&pe(S.prev,S,S.next)>=0)return!1;S=S.prevZ}for(;T&&T.z<=b;){if(T.x>=p&&T.x<=_&&T.y>=x&&T.y<=m&&T!==s&&T!==a&&Yi(o,h,l,u,c,d,T.x,T.y)&&pe(T.prev,T,T.next)>=0)return!1;T=T.nextZ}return!0}function eu(i,t){let e=i;do{const n=e.prev,s=e.next.next;!Pi(n,s)&&Qc(n,e,e.next,s)&&os(n,s)&&os(s,n)&&(t.push(n.i,e.i,s.i),cs(e),cs(e.next),e=i=s),e=e.next}while(e!==i);return Qn(e)}function nu(i,t,e,n,s,r){let a=i;do{let o=a.next.next;for(;o!==a.prev;){if(a.i!==o.i&&uu(a,o)){let l=tl(a,o);a=Qn(a,a.next),l=Qn(l,l.next),as(a,t,e,n,s,r,0),as(l,t,e,n,s,r,0);return}o=o.next}a=a.next}while(a!==i)}function iu(i,t,e,n){const s=[];for(let r=0,a=t.length;r=e.next.y&&e.next.y!==e.y){const u=e.x+(s-e.y)*(e.next.x-e.x)/(e.next.y-e.y);if(u<=n&&u>r&&(r=u,a=e.x=e.x&&e.x>=l&&n!==e.x&&$c(sa.x||e.x===a.x&&ou(a,e)))&&(a=e,h=u)}e=e.next}while(e!==o);return a}function ou(i,t){return pe(i.prev,i,t.prev)<0&&pe(t.next,i,i.next)<0}function cu(i,t,e,n){let s=i;do s.z===0&&(s.z=Pa(s.x,s.y,t,e,n)),s.prevZ=s.prev,s.nextZ=s.next,s=s.next;while(s!==i);s.prevZ.nextZ=null,s.prevZ=null,lu(s)}function lu(i){let t,e=1;do{let n=i,s;i=null;let r=null;for(t=0;n;){t++;let a=n,o=0;for(let c=0;c0||l>0&&a;)o!==0&&(l===0||!a||n.z<=a.z)?(s=n,n=n.nextZ,o--):(s=a,a=a.nextZ,l--),r?r.nextZ=s:i=s,s.prevZ=r,r=s;n=a}r.nextZ=null,e*=2}while(t>1);return i}function Pa(i,t,e,n,s){return i=(i-e)*s|0,t=(t-n)*s|0,i=(i|i<<8)&16711935,i=(i|i<<4)&252645135,i=(i|i<<2)&858993459,i=(i|i<<1)&1431655765,t=(t|t<<8)&16711935,t=(t|t<<4)&252645135,t=(t|t<<2)&858993459,t=(t|t<<1)&1431655765,i|t<<1}function hu(i){let t=i,e=i;do(t.x=(i-a)*(r-o)&&(i-a)*(n-o)>=(e-a)*(t-o)&&(e-a)*(r-o)>=(s-a)*(n-o)}function Yi(i,t,e,n,s,r,a,o){return!(i===a&&t===o)&&$c(i,t,e,n,s,r,a,o)}function uu(i,t){return i.next.i!==t.i&&i.prev.i!==t.i&&!fu(i,t)&&(os(i,t)&&os(t,i)&&du(i,t)&&(pe(i.prev,i,t.prev)||pe(i,t.prev,t))||Pi(i,t)&&pe(i.prev,i,i.next)>0&&pe(t.prev,t,t.next)>0)}function pe(i,t,e){return(t.y-i.y)*(e.x-t.x)-(t.x-i.x)*(e.y-t.y)}function Pi(i,t){return i.x===t.x&&i.y===t.y}function Qc(i,t,e,n){const s=Us(pe(i,t,e)),r=Us(pe(i,t,n)),a=Us(pe(e,n,i)),o=Us(pe(e,n,t));return!!(s!==r&&a!==o||s===0&&Is(i,e,t)||r===0&&Is(i,n,t)||a===0&&Is(e,i,n)||o===0&&Is(e,t,n))}function Is(i,t,e){return t.x<=Math.max(i.x,e.x)&&t.x>=Math.min(i.x,e.x)&&t.y<=Math.max(i.y,e.y)&&t.y>=Math.min(i.y,e.y)}function Us(i){return i>0?1:i<0?-1:0}function fu(i,t){let e=i;do{if(e.i!==i.i&&e.next.i!==i.i&&e.i!==t.i&&e.next.i!==t.i&&Qc(e,e.next,i,t))return!0;e=e.next}while(e!==i);return!1}function os(i,t){return pe(i.prev,i,i.next)<0?pe(i,t,i.next)>=0&&pe(i,i.prev,t)>=0:pe(i,t,i.prev)<0||pe(i,i.next,t)<0}function du(i,t){let e=i,n=!1;const s=(i.x+t.x)/2,r=(i.y+t.y)/2;do e.y>r!=e.next.y>r&&e.next.y!==e.y&&s<(e.next.x-e.x)*(r-e.y)/(e.next.y-e.y)+e.x&&(n=!n),e=e.next;while(e!==i);return n}function tl(i,t){const e=Da(i.i,i.x,i.y),n=Da(t.i,t.x,t.y),s=i.next,r=t.prev;return i.next=t,t.prev=i,e.next=s,s.prev=e,n.next=e,e.prev=n,r.next=n,n.prev=r,n}function ko(i,t,e,n){const s=Da(i,t,e);return n?(s.next=n.next,s.prev=n,n.next.prev=s,n.next=s):(s.prev=s,s.next=s),s}function cs(i){i.next.prev=i.prev,i.prev.next=i.next,i.prevZ&&(i.prevZ.nextZ=i.nextZ),i.nextZ&&(i.nextZ.prevZ=i.prevZ)}function Da(i,t,e){return{i,x:t,y:e,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function pu(i,t,e,n){let s=0;for(let r=t,a=e-n;r2&&i[t-1].equals(i[0])&&i.pop()}function Wo(i,t){for(let e=0;eNumber.EPSILON){const q=Math.sqrt(g),$=Math.sqrt(Mt*Mt+A*A),H=y.x-ft/q,wt=y.y+vt/q,dt=Z.x-A/$,Pt=Z.y+Mt/$,At=((dt-H)*A-(Pt-wt)*Mt)/(vt*A-ft*Mt);Q=H+vt*At-B.x,ot=wt+ft*At-B.y;const tt=Q*Q+ot*ot;if(tt<=2)return new at(Q,ot);et=Math.sqrt(tt/2)}else{let q=!1;vt>Number.EPSILON?Mt>Number.EPSILON&&(q=!0):vt<-Number.EPSILON?Mt<-Number.EPSILON&&(q=!0):Math.sign(ft)===Math.sign(A)&&(q=!0),q?(Q=-ft,ot=vt,et=Math.sqrt(g)):(Q=vt,ot=ft,et=Math.sqrt(g/2))}return new at(Q/et,ot/et)}const rt=[];for(let B=0,y=W.length,Z=y-1,Q=B+1;B=0;B--){const y=B/m,Z=p*Math.cos(y*Math.PI/2),Q=x*Math.sin(y*Math.PI/2)+_;for(let ot=0,et=W.length;ot=0;){const Q=Z;let ot=Z-1;ot<0&&(ot=B.length-1);for(let et=0,vt=h+m*2;et0)&&p.push(S,T,w),(f!==n-1||l0!=t>0&&this.version++,this._anisotropy=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get dispersion(){return this._dispersion}set dispersion(t){this._dispersion>0!=t>0&&this.version++,this._dispersion=t}get sheen(){return this._sheen}set sheen(t){this._sheen>0!=t>0&&this.version++,this._sheen=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.anisotropy=t.anisotropy,this.anisotropyRotation=t.anisotropyRotation,this.anisotropyMap=t.anisotropyMap,this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.dispersion=t.dispersion,this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class vu extends ei{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Yt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Yt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=Xa,this.normalScale=new at(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new nn,this.combine=Fa,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Mu extends ei{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=Zl,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class Su extends ei{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}class $a extends Me{constructor(t,e=1){super(),this.isLight=!0,this.type="Light",this.color=new Yt(t),this.intensity=e}dispose(){}copy(t,e){return super.copy(t,e),this.color.copy(t.color),this.intensity=t.intensity,this}toJSON(t){const e=super.toJSON(t);return e.object.color=this.color.getHex(),e.object.intensity=this.intensity,this.groundColor!==void 0&&(e.object.groundColor=this.groundColor.getHex()),this.distance!==void 0&&(e.object.distance=this.distance),this.angle!==void 0&&(e.object.angle=this.angle),this.decay!==void 0&&(e.object.decay=this.decay),this.penumbra!==void 0&&(e.object.penumbra=this.penumbra),this.shadow!==void 0&&(e.object.shadow=this.shadow.toJSON()),this.target!==void 0&&(e.object.target=this.target.uuid),e}}class yu extends $a{constructor(t,e,n){super(t,n),this.isHemisphereLight=!0,this.type="HemisphereLight",this.position.copy(Me.DEFAULT_UP),this.updateMatrix(),this.groundColor=new Yt(e)}copy(t,e){return super.copy(t,e),this.groundColor.copy(t.groundColor),this}}const Dr=new re,Xo=new D,qo=new D;class el{constructor(t){this.camera=t,this.intensity=1,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new at(512,512),this.mapType=hn,this.map=null,this.mapPass=null,this.matrix=new re,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new Za,this._frameExtents=new at(1,1),this._viewportCount=1,this._viewports=[new se(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(t){const e=this.camera,n=this.matrix;Xo.setFromMatrixPosition(t.matrixWorld),e.position.copy(Xo),qo.setFromMatrixPosition(t.target.matrixWorld),e.lookAt(qo),e.updateMatrixWorld(),Dr.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Dr,e.coordinateSystem,e.reversedDepth),e.reversedDepth?n.set(.5,0,0,.5,0,.5,0,.5,0,0,1,0,0,0,0,1):n.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),n.multiply(Dr)}getViewport(t){return this._viewports[t]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(t){return this.camera=t.camera.clone(),this.intensity=t.intensity,this.bias=t.bias,this.radius=t.radius,this.autoUpdate=t.autoUpdate,this.needsUpdate=t.needsUpdate,this.normalBias=t.normalBias,this.blurSamples=t.blurSamples,this.mapSize.copy(t.mapSize),this}clone(){return new this.constructor().copy(this)}toJSON(){const t={};return this.intensity!==1&&(t.intensity=this.intensity),this.bias!==0&&(t.bias=this.bias),this.normalBias!==0&&(t.normalBias=this.normalBias),this.radius!==1&&(t.radius=this.radius),(this.mapSize.x!==512||this.mapSize.y!==512)&&(t.mapSize=this.mapSize.toArray()),t.camera=this.camera.toJSON(!1).object,delete t.camera.matrix,t}}const Yo=new re,Wi=new D,Lr=new D;class bu extends el{constructor(){super(new ke(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new at(4,2),this._viewportCount=6,this._viewports=[new se(2,1,1,1),new se(0,1,1,1),new se(3,1,1,1),new se(1,1,1,1),new se(3,0,1,1),new se(1,0,1,1)],this._cubeDirections=[new D(1,0,0),new D(-1,0,0),new D(0,0,1),new D(0,0,-1),new D(0,1,0),new D(0,-1,0)],this._cubeUps=[new D(0,1,0),new D(0,1,0),new D(0,1,0),new D(0,1,0),new D(0,0,1),new D(0,0,-1)]}updateMatrices(t,e=0){const n=this.camera,s=this.matrix,r=t.distance||n.far;r!==n.far&&(n.far=r,n.updateProjectionMatrix()),Wi.setFromMatrixPosition(t.matrixWorld),n.position.copy(Wi),Lr.copy(n.position),Lr.add(this._cubeDirections[e]),n.up.copy(this._cubeUps[e]),n.lookAt(Lr),n.updateMatrixWorld(),s.makeTranslation(-Wi.x,-Wi.y,-Wi.z),Yo.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Yo,n.coordinateSystem,n.reversedDepth)}}class Eu extends $a{constructor(t,e,n=0,s=2){super(t,e),this.isPointLight=!0,this.type="PointLight",this.distance=n,this.decay=s,this.shadow=new bu}get power(){return this.intensity*4*Math.PI}set power(t){this.intensity=t/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.decay=t.decay,this.shadow=t.shadow.clone(),this}}class nl extends Vc{constructor(t=-1,e=1,n=1,s=-1,r=.1,a=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=n,this.bottom=s,this.near=r,this.far=a,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=t.view===null?null:Object.assign({},t.view),this}setViewOffset(t,e,n,s,r,a){this.view===null&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=s,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){this.view!==null&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,s=(this.top+this.bottom)/2;let r=n-t,a=n+t,o=s+e,l=s-e;if(this.view!==null&&this.view.enabled){const c=(this.right-this.left)/this.view.fullWidth/this.zoom,h=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=c*this.view.offsetX,a=r+c*this.view.width,o-=h*this.view.offsetY,l=o-h*this.view.height}this.projectionMatrix.makeOrthographic(r,a,o,l,this.near,this.far,this.coordinateSystem,this.reversedDepth),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,this.view!==null&&(e.object.view=Object.assign({},this.view)),e}}class Tu extends el{constructor(){super(new nl(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class Au extends $a{constructor(t,e){super(t,e),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(Me.DEFAULT_UP),this.updateMatrix(),this.target=new Me,this.shadow=new Tu}dispose(){this.shadow.dispose()}copy(t){return super.copy(t),this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}class wu extends ke{constructor(t=[]){super(),this.isArrayCamera=!0,this.isMultiViewCamera=!1,this.cameras=t}}const Zo=new re;class Ru{constructor(t,e,n=0,s=1/0){this.ray=new $s(t,e),this.near=n,this.far=s,this.camera=null,this.layers=new Ya,this.params={Mesh:{},Line:{threshold:1},LOD:{},Points:{threshold:1},Sprite:{}}}set(t,e){this.ray.set(t,e)}setFromCamera(t,e){e.isPerspectiveCamera?(this.ray.origin.setFromMatrixPosition(e.matrixWorld),this.ray.direction.set(t.x,t.y,.5).unproject(e).sub(this.ray.origin).normalize(),this.camera=e):e.isOrthographicCamera?(this.ray.origin.set(t.x,t.y,(e.near+e.far)/(e.near-e.far)).unproject(e),this.ray.direction.set(0,0,-1).transformDirection(e.matrixWorld),this.camera=e):de("Raycaster: Unsupported camera type: "+e.type)}setFromXRController(t){return Zo.identity().extractRotation(t.matrixWorld),this.ray.origin.setFromMatrixPosition(t.matrixWorld),this.ray.direction.set(0,0,-1).applyMatrix4(Zo),this}intersectObject(t,e=!0,n=[]){return La(t,this,n,e),n.sort(Ko),n}intersectObjects(t,e=!0,n=[]){for(let s=0,r=t.length;sp.start-x.start);let d=0;for(let p=1;p 0 + vec4 plane; + #ifdef ALPHA_TO_COVERAGE + float distanceToPlane, distanceGradient; + float clipOpacity = 1.0; + #pragma unroll_loop_start + for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w; + distanceGradient = fwidth( distanceToPlane ) / 2.0; + clipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane ); + if ( clipOpacity == 0.0 ) discard; + } + #pragma unroll_loop_end + #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES + float unionClipOpacity = 1.0; + #pragma unroll_loop_start + for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w; + distanceGradient = fwidth( distanceToPlane ) / 2.0; + unionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane ); + } + #pragma unroll_loop_end + clipOpacity *= 1.0 - unionClipOpacity; + #endif + diffuseColor.a *= clipOpacity; + if ( diffuseColor.a == 0.0 ) discard; + #else + #pragma unroll_loop_start + for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + if ( dot( vClipPosition, plane.xyz ) > plane.w ) discard; + } + #pragma unroll_loop_end + #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES + bool clipped = true; + #pragma unroll_loop_start + for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + clipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped; + } + #pragma unroll_loop_end + if ( clipped ) discard; + #endif + #endif +#endif`,Zu=`#if NUM_CLIPPING_PLANES > 0 + varying vec3 vClipPosition; + uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ]; +#endif`,Ku=`#if NUM_CLIPPING_PLANES > 0 + varying vec3 vClipPosition; +#endif`,ju=`#if NUM_CLIPPING_PLANES > 0 + vClipPosition = - mvPosition.xyz; +#endif`,Ju=`#if defined( USE_COLOR_ALPHA ) + diffuseColor *= vColor; +#elif defined( USE_COLOR ) + diffuseColor.rgb *= vColor; +#endif`,$u=`#if defined( USE_COLOR_ALPHA ) + varying vec4 vColor; +#elif defined( USE_COLOR ) + varying vec3 vColor; +#endif`,Qu=`#if defined( USE_COLOR_ALPHA ) + varying vec4 vColor; +#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) + varying vec3 vColor; +#endif`,tf=`#if defined( USE_COLOR_ALPHA ) + vColor = vec4( 1.0 ); +#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) + vColor = vec3( 1.0 ); +#endif +#ifdef USE_COLOR + vColor *= color; +#endif +#ifdef USE_INSTANCING_COLOR + vColor.xyz *= instanceColor.xyz; +#endif +#ifdef USE_BATCHING_COLOR + vec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) ); + vColor.xyz *= batchingColor.xyz; +#endif`,ef=`#define PI 3.141592653589793 +#define PI2 6.283185307179586 +#define PI_HALF 1.5707963267948966 +#define RECIPROCAL_PI 0.3183098861837907 +#define RECIPROCAL_PI2 0.15915494309189535 +#define EPSILON 1e-6 +#ifndef saturate +#define saturate( a ) clamp( a, 0.0, 1.0 ) +#endif +#define whiteComplement( a ) ( 1.0 - saturate( a ) ) +float pow2( const in float x ) { return x*x; } +vec3 pow2( const in vec3 x ) { return x*x; } +float pow3( const in float x ) { return x*x*x; } +float pow4( const in float x ) { float x2 = x*x; return x2*x2; } +float max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); } +float average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); } +highp float rand( const in vec2 uv ) { + const highp float a = 12.9898, b = 78.233, c = 43758.5453; + highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI ); + return fract( sin( sn ) * c ); +} +#ifdef HIGH_PRECISION + float precisionSafeLength( vec3 v ) { return length( v ); } +#else + float precisionSafeLength( vec3 v ) { + float maxComponent = max3( abs( v ) ); + return length( v / maxComponent ) * maxComponent; + } +#endif +struct IncidentLight { + vec3 color; + vec3 direction; + bool visible; +}; +struct ReflectedLight { + vec3 directDiffuse; + vec3 directSpecular; + vec3 indirectDiffuse; + vec3 indirectSpecular; +}; +#ifdef USE_ALPHAHASH + varying vec3 vPosition; +#endif +vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); +} +vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) { + return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz ); +} +bool isPerspectiveMatrix( mat4 m ) { + return m[ 2 ][ 3 ] == - 1.0; +} +vec2 equirectUv( in vec3 dir ) { + float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5; + float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5; + return vec2( u, v ); +} +vec3 BRDF_Lambert( const in vec3 diffuseColor ) { + return RECIPROCAL_PI * diffuseColor; +} +vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) { + float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); + return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); +} +float F_Schlick( const in float f0, const in float f90, const in float dotVH ) { + float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); + return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); +} // validated`,nf=`#ifdef ENVMAP_TYPE_CUBE_UV + #define cubeUV_minMipLevel 4.0 + #define cubeUV_minTileSize 16.0 + float getFace( vec3 direction ) { + vec3 absDirection = abs( direction ); + float face = - 1.0; + if ( absDirection.x > absDirection.z ) { + if ( absDirection.x > absDirection.y ) + face = direction.x > 0.0 ? 0.0 : 3.0; + else + face = direction.y > 0.0 ? 1.0 : 4.0; + } else { + if ( absDirection.z > absDirection.y ) + face = direction.z > 0.0 ? 2.0 : 5.0; + else + face = direction.y > 0.0 ? 1.0 : 4.0; + } + return face; + } + vec2 getUV( vec3 direction, float face ) { + vec2 uv; + if ( face == 0.0 ) { + uv = vec2( direction.z, direction.y ) / abs( direction.x ); + } else if ( face == 1.0 ) { + uv = vec2( - direction.x, - direction.z ) / abs( direction.y ); + } else if ( face == 2.0 ) { + uv = vec2( - direction.x, direction.y ) / abs( direction.z ); + } else if ( face == 3.0 ) { + uv = vec2( - direction.z, direction.y ) / abs( direction.x ); + } else if ( face == 4.0 ) { + uv = vec2( - direction.x, direction.z ) / abs( direction.y ); + } else { + uv = vec2( direction.x, direction.y ) / abs( direction.z ); + } + return 0.5 * ( uv + 1.0 ); + } + vec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) { + float face = getFace( direction ); + float filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 ); + mipInt = max( mipInt, cubeUV_minMipLevel ); + float faceSize = exp2( mipInt ); + highp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0; + if ( face > 2.0 ) { + uv.y += faceSize; + face -= 3.0; + } + uv.x += face * faceSize; + uv.x += filterInt * 3.0 * cubeUV_minTileSize; + uv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize ); + uv.x *= CUBEUV_TEXEL_WIDTH; + uv.y *= CUBEUV_TEXEL_HEIGHT; + #ifdef texture2DGradEXT + return texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb; + #else + return texture2D( envMap, uv ).rgb; + #endif + } + #define cubeUV_r0 1.0 + #define cubeUV_m0 - 2.0 + #define cubeUV_r1 0.8 + #define cubeUV_m1 - 1.0 + #define cubeUV_r4 0.4 + #define cubeUV_m4 2.0 + #define cubeUV_r5 0.305 + #define cubeUV_m5 3.0 + #define cubeUV_r6 0.21 + #define cubeUV_m6 4.0 + float roughnessToMip( float roughness ) { + float mip = 0.0; + if ( roughness >= cubeUV_r1 ) { + mip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0; + } else if ( roughness >= cubeUV_r4 ) { + mip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1; + } else if ( roughness >= cubeUV_r5 ) { + mip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4; + } else if ( roughness >= cubeUV_r6 ) { + mip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5; + } else { + mip = - 2.0 * log2( 1.16 * roughness ); } + return mip; + } + vec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) { + float mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP ); + float mipF = fract( mip ); + float mipInt = floor( mip ); + vec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt ); + if ( mipF == 0.0 ) { + return vec4( color0, 1.0 ); + } else { + vec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 ); + return vec4( mix( color0, color1, mipF ), 1.0 ); + } + } +#endif`,sf=`vec3 transformedNormal = objectNormal; +#ifdef USE_TANGENT + vec3 transformedTangent = objectTangent; +#endif +#ifdef USE_BATCHING + mat3 bm = mat3( batchingMatrix ); + transformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) ); + transformedNormal = bm * transformedNormal; + #ifdef USE_TANGENT + transformedTangent = bm * transformedTangent; + #endif +#endif +#ifdef USE_INSTANCING + mat3 im = mat3( instanceMatrix ); + transformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) ); + transformedNormal = im * transformedNormal; + #ifdef USE_TANGENT + transformedTangent = im * transformedTangent; + #endif +#endif +transformedNormal = normalMatrix * transformedNormal; +#ifdef FLIP_SIDED + transformedNormal = - transformedNormal; +#endif +#ifdef USE_TANGENT + transformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz; + #ifdef FLIP_SIDED + transformedTangent = - transformedTangent; + #endif +#endif`,rf=`#ifdef USE_DISPLACEMENTMAP + uniform sampler2D displacementMap; + uniform float displacementScale; + uniform float displacementBias; +#endif`,af=`#ifdef USE_DISPLACEMENTMAP + transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias ); +#endif`,of=`#ifdef USE_EMISSIVEMAP + vec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv ); + #ifdef DECODE_VIDEO_TEXTURE_EMISSIVE + emissiveColor = sRGBTransferEOTF( emissiveColor ); + #endif + totalEmissiveRadiance *= emissiveColor.rgb; +#endif`,cf=`#ifdef USE_EMISSIVEMAP + uniform sampler2D emissiveMap; +#endif`,lf="gl_FragColor = linearToOutputTexel( gl_FragColor );",hf=`vec4 LinearTransferOETF( in vec4 value ) { + return value; +} +vec4 sRGBTransferEOTF( in vec4 value ) { + return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a ); +} +vec4 sRGBTransferOETF( in vec4 value ) { + return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a ); +}`,uf=`#ifdef USE_ENVMAP + #ifdef ENV_WORLDPOS + vec3 cameraToFrag; + if ( isOrthographic ) { + cameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) ); + } else { + cameraToFrag = normalize( vWorldPosition - cameraPosition ); + } + vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); + #ifdef ENVMAP_MODE_REFLECTION + vec3 reflectVec = reflect( cameraToFrag, worldNormal ); + #else + vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio ); + #endif + #else + vec3 reflectVec = vReflect; + #endif + #ifdef ENVMAP_TYPE_CUBE + vec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) ); + #else + vec4 envColor = vec4( 0.0 ); + #endif + #ifdef ENVMAP_BLENDING_MULTIPLY + outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity ); + #elif defined( ENVMAP_BLENDING_MIX ) + outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity ); + #elif defined( ENVMAP_BLENDING_ADD ) + outgoingLight += envColor.xyz * specularStrength * reflectivity; + #endif +#endif`,ff=`#ifdef USE_ENVMAP + uniform float envMapIntensity; + uniform float flipEnvMap; + uniform mat3 envMapRotation; + #ifdef ENVMAP_TYPE_CUBE + uniform samplerCube envMap; + #else + uniform sampler2D envMap; + #endif +#endif`,df=`#ifdef USE_ENVMAP + uniform float reflectivity; + #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) + #define ENV_WORLDPOS + #endif + #ifdef ENV_WORLDPOS + varying vec3 vWorldPosition; + uniform float refractionRatio; + #else + varying vec3 vReflect; + #endif +#endif`,pf=`#ifdef USE_ENVMAP + #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) + #define ENV_WORLDPOS + #endif + #ifdef ENV_WORLDPOS + + varying vec3 vWorldPosition; + #else + varying vec3 vReflect; + uniform float refractionRatio; + #endif +#endif`,mf=`#ifdef USE_ENVMAP + #ifdef ENV_WORLDPOS + vWorldPosition = worldPosition.xyz; + #else + vec3 cameraToVertex; + if ( isOrthographic ) { + cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) ); + } else { + cameraToVertex = normalize( worldPosition.xyz - cameraPosition ); + } + vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix ); + #ifdef ENVMAP_MODE_REFLECTION + vReflect = reflect( cameraToVertex, worldNormal ); + #else + vReflect = refract( cameraToVertex, worldNormal, refractionRatio ); + #endif + #endif +#endif`,xf=`#ifdef USE_FOG + vFogDepth = - mvPosition.z; +#endif`,gf=`#ifdef USE_FOG + varying float vFogDepth; +#endif`,_f=`#ifdef USE_FOG + #ifdef FOG_EXP2 + float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth ); + #else + float fogFactor = smoothstep( fogNear, fogFar, vFogDepth ); + #endif + gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor ); +#endif`,vf=`#ifdef USE_FOG + uniform vec3 fogColor; + varying float vFogDepth; + #ifdef FOG_EXP2 + uniform float fogDensity; + #else + uniform float fogNear; + uniform float fogFar; + #endif +#endif`,Mf=`#ifdef USE_GRADIENTMAP + uniform sampler2D gradientMap; +#endif +vec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) { + float dotNL = dot( normal, lightDirection ); + vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 ); + #ifdef USE_GRADIENTMAP + return vec3( texture2D( gradientMap, coord ).r ); + #else + vec2 fw = fwidth( coord ) * 0.5; + return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) ); + #endif +}`,Sf=`#ifdef USE_LIGHTMAP + uniform sampler2D lightMap; + uniform float lightMapIntensity; +#endif`,yf=`LambertMaterial material; +material.diffuseColor = diffuseColor.rgb; +material.specularStrength = specularStrength;`,bf=`varying vec3 vViewPosition; +struct LambertMaterial { + vec3 diffuseColor; + float specularStrength; +}; +void RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) { + float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); + vec3 irradiance = dotNL * directLight.color; + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +#define RE_Direct RE_Direct_Lambert +#define RE_IndirectDiffuse RE_IndirectDiffuse_Lambert`,Ef=`uniform bool receiveShadow; +uniform vec3 ambientLightColor; +#if defined( USE_LIGHT_PROBES ) + uniform vec3 lightProbe[ 9 ]; +#endif +vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) { + float x = normal.x, y = normal.y, z = normal.z; + vec3 result = shCoefficients[ 0 ] * 0.886227; + result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y; + result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z; + result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x; + result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y; + result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z; + result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 ); + result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z; + result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y ); + return result; +} +vec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) { + vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); + vec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe ); + return irradiance; +} +vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) { + vec3 irradiance = ambientLightColor; + return irradiance; +} +float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) { + float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 ); + if ( cutoffDistance > 0.0 ) { + distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) ); + } + return distanceFalloff; +} +float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) { + return smoothstep( coneCosine, penumbraCosine, angleCosine ); +} +#if NUM_DIR_LIGHTS > 0 + struct DirectionalLight { + vec3 direction; + vec3 color; + }; + uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ]; + void getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) { + light.color = directionalLight.color; + light.direction = directionalLight.direction; + light.visible = true; + } +#endif +#if NUM_POINT_LIGHTS > 0 + struct PointLight { + vec3 position; + vec3 color; + float distance; + float decay; + }; + uniform PointLight pointLights[ NUM_POINT_LIGHTS ]; + void getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) { + vec3 lVector = pointLight.position - geometryPosition; + light.direction = normalize( lVector ); + float lightDistance = length( lVector ); + light.color = pointLight.color; + light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay ); + light.visible = ( light.color != vec3( 0.0 ) ); + } +#endif +#if NUM_SPOT_LIGHTS > 0 + struct SpotLight { + vec3 position; + vec3 direction; + vec3 color; + float distance; + float decay; + float coneCos; + float penumbraCos; + }; + uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ]; + void getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) { + vec3 lVector = spotLight.position - geometryPosition; + light.direction = normalize( lVector ); + float angleCos = dot( light.direction, spotLight.direction ); + float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos ); + if ( spotAttenuation > 0.0 ) { + float lightDistance = length( lVector ); + light.color = spotLight.color * spotAttenuation; + light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay ); + light.visible = ( light.color != vec3( 0.0 ) ); + } else { + light.color = vec3( 0.0 ); + light.visible = false; + } + } +#endif +#if NUM_RECT_AREA_LIGHTS > 0 + struct RectAreaLight { + vec3 color; + vec3 position; + vec3 halfWidth; + vec3 halfHeight; + }; + uniform sampler2D ltc_1; uniform sampler2D ltc_2; + uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ]; +#endif +#if NUM_HEMI_LIGHTS > 0 + struct HemisphereLight { + vec3 direction; + vec3 skyColor; + vec3 groundColor; + }; + uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ]; + vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) { + float dotNL = dot( normal, hemiLight.direction ); + float hemiDiffuseWeight = 0.5 * dotNL + 0.5; + vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight ); + return irradiance; + } +#endif`,Tf=`#ifdef USE_ENVMAP + vec3 getIBLIrradiance( const in vec3 normal ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); + vec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 ); + return PI * envMapColor.rgb * envMapIntensity; + #else + return vec3( 0.0 ); + #endif + } + vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 reflectVec = reflect( - viewDir, normal ); + reflectVec = normalize( mix( reflectVec, normal, pow4( roughness ) ) ); + reflectVec = inverseTransformDirection( reflectVec, viewMatrix ); + vec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness ); + return envMapColor.rgb * envMapIntensity; + #else + return vec3( 0.0 ); + #endif + } + #ifdef USE_ANISOTROPY + vec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 bentNormal = cross( bitangent, viewDir ); + bentNormal = normalize( cross( bentNormal, bitangent ) ); + bentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) ); + return getIBLRadiance( viewDir, bentNormal, roughness ); + #else + return vec3( 0.0 ); + #endif + } + #endif +#endif`,Af=`ToonMaterial material; +material.diffuseColor = diffuseColor.rgb;`,wf=`varying vec3 vViewPosition; +struct ToonMaterial { + vec3 diffuseColor; +}; +void RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) { + vec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color; + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +#define RE_Direct RE_Direct_Toon +#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon`,Rf=`BlinnPhongMaterial material; +material.diffuseColor = diffuseColor.rgb; +material.specularColor = specular; +material.specularShininess = shininess; +material.specularStrength = specularStrength;`,Cf=`varying vec3 vViewPosition; +struct BlinnPhongMaterial { + vec3 diffuseColor; + vec3 specularColor; + float specularShininess; + float specularStrength; +}; +void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) { + float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); + vec3 irradiance = dotNL * directLight.color; + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); + reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength; +} +void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +#define RE_Direct RE_Direct_BlinnPhong +#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong`,Pf=`PhysicalMaterial material; +material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor ); +vec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) ); +float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z ); +material.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness; +material.roughness = min( material.roughness, 1.0 ); +#ifdef IOR + material.ior = ior; + #ifdef USE_SPECULAR + float specularIntensityFactor = specularIntensity; + vec3 specularColorFactor = specularColor; + #ifdef USE_SPECULAR_COLORMAP + specularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb; + #endif + #ifdef USE_SPECULAR_INTENSITYMAP + specularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a; + #endif + material.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor ); + #else + float specularIntensityFactor = 1.0; + vec3 specularColorFactor = vec3( 1.0 ); + material.specularF90 = 1.0; + #endif + material.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor ); +#else + material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor ); + material.specularF90 = 1.0; +#endif +#ifdef USE_CLEARCOAT + material.clearcoat = clearcoat; + material.clearcoatRoughness = clearcoatRoughness; + material.clearcoatF0 = vec3( 0.04 ); + material.clearcoatF90 = 1.0; + #ifdef USE_CLEARCOATMAP + material.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x; + #endif + #ifdef USE_CLEARCOAT_ROUGHNESSMAP + material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y; + #endif + material.clearcoat = saturate( material.clearcoat ); material.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 ); + material.clearcoatRoughness += geometryRoughness; + material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 ); +#endif +#ifdef USE_DISPERSION + material.dispersion = dispersion; +#endif +#ifdef USE_IRIDESCENCE + material.iridescence = iridescence; + material.iridescenceIOR = iridescenceIOR; + #ifdef USE_IRIDESCENCEMAP + material.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r; + #endif + #ifdef USE_IRIDESCENCE_THICKNESSMAP + material.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum; + #else + material.iridescenceThickness = iridescenceThicknessMaximum; + #endif +#endif +#ifdef USE_SHEEN + material.sheenColor = sheenColor; + #ifdef USE_SHEEN_COLORMAP + material.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb; + #endif + material.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 ); + #ifdef USE_SHEEN_ROUGHNESSMAP + material.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a; + #endif +#endif +#ifdef USE_ANISOTROPY + #ifdef USE_ANISOTROPYMAP + mat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x ); + vec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb; + vec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b; + #else + vec2 anisotropyV = anisotropyVector; + #endif + material.anisotropy = length( anisotropyV ); + if( material.anisotropy == 0.0 ) { + anisotropyV = vec2( 1.0, 0.0 ); + } else { + anisotropyV /= material.anisotropy; + material.anisotropy = saturate( material.anisotropy ); + } + material.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) ); + material.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y; + material.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y; +#endif`,Df=`uniform sampler2D dfgLUT; +struct PhysicalMaterial { + vec3 diffuseColor; + float roughness; + vec3 specularColor; + float specularF90; + float dispersion; + #ifdef USE_CLEARCOAT + float clearcoat; + float clearcoatRoughness; + vec3 clearcoatF0; + float clearcoatF90; + #endif + #ifdef USE_IRIDESCENCE + float iridescence; + float iridescenceIOR; + float iridescenceThickness; + vec3 iridescenceFresnel; + vec3 iridescenceF0; + #endif + #ifdef USE_SHEEN + vec3 sheenColor; + float sheenRoughness; + #endif + #ifdef IOR + float ior; + #endif + #ifdef USE_TRANSMISSION + float transmission; + float transmissionAlpha; + float thickness; + float attenuationDistance; + vec3 attenuationColor; + #endif + #ifdef USE_ANISOTROPY + float anisotropy; + float alphaT; + vec3 anisotropyT; + vec3 anisotropyB; + #endif +}; +vec3 clearcoatSpecularDirect = vec3( 0.0 ); +vec3 clearcoatSpecularIndirect = vec3( 0.0 ); +vec3 sheenSpecularDirect = vec3( 0.0 ); +vec3 sheenSpecularIndirect = vec3(0.0 ); +vec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) { + float x = clamp( 1.0 - dotVH, 0.0, 1.0 ); + float x2 = x * x; + float x5 = clamp( x * x2 * x2, 0.0, 0.9999 ); + return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 ); +} +float V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) { + float a2 = pow2( alpha ); + float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) ); + float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) ); + return 0.5 / max( gv + gl, EPSILON ); +} +float D_GGX( const in float alpha, const in float dotNH ) { + float a2 = pow2( alpha ); + float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; + return RECIPROCAL_PI * a2 / pow2( denom ); +} +#ifdef USE_ANISOTROPY + float V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) { + float gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) ); + float gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) ); + float v = 0.5 / ( gv + gl ); + return saturate(v); + } + float D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) { + float a2 = alphaT * alphaB; + highp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH ); + highp float v2 = dot( v, v ); + float w2 = a2 / v2; + return RECIPROCAL_PI * a2 * pow2 ( w2 ); + } +#endif +#ifdef USE_CLEARCOAT + vec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) { + vec3 f0 = material.clearcoatF0; + float f90 = material.clearcoatF90; + float roughness = material.clearcoatRoughness; + float alpha = pow2( roughness ); + vec3 halfDir = normalize( lightDir + viewDir ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float dotVH = saturate( dot( viewDir, halfDir ) ); + vec3 F = F_Schlick( f0, f90, dotVH ); + float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); + float D = D_GGX( alpha, dotNH ); + return F * ( V * D ); + } +#endif +vec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) { + vec3 f0 = material.specularColor; + float f90 = material.specularF90; + float roughness = material.roughness; + float alpha = pow2( roughness ); + vec3 halfDir = normalize( lightDir + viewDir ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float dotVH = saturate( dot( viewDir, halfDir ) ); + vec3 F = F_Schlick( f0, f90, dotVH ); + #ifdef USE_IRIDESCENCE + F = mix( F, material.iridescenceFresnel, material.iridescence ); + #endif + #ifdef USE_ANISOTROPY + float dotTL = dot( material.anisotropyT, lightDir ); + float dotTV = dot( material.anisotropyT, viewDir ); + float dotTH = dot( material.anisotropyT, halfDir ); + float dotBL = dot( material.anisotropyB, lightDir ); + float dotBV = dot( material.anisotropyB, viewDir ); + float dotBH = dot( material.anisotropyB, halfDir ); + float V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL ); + float D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH ); + #else + float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); + float D = D_GGX( alpha, dotNH ); + #endif + return F * ( V * D ); +} +vec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) { + const float LUT_SIZE = 64.0; + const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; + const float LUT_BIAS = 0.5 / LUT_SIZE; + float dotNV = saturate( dot( N, V ) ); + vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) ); + uv = uv * LUT_SCALE + LUT_BIAS; + return uv; +} +float LTC_ClippedSphereFormFactor( const in vec3 f ) { + float l = length( f ); + return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 ); +} +vec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) { + float x = dot( v1, v2 ); + float y = abs( x ); + float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y; + float b = 3.4175940 + ( 4.1616724 + y ) * y; + float v = a / b; + float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v; + return cross( v1, v2 ) * theta_sintheta; +} +vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) { + vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ]; + vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ]; + vec3 lightNormal = cross( v1, v2 ); + if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 ); + vec3 T1, T2; + T1 = normalize( V - N * dot( V, N ) ); + T2 = - cross( N, T1 ); + mat3 mat = mInv * transpose( mat3( T1, T2, N ) ); + vec3 coords[ 4 ]; + coords[ 0 ] = mat * ( rectCoords[ 0 ] - P ); + coords[ 1 ] = mat * ( rectCoords[ 1 ] - P ); + coords[ 2 ] = mat * ( rectCoords[ 2 ] - P ); + coords[ 3 ] = mat * ( rectCoords[ 3 ] - P ); + coords[ 0 ] = normalize( coords[ 0 ] ); + coords[ 1 ] = normalize( coords[ 1 ] ); + coords[ 2 ] = normalize( coords[ 2 ] ); + coords[ 3 ] = normalize( coords[ 3 ] ); + vec3 vectorFormFactor = vec3( 0.0 ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] ); + float result = LTC_ClippedSphereFormFactor( vectorFormFactor ); + return vec3( result ); +} +#if defined( USE_SHEEN ) +float D_Charlie( float roughness, float dotNH ) { + float alpha = pow2( roughness ); + float invAlpha = 1.0 / alpha; + float cos2h = dotNH * dotNH; + float sin2h = max( 1.0 - cos2h, 0.0078125 ); + return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI ); +} +float V_Neubelt( float dotNV, float dotNL ) { + return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) ); +} +vec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) { + vec3 halfDir = normalize( lightDir + viewDir ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float D = D_Charlie( sheenRoughness, dotNH ); + float V = V_Neubelt( dotNV, dotNL ); + return sheenColor * ( D * V ); +} +#endif +float IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) { + float dotNV = saturate( dot( normal, viewDir ) ); + float r2 = roughness * roughness; + float a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95; + float b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72; + float DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) ); + return saturate( DG * RECIPROCAL_PI ); +} +vec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) { + float dotNV = saturate( dot( normal, viewDir ) ); + vec2 uv = vec2( roughness, dotNV ); + return texture2D( dfgLUT, uv ).rg; +} +vec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) { + vec2 fab = DFGApprox( normal, viewDir, roughness ); + return specularColor * fab.x + specularF90 * fab.y; +} +#ifdef USE_IRIDESCENCE +void computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) { +#else +void computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) { +#endif + vec2 fab = DFGApprox( normal, viewDir, roughness ); + #ifdef USE_IRIDESCENCE + vec3 Fr = mix( specularColor, iridescenceF0, iridescence ); + #else + vec3 Fr = specularColor; + #endif + vec3 FssEss = Fr * fab.x + specularF90 * fab.y; + float Ess = fab.x + fab.y; + float Ems = 1.0 - Ess; + vec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619; vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg ); + singleScatter += FssEss; + multiScatter += Fms * Ems; +} +vec3 BRDF_GGX_Multiscatter( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) { + vec3 singleScatter = BRDF_GGX( lightDir, viewDir, normal, material ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + vec2 dfgV = DFGApprox( vec3(0.0, 0.0, 1.0), vec3(sqrt(1.0 - dotNV * dotNV), 0.0, dotNV), material.roughness ); + vec2 dfgL = DFGApprox( vec3(0.0, 0.0, 1.0), vec3(sqrt(1.0 - dotNL * dotNL), 0.0, dotNL), material.roughness ); + vec3 FssEss_V = material.specularColor * dfgV.x + material.specularF90 * dfgV.y; + vec3 FssEss_L = material.specularColor * dfgL.x + material.specularF90 * dfgL.y; + float Ess_V = dfgV.x + dfgV.y; + float Ess_L = dfgL.x + dfgL.y; + float Ems_V = 1.0 - Ess_V; + float Ems_L = 1.0 - Ess_L; + vec3 Favg = material.specularColor + ( 1.0 - material.specularColor ) * 0.047619; + vec3 Fms = FssEss_V * FssEss_L * Favg / ( 1.0 - Ems_V * Ems_L * Favg * Favg + EPSILON ); + float compensationFactor = Ems_V * Ems_L; + vec3 multiScatter = Fms * compensationFactor; + return singleScatter + multiScatter; +} +#if NUM_RECT_AREA_LIGHTS > 0 + void RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { + vec3 normal = geometryNormal; + vec3 viewDir = geometryViewDir; + vec3 position = geometryPosition; + vec3 lightPos = rectAreaLight.position; + vec3 halfWidth = rectAreaLight.halfWidth; + vec3 halfHeight = rectAreaLight.halfHeight; + vec3 lightColor = rectAreaLight.color; + float roughness = material.roughness; + vec3 rectCoords[ 4 ]; + rectCoords[ 0 ] = lightPos + halfWidth - halfHeight; rectCoords[ 1 ] = lightPos - halfWidth - halfHeight; + rectCoords[ 2 ] = lightPos - halfWidth + halfHeight; + rectCoords[ 3 ] = lightPos + halfWidth + halfHeight; + vec2 uv = LTC_Uv( normal, viewDir, roughness ); + vec4 t1 = texture2D( ltc_1, uv ); + vec4 t2 = texture2D( ltc_2, uv ); + mat3 mInv = mat3( + vec3( t1.x, 0, t1.y ), + vec3( 0, 1, 0 ), + vec3( t1.z, 0, t1.w ) + ); + vec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y ); + reflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords ); + reflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords ); + } +#endif +void RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { + float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); + vec3 irradiance = dotNL * directLight.color; + #ifdef USE_CLEARCOAT + float dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) ); + vec3 ccIrradiance = dotNLcc * directLight.color; + clearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material ); + #endif + #ifdef USE_SHEEN + sheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness ); + #endif + reflectedLight.directSpecular += irradiance * BRDF_GGX_Multiscatter( directLight.direction, geometryViewDir, geometryNormal, material ); + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) { + #ifdef USE_CLEARCOAT + clearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness ); + #endif + #ifdef USE_SHEEN + sheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ); + #endif + vec3 singleScattering = vec3( 0.0 ); + vec3 multiScattering = vec3( 0.0 ); + vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI; + #ifdef USE_IRIDESCENCE + computeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering ); + #else + computeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering ); + #endif + vec3 totalScattering = singleScattering + multiScattering; + vec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) ); + reflectedLight.indirectSpecular += radiance * singleScattering; + reflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance; + reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance; +} +#define RE_Direct RE_Direct_Physical +#define RE_Direct_RectArea RE_Direct_RectArea_Physical +#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical +#define RE_IndirectSpecular RE_IndirectSpecular_Physical +float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) { + return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ); +}`,Lf=` +vec3 geometryPosition = - vViewPosition; +vec3 geometryNormal = normal; +vec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition ); +vec3 geometryClearcoatNormal = vec3( 0.0 ); +#ifdef USE_CLEARCOAT + geometryClearcoatNormal = clearcoatNormal; +#endif +#ifdef USE_IRIDESCENCE + float dotNVi = saturate( dot( normal, geometryViewDir ) ); + if ( material.iridescenceThickness == 0.0 ) { + material.iridescence = 0.0; + } else { + material.iridescence = saturate( material.iridescence ); + } + if ( material.iridescence > 0.0 ) { + material.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor ); + material.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi ); + } +#endif +IncidentLight directLight; +#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct ) + PointLight pointLight; + #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0 + PointLightShadow pointLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) { + pointLight = pointLights[ i ]; + getPointLightInfo( pointLight, geometryPosition, directLight ); + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) + pointLightShadow = pointLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct ) + SpotLight spotLight; + vec4 spotColor; + vec3 spotLightCoord; + bool inSpotLightMap; + #if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0 + SpotLightShadow spotLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) { + spotLight = spotLights[ i ]; + getSpotLightInfo( spotLight, geometryPosition, directLight ); + #if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS ) + #define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX + #elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + #define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS + #else + #define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS ) + #endif + #if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS ) + spotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w; + inSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) ); + spotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy ); + directLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color; + #endif + #undef SPOT_LIGHT_MAP_INDEX + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + spotLightShadow = spotLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct ) + DirectionalLight directionalLight; + #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0 + DirectionalLightShadow directionalLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) { + directionalLight = directionalLights[ i ]; + getDirectionalLightInfo( directionalLight, directLight ); + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS ) + directionalLightShadow = directionalLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea ) + RectAreaLight rectAreaLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) { + rectAreaLight = rectAreaLights[ i ]; + RE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if defined( RE_IndirectDiffuse ) + vec3 iblIrradiance = vec3( 0.0 ); + vec3 irradiance = getAmbientLightIrradiance( ambientLightColor ); + #if defined( USE_LIGHT_PROBES ) + irradiance += getLightProbeIrradiance( lightProbe, geometryNormal ); + #endif + #if ( NUM_HEMI_LIGHTS > 0 ) + #pragma unroll_loop_start + for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) { + irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal ); + } + #pragma unroll_loop_end + #endif +#endif +#if defined( RE_IndirectSpecular ) + vec3 radiance = vec3( 0.0 ); + vec3 clearcoatRadiance = vec3( 0.0 ); +#endif`,If=`#if defined( RE_IndirectDiffuse ) + #ifdef USE_LIGHTMAP + vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); + vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; + irradiance += lightMapIrradiance; + #endif + #if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV ) + iblIrradiance += getIBLIrradiance( geometryNormal ); + #endif +#endif +#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular ) + #ifdef USE_ANISOTROPY + radiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy ); + #else + radiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness ); + #endif + #ifdef USE_CLEARCOAT + clearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness ); + #endif +#endif`,Uf=`#if defined( RE_IndirectDiffuse ) + RE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); +#endif +#if defined( RE_IndirectSpecular ) + RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); +#endif`,Nf=`#if defined( USE_LOGARITHMIC_DEPTH_BUFFER ) + gl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5; +#endif`,Ff=`#if defined( USE_LOGARITHMIC_DEPTH_BUFFER ) + uniform float logDepthBufFC; + varying float vFragDepth; + varying float vIsPerspective; +#endif`,Of=`#ifdef USE_LOGARITHMIC_DEPTH_BUFFER + varying float vFragDepth; + varying float vIsPerspective; +#endif`,Bf=`#ifdef USE_LOGARITHMIC_DEPTH_BUFFER + vFragDepth = 1.0 + gl_Position.w; + vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) ); +#endif`,zf=`#ifdef USE_MAP + vec4 sampledDiffuseColor = texture2D( map, vMapUv ); + #ifdef DECODE_VIDEO_TEXTURE + sampledDiffuseColor = sRGBTransferEOTF( sampledDiffuseColor ); + #endif + diffuseColor *= sampledDiffuseColor; +#endif`,Vf=`#ifdef USE_MAP + uniform sampler2D map; +#endif`,Gf=`#if defined( USE_MAP ) || defined( USE_ALPHAMAP ) + #if defined( USE_POINTS_UV ) + vec2 uv = vUv; + #else + vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy; + #endif +#endif +#ifdef USE_MAP + diffuseColor *= texture2D( map, uv ); +#endif +#ifdef USE_ALPHAMAP + diffuseColor.a *= texture2D( alphaMap, uv ).g; +#endif`,kf=`#if defined( USE_POINTS_UV ) + varying vec2 vUv; +#else + #if defined( USE_MAP ) || defined( USE_ALPHAMAP ) + uniform mat3 uvTransform; + #endif +#endif +#ifdef USE_MAP + uniform sampler2D map; +#endif +#ifdef USE_ALPHAMAP + uniform sampler2D alphaMap; +#endif`,Hf=`float metalnessFactor = metalness; +#ifdef USE_METALNESSMAP + vec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv ); + metalnessFactor *= texelMetalness.b; +#endif`,Wf=`#ifdef USE_METALNESSMAP + uniform sampler2D metalnessMap; +#endif`,Xf=`#ifdef USE_INSTANCING_MORPH + float morphTargetInfluences[ MORPHTARGETS_COUNT ]; + float morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + morphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r; + } +#endif`,qf=`#if defined( USE_MORPHCOLORS ) + vColor *= morphTargetBaseInfluence; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + #if defined( USE_COLOR_ALPHA ) + if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ]; + #elif defined( USE_COLOR ) + if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ]; + #endif + } +#endif`,Yf=`#ifdef USE_MORPHNORMALS + objectNormal *= morphTargetBaseInfluence; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + if ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ]; + } +#endif`,Zf=`#ifdef USE_MORPHTARGETS + #ifndef USE_INSTANCING_MORPH + uniform float morphTargetBaseInfluence; + uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ]; + #endif + uniform sampler2DArray morphTargetsTexture; + uniform ivec2 morphTargetsTextureSize; + vec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) { + int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset; + int y = texelIndex / morphTargetsTextureSize.x; + int x = texelIndex - y * morphTargetsTextureSize.x; + ivec3 morphUV = ivec3( x, y, morphTargetIndex ); + return texelFetch( morphTargetsTexture, morphUV, 0 ); + } +#endif`,Kf=`#ifdef USE_MORPHTARGETS + transformed *= morphTargetBaseInfluence; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + if ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ]; + } +#endif`,jf=`float faceDirection = gl_FrontFacing ? 1.0 : - 1.0; +#ifdef FLAT_SHADED + vec3 fdx = dFdx( vViewPosition ); + vec3 fdy = dFdy( vViewPosition ); + vec3 normal = normalize( cross( fdx, fdy ) ); +#else + vec3 normal = normalize( vNormal ); + #ifdef DOUBLE_SIDED + normal *= faceDirection; + #endif +#endif +#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) + #ifdef USE_TANGENT + mat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); + #else + mat3 tbn = getTangentFrame( - vViewPosition, normal, + #if defined( USE_NORMALMAP ) + vNormalMapUv + #elif defined( USE_CLEARCOAT_NORMALMAP ) + vClearcoatNormalMapUv + #else + vUv + #endif + ); + #endif + #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED ) + tbn[0] *= faceDirection; + tbn[1] *= faceDirection; + #endif +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + #ifdef USE_TANGENT + mat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); + #else + mat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv ); + #endif + #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED ) + tbn2[0] *= faceDirection; + tbn2[1] *= faceDirection; + #endif +#endif +vec3 nonPerturbedNormal = normal;`,Jf=`#ifdef USE_NORMALMAP_OBJECTSPACE + normal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; + #ifdef FLIP_SIDED + normal = - normal; + #endif + #ifdef DOUBLE_SIDED + normal = normal * faceDirection; + #endif + normal = normalize( normalMatrix * normal ); +#elif defined( USE_NORMALMAP_TANGENTSPACE ) + vec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; + mapN.xy *= normalScale; + normal = normalize( tbn * mapN ); +#elif defined( USE_BUMPMAP ) + normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection ); +#endif`,$f=`#ifndef FLAT_SHADED + varying vec3 vNormal; + #ifdef USE_TANGENT + varying vec3 vTangent; + varying vec3 vBitangent; + #endif +#endif`,Qf=`#ifndef FLAT_SHADED + varying vec3 vNormal; + #ifdef USE_TANGENT + varying vec3 vTangent; + varying vec3 vBitangent; + #endif +#endif`,td=`#ifndef FLAT_SHADED + vNormal = normalize( transformedNormal ); + #ifdef USE_TANGENT + vTangent = normalize( transformedTangent ); + vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w ); + #endif +#endif`,ed=`#ifdef USE_NORMALMAP + uniform sampler2D normalMap; + uniform vec2 normalScale; +#endif +#ifdef USE_NORMALMAP_OBJECTSPACE + uniform mat3 normalMatrix; +#endif +#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) ) + mat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) { + vec3 q0 = dFdx( eye_pos.xyz ); + vec3 q1 = dFdy( eye_pos.xyz ); + vec2 st0 = dFdx( uv.st ); + vec2 st1 = dFdy( uv.st ); + vec3 N = surf_norm; + vec3 q1perp = cross( q1, N ); + vec3 q0perp = cross( N, q0 ); + vec3 T = q1perp * st0.x + q0perp * st1.x; + vec3 B = q1perp * st0.y + q0perp * st1.y; + float det = max( dot( T, T ), dot( B, B ) ); + float scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det ); + return mat3( T * scale, B * scale, N ); + } +#endif`,nd=`#ifdef USE_CLEARCOAT + vec3 clearcoatNormal = nonPerturbedNormal; +#endif`,id=`#ifdef USE_CLEARCOAT_NORMALMAP + vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0; + clearcoatMapN.xy *= clearcoatNormalScale; + clearcoatNormal = normalize( tbn2 * clearcoatMapN ); +#endif`,sd=`#ifdef USE_CLEARCOATMAP + uniform sampler2D clearcoatMap; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + uniform sampler2D clearcoatNormalMap; + uniform vec2 clearcoatNormalScale; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + uniform sampler2D clearcoatRoughnessMap; +#endif`,rd=`#ifdef USE_IRIDESCENCEMAP + uniform sampler2D iridescenceMap; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + uniform sampler2D iridescenceThicknessMap; +#endif`,ad=`#ifdef OPAQUE +diffuseColor.a = 1.0; +#endif +#ifdef USE_TRANSMISSION +diffuseColor.a *= material.transmissionAlpha; +#endif +gl_FragColor = vec4( outgoingLight, diffuseColor.a );`,od=`vec3 packNormalToRGB( const in vec3 normal ) { + return normalize( normal ) * 0.5 + 0.5; +} +vec3 unpackRGBToNormal( const in vec3 rgb ) { + return 2.0 * rgb.xyz - 1.0; +} +const float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.; +const float Inv255 = 1. / 255.; +const vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 ); +const vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g ); +const vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b ); +const vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a ); +vec4 packDepthToRGBA( const in float v ) { + if( v <= 0.0 ) + return vec4( 0., 0., 0., 0. ); + if( v >= 1.0 ) + return vec4( 1., 1., 1., 1. ); + float vuf; + float af = modf( v * PackFactors.a, vuf ); + float bf = modf( vuf * ShiftRight8, vuf ); + float gf = modf( vuf * ShiftRight8, vuf ); + return vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af ); +} +vec3 packDepthToRGB( const in float v ) { + if( v <= 0.0 ) + return vec3( 0., 0., 0. ); + if( v >= 1.0 ) + return vec3( 1., 1., 1. ); + float vuf; + float bf = modf( v * PackFactors.b, vuf ); + float gf = modf( vuf * ShiftRight8, vuf ); + return vec3( vuf * Inv255, gf * PackUpscale, bf ); +} +vec2 packDepthToRG( const in float v ) { + if( v <= 0.0 ) + return vec2( 0., 0. ); + if( v >= 1.0 ) + return vec2( 1., 1. ); + float vuf; + float gf = modf( v * 256., vuf ); + return vec2( vuf * Inv255, gf ); +} +float unpackRGBAToDepth( const in vec4 v ) { + return dot( v, UnpackFactors4 ); +} +float unpackRGBToDepth( const in vec3 v ) { + return dot( v, UnpackFactors3 ); +} +float unpackRGToDepth( const in vec2 v ) { + return v.r * UnpackFactors2.r + v.g * UnpackFactors2.g; +} +vec4 pack2HalfToRGBA( const in vec2 v ) { + vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) ); + return vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w ); +} +vec2 unpackRGBATo2Half( const in vec4 v ) { + return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) ); +} +float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) { + return ( viewZ + near ) / ( near - far ); +} +float orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) { + return depth * ( near - far ) - near; +} +float viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) { + return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ ); +} +float perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) { + return ( near * far ) / ( ( far - near ) * depth - far ); +}`,cd=`#ifdef PREMULTIPLIED_ALPHA + gl_FragColor.rgb *= gl_FragColor.a; +#endif`,ld=`vec4 mvPosition = vec4( transformed, 1.0 ); +#ifdef USE_BATCHING + mvPosition = batchingMatrix * mvPosition; +#endif +#ifdef USE_INSTANCING + mvPosition = instanceMatrix * mvPosition; +#endif +mvPosition = modelViewMatrix * mvPosition; +gl_Position = projectionMatrix * mvPosition;`,hd=`#ifdef DITHERING + gl_FragColor.rgb = dithering( gl_FragColor.rgb ); +#endif`,ud=`#ifdef DITHERING + vec3 dithering( vec3 color ) { + float grid_position = rand( gl_FragCoord.xy ); + vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 ); + dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position ); + return color + dither_shift_RGB; + } +#endif`,fd=`float roughnessFactor = roughness; +#ifdef USE_ROUGHNESSMAP + vec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv ); + roughnessFactor *= texelRoughness.g; +#endif`,dd=`#ifdef USE_ROUGHNESSMAP + uniform sampler2D roughnessMap; +#endif`,pd=`#if NUM_SPOT_LIGHT_COORDS > 0 + varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; +#endif +#if NUM_SPOT_LIGHT_MAPS > 0 + uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ]; +#endif +#ifdef USE_SHADOWMAP + #if NUM_DIR_LIGHT_SHADOWS > 0 + uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ]; + varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ]; + struct DirectionalLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ]; + #endif + #if NUM_SPOT_LIGHT_SHADOWS > 0 + uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ]; + struct SpotLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ]; + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + uniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ]; + varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ]; + struct PointLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + float shadowCameraNear; + float shadowCameraFar; + }; + uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ]; + #endif + float texture2DCompare( sampler2D depths, vec2 uv, float compare ) { + float depth = unpackRGBAToDepth( texture2D( depths, uv ) ); + #ifdef USE_REVERSED_DEPTH_BUFFER + return step( depth, compare ); + #else + return step( compare, depth ); + #endif + } + vec2 texture2DDistribution( sampler2D shadow, vec2 uv ) { + return unpackRGBATo2Half( texture2D( shadow, uv ) ); + } + float VSMShadow( sampler2D shadow, vec2 uv, float compare ) { + float occlusion = 1.0; + vec2 distribution = texture2DDistribution( shadow, uv ); + #ifdef USE_REVERSED_DEPTH_BUFFER + float hard_shadow = step( distribution.x, compare ); + #else + float hard_shadow = step( compare, distribution.x ); + #endif + if ( hard_shadow != 1.0 ) { + float distance = compare - distribution.x; + float variance = max( 0.00000, distribution.y * distribution.y ); + float softness_probability = variance / (variance + distance * distance ); softness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); occlusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 ); + } + return occlusion; + } + float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) { + float shadow = 1.0; + shadowCoord.xyz /= shadowCoord.w; + shadowCoord.z += shadowBias; + bool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0; + bool frustumTest = inFrustum && shadowCoord.z <= 1.0; + if ( frustumTest ) { + #if defined( SHADOWMAP_TYPE_PCF ) + vec2 texelSize = vec2( 1.0 ) / shadowMapSize; + float dx0 = - texelSize.x * shadowRadius; + float dy0 = - texelSize.y * shadowRadius; + float dx1 = + texelSize.x * shadowRadius; + float dy1 = + texelSize.y * shadowRadius; + float dx2 = dx0 / 2.0; + float dy2 = dy0 / 2.0; + float dx3 = dx1 / 2.0; + float dy3 = dy1 / 2.0; + shadow = ( + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z ) + ) * ( 1.0 / 17.0 ); + #elif defined( SHADOWMAP_TYPE_PCF_SOFT ) + vec2 texelSize = vec2( 1.0 ) / shadowMapSize; + float dx = texelSize.x; + float dy = texelSize.y; + vec2 uv = shadowCoord.xy; + vec2 f = fract( uv * shadowMapSize + 0.5 ); + uv -= f * texelSize; + shadow = ( + texture2DCompare( shadowMap, uv, shadowCoord.z ) + + texture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) + + texture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) + + mix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ), + f.x ) + + mix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ), + f.x ) + + mix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ), + f.y ) + + mix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ), + f.y ) + + mix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ), + f.x ), + mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ), + f.x ), + f.y ) + ) * ( 1.0 / 9.0 ); + #elif defined( SHADOWMAP_TYPE_VSM ) + shadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z ); + #else + shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ); + #endif + } + return mix( 1.0, shadow, shadowIntensity ); + } + vec2 cubeToUV( vec3 v, float texelSizeY ) { + vec3 absV = abs( v ); + float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) ); + absV *= scaleToCube; + v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY ); + vec2 planar = v.xy; + float almostATexel = 1.5 * texelSizeY; + float almostOne = 1.0 - almostATexel; + if ( absV.z >= almostOne ) { + if ( v.z > 0.0 ) + planar.x = 4.0 - v.x; + } else if ( absV.x >= almostOne ) { + float signX = sign( v.x ); + planar.x = v.z * signX + 2.0 * signX; + } else if ( absV.y >= almostOne ) { + float signY = sign( v.y ); + planar.x = v.x + 2.0 * signY + 2.0; + planar.y = v.z * signY - 2.0; + } + return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 ); + } + float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) { + float shadow = 1.0; + vec3 lightToPosition = shadowCoord.xyz; + + float lightToPositionLength = length( lightToPosition ); + if ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) { + float dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); dp += shadowBias; + vec3 bd3D = normalize( lightToPosition ); + vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) ); + #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM ) + vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y; + shadow = ( + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp ) + ) * ( 1.0 / 9.0 ); + #else + shadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ); + #endif + } + return mix( 1.0, shadow, shadowIntensity ); + } +#endif`,md=`#if NUM_SPOT_LIGHT_COORDS > 0 + uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ]; + varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; +#endif +#ifdef USE_SHADOWMAP + #if NUM_DIR_LIGHT_SHADOWS > 0 + uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ]; + varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ]; + struct DirectionalLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ]; + #endif + #if NUM_SPOT_LIGHT_SHADOWS > 0 + struct SpotLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ]; + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ]; + varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ]; + struct PointLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + float shadowCameraNear; + float shadowCameraFar; + }; + uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ]; + #endif +#endif`,xd=`#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 ) + vec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix ); + vec4 shadowWorldPosition; +#endif +#if defined( USE_SHADOWMAP ) + #if NUM_DIR_LIGHT_SHADOWS > 0 + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) { + shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 ); + vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition; + } + #pragma unroll_loop_end + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) { + shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 ); + vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition; + } + #pragma unroll_loop_end + #endif +#endif +#if NUM_SPOT_LIGHT_COORDS > 0 + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) { + shadowWorldPosition = worldPosition; + #if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + shadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias; + #endif + vSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition; + } + #pragma unroll_loop_end +#endif`,gd=`float getShadowMask() { + float shadow = 1.0; + #ifdef USE_SHADOWMAP + #if NUM_DIR_LIGHT_SHADOWS > 0 + DirectionalLightShadow directionalLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) { + directionalLight = directionalLightShadows[ i ]; + shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; + } + #pragma unroll_loop_end + #endif + #if NUM_SPOT_LIGHT_SHADOWS > 0 + SpotLightShadow spotLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) { + spotLight = spotLightShadows[ i ]; + shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0; + } + #pragma unroll_loop_end + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + PointLightShadow pointLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) { + pointLight = pointLightShadows[ i ]; + shadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0; + } + #pragma unroll_loop_end + #endif + #endif + return shadow; +}`,_d=`#ifdef USE_SKINNING + mat4 boneMatX = getBoneMatrix( skinIndex.x ); + mat4 boneMatY = getBoneMatrix( skinIndex.y ); + mat4 boneMatZ = getBoneMatrix( skinIndex.z ); + mat4 boneMatW = getBoneMatrix( skinIndex.w ); +#endif`,vd=`#ifdef USE_SKINNING + uniform mat4 bindMatrix; + uniform mat4 bindMatrixInverse; + uniform highp sampler2D boneTexture; + mat4 getBoneMatrix( const in float i ) { + int size = textureSize( boneTexture, 0 ).x; + int j = int( i ) * 4; + int x = j % size; + int y = j / size; + vec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 ); + vec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 ); + vec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 ); + vec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 ); + return mat4( v1, v2, v3, v4 ); + } +#endif`,Md=`#ifdef USE_SKINNING + vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 ); + vec4 skinned = vec4( 0.0 ); + skinned += boneMatX * skinVertex * skinWeight.x; + skinned += boneMatY * skinVertex * skinWeight.y; + skinned += boneMatZ * skinVertex * skinWeight.z; + skinned += boneMatW * skinVertex * skinWeight.w; + transformed = ( bindMatrixInverse * skinned ).xyz; +#endif`,Sd=`#ifdef USE_SKINNING + mat4 skinMatrix = mat4( 0.0 ); + skinMatrix += skinWeight.x * boneMatX; + skinMatrix += skinWeight.y * boneMatY; + skinMatrix += skinWeight.z * boneMatZ; + skinMatrix += skinWeight.w * boneMatW; + skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix; + objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz; + #ifdef USE_TANGENT + objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz; + #endif +#endif`,yd=`float specularStrength; +#ifdef USE_SPECULARMAP + vec4 texelSpecular = texture2D( specularMap, vSpecularMapUv ); + specularStrength = texelSpecular.r; +#else + specularStrength = 1.0; +#endif`,bd=`#ifdef USE_SPECULARMAP + uniform sampler2D specularMap; +#endif`,Ed=`#if defined( TONE_MAPPING ) + gl_FragColor.rgb = toneMapping( gl_FragColor.rgb ); +#endif`,Td=`#ifndef saturate +#define saturate( a ) clamp( a, 0.0, 1.0 ) +#endif +uniform float toneMappingExposure; +vec3 LinearToneMapping( vec3 color ) { + return saturate( toneMappingExposure * color ); +} +vec3 ReinhardToneMapping( vec3 color ) { + color *= toneMappingExposure; + return saturate( color / ( vec3( 1.0 ) + color ) ); +} +vec3 CineonToneMapping( vec3 color ) { + color *= toneMappingExposure; + color = max( vec3( 0.0 ), color - 0.004 ); + return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) ); +} +vec3 RRTAndODTFit( vec3 v ) { + vec3 a = v * ( v + 0.0245786 ) - 0.000090537; + vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081; + return a / b; +} +vec3 ACESFilmicToneMapping( vec3 color ) { + const mat3 ACESInputMat = mat3( + vec3( 0.59719, 0.07600, 0.02840 ), vec3( 0.35458, 0.90834, 0.13383 ), + vec3( 0.04823, 0.01566, 0.83777 ) + ); + const mat3 ACESOutputMat = mat3( + vec3( 1.60475, -0.10208, -0.00327 ), vec3( -0.53108, 1.10813, -0.07276 ), + vec3( -0.07367, -0.00605, 1.07602 ) + ); + color *= toneMappingExposure / 0.6; + color = ACESInputMat * color; + color = RRTAndODTFit( color ); + color = ACESOutputMat * color; + return saturate( color ); +} +const mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3( + vec3( 1.6605, - 0.1246, - 0.0182 ), + vec3( - 0.5876, 1.1329, - 0.1006 ), + vec3( - 0.0728, - 0.0083, 1.1187 ) +); +const mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3( + vec3( 0.6274, 0.0691, 0.0164 ), + vec3( 0.3293, 0.9195, 0.0880 ), + vec3( 0.0433, 0.0113, 0.8956 ) +); +vec3 agxDefaultContrastApprox( vec3 x ) { + vec3 x2 = x * x; + vec3 x4 = x2 * x2; + return + 15.5 * x4 * x2 + - 40.14 * x4 * x + + 31.96 * x4 + - 6.868 * x2 * x + + 0.4298 * x2 + + 0.1191 * x + - 0.00232; +} +vec3 AgXToneMapping( vec3 color ) { + const mat3 AgXInsetMatrix = mat3( + vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ), + vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ), + vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 ) + ); + const mat3 AgXOutsetMatrix = mat3( + vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ), + vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ), + vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 ) + ); + const float AgxMinEv = - 12.47393; const float AgxMaxEv = 4.026069; + color *= toneMappingExposure; + color = LINEAR_SRGB_TO_LINEAR_REC2020 * color; + color = AgXInsetMatrix * color; + color = max( color, 1e-10 ); color = log2( color ); + color = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv ); + color = clamp( color, 0.0, 1.0 ); + color = agxDefaultContrastApprox( color ); + color = AgXOutsetMatrix * color; + color = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) ); + color = LINEAR_REC2020_TO_LINEAR_SRGB * color; + color = clamp( color, 0.0, 1.0 ); + return color; +} +vec3 NeutralToneMapping( vec3 color ) { + const float StartCompression = 0.8 - 0.04; + const float Desaturation = 0.15; + color *= toneMappingExposure; + float x = min( color.r, min( color.g, color.b ) ); + float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; + color -= offset; + float peak = max( color.r, max( color.g, color.b ) ); + if ( peak < StartCompression ) return color; + float d = 1. - StartCompression; + float newPeak = 1. - d * d / ( peak + d - StartCompression ); + color *= newPeak / peak; + float g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. ); + return mix( color, vec3( newPeak ), g ); +} +vec3 CustomToneMapping( vec3 color ) { return color; }`,Ad=`#ifdef USE_TRANSMISSION + material.transmission = transmission; + material.transmissionAlpha = 1.0; + material.thickness = thickness; + material.attenuationDistance = attenuationDistance; + material.attenuationColor = attenuationColor; + #ifdef USE_TRANSMISSIONMAP + material.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r; + #endif + #ifdef USE_THICKNESSMAP + material.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g; + #endif + vec3 pos = vWorldPosition; + vec3 v = normalize( cameraPosition - pos ); + vec3 n = inverseTransformDirection( normal, viewMatrix ); + vec4 transmitted = getIBLVolumeRefraction( + n, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, + pos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness, + material.attenuationColor, material.attenuationDistance ); + material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission ); + totalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission ); +#endif`,wd=`#ifdef USE_TRANSMISSION + uniform float transmission; + uniform float thickness; + uniform float attenuationDistance; + uniform vec3 attenuationColor; + #ifdef USE_TRANSMISSIONMAP + uniform sampler2D transmissionMap; + #endif + #ifdef USE_THICKNESSMAP + uniform sampler2D thicknessMap; + #endif + uniform vec2 transmissionSamplerSize; + uniform sampler2D transmissionSamplerMap; + uniform mat4 modelMatrix; + uniform mat4 projectionMatrix; + varying vec3 vWorldPosition; + float w0( float a ) { + return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 ); + } + float w1( float a ) { + return ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 ); + } + float w2( float a ){ + return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 ); + } + float w3( float a ) { + return ( 1.0 / 6.0 ) * ( a * a * a ); + } + float g0( float a ) { + return w0( a ) + w1( a ); + } + float g1( float a ) { + return w2( a ) + w3( a ); + } + float h0( float a ) { + return - 1.0 + w1( a ) / ( w0( a ) + w1( a ) ); + } + float h1( float a ) { + return 1.0 + w3( a ) / ( w2( a ) + w3( a ) ); + } + vec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) { + uv = uv * texelSize.zw + 0.5; + vec2 iuv = floor( uv ); + vec2 fuv = fract( uv ); + float g0x = g0( fuv.x ); + float g1x = g1( fuv.x ); + float h0x = h0( fuv.x ); + float h1x = h1( fuv.x ); + float h0y = h0( fuv.y ); + float h1y = h1( fuv.y ); + vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; + vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; + vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; + vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; + return g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) + + g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) ); + } + vec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) { + vec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) ); + vec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) ); + vec2 fLodSizeInv = 1.0 / fLodSize; + vec2 cLodSizeInv = 1.0 / cLodSize; + vec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) ); + vec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) ); + return mix( fSample, cSample, fract( lod ) ); + } + vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) { + vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior ); + vec3 modelScale; + modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) ); + modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) ); + modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) ); + return normalize( refractionVector ) * thickness * modelScale; + } + float applyIorToRoughness( const in float roughness, const in float ior ) { + return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 ); + } + vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) { + float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); + return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod ); + } + vec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) { + if ( isinf( attenuationDistance ) ) { + return vec3( 1.0 ); + } else { + vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance; + vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); return transmittance; + } + } + vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor, + const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix, + const in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness, + const in vec3 attenuationColor, const in float attenuationDistance ) { + vec4 transmittedLight; + vec3 transmittance; + #ifdef USE_DISPERSION + float halfSpread = ( ior - 1.0 ) * 0.025 * dispersion; + vec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread ); + for ( int i = 0; i < 3; i ++ ) { + vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix ); + vec3 refractedRayExit = position + transmissionRay; + vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); + vec2 refractionCoords = ndcPos.xy / ndcPos.w; + refractionCoords += 1.0; + refractionCoords /= 2.0; + vec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] ); + transmittedLight[ i ] = transmissionSample[ i ]; + transmittedLight.a += transmissionSample.a; + transmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ]; + } + transmittedLight.a /= 3.0; + #else + vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); + vec3 refractedRayExit = position + transmissionRay; + vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); + vec2 refractionCoords = ndcPos.xy / ndcPos.w; + refractionCoords += 1.0; + refractionCoords /= 2.0; + transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); + transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ); + #endif + vec3 attenuatedColor = transmittance * transmittedLight.rgb; + vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness ); + float transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0; + return vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor ); + } +#endif`,Rd=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) + varying vec2 vUv; +#endif +#ifdef USE_MAP + varying vec2 vMapUv; +#endif +#ifdef USE_ALPHAMAP + varying vec2 vAlphaMapUv; +#endif +#ifdef USE_LIGHTMAP + varying vec2 vLightMapUv; +#endif +#ifdef USE_AOMAP + varying vec2 vAoMapUv; +#endif +#ifdef USE_BUMPMAP + varying vec2 vBumpMapUv; +#endif +#ifdef USE_NORMALMAP + varying vec2 vNormalMapUv; +#endif +#ifdef USE_EMISSIVEMAP + varying vec2 vEmissiveMapUv; +#endif +#ifdef USE_METALNESSMAP + varying vec2 vMetalnessMapUv; +#endif +#ifdef USE_ROUGHNESSMAP + varying vec2 vRoughnessMapUv; +#endif +#ifdef USE_ANISOTROPYMAP + varying vec2 vAnisotropyMapUv; +#endif +#ifdef USE_CLEARCOATMAP + varying vec2 vClearcoatMapUv; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + varying vec2 vClearcoatNormalMapUv; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + varying vec2 vClearcoatRoughnessMapUv; +#endif +#ifdef USE_IRIDESCENCEMAP + varying vec2 vIridescenceMapUv; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + varying vec2 vIridescenceThicknessMapUv; +#endif +#ifdef USE_SHEEN_COLORMAP + varying vec2 vSheenColorMapUv; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + varying vec2 vSheenRoughnessMapUv; +#endif +#ifdef USE_SPECULARMAP + varying vec2 vSpecularMapUv; +#endif +#ifdef USE_SPECULAR_COLORMAP + varying vec2 vSpecularColorMapUv; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + varying vec2 vSpecularIntensityMapUv; +#endif +#ifdef USE_TRANSMISSIONMAP + uniform mat3 transmissionMapTransform; + varying vec2 vTransmissionMapUv; +#endif +#ifdef USE_THICKNESSMAP + uniform mat3 thicknessMapTransform; + varying vec2 vThicknessMapUv; +#endif`,Cd=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) + varying vec2 vUv; +#endif +#ifdef USE_MAP + uniform mat3 mapTransform; + varying vec2 vMapUv; +#endif +#ifdef USE_ALPHAMAP + uniform mat3 alphaMapTransform; + varying vec2 vAlphaMapUv; +#endif +#ifdef USE_LIGHTMAP + uniform mat3 lightMapTransform; + varying vec2 vLightMapUv; +#endif +#ifdef USE_AOMAP + uniform mat3 aoMapTransform; + varying vec2 vAoMapUv; +#endif +#ifdef USE_BUMPMAP + uniform mat3 bumpMapTransform; + varying vec2 vBumpMapUv; +#endif +#ifdef USE_NORMALMAP + uniform mat3 normalMapTransform; + varying vec2 vNormalMapUv; +#endif +#ifdef USE_DISPLACEMENTMAP + uniform mat3 displacementMapTransform; + varying vec2 vDisplacementMapUv; +#endif +#ifdef USE_EMISSIVEMAP + uniform mat3 emissiveMapTransform; + varying vec2 vEmissiveMapUv; +#endif +#ifdef USE_METALNESSMAP + uniform mat3 metalnessMapTransform; + varying vec2 vMetalnessMapUv; +#endif +#ifdef USE_ROUGHNESSMAP + uniform mat3 roughnessMapTransform; + varying vec2 vRoughnessMapUv; +#endif +#ifdef USE_ANISOTROPYMAP + uniform mat3 anisotropyMapTransform; + varying vec2 vAnisotropyMapUv; +#endif +#ifdef USE_CLEARCOATMAP + uniform mat3 clearcoatMapTransform; + varying vec2 vClearcoatMapUv; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + uniform mat3 clearcoatNormalMapTransform; + varying vec2 vClearcoatNormalMapUv; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + uniform mat3 clearcoatRoughnessMapTransform; + varying vec2 vClearcoatRoughnessMapUv; +#endif +#ifdef USE_SHEEN_COLORMAP + uniform mat3 sheenColorMapTransform; + varying vec2 vSheenColorMapUv; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + uniform mat3 sheenRoughnessMapTransform; + varying vec2 vSheenRoughnessMapUv; +#endif +#ifdef USE_IRIDESCENCEMAP + uniform mat3 iridescenceMapTransform; + varying vec2 vIridescenceMapUv; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + uniform mat3 iridescenceThicknessMapTransform; + varying vec2 vIridescenceThicknessMapUv; +#endif +#ifdef USE_SPECULARMAP + uniform mat3 specularMapTransform; + varying vec2 vSpecularMapUv; +#endif +#ifdef USE_SPECULAR_COLORMAP + uniform mat3 specularColorMapTransform; + varying vec2 vSpecularColorMapUv; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + uniform mat3 specularIntensityMapTransform; + varying vec2 vSpecularIntensityMapUv; +#endif +#ifdef USE_TRANSMISSIONMAP + uniform mat3 transmissionMapTransform; + varying vec2 vTransmissionMapUv; +#endif +#ifdef USE_THICKNESSMAP + uniform mat3 thicknessMapTransform; + varying vec2 vThicknessMapUv; +#endif`,Pd=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) + vUv = vec3( uv, 1 ).xy; +#endif +#ifdef USE_MAP + vMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy; +#endif +#ifdef USE_ALPHAMAP + vAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_LIGHTMAP + vLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_AOMAP + vAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_BUMPMAP + vBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_NORMALMAP + vNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_DISPLACEMENTMAP + vDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_EMISSIVEMAP + vEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_METALNESSMAP + vMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_ROUGHNESSMAP + vRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_ANISOTROPYMAP + vAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_CLEARCOATMAP + vClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + vClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + vClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_IRIDESCENCEMAP + vIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + vIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SHEEN_COLORMAP + vSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + vSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SPECULARMAP + vSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SPECULAR_COLORMAP + vSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + vSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_TRANSMISSIONMAP + vTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_THICKNESSMAP + vThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy; +#endif`,Dd=`#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0 + vec4 worldPosition = vec4( transformed, 1.0 ); + #ifdef USE_BATCHING + worldPosition = batchingMatrix * worldPosition; + #endif + #ifdef USE_INSTANCING + worldPosition = instanceMatrix * worldPosition; + #endif + worldPosition = modelMatrix * worldPosition; +#endif`;const Ld=`varying vec2 vUv; +uniform mat3 uvTransform; +void main() { + vUv = ( uvTransform * vec3( uv, 1 ) ).xy; + gl_Position = vec4( position.xy, 1.0, 1.0 ); +}`,Id=`uniform sampler2D t2D; +uniform float backgroundIntensity; +varying vec2 vUv; +void main() { + vec4 texColor = texture2D( t2D, vUv ); + #ifdef DECODE_VIDEO_TEXTURE + texColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w ); + #endif + texColor.rgb *= backgroundIntensity; + gl_FragColor = texColor; + #include + #include +}`,Ud=`varying vec3 vWorldDirection; +#include +void main() { + vWorldDirection = transformDirection( position, modelMatrix ); + #include + #include + gl_Position.z = gl_Position.w; +}`,Nd=`#ifdef ENVMAP_TYPE_CUBE + uniform samplerCube envMap; +#elif defined( ENVMAP_TYPE_CUBE_UV ) + uniform sampler2D envMap; +#endif +uniform float flipEnvMap; +uniform float backgroundBlurriness; +uniform float backgroundIntensity; +uniform mat3 backgroundRotation; +varying vec3 vWorldDirection; +#include +void main() { + #ifdef ENVMAP_TYPE_CUBE + vec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) ); + #elif defined( ENVMAP_TYPE_CUBE_UV ) + vec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness ); + #else + vec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + #endif + texColor.rgb *= backgroundIntensity; + gl_FragColor = texColor; + #include + #include +}`,Fd=`varying vec3 vWorldDirection; +#include +void main() { + vWorldDirection = transformDirection( position, modelMatrix ); + #include + #include + gl_Position.z = gl_Position.w; +}`,Od=`uniform samplerCube tCube; +uniform float tFlip; +uniform float opacity; +varying vec3 vWorldDirection; +void main() { + vec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) ); + gl_FragColor = texColor; + gl_FragColor.a *= opacity; + #include + #include +}`,Bd=`#include +#include +#include +#include +#include +#include +#include +#include +varying vec2 vHighPrecisionZW; +void main() { + #include + #include + #include + #include + #ifdef USE_DISPLACEMENTMAP + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + vHighPrecisionZW = gl_Position.zw; +}`,zd=`#if DEPTH_PACKING == 3200 + uniform float opacity; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +varying vec2 vHighPrecisionZW; +void main() { + vec4 diffuseColor = vec4( 1.0 ); + #include + #if DEPTH_PACKING == 3200 + diffuseColor.a = opacity; + #endif + #include + #include + #include + #include + #include + #ifdef USE_REVERSED_DEPTH_BUFFER + float fragCoordZ = vHighPrecisionZW[ 0 ] / vHighPrecisionZW[ 1 ]; + #else + float fragCoordZ = 0.5 * vHighPrecisionZW[ 0 ] / vHighPrecisionZW[ 1 ] + 0.5; + #endif + #if DEPTH_PACKING == 3200 + gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity ); + #elif DEPTH_PACKING == 3201 + gl_FragColor = packDepthToRGBA( fragCoordZ ); + #elif DEPTH_PACKING == 3202 + gl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 ); + #elif DEPTH_PACKING == 3203 + gl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 ); + #endif +}`,Vd=`#define DISTANCE +varying vec3 vWorldPosition; +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #ifdef USE_DISPLACEMENTMAP + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + vWorldPosition = worldPosition.xyz; +}`,Gd=`#define DISTANCE +uniform vec3 referencePosition; +uniform float nearDistance; +uniform float farDistance; +varying vec3 vWorldPosition; +#include +#include +#include +#include +#include +#include +#include +#include +void main () { + vec4 diffuseColor = vec4( 1.0 ); + #include + #include + #include + #include + #include + float dist = length( vWorldPosition - referencePosition ); + dist = ( dist - nearDistance ) / ( farDistance - nearDistance ); + dist = saturate( dist ); + gl_FragColor = packDepthToRGBA( dist ); +}`,kd=`varying vec3 vWorldDirection; +#include +void main() { + vWorldDirection = transformDirection( position, modelMatrix ); + #include + #include +}`,Hd=`uniform sampler2D tEquirect; +varying vec3 vWorldDirection; +#include +void main() { + vec3 direction = normalize( vWorldDirection ); + vec2 sampleUV = equirectUv( direction ); + gl_FragColor = texture2D( tEquirect, sampleUV ); + #include + #include +}`,Wd=`uniform float scale; +attribute float lineDistance; +varying float vLineDistance; +#include +#include +#include +#include +#include +#include +#include +void main() { + vLineDistance = scale * lineDistance; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +}`,Xd=`uniform vec3 diffuse; +uniform float opacity; +uniform float dashSize; +uniform float totalSize; +varying float vLineDistance; +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + if ( mod( vLineDistance, totalSize ) > dashSize ) { + discard; + } + vec3 outgoingLight = vec3( 0.0 ); + #include + #include + #include + outgoingLight = diffuseColor.rgb; + #include + #include + #include + #include + #include +}`,qd=`#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #if defined ( USE_ENVMAP ) || defined ( USE_SKINNING ) + #include + #include + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + #include + #include +}`,Yd=`uniform vec3 diffuse; +uniform float opacity; +#ifndef FLAT_SHADED + varying vec3 vNormal; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + #include + #include + #include + #include + #include + #include + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + #ifdef USE_LIGHTMAP + vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); + reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI; + #else + reflectedLight.indirectDiffuse += vec3( 1.0 ); + #endif + #include + reflectedLight.indirectDiffuse *= diffuseColor.rgb; + vec3 outgoingLight = reflectedLight.indirectDiffuse; + #include + #include + #include + #include + #include + #include + #include +}`,Zd=`#define LAMBERT +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include + #include +}`,Kd=`#define LAMBERT +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; + #include + #include + #include + #include + #include + #include + #include +}`,jd=`#define MATCAP +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; +}`,Jd=`#define MATCAP +uniform vec3 diffuse; +uniform float opacity; +uniform sampler2D matcap; +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 viewDir = normalize( vViewPosition ); + vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) ); + vec3 y = cross( viewDir, x ); + vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; + #ifdef USE_MATCAP + vec4 matcapColor = texture2D( matcap, uv ); + #else + vec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 ); + #endif + vec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb; + #include + #include + #include + #include + #include + #include +}`,$d=`#define NORMAL +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) + varying vec3 vViewPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) + vViewPosition = - mvPosition.xyz; +#endif +}`,Qd=`#define NORMAL +uniform float opacity; +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) + varying vec3 vViewPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity ); + #include + #include + #include + #include + gl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a ); + #ifdef OPAQUE + gl_FragColor.a = 1.0; + #endif +}`,tp=`#define PHONG +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include + #include +}`,ep=`#define PHONG +uniform vec3 diffuse; +uniform vec3 emissive; +uniform vec3 specular; +uniform float shininess; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance; + #include + #include + #include + #include + #include + #include + #include +}`,np=`#define STANDARD +varying vec3 vViewPosition; +#ifdef USE_TRANSMISSION + varying vec3 vWorldPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include +#ifdef USE_TRANSMISSION + vWorldPosition = worldPosition.xyz; +#endif +}`,ip=`#define STANDARD +#ifdef PHYSICAL + #define IOR + #define USE_SPECULAR +#endif +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float roughness; +uniform float metalness; +uniform float opacity; +#ifdef IOR + uniform float ior; +#endif +#ifdef USE_SPECULAR + uniform float specularIntensity; + uniform vec3 specularColor; + #ifdef USE_SPECULAR_COLORMAP + uniform sampler2D specularColorMap; + #endif + #ifdef USE_SPECULAR_INTENSITYMAP + uniform sampler2D specularIntensityMap; + #endif +#endif +#ifdef USE_CLEARCOAT + uniform float clearcoat; + uniform float clearcoatRoughness; +#endif +#ifdef USE_DISPERSION + uniform float dispersion; +#endif +#ifdef USE_IRIDESCENCE + uniform float iridescence; + uniform float iridescenceIOR; + uniform float iridescenceThicknessMinimum; + uniform float iridescenceThicknessMaximum; +#endif +#ifdef USE_SHEEN + uniform vec3 sheenColor; + uniform float sheenRoughness; + #ifdef USE_SHEEN_COLORMAP + uniform sampler2D sheenColorMap; + #endif + #ifdef USE_SHEEN_ROUGHNESSMAP + uniform sampler2D sheenRoughnessMap; + #endif +#endif +#ifdef USE_ANISOTROPY + uniform vec2 anisotropyVector; + #ifdef USE_ANISOTROPYMAP + uniform sampler2D anisotropyMap; + #endif +#endif +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse; + vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular; + #include + vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance; + #ifdef USE_SHEEN + float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor ); + outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect; + #endif + #ifdef USE_CLEARCOAT + float dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) ); + vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc ); + outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat; + #endif + #include + #include + #include + #include + #include + #include +}`,sp=`#define TOON +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include +}`,rp=`#define TOON +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; + #include + #include + #include + #include + #include + #include +}`,ap=`uniform float size; +uniform float scale; +#include +#include +#include +#include +#include +#include +#ifdef USE_POINTS_UV + varying vec2 vUv; + uniform mat3 uvTransform; +#endif +void main() { + #ifdef USE_POINTS_UV + vUv = ( uvTransform * vec3( uv, 1 ) ).xy; + #endif + #include + #include + #include + #include + #include + #include + gl_PointSize = size; + #ifdef USE_SIZEATTENUATION + bool isPerspective = isPerspectiveMatrix( projectionMatrix ); + if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z ); + #endif + #include + #include + #include + #include +}`,op=`uniform vec3 diffuse; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + vec3 outgoingLight = vec3( 0.0 ); + #include + #include + #include + #include + #include + outgoingLight = diffuseColor.rgb; + #include + #include + #include + #include + #include +}`,cp=`#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +}`,lp=`uniform vec3 color; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + gl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) ); + #include + #include + #include +}`,hp=`uniform float rotation; +uniform vec2 center; +#include +#include +#include +#include +#include +void main() { + #include + vec4 mvPosition = modelViewMatrix[ 3 ]; + vec2 scale = vec2( length( modelMatrix[ 0 ].xyz ), length( modelMatrix[ 1 ].xyz ) ); + #ifndef USE_SIZEATTENUATION + bool isPerspective = isPerspectiveMatrix( projectionMatrix ); + if ( isPerspective ) scale *= - mvPosition.z; + #endif + vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale; + vec2 rotatedPosition; + rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y; + rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y; + mvPosition.xy += rotatedPosition; + gl_Position = projectionMatrix * mvPosition; + #include + #include + #include +}`,up=`uniform vec3 diffuse; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + vec3 outgoingLight = vec3( 0.0 ); + #include + #include + #include + #include + #include + outgoingLight = diffuseColor.rgb; + #include + #include + #include + #include +}`,Wt={alphahash_fragment:Lu,alphahash_pars_fragment:Iu,alphamap_fragment:Uu,alphamap_pars_fragment:Nu,alphatest_fragment:Fu,alphatest_pars_fragment:Ou,aomap_fragment:Bu,aomap_pars_fragment:zu,batching_pars_vertex:Vu,batching_vertex:Gu,begin_vertex:ku,beginnormal_vertex:Hu,bsdfs:Wu,iridescence_fragment:Xu,bumpmap_pars_fragment:qu,clipping_planes_fragment:Yu,clipping_planes_pars_fragment:Zu,clipping_planes_pars_vertex:Ku,clipping_planes_vertex:ju,color_fragment:Ju,color_pars_fragment:$u,color_pars_vertex:Qu,color_vertex:tf,common:ef,cube_uv_reflection_fragment:nf,defaultnormal_vertex:sf,displacementmap_pars_vertex:rf,displacementmap_vertex:af,emissivemap_fragment:of,emissivemap_pars_fragment:cf,colorspace_fragment:lf,colorspace_pars_fragment:hf,envmap_fragment:uf,envmap_common_pars_fragment:ff,envmap_pars_fragment:df,envmap_pars_vertex:pf,envmap_physical_pars_fragment:Tf,envmap_vertex:mf,fog_vertex:xf,fog_pars_vertex:gf,fog_fragment:_f,fog_pars_fragment:vf,gradientmap_pars_fragment:Mf,lightmap_pars_fragment:Sf,lights_lambert_fragment:yf,lights_lambert_pars_fragment:bf,lights_pars_begin:Ef,lights_toon_fragment:Af,lights_toon_pars_fragment:wf,lights_phong_fragment:Rf,lights_phong_pars_fragment:Cf,lights_physical_fragment:Pf,lights_physical_pars_fragment:Df,lights_fragment_begin:Lf,lights_fragment_maps:If,lights_fragment_end:Uf,logdepthbuf_fragment:Nf,logdepthbuf_pars_fragment:Ff,logdepthbuf_pars_vertex:Of,logdepthbuf_vertex:Bf,map_fragment:zf,map_pars_fragment:Vf,map_particle_fragment:Gf,map_particle_pars_fragment:kf,metalnessmap_fragment:Hf,metalnessmap_pars_fragment:Wf,morphinstance_vertex:Xf,morphcolor_vertex:qf,morphnormal_vertex:Yf,morphtarget_pars_vertex:Zf,morphtarget_vertex:Kf,normal_fragment_begin:jf,normal_fragment_maps:Jf,normal_pars_fragment:$f,normal_pars_vertex:Qf,normal_vertex:td,normalmap_pars_fragment:ed,clearcoat_normal_fragment_begin:nd,clearcoat_normal_fragment_maps:id,clearcoat_pars_fragment:sd,iridescence_pars_fragment:rd,opaque_fragment:ad,packing:od,premultiplied_alpha_fragment:cd,project_vertex:ld,dithering_fragment:hd,dithering_pars_fragment:ud,roughnessmap_fragment:fd,roughnessmap_pars_fragment:dd,shadowmap_pars_fragment:pd,shadowmap_pars_vertex:md,shadowmap_vertex:xd,shadowmask_pars_fragment:gd,skinbase_vertex:_d,skinning_pars_vertex:vd,skinning_vertex:Md,skinnormal_vertex:Sd,specularmap_fragment:yd,specularmap_pars_fragment:bd,tonemapping_fragment:Ed,tonemapping_pars_fragment:Td,transmission_fragment:Ad,transmission_pars_fragment:wd,uv_pars_fragment:Rd,uv_pars_vertex:Cd,uv_vertex:Pd,worldpos_vertex:Dd,background_vert:Ld,background_frag:Id,backgroundCube_vert:Ud,backgroundCube_frag:Nd,cube_vert:Fd,cube_frag:Od,depth_vert:Bd,depth_frag:zd,distanceRGBA_vert:Vd,distanceRGBA_frag:Gd,equirect_vert:kd,equirect_frag:Hd,linedashed_vert:Wd,linedashed_frag:Xd,meshbasic_vert:qd,meshbasic_frag:Yd,meshlambert_vert:Zd,meshlambert_frag:Kd,meshmatcap_vert:jd,meshmatcap_frag:Jd,meshnormal_vert:$d,meshnormal_frag:Qd,meshphong_vert:tp,meshphong_frag:ep,meshphysical_vert:np,meshphysical_frag:ip,meshtoon_vert:sp,meshtoon_frag:rp,points_vert:ap,points_frag:op,shadow_vert:cp,shadow_frag:lp,sprite_vert:hp,sprite_frag:up},pt={common:{diffuse:{value:new Yt(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new Ht},alphaMap:{value:null},alphaMapTransform:{value:new Ht},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new Ht}},envmap:{envMap:{value:null},envMapRotation:{value:new Ht},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98},dfgLUT:{value:null}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new Ht}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new Ht}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new Ht},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new Ht},normalScale:{value:new at(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new Ht},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new Ht}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new Ht}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new Ht}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Yt(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Yt(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new Ht},alphaTest:{value:0},uvTransform:{value:new Ht}},sprite:{diffuse:{value:new Yt(16777215)},opacity:{value:1},center:{value:new at(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new Ht},alphaMap:{value:null},alphaMapTransform:{value:new Ht},alphaTest:{value:0}}},an={basic:{uniforms:Pe([pt.common,pt.specularmap,pt.envmap,pt.aomap,pt.lightmap,pt.fog]),vertexShader:Wt.meshbasic_vert,fragmentShader:Wt.meshbasic_frag},lambert:{uniforms:Pe([pt.common,pt.specularmap,pt.envmap,pt.aomap,pt.lightmap,pt.emissivemap,pt.bumpmap,pt.normalmap,pt.displacementmap,pt.fog,pt.lights,{emissive:{value:new Yt(0)}}]),vertexShader:Wt.meshlambert_vert,fragmentShader:Wt.meshlambert_frag},phong:{uniforms:Pe([pt.common,pt.specularmap,pt.envmap,pt.aomap,pt.lightmap,pt.emissivemap,pt.bumpmap,pt.normalmap,pt.displacementmap,pt.fog,pt.lights,{emissive:{value:new Yt(0)},specular:{value:new Yt(1118481)},shininess:{value:30}}]),vertexShader:Wt.meshphong_vert,fragmentShader:Wt.meshphong_frag},standard:{uniforms:Pe([pt.common,pt.envmap,pt.aomap,pt.lightmap,pt.emissivemap,pt.bumpmap,pt.normalmap,pt.displacementmap,pt.roughnessmap,pt.metalnessmap,pt.fog,pt.lights,{emissive:{value:new Yt(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:Wt.meshphysical_vert,fragmentShader:Wt.meshphysical_frag},toon:{uniforms:Pe([pt.common,pt.aomap,pt.lightmap,pt.emissivemap,pt.bumpmap,pt.normalmap,pt.displacementmap,pt.gradientmap,pt.fog,pt.lights,{emissive:{value:new Yt(0)}}]),vertexShader:Wt.meshtoon_vert,fragmentShader:Wt.meshtoon_frag},matcap:{uniforms:Pe([pt.common,pt.bumpmap,pt.normalmap,pt.displacementmap,pt.fog,{matcap:{value:null}}]),vertexShader:Wt.meshmatcap_vert,fragmentShader:Wt.meshmatcap_frag},points:{uniforms:Pe([pt.points,pt.fog]),vertexShader:Wt.points_vert,fragmentShader:Wt.points_frag},dashed:{uniforms:Pe([pt.common,pt.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:Wt.linedashed_vert,fragmentShader:Wt.linedashed_frag},depth:{uniforms:Pe([pt.common,pt.displacementmap]),vertexShader:Wt.depth_vert,fragmentShader:Wt.depth_frag},normal:{uniforms:Pe([pt.common,pt.bumpmap,pt.normalmap,pt.displacementmap,{opacity:{value:1}}]),vertexShader:Wt.meshnormal_vert,fragmentShader:Wt.meshnormal_frag},sprite:{uniforms:Pe([pt.sprite,pt.fog]),vertexShader:Wt.sprite_vert,fragmentShader:Wt.sprite_frag},background:{uniforms:{uvTransform:{value:new Ht},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:Wt.background_vert,fragmentShader:Wt.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new Ht}},vertexShader:Wt.backgroundCube_vert,fragmentShader:Wt.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:Wt.cube_vert,fragmentShader:Wt.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:Wt.equirect_vert,fragmentShader:Wt.equirect_frag},distanceRGBA:{uniforms:Pe([pt.common,pt.displacementmap,{referencePosition:{value:new D},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:Wt.distanceRGBA_vert,fragmentShader:Wt.distanceRGBA_frag},shadow:{uniforms:Pe([pt.lights,pt.fog,{color:{value:new Yt(0)},opacity:{value:1}}]),vertexShader:Wt.shadow_vert,fragmentShader:Wt.shadow_frag}};an.physical={uniforms:Pe([an.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new Ht},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new Ht},clearcoatNormalScale:{value:new at(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new Ht},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new Ht},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new Ht},sheen:{value:0},sheenColor:{value:new Yt(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new Ht},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new Ht},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new Ht},transmissionSamplerSize:{value:new at},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new Ht},attenuationDistance:{value:0},attenuationColor:{value:new Yt(0)},specularColor:{value:new Yt(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new Ht},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new Ht},anisotropyVector:{value:new at},anisotropyMap:{value:null},anisotropyMapTransform:{value:new Ht}}]),vertexShader:Wt.meshphysical_vert,fragmentShader:Wt.meshphysical_frag};const Ns={r:0,b:0,g:0},Wn=new nn,fp=new re;function dp(i,t,e,n,s,r,a){const o=new Yt(0);let l=r===!0?0:1,c,h,u=null,d=0,p=null;function x(S){let T=S.isScene===!0?S.background:null;return T&&T.isTexture&&(T=(S.backgroundBlurriness>0?e:t).get(T)),T}function _(S){let T=!1;const R=x(S);R===null?f(o,l):R&&R.isColor&&(f(R,1),T=!0);const w=i.xr.getEnvironmentBlendMode();w==="additive"?n.buffers.color.setClear(0,0,0,1,a):w==="alpha-blend"&&n.buffers.color.setClear(0,0,0,0,a),(i.autoClear||T)&&(n.buffers.depth.setTest(!0),n.buffers.depth.setMask(!0),n.buffers.color.setMask(!0),i.clear(i.autoClearColor,i.autoClearDepth,i.autoClearStencil))}function m(S,T){const R=x(T);R&&(R.isCubeTexture||R.mapping===Js)?(h===void 0&&(h=new Vt(new oe(1,1,1),new En({name:"BackgroundCubeMaterial",uniforms:Ci(an.backgroundCube.uniforms),vertexShader:an.backgroundCube.vertexShader,fragmentShader:an.backgroundCube.fragmentShader,side:Le,depthTest:!1,depthWrite:!1,fog:!1,allowOverride:!1})),h.geometry.deleteAttribute("normal"),h.geometry.deleteAttribute("uv"),h.onBeforeRender=function(w,L,F){this.matrixWorld.copyPosition(F.matrixWorld)},Object.defineProperty(h.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),s.update(h)),Wn.copy(T.backgroundRotation),Wn.x*=-1,Wn.y*=-1,Wn.z*=-1,R.isCubeTexture&&R.isRenderTargetTexture===!1&&(Wn.y*=-1,Wn.z*=-1),h.material.uniforms.envMap.value=R,h.material.uniforms.flipEnvMap.value=R.isCubeTexture&&R.isRenderTargetTexture===!1?-1:1,h.material.uniforms.backgroundBlurriness.value=T.backgroundBlurriness,h.material.uniforms.backgroundIntensity.value=T.backgroundIntensity,h.material.uniforms.backgroundRotation.value.setFromMatrix4(fp.makeRotationFromEuler(Wn)),h.material.toneMapped=$t.getTransfer(R.colorSpace)!==ne,(u!==R||d!==R.version||p!==i.toneMapping)&&(h.material.needsUpdate=!0,u=R,d=R.version,p=i.toneMapping),h.layers.enableAll(),S.unshift(h,h.geometry,h.material,0,0,null)):R&&R.isTexture&&(c===void 0&&(c=new Vt(new Nn(2,2),new En({name:"BackgroundMaterial",uniforms:Ci(an.background.uniforms),vertexShader:an.background.vertexShader,fragmentShader:an.background.fragmentShader,side:Fn,depthTest:!1,depthWrite:!1,fog:!1,allowOverride:!1})),c.geometry.deleteAttribute("normal"),Object.defineProperty(c.material,"map",{get:function(){return this.uniforms.t2D.value}}),s.update(c)),c.material.uniforms.t2D.value=R,c.material.uniforms.backgroundIntensity.value=T.backgroundIntensity,c.material.toneMapped=$t.getTransfer(R.colorSpace)!==ne,R.matrixAutoUpdate===!0&&R.updateMatrix(),c.material.uniforms.uvTransform.value.copy(R.matrix),(u!==R||d!==R.version||p!==i.toneMapping)&&(c.material.needsUpdate=!0,u=R,d=R.version,p=i.toneMapping),c.layers.enableAll(),S.unshift(c,c.geometry,c.material,0,0,null))}function f(S,T){S.getRGB(Ns,zc(i)),n.buffers.color.setClear(Ns.r,Ns.g,Ns.b,T,a)}function b(){h!==void 0&&(h.geometry.dispose(),h.material.dispose(),h=void 0),c!==void 0&&(c.geometry.dispose(),c.material.dispose(),c=void 0)}return{getClearColor:function(){return o},setClearColor:function(S,T=1){o.set(S),l=T,f(o,l)},getClearAlpha:function(){return l},setClearAlpha:function(S){l=S,f(o,l)},render:_,addToRenderList:m,dispose:b}}function pp(i,t){const e=i.getParameter(i.MAX_VERTEX_ATTRIBS),n={},s=d(null);let r=s,a=!1;function o(M,P,O,z,k){let W=!1;const Y=u(z,O,P);r!==Y&&(r=Y,c(r.object)),W=p(M,z,O,k),W&&x(M,z,O,k),k!==null&&t.update(k,i.ELEMENT_ARRAY_BUFFER),(W||a)&&(a=!1,T(M,P,O,z),k!==null&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,t.get(k).buffer))}function l(){return i.createVertexArray()}function c(M){return i.bindVertexArray(M)}function h(M){return i.deleteVertexArray(M)}function u(M,P,O){const z=O.wireframe===!0;let k=n[M.id];k===void 0&&(k={},n[M.id]=k);let W=k[P.id];W===void 0&&(W={},k[P.id]=W);let Y=W[z];return Y===void 0&&(Y=d(l()),W[z]=Y),Y}function d(M){const P=[],O=[],z=[];for(let k=0;k=0){const st=k[X];let St=W[X];if(St===void 0&&(X==="instanceMatrix"&&M.instanceMatrix&&(St=M.instanceMatrix),X==="instanceColor"&&M.instanceColor&&(St=M.instanceColor)),st===void 0||st.attribute!==St||St&&st.data!==St.data)return!0;Y++}return r.attributesNum!==Y||r.index!==z}function x(M,P,O,z){const k={},W=P.attributes;let Y=0;const nt=O.getAttributes();for(const X in nt)if(nt[X].location>=0){let st=W[X];st===void 0&&(X==="instanceMatrix"&&M.instanceMatrix&&(st=M.instanceMatrix),X==="instanceColor"&&M.instanceColor&&(st=M.instanceColor));const St={};St.attribute=st,st&&st.data&&(St.data=st.data),k[X]=St,Y++}r.attributes=k,r.attributesNum=Y,r.index=z}function _(){const M=r.newAttributes;for(let P=0,O=M.length;P=0){let rt=k[nt];if(rt===void 0&&(nt==="instanceMatrix"&&M.instanceMatrix&&(rt=M.instanceMatrix),nt==="instanceColor"&&M.instanceColor&&(rt=M.instanceColor)),rt!==void 0){const st=rt.normalized,St=rt.itemSize,Gt=t.get(rt);if(Gt===void 0)continue;const qt=Gt.buffer,jt=Gt.type,Kt=Gt.bytesPerElement,K=jt===i.INT||jt===i.UNSIGNED_INT||rt.gpuType===Oa;if(rt.isInterleavedBufferAttribute){const J=rt.data,xt=J.stride,Rt=rt.offset;if(J.isInstancedInterleavedBuffer){for(let Tt=0;Tt0&&i.getShaderPrecisionFormat(i.FRAGMENT_SHADER,i.HIGH_FLOAT).precision>0)return"highp";L="mediump"}return L==="mediump"&&i.getShaderPrecisionFormat(i.VERTEX_SHADER,i.MEDIUM_FLOAT).precision>0&&i.getShaderPrecisionFormat(i.FRAGMENT_SHADER,i.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let c=e.precision!==void 0?e.precision:"highp";const h=l(c);h!==c&&(Bt("WebGLRenderer:",c,"not supported, using",h,"instead."),c=h);const u=e.logarithmicDepthBuffer===!0,d=e.reversedDepthBuffer===!0&&t.has("EXT_clip_control"),p=i.getParameter(i.MAX_TEXTURE_IMAGE_UNITS),x=i.getParameter(i.MAX_VERTEX_TEXTURE_IMAGE_UNITS),_=i.getParameter(i.MAX_TEXTURE_SIZE),m=i.getParameter(i.MAX_CUBE_MAP_TEXTURE_SIZE),f=i.getParameter(i.MAX_VERTEX_ATTRIBS),b=i.getParameter(i.MAX_VERTEX_UNIFORM_VECTORS),S=i.getParameter(i.MAX_VARYING_VECTORS),T=i.getParameter(i.MAX_FRAGMENT_UNIFORM_VECTORS),R=x>0,w=i.getParameter(i.MAX_SAMPLES);return{isWebGL2:!0,getMaxAnisotropy:r,getMaxPrecision:l,textureFormatReadable:a,textureTypeReadable:o,precision:c,logarithmicDepthBuffer:u,reversedDepthBuffer:d,maxTextures:p,maxVertexTextures:x,maxTextureSize:_,maxCubemapSize:m,maxAttributes:f,maxVertexUniforms:b,maxVaryings:S,maxFragmentUniforms:T,vertexTextures:R,maxSamples:w}}function gp(i){const t=this;let e=null,n=0,s=!1,r=!1;const a=new Dn,o=new Ht,l={value:null,needsUpdate:!1};this.uniform=l,this.numPlanes=0,this.numIntersection=0,this.init=function(u,d){const p=u.length!==0||d||n!==0||s;return s=d,n=u.length,p},this.beginShadows=function(){r=!0,h(null)},this.endShadows=function(){r=!1},this.setGlobalState=function(u,d){e=h(u,d,0)},this.setState=function(u,d,p){const x=u.clippingPlanes,_=u.clipIntersection,m=u.clipShadows,f=i.get(u);if(!s||x===null||x.length===0||r&&!m)r?h(null):c();else{const b=r?0:n,S=b*4;let T=f.clippingState||null;l.value=T,T=h(x,d,S,p);for(let R=0;R!==S;++R)T[R]=e[R];f.clippingState=T,this.numIntersection=_?this.numPlanes:0,this.numPlanes+=b}};function c(){l.value!==e&&(l.value=e,l.needsUpdate=n>0),t.numPlanes=n,t.numIntersection=0}function h(u,d,p,x){const _=u!==null?u.length:0;let m=null;if(_!==0){if(m=l.value,x!==!0||m===null){const f=p+_*4,b=d.matrixWorldInverse;o.getNormalMatrix(b),(m===null||m.length0){const c=new Ph(l.height);return c.fromEquirectangularTexture(i,a),t.set(a,c),a.addEventListener("dispose",s),e(c.texture,a.mapping)}else return null}}return a}function s(a){const o=a.target;o.removeEventListener("dispose",s);const l=t.get(o);l!==void 0&&(t.delete(o),l.dispose())}function r(){t=new WeakMap}return{get:n,dispose:r}}const In=4,$o=[.125,.215,.35,.446,.526,.582],Zn=20,vp=256,Xi=new nl,Qo=new Yt;let Ir=null,Ur=0,Nr=0,Fr=!1;const Mp=new D;class Ia{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._sizeLods=[],this._sigmas=[],this._lodMeshes=[],this._backgroundBox=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._blurMaterial=null,this._ggxMaterial=null}fromScene(t,e=0,n=.1,s=100,r={}){const{size:a=256,position:o=Mp}=r;Ir=this._renderer.getRenderTarget(),Ur=this._renderer.getActiveCubeFace(),Nr=this._renderer.getActiveMipmapLevel(),Fr=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(a);const l=this._allocateTargets();return l.depthBuffer=!0,this._sceneToCubeUV(t,n,s,l,o),e>0&&this._blur(l,0,0,e),this._applyPMREM(l),this._cleanup(l),l}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){this._cubemapMaterial===null&&(this._cubemapMaterial=nc(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){this._equirectMaterial===null&&(this._equirectMaterial=ec(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),this._cubemapMaterial!==null&&this._cubemapMaterial.dispose(),this._equirectMaterial!==null&&this._equirectMaterial.dispose(),this._backgroundBox!==null&&(this._backgroundBox.geometry.dispose(),this._backgroundBox.material.dispose())}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){this._blurMaterial!==null&&this._blurMaterial.dispose(),this._ggxMaterial!==null&&this._ggxMaterial.dispose(),this._pingPongRenderTarget!==null&&this._pingPongRenderTarget.dispose();for(let t=0;t2?R:0,R,R),u.setRenderTarget(s),f&&u.render(_,l),u.render(t,l)}u.toneMapping=p,u.autoClear=d,t.background=b}_textureToCubeUV(t,e){const n=this._renderer,s=t.mapping===Ai||t.mapping===wi;s?(this._cubemapMaterial===null&&(this._cubemapMaterial=nc()),this._cubemapMaterial.uniforms.flipEnvMap.value=t.isRenderTargetTexture===!1?-1:1):this._equirectMaterial===null&&(this._equirectMaterial=ec());const r=s?this._cubemapMaterial:this._equirectMaterial,a=this._lodMeshes[0];a.material=r;const o=r.uniforms;o.envMap.value=t;const l=this._cubeSize;gi(e,0,0,3*l,2*l),n.setRenderTarget(e),n.render(a,Xi)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;const s=this._lodMeshes.length;for(let r=1;rx-In?n-x+In:0),f=4*(this._cubeSize-_);l.envMap.value=t.texture,l.roughness.value=p,l.mipInt.value=x-e,gi(r,m,f,3*_,2*_),s.setRenderTarget(r),s.render(o,Xi),l.envMap.value=r.texture,l.roughness.value=0,l.mipInt.value=x-n,gi(t,m,f,3*_,2*_),s.setRenderTarget(t),s.render(o,Xi)}_blur(t,e,n,s,r){const a=this._pingPongRenderTarget;this._halfBlur(t,a,e,n,s,"latitudinal",r),this._halfBlur(a,t,n,n,s,"longitudinal",r)}_halfBlur(t,e,n,s,r,a,o){const l=this._renderer,c=this._blurMaterial;a!=="latitudinal"&&a!=="longitudinal"&&de("blur direction must be either latitudinal or longitudinal!");const h=3,u=this._lodMeshes[s];u.material=c;const d=c.uniforms,p=this._sizeLods[n]-1,x=isFinite(r)?Math.PI/(2*p):2*Math.PI/(2*Zn-1),_=r/x,m=isFinite(r)?1+Math.floor(h*_):Zn;m>Zn&&Bt(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to ${Zn}`);const f=[];let b=0;for(let L=0;LS-In?s-S+In:0),w=4*(this._cubeSize-T);gi(e,R,w,3*T,2*T),l.setRenderTarget(e),l.render(u,Xi)}}function Sp(i){const t=[],e=[],n=[];let s=i;const r=i-In+1+$o.length;for(let a=0;ai-In?l=$o[a-i+In-1]:a===0&&(l=0),e.push(l);const c=1/(o-2),h=-c,u=1+c,d=[h,h,u,h,u,u,h,h,u,u,h,u],p=6,x=6,_=3,m=2,f=1,b=new Float32Array(_*x*p),S=new Float32Array(m*x*p),T=new Float32Array(f*x*p);for(let w=0;w2?0:-1,E=[L,F,0,L+2/3,F,0,L+2/3,F+1,0,L,F,0,L+2/3,F+1,0,L,F+1,0];b.set(E,_*x*w),S.set(d,m*x*w);const M=[w,w,w,w,w,w];T.set(M,f*x*w)}const R=new Ie;R.setAttribute("position",new en(b,_)),R.setAttribute("uv",new en(S,m)),R.setAttribute("faceIndex",new en(T,f)),n.push(new Vt(R,null)),s>In&&s--}return{lodMeshes:n,sizeLods:t,sigmas:e}}function tc(i,t,e){const n=new $n(i,t,e);return n.texture.mapping=Js,n.texture.name="PMREM.cubeUv",n.scissorTest=!0,n}function gi(i,t,e,n,s){i.viewport.set(t,e,n,s),i.scissor.set(t,e,n,s)}function yp(i,t,e){return new En({name:"PMREMGGXConvolution",defines:{GGX_SAMPLES:vp,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/e,CUBEUV_MAX_MIP:`${i}.0`},uniforms:{envMap:{value:null},roughness:{value:0},mipInt:{value:0}},vertexShader:Qs(),fragmentShader:` + + precision highp float; + precision highp int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + uniform float roughness; + uniform float mipInt; + + #define ENVMAP_TYPE_CUBE_UV + #include + + #define PI 3.14159265359 + + // Van der Corput radical inverse + float radicalInverse_VdC(uint bits) { + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 + } + + // Hammersley sequence + vec2 hammersley(uint i, uint N) { + return vec2(float(i) / float(N), radicalInverse_VdC(i)); + } + + // GGX VNDF importance sampling (Eric Heitz 2018) + // "Sampling the GGX Distribution of Visible Normals" + // https://jcgt.org/published/0007/04/01/ + vec3 importanceSampleGGX_VNDF(vec2 Xi, vec3 V, float roughness) { + float alpha = roughness * roughness; + + // Section 3.2: Transform view direction to hemisphere configuration + vec3 Vh = normalize(vec3(alpha * V.x, alpha * V.y, V.z)); + + // Section 4.1: Orthonormal basis + float lensq = Vh.x * Vh.x + Vh.y * Vh.y; + vec3 T1 = lensq > 0.0 ? vec3(-Vh.y, Vh.x, 0.0) / sqrt(lensq) : vec3(1.0, 0.0, 0.0); + vec3 T2 = cross(Vh, T1); + + // Section 4.2: Parameterization of projected area + float r = sqrt(Xi.x); + float phi = 2.0 * PI * Xi.y; + float t1 = r * cos(phi); + float t2 = r * sin(phi); + float s = 0.5 * (1.0 + Vh.z); + t2 = (1.0 - s) * sqrt(1.0 - t1 * t1) + s * t2; + + // Section 4.3: Reprojection onto hemisphere + vec3 Nh = t1 * T1 + t2 * T2 + sqrt(max(0.0, 1.0 - t1 * t1 - t2 * t2)) * Vh; + + // Section 3.4: Transform back to ellipsoid configuration + return normalize(vec3(alpha * Nh.x, alpha * Nh.y, max(0.0, Nh.z))); + } + + void main() { + vec3 N = normalize(vOutputDirection); + vec3 V = N; // Assume view direction equals normal for pre-filtering + + vec3 prefilteredColor = vec3(0.0); + float totalWeight = 0.0; + + // For very low roughness, just sample the environment directly + if (roughness < 0.001) { + gl_FragColor = vec4(bilinearCubeUV(envMap, N, mipInt), 1.0); + return; + } + + // Tangent space basis for VNDF sampling + vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangent = normalize(cross(up, N)); + vec3 bitangent = cross(N, tangent); + + for(uint i = 0u; i < uint(GGX_SAMPLES); i++) { + vec2 Xi = hammersley(i, uint(GGX_SAMPLES)); + + // For PMREM, V = N, so in tangent space V is always (0, 0, 1) + vec3 H_tangent = importanceSampleGGX_VNDF(Xi, vec3(0.0, 0.0, 1.0), roughness); + + // Transform H back to world space + vec3 H = normalize(tangent * H_tangent.x + bitangent * H_tangent.y + N * H_tangent.z); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(dot(N, L), 0.0); + + if(NdotL > 0.0) { + // Sample environment at fixed mip level + // VNDF importance sampling handles the distribution filtering + vec3 sampleColor = bilinearCubeUV(envMap, L, mipInt); + + // Weight by NdotL for the split-sum approximation + // VNDF PDF naturally accounts for the visible microfacet distribution + prefilteredColor += sampleColor * NdotL; + totalWeight += NdotL; + } + } + + if (totalWeight > 0.0) { + prefilteredColor = prefilteredColor / totalWeight; + } + + gl_FragColor = vec4(prefilteredColor, 1.0); + } + `,blending:yn,depthTest:!1,depthWrite:!1})}function bp(i,t,e){const n=new Float32Array(Zn),s=new D(0,1,0);return new En({name:"SphericalGaussianBlur",defines:{n:Zn,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/e,CUBEUV_MAX_MIP:`${i}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:n},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:s}},vertexShader:Qs(),fragmentShader:` + + precision mediump float; + precision mediump int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + uniform int samples; + uniform float weights[ n ]; + uniform bool latitudinal; + uniform float dTheta; + uniform float mipInt; + uniform vec3 poleAxis; + + #define ENVMAP_TYPE_CUBE_UV + #include + + vec3 getSample( float theta, vec3 axis ) { + + float cosTheta = cos( theta ); + // Rodrigues' axis-angle rotation + vec3 sampleDirection = vOutputDirection * cosTheta + + cross( axis, vOutputDirection ) * sin( theta ) + + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); + + return bilinearCubeUV( envMap, sampleDirection, mipInt ); + + } + + void main() { + + vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); + + if ( all( equal( axis, vec3( 0.0 ) ) ) ) { + + axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); + + } + + axis = normalize( axis ); + + gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); + + for ( int i = 1; i < n; i++ ) { + + if ( i >= samples ) { + + break; + + } + + float theta = dTheta * float( i ); + gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); + gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); + + } + + } + `,blending:yn,depthTest:!1,depthWrite:!1})}function ec(){return new En({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:Qs(),fragmentShader:` + + precision mediump float; + precision mediump int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + + #include + + void main() { + + vec3 outputDirection = normalize( vOutputDirection ); + vec2 uv = equirectUv( outputDirection ); + + gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); + + } + `,blending:yn,depthTest:!1,depthWrite:!1})}function nc(){return new En({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:Qs(),fragmentShader:` + + precision mediump float; + precision mediump int; + + uniform float flipEnvMap; + + varying vec3 vOutputDirection; + + uniform samplerCube envMap; + + void main() { + + gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); + + } + `,blending:yn,depthTest:!1,depthWrite:!1})}function Qs(){return` + + precision mediump float; + precision mediump int; + + attribute float faceIndex; + + varying vec3 vOutputDirection; + + // RH coordinate system; PMREM face-indexing convention + vec3 getDirection( vec2 uv, float face ) { + + uv = 2.0 * uv - 1.0; + + vec3 direction = vec3( uv, 1.0 ); + + if ( face == 0.0 ) { + + direction = direction.zyx; // ( 1, v, u ) pos x + + } else if ( face == 1.0 ) { + + direction = direction.xzy; + direction.xz *= -1.0; // ( -u, 1, -v ) pos y + + } else if ( face == 2.0 ) { + + direction.x *= -1.0; // ( -u, v, 1 ) pos z + + } else if ( face == 3.0 ) { + + direction = direction.zyx; + direction.xz *= -1.0; // ( -1, v, -u ) neg x + + } else if ( face == 4.0 ) { + + direction = direction.xzy; + direction.xy *= -1.0; // ( -u, -1, v ) neg y + + } else if ( face == 5.0 ) { + + direction.z *= -1.0; // ( u, v, -1 ) neg z + + } + + return direction; + + } + + void main() { + + vOutputDirection = getDirection( uv, faceIndex ); + gl_Position = vec4( position, 1.0 ); + + } + `}function Ep(i){let t=new WeakMap,e=null;function n(o){if(o&&o.isTexture){const l=o.mapping,c=l===jr||l===Jr,h=l===Ai||l===wi;if(c||h){let u=t.get(o);const d=u!==void 0?u.texture.pmremVersion:0;if(o.isRenderTargetTexture&&o.pmremVersion!==d)return e===null&&(e=new Ia(i)),u=c?e.fromEquirectangular(o,u):e.fromCubemap(o,u),u.texture.pmremVersion=o.pmremVersion,t.set(o,u),u.texture;if(u!==void 0)return u.texture;{const p=o.image;return c&&p&&p.height>0||h&&p&&s(p)?(e===null&&(e=new Ia(i)),u=c?e.fromEquirectangular(o):e.fromCubemap(o),u.texture.pmremVersion=o.pmremVersion,t.set(o,u),o.addEventListener("dispose",r),u.texture):null}}}return o}function s(o){let l=0;const c=6;for(let h=0;ht.maxTextureSize&&(R=Math.ceil(T/t.maxTextureSize),T=t.maxTextureSize);const w=new Float32Array(T*R*4*u),L=new Nc(w,T,R,u);L.type=on,L.needsUpdate=!0;const F=S*4;for(let M=0;M0)return i;const s=t*e;let r=sc[s];if(r===void 0&&(r=new Float32Array(s),sc[s]=r),t!==0){n.toArray(r,0);for(let a=1,o=0;a!==t;++a)o+=e,i[a].toArray(r,o)}return r}function Se(i,t){if(i.length!==t.length)return!1;for(let e=0,n=i.length;e":" "} ${o}: ${e[a]}`)}return n.join(` +`)}const uc=new Ht;function E0(i){$t._getMatrix(uc,$t.workingColorSpace,i);const t=`mat3( ${uc.elements.map(e=>e.toFixed(4))} )`;switch($t.getTransfer(i)){case Ws:return[t,"LinearTransferOETF"];case ne:return[t,"sRGBTransferOETF"];default:return Bt("WebGLProgram: Unsupported color space: ",i),[t,"LinearTransferOETF"]}}function fc(i,t,e){const n=i.getShaderParameter(t,i.COMPILE_STATUS),r=(i.getShaderInfoLog(t)||"").trim();if(n&&r==="")return"";const a=/ERROR: 0:(\d+)/.exec(r);if(a){const o=parseInt(a[1]);return e.toUpperCase()+` + +`+r+` + +`+b0(i.getShaderSource(t),o)}else return r}function T0(i,t){const e=E0(t);return[`vec4 ${i}( vec4 value ) {`,` return ${e[1]}( vec4( value.rgb * ${e[0]}, value.a ) );`,"}"].join(` +`)}function A0(i,t){let e;switch(t){case Gl:e="Linear";break;case kl:e="Reinhard";break;case Hl:e="Cineon";break;case Tc:e="ACESFilmic";break;case Xl:e="AgX";break;case ql:e="Neutral";break;case Wl:e="Custom";break;default:Bt("WebGLProgram: Unsupported toneMapping:",t),e="Linear"}return"vec3 "+i+"( vec3 color ) { return "+e+"ToneMapping( color ); }"}const Fs=new D;function w0(){$t.getLuminanceCoefficients(Fs);const i=Fs.x.toFixed(4),t=Fs.y.toFixed(4),e=Fs.z.toFixed(4);return["float luminance( const in vec3 rgb ) {",` const vec3 weights = vec3( ${i}, ${t}, ${e} );`," return dot( weights, rgb );","}"].join(` +`)}function R0(i){return[i.extensionClipCullDistance?"#extension GL_ANGLE_clip_cull_distance : require":"",i.extensionMultiDraw?"#extension GL_ANGLE_multi_draw : require":""].filter(Zi).join(` +`)}function C0(i){const t=[];for(const e in i){const n=i[e];n!==!1&&t.push("#define "+e+" "+n)}return t.join(` +`)}function P0(i,t){const e={},n=i.getProgramParameter(t,i.ACTIVE_ATTRIBUTES);for(let s=0;s/gm;function Ua(i){return i.replace(D0,I0)}const L0=new Map;function I0(i,t){let e=Wt[t];if(e===void 0){const n=L0.get(t);if(n!==void 0)e=Wt[n],Bt('WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',t,n);else throw new Error("Can not resolve #include <"+t+">")}return Ua(e)}const U0=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function mc(i){return i.replace(U0,N0)}function N0(i,t,e,n){let s="";for(let r=parseInt(t);r0&&(m+=` +`),f=["#define SHADER_TYPE "+e.shaderType,"#define SHADER_NAME "+e.shaderName,x].filter(Zi).join(` +`),f.length>0&&(f+=` +`)):(m=[xc(e),"#define SHADER_TYPE "+e.shaderType,"#define SHADER_NAME "+e.shaderName,x,e.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",e.batching?"#define USE_BATCHING":"",e.batchingColor?"#define USE_BATCHING_COLOR":"",e.instancing?"#define USE_INSTANCING":"",e.instancingColor?"#define USE_INSTANCING_COLOR":"",e.instancingMorph?"#define USE_INSTANCING_MORPH":"",e.useFog&&e.fog?"#define USE_FOG":"",e.useFog&&e.fogExp2?"#define FOG_EXP2":"",e.map?"#define USE_MAP":"",e.envMap?"#define USE_ENVMAP":"",e.envMap?"#define "+h:"",e.lightMap?"#define USE_LIGHTMAP":"",e.aoMap?"#define USE_AOMAP":"",e.bumpMap?"#define USE_BUMPMAP":"",e.normalMap?"#define USE_NORMALMAP":"",e.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",e.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",e.displacementMap?"#define USE_DISPLACEMENTMAP":"",e.emissiveMap?"#define USE_EMISSIVEMAP":"",e.anisotropy?"#define USE_ANISOTROPY":"",e.anisotropyMap?"#define USE_ANISOTROPYMAP":"",e.clearcoatMap?"#define USE_CLEARCOATMAP":"",e.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",e.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",e.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",e.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",e.specularMap?"#define USE_SPECULARMAP":"",e.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",e.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",e.roughnessMap?"#define USE_ROUGHNESSMAP":"",e.metalnessMap?"#define USE_METALNESSMAP":"",e.alphaMap?"#define USE_ALPHAMAP":"",e.alphaHash?"#define USE_ALPHAHASH":"",e.transmission?"#define USE_TRANSMISSION":"",e.transmissionMap?"#define USE_TRANSMISSIONMAP":"",e.thicknessMap?"#define USE_THICKNESSMAP":"",e.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",e.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",e.mapUv?"#define MAP_UV "+e.mapUv:"",e.alphaMapUv?"#define ALPHAMAP_UV "+e.alphaMapUv:"",e.lightMapUv?"#define LIGHTMAP_UV "+e.lightMapUv:"",e.aoMapUv?"#define AOMAP_UV "+e.aoMapUv:"",e.emissiveMapUv?"#define EMISSIVEMAP_UV "+e.emissiveMapUv:"",e.bumpMapUv?"#define BUMPMAP_UV "+e.bumpMapUv:"",e.normalMapUv?"#define NORMALMAP_UV "+e.normalMapUv:"",e.displacementMapUv?"#define DISPLACEMENTMAP_UV "+e.displacementMapUv:"",e.metalnessMapUv?"#define METALNESSMAP_UV "+e.metalnessMapUv:"",e.roughnessMapUv?"#define ROUGHNESSMAP_UV "+e.roughnessMapUv:"",e.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+e.anisotropyMapUv:"",e.clearcoatMapUv?"#define CLEARCOATMAP_UV "+e.clearcoatMapUv:"",e.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+e.clearcoatNormalMapUv:"",e.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+e.clearcoatRoughnessMapUv:"",e.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+e.iridescenceMapUv:"",e.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+e.iridescenceThicknessMapUv:"",e.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+e.sheenColorMapUv:"",e.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+e.sheenRoughnessMapUv:"",e.specularMapUv?"#define SPECULARMAP_UV "+e.specularMapUv:"",e.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+e.specularColorMapUv:"",e.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+e.specularIntensityMapUv:"",e.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+e.transmissionMapUv:"",e.thicknessMapUv?"#define THICKNESSMAP_UV "+e.thicknessMapUv:"",e.vertexTangents&&e.flatShading===!1?"#define USE_TANGENT":"",e.vertexColors?"#define USE_COLOR":"",e.vertexAlphas?"#define USE_COLOR_ALPHA":"",e.vertexUv1s?"#define USE_UV1":"",e.vertexUv2s?"#define USE_UV2":"",e.vertexUv3s?"#define USE_UV3":"",e.pointsUvs?"#define USE_POINTS_UV":"",e.flatShading?"#define FLAT_SHADED":"",e.skinning?"#define USE_SKINNING":"",e.morphTargets?"#define USE_MORPHTARGETS":"",e.morphNormals&&e.flatShading===!1?"#define USE_MORPHNORMALS":"",e.morphColors?"#define USE_MORPHCOLORS":"",e.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+e.morphTextureStride:"",e.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+e.morphTargetsCount:"",e.doubleSided?"#define DOUBLE_SIDED":"",e.flipSided?"#define FLIP_SIDED":"",e.shadowMapEnabled?"#define USE_SHADOWMAP":"",e.shadowMapEnabled?"#define "+l:"",e.sizeAttenuation?"#define USE_SIZEATTENUATION":"",e.numLightProbes>0?"#define USE_LIGHT_PROBES":"",e.logarithmicDepthBuffer?"#define USE_LOGARITHMIC_DEPTH_BUFFER":"",e.reversedDepthBuffer?"#define USE_REVERSED_DEPTH_BUFFER":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING"," attribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR"," attribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH"," uniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1"," attribute vec2 uv1;","#endif","#ifdef USE_UV2"," attribute vec2 uv2;","#endif","#ifdef USE_UV3"," attribute vec2 uv3;","#endif","#ifdef USE_TANGENT"," attribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )"," attribute vec4 color;","#elif defined( USE_COLOR )"," attribute vec3 color;","#endif","#ifdef USE_SKINNING"," attribute vec4 skinIndex;"," attribute vec4 skinWeight;","#endif",` +`].filter(Zi).join(` +`),f=[xc(e),"#define SHADER_TYPE "+e.shaderType,"#define SHADER_NAME "+e.shaderName,x,e.useFog&&e.fog?"#define USE_FOG":"",e.useFog&&e.fogExp2?"#define FOG_EXP2":"",e.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",e.map?"#define USE_MAP":"",e.matcap?"#define USE_MATCAP":"",e.envMap?"#define USE_ENVMAP":"",e.envMap?"#define "+c:"",e.envMap?"#define "+h:"",e.envMap?"#define "+u:"",d?"#define CUBEUV_TEXEL_WIDTH "+d.texelWidth:"",d?"#define CUBEUV_TEXEL_HEIGHT "+d.texelHeight:"",d?"#define CUBEUV_MAX_MIP "+d.maxMip+".0":"",e.lightMap?"#define USE_LIGHTMAP":"",e.aoMap?"#define USE_AOMAP":"",e.bumpMap?"#define USE_BUMPMAP":"",e.normalMap?"#define USE_NORMALMAP":"",e.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",e.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",e.emissiveMap?"#define USE_EMISSIVEMAP":"",e.anisotropy?"#define USE_ANISOTROPY":"",e.anisotropyMap?"#define USE_ANISOTROPYMAP":"",e.clearcoat?"#define USE_CLEARCOAT":"",e.clearcoatMap?"#define USE_CLEARCOATMAP":"",e.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",e.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",e.dispersion?"#define USE_DISPERSION":"",e.iridescence?"#define USE_IRIDESCENCE":"",e.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",e.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",e.specularMap?"#define USE_SPECULARMAP":"",e.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",e.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",e.roughnessMap?"#define USE_ROUGHNESSMAP":"",e.metalnessMap?"#define USE_METALNESSMAP":"",e.alphaMap?"#define USE_ALPHAMAP":"",e.alphaTest?"#define USE_ALPHATEST":"",e.alphaHash?"#define USE_ALPHAHASH":"",e.sheen?"#define USE_SHEEN":"",e.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",e.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",e.transmission?"#define USE_TRANSMISSION":"",e.transmissionMap?"#define USE_TRANSMISSIONMAP":"",e.thicknessMap?"#define USE_THICKNESSMAP":"",e.vertexTangents&&e.flatShading===!1?"#define USE_TANGENT":"",e.vertexColors||e.instancingColor||e.batchingColor?"#define USE_COLOR":"",e.vertexAlphas?"#define USE_COLOR_ALPHA":"",e.vertexUv1s?"#define USE_UV1":"",e.vertexUv2s?"#define USE_UV2":"",e.vertexUv3s?"#define USE_UV3":"",e.pointsUvs?"#define USE_POINTS_UV":"",e.gradientMap?"#define USE_GRADIENTMAP":"",e.flatShading?"#define FLAT_SHADED":"",e.doubleSided?"#define DOUBLE_SIDED":"",e.flipSided?"#define FLIP_SIDED":"",e.shadowMapEnabled?"#define USE_SHADOWMAP":"",e.shadowMapEnabled?"#define "+l:"",e.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",e.numLightProbes>0?"#define USE_LIGHT_PROBES":"",e.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",e.decodeVideoTextureEmissive?"#define DECODE_VIDEO_TEXTURE_EMISSIVE":"",e.logarithmicDepthBuffer?"#define USE_LOGARITHMIC_DEPTH_BUFFER":"",e.reversedDepthBuffer?"#define USE_REVERSED_DEPTH_BUFFER":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",e.toneMapping!==Un?"#define TONE_MAPPING":"",e.toneMapping!==Un?Wt.tonemapping_pars_fragment:"",e.toneMapping!==Un?A0("toneMapping",e.toneMapping):"",e.dithering?"#define DITHERING":"",e.opaque?"#define OPAQUE":"",Wt.colorspace_pars_fragment,T0("linearToOutputTexel",e.outputColorSpace),w0(),e.useDepthPacking?"#define DEPTH_PACKING "+e.depthPacking:"",` +`].filter(Zi).join(` +`)),a=Ua(a),a=dc(a,e),a=pc(a,e),o=Ua(o),o=dc(o,e),o=pc(o,e),a=mc(a),o=mc(o),e.isRawShaderMaterial!==!0&&(b=`#version 300 es +`,m=[p,"#define attribute in","#define varying out","#define texture2D texture"].join(` +`)+` +`+m,f=["#define varying in",e.glslVersion===mo?"":"layout(location = 0) out highp vec4 pc_fragColor;",e.glslVersion===mo?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join(` +`)+` +`+f);const S=b+m+a,T=b+f+o,R=hc(s,s.VERTEX_SHADER,S),w=hc(s,s.FRAGMENT_SHADER,T);s.attachShader(_,R),s.attachShader(_,w),e.index0AttributeName!==void 0?s.bindAttribLocation(_,0,e.index0AttributeName):e.morphTargets===!0&&s.bindAttribLocation(_,0,"position"),s.linkProgram(_);function L(P){if(i.debug.checkShaderErrors){const O=s.getProgramInfoLog(_)||"",z=s.getShaderInfoLog(R)||"",k=s.getShaderInfoLog(w)||"",W=O.trim(),Y=z.trim(),nt=k.trim();let X=!0,rt=!0;if(s.getProgramParameter(_,s.LINK_STATUS)===!1)if(X=!1,typeof i.debug.onShaderError=="function")i.debug.onShaderError(s,_,R,w);else{const st=fc(s,R,"vertex"),St=fc(s,w,"fragment");de("THREE.WebGLProgram: Shader Error "+s.getError()+" - VALIDATE_STATUS "+s.getProgramParameter(_,s.VALIDATE_STATUS)+` + +Material Name: `+P.name+` +Material Type: `+P.type+` + +Program Info Log: `+W+` +`+st+` +`+St)}else W!==""?Bt("WebGLProgram: Program Info Log:",W):(Y===""||nt==="")&&(rt=!1);rt&&(P.diagnostics={runnable:X,programLog:W,vertexShader:{log:Y,prefix:m},fragmentShader:{log:nt,prefix:f}})}s.deleteShader(R),s.deleteShader(w),F=new Hs(s,_),E=P0(s,_)}let F;this.getUniforms=function(){return F===void 0&&L(this),F};let E;this.getAttributes=function(){return E===void 0&&L(this),E};let M=e.rendererExtensionParallelShaderCompile===!1;return this.isReady=function(){return M===!1&&(M=s.getProgramParameter(_,S0)),M},this.destroy=function(){n.releaseStatesOfProgram(this),s.deleteProgram(_),this.program=void 0},this.type=e.shaderType,this.name=e.shaderName,this.id=y0++,this.cacheKey=t,this.usedTimes=1,this.program=_,this.vertexShader=R,this.fragmentShader=w,this}let k0=0;class H0{constructor(){this.shaderCache=new Map,this.materialCache=new Map}update(t){const e=t.vertexShader,n=t.fragmentShader,s=this._getShaderStage(e),r=this._getShaderStage(n),a=this._getShaderCacheForMaterial(t);return a.has(s)===!1&&(a.add(s),s.usedTimes++),a.has(r)===!1&&(a.add(r),r.usedTimes++),this}remove(t){const e=this.materialCache.get(t);for(const n of e)n.usedTimes--,n.usedTimes===0&&this.shaderCache.delete(n.code);return this.materialCache.delete(t),this}getVertexShaderID(t){return this._getShaderStage(t.vertexShader).id}getFragmentShaderID(t){return this._getShaderStage(t.fragmentShader).id}dispose(){this.shaderCache.clear(),this.materialCache.clear()}_getShaderCacheForMaterial(t){const e=this.materialCache;let n=e.get(t);return n===void 0&&(n=new Set,e.set(t,n)),n}_getShaderStage(t){const e=this.shaderCache;let n=e.get(t);return n===void 0&&(n=new W0(t),e.set(t,n)),n}}class W0{constructor(t){this.id=k0++,this.code=t,this.usedTimes=0}}function X0(i,t,e,n,s,r,a){const o=new Ya,l=new H0,c=new Set,h=[],u=s.logarithmicDepthBuffer,d=s.vertexTextures;let p=s.precision;const x={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distanceRGBA",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"toon",MeshStandardMaterial:"physical",MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"};function _(E){return c.add(E),E===0?"uv":`uv${E}`}function m(E,M,P,O,z){const k=O.fog,W=z.geometry,Y=E.isMeshStandardMaterial?O.environment:null,nt=(E.isMeshStandardMaterial?e:t).get(E.envMap||Y),X=nt&&nt.mapping===Js?nt.image.height:null,rt=x[E.type];E.precision!==null&&(p=s.getMaxPrecision(E.precision),p!==E.precision&&Bt("WebGLProgram.getParameters:",E.precision,"not supported, using",p,"instead."));const st=W.morphAttributes.position||W.morphAttributes.normal||W.morphAttributes.color,St=st!==void 0?st.length:0;let Gt=0;W.morphAttributes.position!==void 0&&(Gt=1),W.morphAttributes.normal!==void 0&&(Gt=2),W.morphAttributes.color!==void 0&&(Gt=3);let qt,jt,Kt,K;if(rt){const te=an[rt];qt=te.vertexShader,jt=te.fragmentShader}else qt=E.vertexShader,jt=E.fragmentShader,l.update(E),Kt=l.getVertexShaderID(E),K=l.getFragmentShaderID(E);const J=i.getRenderTarget(),xt=i.state.buffers.depth.getReversed(),Rt=z.isInstancedMesh===!0,Tt=z.isBatchedMesh===!0,kt=!!E.map,Qt=!!E.matcap,Ct=!!nt,B=!!E.aoMap,y=!!E.lightMap,Z=!!E.bumpMap,Q=!!E.normalMap,ot=!!E.displacementMap,et=!!E.emissiveMap,vt=!!E.metalnessMap,ft=!!E.roughnessMap,Mt=E.anisotropy>0,A=E.clearcoat>0,g=E.dispersion>0,N=E.iridescence>0,q=E.sheen>0,$=E.transmission>0,H=Mt&&!!E.anisotropyMap,wt=A&&!!E.clearcoatMap,dt=A&&!!E.clearcoatNormalMap,Pt=A&&!!E.clearcoatRoughnessMap,At=N&&!!E.iridescenceMap,tt=N&&!!E.iridescenceThicknessMap,lt=q&&!!E.sheenColorMap,Nt=q&&!!E.sheenRoughnessMap,It=!!E.specularMap,_t=!!E.specularColorMap,Ot=!!E.specularIntensityMap,C=$&&!!E.transmissionMap,mt=$&&!!E.thicknessMap,ht=!!E.gradientMap,ut=!!E.alphaMap,it=E.alphaTest>0,j=!!E.alphaHash,bt=!!E.extensions;let zt=Un;E.toneMapped&&(J===null||J.isXRRenderTarget===!0)&&(zt=i.toneMapping);const ce={shaderID:rt,shaderType:E.type,shaderName:E.name,vertexShader:qt,fragmentShader:jt,defines:E.defines,customVertexShaderID:Kt,customFragmentShaderID:K,isRawShaderMaterial:E.isRawShaderMaterial===!0,glslVersion:E.glslVersion,precision:p,batching:Tt,batchingColor:Tt&&z._colorsTexture!==null,instancing:Rt,instancingColor:Rt&&z.instanceColor!==null,instancingMorph:Rt&&z.morphTexture!==null,supportsVertexTextures:d,outputColorSpace:J===null?i.outputColorSpace:J.isXRRenderTarget===!0?J.texture.colorSpace:Ri,alphaToCoverage:!!E.alphaToCoverage,map:kt,matcap:Qt,envMap:Ct,envMapMode:Ct&&nt.mapping,envMapCubeUVHeight:X,aoMap:B,lightMap:y,bumpMap:Z,normalMap:Q,displacementMap:d&&ot,emissiveMap:et,normalMapObjectSpace:Q&&E.normalMapType===jl,normalMapTangentSpace:Q&&E.normalMapType===Xa,metalnessMap:vt,roughnessMap:ft,anisotropy:Mt,anisotropyMap:H,clearcoat:A,clearcoatMap:wt,clearcoatNormalMap:dt,clearcoatRoughnessMap:Pt,dispersion:g,iridescence:N,iridescenceMap:At,iridescenceThicknessMap:tt,sheen:q,sheenColorMap:lt,sheenRoughnessMap:Nt,specularMap:It,specularColorMap:_t,specularIntensityMap:Ot,transmission:$,transmissionMap:C,thicknessMap:mt,gradientMap:ht,opaque:E.transparent===!1&&E.blending===bi&&E.alphaToCoverage===!1,alphaMap:ut,alphaTest:it,alphaHash:j,combine:E.combine,mapUv:kt&&_(E.map.channel),aoMapUv:B&&_(E.aoMap.channel),lightMapUv:y&&_(E.lightMap.channel),bumpMapUv:Z&&_(E.bumpMap.channel),normalMapUv:Q&&_(E.normalMap.channel),displacementMapUv:ot&&_(E.displacementMap.channel),emissiveMapUv:et&&_(E.emissiveMap.channel),metalnessMapUv:vt&&_(E.metalnessMap.channel),roughnessMapUv:ft&&_(E.roughnessMap.channel),anisotropyMapUv:H&&_(E.anisotropyMap.channel),clearcoatMapUv:wt&&_(E.clearcoatMap.channel),clearcoatNormalMapUv:dt&&_(E.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:Pt&&_(E.clearcoatRoughnessMap.channel),iridescenceMapUv:At&&_(E.iridescenceMap.channel),iridescenceThicknessMapUv:tt&&_(E.iridescenceThicknessMap.channel),sheenColorMapUv:lt&&_(E.sheenColorMap.channel),sheenRoughnessMapUv:Nt&&_(E.sheenRoughnessMap.channel),specularMapUv:It&&_(E.specularMap.channel),specularColorMapUv:_t&&_(E.specularColorMap.channel),specularIntensityMapUv:Ot&&_(E.specularIntensityMap.channel),transmissionMapUv:C&&_(E.transmissionMap.channel),thicknessMapUv:mt&&_(E.thicknessMap.channel),alphaMapUv:ut&&_(E.alphaMap.channel),vertexTangents:!!W.attributes.tangent&&(Q||Mt),vertexColors:E.vertexColors,vertexAlphas:E.vertexColors===!0&&!!W.attributes.color&&W.attributes.color.itemSize===4,pointsUvs:z.isPoints===!0&&!!W.attributes.uv&&(kt||ut),fog:!!k,useFog:E.fog===!0,fogExp2:!!k&&k.isFogExp2,flatShading:E.flatShading===!0&&E.wireframe===!1,sizeAttenuation:E.sizeAttenuation===!0,logarithmicDepthBuffer:u,reversedDepthBuffer:xt,skinning:z.isSkinnedMesh===!0,morphTargets:W.morphAttributes.position!==void 0,morphNormals:W.morphAttributes.normal!==void 0,morphColors:W.morphAttributes.color!==void 0,morphTargetsCount:St,morphTextureStride:Gt,numDirLights:M.directional.length,numPointLights:M.point.length,numSpotLights:M.spot.length,numSpotLightMaps:M.spotLightMap.length,numRectAreaLights:M.rectArea.length,numHemiLights:M.hemi.length,numDirLightShadows:M.directionalShadowMap.length,numPointLightShadows:M.pointShadowMap.length,numSpotLightShadows:M.spotShadowMap.length,numSpotLightShadowsWithMaps:M.numSpotLightShadowsWithMaps,numLightProbes:M.numLightProbes,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:E.dithering,shadowMapEnabled:i.shadowMap.enabled&&P.length>0,shadowMapType:i.shadowMap.type,toneMapping:zt,decodeVideoTexture:kt&&E.map.isVideoTexture===!0&&$t.getTransfer(E.map.colorSpace)===ne,decodeVideoTextureEmissive:et&&E.emissiveMap.isVideoTexture===!0&&$t.getTransfer(E.emissiveMap.colorSpace)===ne,premultipliedAlpha:E.premultipliedAlpha,doubleSided:E.side===Mn,flipSided:E.side===Le,useDepthPacking:E.depthPacking>=0,depthPacking:E.depthPacking||0,index0AttributeName:E.index0AttributeName,extensionClipCullDistance:bt&&E.extensions.clipCullDistance===!0&&n.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(bt&&E.extensions.multiDraw===!0||Tt)&&n.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:n.has("KHR_parallel_shader_compile"),customProgramCacheKey:E.customProgramCacheKey()};return ce.vertexUv1s=c.has(1),ce.vertexUv2s=c.has(2),ce.vertexUv3s=c.has(3),c.clear(),ce}function f(E){const M=[];if(E.shaderID?M.push(E.shaderID):(M.push(E.customVertexShaderID),M.push(E.customFragmentShaderID)),E.defines!==void 0)for(const P in E.defines)M.push(P),M.push(E.defines[P]);return E.isRawShaderMaterial===!1&&(b(M,E),S(M,E),M.push(i.outputColorSpace)),M.push(E.customProgramCacheKey),M.join()}function b(E,M){E.push(M.precision),E.push(M.outputColorSpace),E.push(M.envMapMode),E.push(M.envMapCubeUVHeight),E.push(M.mapUv),E.push(M.alphaMapUv),E.push(M.lightMapUv),E.push(M.aoMapUv),E.push(M.bumpMapUv),E.push(M.normalMapUv),E.push(M.displacementMapUv),E.push(M.emissiveMapUv),E.push(M.metalnessMapUv),E.push(M.roughnessMapUv),E.push(M.anisotropyMapUv),E.push(M.clearcoatMapUv),E.push(M.clearcoatNormalMapUv),E.push(M.clearcoatRoughnessMapUv),E.push(M.iridescenceMapUv),E.push(M.iridescenceThicknessMapUv),E.push(M.sheenColorMapUv),E.push(M.sheenRoughnessMapUv),E.push(M.specularMapUv),E.push(M.specularColorMapUv),E.push(M.specularIntensityMapUv),E.push(M.transmissionMapUv),E.push(M.thicknessMapUv),E.push(M.combine),E.push(M.fogExp2),E.push(M.sizeAttenuation),E.push(M.morphTargetsCount),E.push(M.morphAttributeCount),E.push(M.numDirLights),E.push(M.numPointLights),E.push(M.numSpotLights),E.push(M.numSpotLightMaps),E.push(M.numHemiLights),E.push(M.numRectAreaLights),E.push(M.numDirLightShadows),E.push(M.numPointLightShadows),E.push(M.numSpotLightShadows),E.push(M.numSpotLightShadowsWithMaps),E.push(M.numLightProbes),E.push(M.shadowMapType),E.push(M.toneMapping),E.push(M.numClippingPlanes),E.push(M.numClipIntersection),E.push(M.depthPacking)}function S(E,M){o.disableAll(),M.supportsVertexTextures&&o.enable(0),M.instancing&&o.enable(1),M.instancingColor&&o.enable(2),M.instancingMorph&&o.enable(3),M.matcap&&o.enable(4),M.envMap&&o.enable(5),M.normalMapObjectSpace&&o.enable(6),M.normalMapTangentSpace&&o.enable(7),M.clearcoat&&o.enable(8),M.iridescence&&o.enable(9),M.alphaTest&&o.enable(10),M.vertexColors&&o.enable(11),M.vertexAlphas&&o.enable(12),M.vertexUv1s&&o.enable(13),M.vertexUv2s&&o.enable(14),M.vertexUv3s&&o.enable(15),M.vertexTangents&&o.enable(16),M.anisotropy&&o.enable(17),M.alphaHash&&o.enable(18),M.batching&&o.enable(19),M.dispersion&&o.enable(20),M.batchingColor&&o.enable(21),M.gradientMap&&o.enable(22),E.push(o.mask),o.disableAll(),M.fog&&o.enable(0),M.useFog&&o.enable(1),M.flatShading&&o.enable(2),M.logarithmicDepthBuffer&&o.enable(3),M.reversedDepthBuffer&&o.enable(4),M.skinning&&o.enable(5),M.morphTargets&&o.enable(6),M.morphNormals&&o.enable(7),M.morphColors&&o.enable(8),M.premultipliedAlpha&&o.enable(9),M.shadowMapEnabled&&o.enable(10),M.doubleSided&&o.enable(11),M.flipSided&&o.enable(12),M.useDepthPacking&&o.enable(13),M.dithering&&o.enable(14),M.transmission&&o.enable(15),M.sheen&&o.enable(16),M.opaque&&o.enable(17),M.pointsUvs&&o.enable(18),M.decodeVideoTexture&&o.enable(19),M.decodeVideoTextureEmissive&&o.enable(20),M.alphaToCoverage&&o.enable(21),E.push(o.mask)}function T(E){const M=x[E.type];let P;if(M){const O=an[M];P=Ah.clone(O.uniforms)}else P=E.uniforms;return P}function R(E,M){let P;for(let O=0,z=h.length;O0?n.push(f):p.transparent===!0?s.push(f):e.push(f)}function l(u,d,p,x,_,m){const f=a(u,d,p,x,_,m);p.transmission>0?n.unshift(f):p.transparent===!0?s.unshift(f):e.unshift(f)}function c(u,d){e.length>1&&e.sort(u||Y0),n.length>1&&n.sort(d||gc),s.length>1&&s.sort(d||gc)}function h(){for(let u=t,d=i.length;u=r.length?(a=new _c,r.push(a)):a=r[s],a}function e(){i=new WeakMap}return{get:t,dispose:e}}function K0(){const i={};return{get:function(t){if(i[t.id]!==void 0)return i[t.id];let e;switch(t.type){case"DirectionalLight":e={direction:new D,color:new Yt};break;case"SpotLight":e={position:new D,direction:new D,color:new Yt,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":e={position:new D,color:new Yt,distance:0,decay:0};break;case"HemisphereLight":e={direction:new D,skyColor:new Yt,groundColor:new Yt};break;case"RectAreaLight":e={color:new Yt,position:new D,halfWidth:new D,halfHeight:new D};break}return i[t.id]=e,e}}}function j0(){const i={};return{get:function(t){if(i[t.id]!==void 0)return i[t.id];let e;switch(t.type){case"DirectionalLight":e={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new at};break;case"SpotLight":e={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new at};break;case"PointLight":e={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new at,shadowCameraNear:1,shadowCameraFar:1e3};break}return i[t.id]=e,e}}}let J0=0;function $0(i,t){return(t.castShadow?2:0)-(i.castShadow?2:0)+(t.map?1:0)-(i.map?1:0)}function Q0(i){const t=new K0,e=j0(),n={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let c=0;c<9;c++)n.probe.push(new D);const s=new D,r=new re,a=new re;function o(c){let h=0,u=0,d=0;for(let E=0;E<9;E++)n.probe[E].set(0,0,0);let p=0,x=0,_=0,m=0,f=0,b=0,S=0,T=0,R=0,w=0,L=0;c.sort($0);for(let E=0,M=c.length;E0&&(i.has("OES_texture_float_linear")===!0?(n.rectAreaLTC1=pt.LTC_FLOAT_1,n.rectAreaLTC2=pt.LTC_FLOAT_2):(n.rectAreaLTC1=pt.LTC_HALF_1,n.rectAreaLTC2=pt.LTC_HALF_2)),n.ambient[0]=h,n.ambient[1]=u,n.ambient[2]=d;const F=n.hash;(F.directionalLength!==p||F.pointLength!==x||F.spotLength!==_||F.rectAreaLength!==m||F.hemiLength!==f||F.numDirectionalShadows!==b||F.numPointShadows!==S||F.numSpotShadows!==T||F.numSpotMaps!==R||F.numLightProbes!==L)&&(n.directional.length=p,n.spot.length=_,n.rectArea.length=m,n.point.length=x,n.hemi.length=f,n.directionalShadow.length=b,n.directionalShadowMap.length=b,n.pointShadow.length=S,n.pointShadowMap.length=S,n.spotShadow.length=T,n.spotShadowMap.length=T,n.directionalShadowMatrix.length=b,n.pointShadowMatrix.length=S,n.spotLightMatrix.length=T+R-w,n.spotLightMap.length=R,n.numSpotLightShadowsWithMaps=w,n.numLightProbes=L,F.directionalLength=p,F.pointLength=x,F.spotLength=_,F.rectAreaLength=m,F.hemiLength=f,F.numDirectionalShadows=b,F.numPointShadows=S,F.numSpotShadows=T,F.numSpotMaps=R,F.numLightProbes=L,n.version=J0++)}function l(c,h){let u=0,d=0,p=0,x=0,_=0;const m=h.matrixWorldInverse;for(let f=0,b=c.length;f=a.length?(o=new vc(i),a.push(o)):o=a[r],o}function n(){t=new WeakMap}return{get:e,dispose:n}}const em=`void main() { + gl_Position = vec4( position, 1.0 ); +}`,nm=`uniform sampler2D shadow_pass; +uniform vec2 resolution; +uniform float radius; +#include +void main() { + const float samples = float( VSM_SAMPLES ); + float mean = 0.0; + float squared_mean = 0.0; + float uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 ); + float uvStart = samples <= 1.0 ? 0.0 : - 1.0; + for ( float i = 0.0; i < samples; i ++ ) { + float uvOffset = uvStart + i * uvStride; + #ifdef HORIZONTAL_PASS + vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) ); + mean += distribution.x; + squared_mean += distribution.y * distribution.y + distribution.x * distribution.x; + #else + float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) ); + mean += depth; + squared_mean += depth * depth; + #endif + } + mean = mean / samples; + squared_mean = squared_mean / samples; + float std_dev = sqrt( squared_mean - mean * mean ); + gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) ); +}`;function im(i,t,e){let n=new Za;const s=new at,r=new at,a=new se,o=new Mu({depthPacking:Kl}),l=new Su,c={},h=e.maxTextureSize,u={[Fn]:Le,[Le]:Fn,[Mn]:Mn},d=new En({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new at},radius:{value:4}},vertexShader:em,fragmentShader:nm}),p=d.clone();p.defines.HORIZONTAL_PASS=1;const x=new Ie;x.setAttribute("position",new en(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const _=new Vt(x,d),m=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=bc;let f=this.type;this.render=function(w,L,F){if(m.enabled===!1||m.autoUpdate===!1&&m.needsUpdate===!1||w.length===0)return;const E=i.getRenderTarget(),M=i.getActiveCubeFace(),P=i.getActiveMipmapLevel(),O=i.state;O.setBlending(yn),O.buffers.depth.getReversed()===!0?O.buffers.color.setClear(0,0,0,0):O.buffers.color.setClear(1,1,1,1),O.buffers.depth.setTest(!0),O.setScissorTest(!1);const z=f!==_n&&this.type===_n,k=f===_n&&this.type!==_n;for(let W=0,Y=w.length;Wh||s.y>h)&&(s.x>h&&(r.x=Math.floor(h/rt.x),s.x=r.x*rt.x,X.mapSize.x=r.x),s.y>h&&(r.y=Math.floor(h/rt.y),s.y=r.y*rt.y,X.mapSize.y=r.y)),X.map===null||z===!0||k===!0){const St=this.type!==_n?{minFilter:He,magFilter:He}:{};X.map!==null&&X.map.dispose(),X.map=new $n(s.x,s.y,St),X.map.texture.name=nt.name+".shadowMap",X.camera.updateProjectionMatrix()}i.setRenderTarget(X.map),i.clear();const st=X.getViewportCount();for(let St=0;St0||L.map&&L.alphaTest>0||L.alphaToCoverage===!0){const O=M.uuid,z=L.uuid;let k=c[O];k===void 0&&(k={},c[O]=k);let W=k[z];W===void 0&&(W=M.clone(),k[z]=W,L.addEventListener("dispose",R)),M=W}if(M.visible=L.visible,M.wireframe=L.wireframe,E===_n?M.side=L.shadowSide!==null?L.shadowSide:L.side:M.side=L.shadowSide!==null?L.shadowSide:u[L.side],M.alphaMap=L.alphaMap,M.alphaTest=L.alphaToCoverage===!0?.5:L.alphaTest,M.map=L.map,M.clipShadows=L.clipShadows,M.clippingPlanes=L.clippingPlanes,M.clipIntersection=L.clipIntersection,M.displacementMap=L.displacementMap,M.displacementScale=L.displacementScale,M.displacementBias=L.displacementBias,M.wireframeLinewidth=L.wireframeLinewidth,M.linewidth=L.linewidth,F.isPointLight===!0&&M.isMeshDistanceMaterial===!0){const O=i.properties.get(M);O.light=F}return M}function T(w,L,F,E,M){if(w.visible===!1)return;if(w.layers.test(L.layers)&&(w.isMesh||w.isLine||w.isPoints)&&(w.castShadow||w.receiveShadow&&M===_n)&&(!w.frustumCulled||n.intersectsObject(w))){w.modelViewMatrix.multiplyMatrices(F.matrixWorldInverse,w.matrixWorld);const z=t.update(w),k=w.material;if(Array.isArray(k)){const W=z.groups;for(let Y=0,nt=W.length;Y=1):X.indexOf("OpenGL ES")!==-1&&(nt=parseFloat(/^OpenGL ES (\d)/.exec(X)[1]),Y=nt>=2);let rt=null,st={};const St=i.getParameter(i.SCISSOR_BOX),Gt=i.getParameter(i.VIEWPORT),qt=new se().fromArray(St),jt=new se().fromArray(Gt);function Kt(C,mt,ht,ut){const it=new Uint8Array(4),j=i.createTexture();i.bindTexture(C,j),i.texParameteri(C,i.TEXTURE_MIN_FILTER,i.NEAREST),i.texParameteri(C,i.TEXTURE_MAG_FILTER,i.NEAREST);for(let bt=0;bt"u"?!1:/OculusBrowser/g.test(navigator.userAgent),c=new at,h=new WeakMap;let u;const d=new WeakMap;let p=!1;try{p=typeof OffscreenCanvas<"u"&&new OffscreenCanvas(1,1).getContext("2d")!==null}catch{}function x(A,g){return p?new OffscreenCanvas(A,g):qs("canvas")}function _(A,g,N){let q=1;const $=Mt(A);if(($.width>N||$.height>N)&&(q=N/Math.max($.width,$.height)),q<1)if(typeof HTMLImageElement<"u"&&A instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&A instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&A instanceof ImageBitmap||typeof VideoFrame<"u"&&A instanceof VideoFrame){const H=Math.floor(q*$.width),wt=Math.floor(q*$.height);u===void 0&&(u=x(H,wt));const dt=g?x(H,wt):u;return dt.width=H,dt.height=wt,dt.getContext("2d").drawImage(A,0,0,H,wt),Bt("WebGLRenderer: Texture has been resized from ("+$.width+"x"+$.height+") to ("+H+"x"+wt+")."),dt}else return"data"in A&&Bt("WebGLRenderer: Image in DataTexture is too big ("+$.width+"x"+$.height+")."),A;return A}function m(A){return A.generateMipmaps}function f(A){i.generateMipmap(A)}function b(A){return A.isWebGLCubeRenderTarget?i.TEXTURE_CUBE_MAP:A.isWebGL3DRenderTarget?i.TEXTURE_3D:A.isWebGLArrayRenderTarget||A.isCompressedArrayTexture?i.TEXTURE_2D_ARRAY:i.TEXTURE_2D}function S(A,g,N,q,$=!1){if(A!==null){if(i[A]!==void 0)return i[A];Bt("WebGLRenderer: Attempt to use non-existing WebGL internal format '"+A+"'")}let H=g;if(g===i.RED&&(N===i.FLOAT&&(H=i.R32F),N===i.HALF_FLOAT&&(H=i.R16F),N===i.UNSIGNED_BYTE&&(H=i.R8)),g===i.RED_INTEGER&&(N===i.UNSIGNED_BYTE&&(H=i.R8UI),N===i.UNSIGNED_SHORT&&(H=i.R16UI),N===i.UNSIGNED_INT&&(H=i.R32UI),N===i.BYTE&&(H=i.R8I),N===i.SHORT&&(H=i.R16I),N===i.INT&&(H=i.R32I)),g===i.RG&&(N===i.FLOAT&&(H=i.RG32F),N===i.HALF_FLOAT&&(H=i.RG16F),N===i.UNSIGNED_BYTE&&(H=i.RG8)),g===i.RG_INTEGER&&(N===i.UNSIGNED_BYTE&&(H=i.RG8UI),N===i.UNSIGNED_SHORT&&(H=i.RG16UI),N===i.UNSIGNED_INT&&(H=i.RG32UI),N===i.BYTE&&(H=i.RG8I),N===i.SHORT&&(H=i.RG16I),N===i.INT&&(H=i.RG32I)),g===i.RGB_INTEGER&&(N===i.UNSIGNED_BYTE&&(H=i.RGB8UI),N===i.UNSIGNED_SHORT&&(H=i.RGB16UI),N===i.UNSIGNED_INT&&(H=i.RGB32UI),N===i.BYTE&&(H=i.RGB8I),N===i.SHORT&&(H=i.RGB16I),N===i.INT&&(H=i.RGB32I)),g===i.RGBA_INTEGER&&(N===i.UNSIGNED_BYTE&&(H=i.RGBA8UI),N===i.UNSIGNED_SHORT&&(H=i.RGBA16UI),N===i.UNSIGNED_INT&&(H=i.RGBA32UI),N===i.BYTE&&(H=i.RGBA8I),N===i.SHORT&&(H=i.RGBA16I),N===i.INT&&(H=i.RGBA32I)),g===i.RGB&&(N===i.UNSIGNED_INT_5_9_9_9_REV&&(H=i.RGB9_E5),N===i.UNSIGNED_INT_10F_11F_11F_REV&&(H=i.R11F_G11F_B10F)),g===i.RGBA){const wt=$?Ws:$t.getTransfer(q);N===i.FLOAT&&(H=i.RGBA32F),N===i.HALF_FLOAT&&(H=i.RGBA16F),N===i.UNSIGNED_BYTE&&(H=wt===ne?i.SRGB8_ALPHA8:i.RGBA8),N===i.UNSIGNED_SHORT_4_4_4_4&&(H=i.RGBA4),N===i.UNSIGNED_SHORT_5_5_5_1&&(H=i.RGB5_A1)}return(H===i.R16F||H===i.R32F||H===i.RG16F||H===i.RG32F||H===i.RGBA16F||H===i.RGBA32F)&&t.get("EXT_color_buffer_float"),H}function T(A,g){let N;return A?g===null||g===jn||g===ts?N=i.DEPTH24_STENCIL8:g===on?N=i.DEPTH32F_STENCIL8:g===Qi&&(N=i.DEPTH24_STENCIL8,Bt("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):g===null||g===jn||g===ts?N=i.DEPTH_COMPONENT24:g===on?N=i.DEPTH_COMPONENT32F:g===Qi&&(N=i.DEPTH_COMPONENT16),N}function R(A,g){return m(A)===!0||A.isFramebufferTexture&&A.minFilter!==He&&A.minFilter!==Ye?Math.log2(Math.max(g.width,g.height))+1:A.mipmaps!==void 0&&A.mipmaps.length>0?A.mipmaps.length:A.isCompressedTexture&&Array.isArray(A.image)?g.mipmaps.length:1}function w(A){const g=A.target;g.removeEventListener("dispose",w),F(g),g.isVideoTexture&&h.delete(g)}function L(A){const g=A.target;g.removeEventListener("dispose",L),M(g)}function F(A){const g=n.get(A);if(g.__webglInit===void 0)return;const N=A.source,q=d.get(N);if(q){const $=q[g.__cacheKey];$.usedTimes--,$.usedTimes===0&&E(A),Object.keys(q).length===0&&d.delete(N)}n.remove(A)}function E(A){const g=n.get(A);i.deleteTexture(g.__webglTexture);const N=A.source,q=d.get(N);delete q[g.__cacheKey],a.memory.textures--}function M(A){const g=n.get(A);if(A.depthTexture&&(A.depthTexture.dispose(),n.remove(A.depthTexture)),A.isWebGLCubeRenderTarget)for(let q=0;q<6;q++){if(Array.isArray(g.__webglFramebuffer[q]))for(let $=0;$=s.maxTextures&&Bt("WebGLTextures: Trying to use "+A+" texture units while this GPU supports only "+s.maxTextures),P+=1,A}function k(A){const g=[];return g.push(A.wrapS),g.push(A.wrapT),g.push(A.wrapR||0),g.push(A.magFilter),g.push(A.minFilter),g.push(A.anisotropy),g.push(A.internalFormat),g.push(A.format),g.push(A.type),g.push(A.generateMipmaps),g.push(A.premultiplyAlpha),g.push(A.flipY),g.push(A.unpackAlignment),g.push(A.colorSpace),g.join()}function W(A,g){const N=n.get(A);if(A.isVideoTexture&&vt(A),A.isRenderTargetTexture===!1&&A.isExternalTexture!==!0&&A.version>0&&N.__version!==A.version){const q=A.image;if(q===null)Bt("WebGLRenderer: Texture marked for update but no image data found.");else if(q.complete===!1)Bt("WebGLRenderer: Texture marked for update but image is incomplete");else{K(N,A,g);return}}else A.isExternalTexture&&(N.__webglTexture=A.sourceTexture?A.sourceTexture:null);e.bindTexture(i.TEXTURE_2D,N.__webglTexture,i.TEXTURE0+g)}function Y(A,g){const N=n.get(A);if(A.isRenderTargetTexture===!1&&A.version>0&&N.__version!==A.version){K(N,A,g);return}else A.isExternalTexture&&(N.__webglTexture=A.sourceTexture?A.sourceTexture:null);e.bindTexture(i.TEXTURE_2D_ARRAY,N.__webglTexture,i.TEXTURE0+g)}function nt(A,g){const N=n.get(A);if(A.isRenderTargetTexture===!1&&A.version>0&&N.__version!==A.version){K(N,A,g);return}e.bindTexture(i.TEXTURE_3D,N.__webglTexture,i.TEXTURE0+g)}function X(A,g){const N=n.get(A);if(A.version>0&&N.__version!==A.version){J(N,A,g);return}e.bindTexture(i.TEXTURE_CUBE_MAP,N.__webglTexture,i.TEXTURE0+g)}const rt={[$r]:i.REPEAT,[Sn]:i.CLAMP_TO_EDGE,[Qr]:i.MIRRORED_REPEAT},st={[He]:i.NEAREST,[Yl]:i.NEAREST_MIPMAP_NEAREST,[us]:i.NEAREST_MIPMAP_LINEAR,[Ye]:i.LINEAR,[ir]:i.LINEAR_MIPMAP_NEAREST,[Kn]:i.LINEAR_MIPMAP_LINEAR},St={[Jl]:i.NEVER,[ih]:i.ALWAYS,[$l]:i.LESS,[Ic]:i.LEQUAL,[Ql]:i.EQUAL,[nh]:i.GEQUAL,[th]:i.GREATER,[eh]:i.NOTEQUAL};function Gt(A,g){if(g.type===on&&t.has("OES_texture_float_linear")===!1&&(g.magFilter===Ye||g.magFilter===ir||g.magFilter===us||g.magFilter===Kn||g.minFilter===Ye||g.minFilter===ir||g.minFilter===us||g.minFilter===Kn)&&Bt("WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),i.texParameteri(A,i.TEXTURE_WRAP_S,rt[g.wrapS]),i.texParameteri(A,i.TEXTURE_WRAP_T,rt[g.wrapT]),(A===i.TEXTURE_3D||A===i.TEXTURE_2D_ARRAY)&&i.texParameteri(A,i.TEXTURE_WRAP_R,rt[g.wrapR]),i.texParameteri(A,i.TEXTURE_MAG_FILTER,st[g.magFilter]),i.texParameteri(A,i.TEXTURE_MIN_FILTER,st[g.minFilter]),g.compareFunction&&(i.texParameteri(A,i.TEXTURE_COMPARE_MODE,i.COMPARE_REF_TO_TEXTURE),i.texParameteri(A,i.TEXTURE_COMPARE_FUNC,St[g.compareFunction])),t.has("EXT_texture_filter_anisotropic")===!0){if(g.magFilter===He||g.minFilter!==us&&g.minFilter!==Kn||g.type===on&&t.has("OES_texture_float_linear")===!1)return;if(g.anisotropy>1||n.get(g).__currentAnisotropy){const N=t.get("EXT_texture_filter_anisotropic");i.texParameterf(A,N.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(g.anisotropy,s.getMaxAnisotropy())),n.get(g).__currentAnisotropy=g.anisotropy}}}function qt(A,g){let N=!1;A.__webglInit===void 0&&(A.__webglInit=!0,g.addEventListener("dispose",w));const q=g.source;let $=d.get(q);$===void 0&&($={},d.set(q,$));const H=k(g);if(H!==A.__cacheKey){$[H]===void 0&&($[H]={texture:i.createTexture(),usedTimes:0},a.memory.textures++,N=!0),$[H].usedTimes++;const wt=$[A.__cacheKey];wt!==void 0&&($[A.__cacheKey].usedTimes--,wt.usedTimes===0&&E(g)),A.__cacheKey=H,A.__webglTexture=$[H].texture}return N}function jt(A,g,N){return Math.floor(Math.floor(A/N)/g)}function Kt(A,g,N,q){const H=A.updateRanges;if(H.length===0)e.texSubImage2D(i.TEXTURE_2D,0,0,0,g.width,g.height,N,q,g.data);else{H.sort((tt,lt)=>tt.start-lt.start);let wt=0;for(let tt=1;tt0){C&&mt&&e.texStorage2D(i.TEXTURE_2D,ut,It,Ot[0].width,Ot[0].height);for(let it=0,j=Ot.length;it0){const bt=Jo(_t.width,_t.height,g.format,g.type);for(const zt of g.layerUpdates){const ce=_t.data.subarray(zt*bt/_t.data.BYTES_PER_ELEMENT,(zt+1)*bt/_t.data.BYTES_PER_ELEMENT);e.compressedTexSubImage3D(i.TEXTURE_2D_ARRAY,it,0,0,zt,_t.width,_t.height,1,lt,ce)}g.clearLayerUpdates()}else e.compressedTexSubImage3D(i.TEXTURE_2D_ARRAY,it,0,0,0,_t.width,_t.height,tt.depth,lt,_t.data)}else e.compressedTexImage3D(i.TEXTURE_2D_ARRAY,it,It,_t.width,_t.height,tt.depth,0,_t.data,0,0);else Bt("WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else C?ht&&e.texSubImage3D(i.TEXTURE_2D_ARRAY,it,0,0,0,_t.width,_t.height,tt.depth,lt,Nt,_t.data):e.texImage3D(i.TEXTURE_2D_ARRAY,it,It,_t.width,_t.height,tt.depth,0,lt,Nt,_t.data)}else{C&&mt&&e.texStorage2D(i.TEXTURE_2D,ut,It,Ot[0].width,Ot[0].height);for(let it=0,j=Ot.length;it0){const it=Jo(tt.width,tt.height,g.format,g.type);for(const j of g.layerUpdates){const bt=tt.data.subarray(j*it/tt.data.BYTES_PER_ELEMENT,(j+1)*it/tt.data.BYTES_PER_ELEMENT);e.texSubImage3D(i.TEXTURE_2D_ARRAY,0,0,0,j,tt.width,tt.height,1,lt,Nt,bt)}g.clearLayerUpdates()}else e.texSubImage3D(i.TEXTURE_2D_ARRAY,0,0,0,0,tt.width,tt.height,tt.depth,lt,Nt,tt.data)}else e.texImage3D(i.TEXTURE_2D_ARRAY,0,It,tt.width,tt.height,tt.depth,0,lt,Nt,tt.data);else if(g.isData3DTexture)C?(mt&&e.texStorage3D(i.TEXTURE_3D,ut,It,tt.width,tt.height,tt.depth),ht&&e.texSubImage3D(i.TEXTURE_3D,0,0,0,0,tt.width,tt.height,tt.depth,lt,Nt,tt.data)):e.texImage3D(i.TEXTURE_3D,0,It,tt.width,tt.height,tt.depth,0,lt,Nt,tt.data);else if(g.isFramebufferTexture){if(mt)if(C)e.texStorage2D(i.TEXTURE_2D,ut,It,tt.width,tt.height);else{let it=tt.width,j=tt.height;for(let bt=0;bt>=1,j>>=1}}else if(Ot.length>0){if(C&&mt){const it=Mt(Ot[0]);e.texStorage2D(i.TEXTURE_2D,ut,It,it.width,it.height)}for(let it=0,j=Ot.length;it0&&ut++;const j=Mt(lt[0]);e.texStorage2D(i.TEXTURE_CUBE_MAP,ut,Ot,j.width,j.height)}for(let j=0;j<6;j++)if(tt){C?ht&&e.texSubImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+j,0,0,0,lt[j].width,lt[j].height,It,_t,lt[j].data):e.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+j,0,Ot,lt[j].width,lt[j].height,0,It,_t,lt[j].data);for(let bt=0;bt>H),Nt=Math.max(1,g.height>>H);$===i.TEXTURE_3D||$===i.TEXTURE_2D_ARRAY?e.texImage3D($,H,Pt,lt,Nt,g.depth,0,wt,dt,null):e.texImage2D($,H,Pt,lt,Nt,0,wt,dt,null)}e.bindFramebuffer(i.FRAMEBUFFER,A),et(g)?o.framebufferTexture2DMultisampleEXT(i.FRAMEBUFFER,q,$,tt.__webglTexture,0,ot(g)):($===i.TEXTURE_2D||$>=i.TEXTURE_CUBE_MAP_POSITIVE_X&&$<=i.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&i.framebufferTexture2D(i.FRAMEBUFFER,q,$,tt.__webglTexture,H),e.bindFramebuffer(i.FRAMEBUFFER,null)}function Rt(A,g,N){if(i.bindRenderbuffer(i.RENDERBUFFER,A),g.depthBuffer){const q=g.depthTexture,$=q&&q.isDepthTexture?q.type:null,H=T(g.stencilBuffer,$),wt=g.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,dt=ot(g);et(g)?o.renderbufferStorageMultisampleEXT(i.RENDERBUFFER,dt,H,g.width,g.height):N?i.renderbufferStorageMultisample(i.RENDERBUFFER,dt,H,g.width,g.height):i.renderbufferStorage(i.RENDERBUFFER,H,g.width,g.height),i.framebufferRenderbuffer(i.FRAMEBUFFER,wt,i.RENDERBUFFER,A)}else{const q=g.textures;for(let $=0;${delete g.__boundDepthTexture,delete g.__depthDisposeCallback,q.removeEventListener("dispose",$)};q.addEventListener("dispose",$),g.__depthDisposeCallback=$}g.__boundDepthTexture=q}if(A.depthTexture&&!g.__autoAllocateDepthBuffer){if(N)throw new Error("target.depthTexture not supported in Cube render targets");const q=A.texture.mipmaps;q&&q.length>0?Tt(g.__webglFramebuffer[0],A):Tt(g.__webglFramebuffer,A)}else if(N){g.__webglDepthbuffer=[];for(let q=0;q<6;q++)if(e.bindFramebuffer(i.FRAMEBUFFER,g.__webglFramebuffer[q]),g.__webglDepthbuffer[q]===void 0)g.__webglDepthbuffer[q]=i.createRenderbuffer(),Rt(g.__webglDepthbuffer[q],A,!1);else{const $=A.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,H=g.__webglDepthbuffer[q];i.bindRenderbuffer(i.RENDERBUFFER,H),i.framebufferRenderbuffer(i.FRAMEBUFFER,$,i.RENDERBUFFER,H)}}else{const q=A.texture.mipmaps;if(q&&q.length>0?e.bindFramebuffer(i.FRAMEBUFFER,g.__webglFramebuffer[0]):e.bindFramebuffer(i.FRAMEBUFFER,g.__webglFramebuffer),g.__webglDepthbuffer===void 0)g.__webglDepthbuffer=i.createRenderbuffer(),Rt(g.__webglDepthbuffer,A,!1);else{const $=A.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,H=g.__webglDepthbuffer;i.bindRenderbuffer(i.RENDERBUFFER,H),i.framebufferRenderbuffer(i.FRAMEBUFFER,$,i.RENDERBUFFER,H)}}e.bindFramebuffer(i.FRAMEBUFFER,null)}function Qt(A,g,N){const q=n.get(A);g!==void 0&&xt(q.__webglFramebuffer,A,A.texture,i.COLOR_ATTACHMENT0,i.TEXTURE_2D,0),N!==void 0&&kt(A)}function Ct(A){const g=A.texture,N=n.get(A),q=n.get(g);A.addEventListener("dispose",L);const $=A.textures,H=A.isWebGLCubeRenderTarget===!0,wt=$.length>1;if(wt||(q.__webglTexture===void 0&&(q.__webglTexture=i.createTexture()),q.__version=g.version,a.memory.textures++),H){N.__webglFramebuffer=[];for(let dt=0;dt<6;dt++)if(g.mipmaps&&g.mipmaps.length>0){N.__webglFramebuffer[dt]=[];for(let Pt=0;Pt0){N.__webglFramebuffer=[];for(let dt=0;dt0&&et(A)===!1){N.__webglMultisampledFramebuffer=i.createFramebuffer(),N.__webglColorRenderbuffer=[],e.bindFramebuffer(i.FRAMEBUFFER,N.__webglMultisampledFramebuffer);for(let dt=0;dt<$.length;dt++){const Pt=$[dt];N.__webglColorRenderbuffer[dt]=i.createRenderbuffer(),i.bindRenderbuffer(i.RENDERBUFFER,N.__webglColorRenderbuffer[dt]);const At=r.convert(Pt.format,Pt.colorSpace),tt=r.convert(Pt.type),lt=S(Pt.internalFormat,At,tt,Pt.colorSpace,A.isXRRenderTarget===!0),Nt=ot(A);i.renderbufferStorageMultisample(i.RENDERBUFFER,Nt,lt,A.width,A.height),i.framebufferRenderbuffer(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0+dt,i.RENDERBUFFER,N.__webglColorRenderbuffer[dt])}i.bindRenderbuffer(i.RENDERBUFFER,null),A.depthBuffer&&(N.__webglDepthRenderbuffer=i.createRenderbuffer(),Rt(N.__webglDepthRenderbuffer,A,!0)),e.bindFramebuffer(i.FRAMEBUFFER,null)}}if(H){e.bindTexture(i.TEXTURE_CUBE_MAP,q.__webglTexture),Gt(i.TEXTURE_CUBE_MAP,g);for(let dt=0;dt<6;dt++)if(g.mipmaps&&g.mipmaps.length>0)for(let Pt=0;Pt0)for(let Pt=0;Pt0){if(et(A)===!1){const g=A.textures,N=A.width,q=A.height;let $=i.COLOR_BUFFER_BIT;const H=A.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,wt=n.get(A),dt=g.length>1;if(dt)for(let At=0;At0?e.bindFramebuffer(i.DRAW_FRAMEBUFFER,wt.__webglFramebuffer[0]):e.bindFramebuffer(i.DRAW_FRAMEBUFFER,wt.__webglFramebuffer);for(let At=0;At0&&t.has("WEBGL_multisampled_render_to_texture")===!0&&g.__useRenderToTexture!==!1}function vt(A){const g=a.render.frame;h.get(A)!==g&&(h.set(A,g),A.update())}function ft(A,g){const N=A.colorSpace,q=A.format,$=A.type;return A.isCompressedTexture===!0||A.isVideoTexture===!0||N!==Ri&&N!==Ln&&($t.getTransfer(N)===ne?(q!==tn||$!==hn)&&Bt("WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):de("WebGLTextures: Unsupported texture color space:",N)),g}function Mt(A){return typeof HTMLImageElement<"u"&&A instanceof HTMLImageElement?(c.width=A.naturalWidth||A.width,c.height=A.naturalHeight||A.height):typeof VideoFrame<"u"&&A instanceof VideoFrame?(c.width=A.displayWidth,c.height=A.displayHeight):(c.width=A.width,c.height=A.height),c}this.allocateTextureUnit=z,this.resetTextureUnits=O,this.setTexture2D=W,this.setTexture2DArray=Y,this.setTexture3D=nt,this.setTextureCube=X,this.rebindTextures=Qt,this.setupRenderTarget=Ct,this.updateRenderTargetMipmap=B,this.updateMultisampleRenderTarget=Q,this.setupDepthRenderbuffer=kt,this.setupFrameBufferTexture=xt,this.useMultisampledRTT=et}function om(i,t){function e(n,s=Ln){let r;const a=$t.getTransfer(s);if(n===hn)return i.UNSIGNED_BYTE;if(n===Ba)return i.UNSIGNED_SHORT_4_4_4_4;if(n===za)return i.UNSIGNED_SHORT_5_5_5_1;if(n===Cc)return i.UNSIGNED_INT_5_9_9_9_REV;if(n===Pc)return i.UNSIGNED_INT_10F_11F_11F_REV;if(n===wc)return i.BYTE;if(n===Rc)return i.SHORT;if(n===Qi)return i.UNSIGNED_SHORT;if(n===Oa)return i.INT;if(n===jn)return i.UNSIGNED_INT;if(n===on)return i.FLOAT;if(n===Di)return i.HALF_FLOAT;if(n===Dc)return i.ALPHA;if(n===Lc)return i.RGB;if(n===tn)return i.RGBA;if(n===es)return i.DEPTH_COMPONENT;if(n===ns)return i.DEPTH_STENCIL;if(n===Va)return i.RED;if(n===Ga)return i.RED_INTEGER;if(n===ka)return i.RG;if(n===Ha)return i.RG_INTEGER;if(n===Wa)return i.RGBA_INTEGER;if(n===Bs||n===zs||n===Vs||n===Gs)if(a===ne)if(r=t.get("WEBGL_compressed_texture_s3tc_srgb"),r!==null){if(n===Bs)return r.COMPRESSED_SRGB_S3TC_DXT1_EXT;if(n===zs)return r.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;if(n===Vs)return r.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;if(n===Gs)return r.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}else return null;else if(r=t.get("WEBGL_compressed_texture_s3tc"),r!==null){if(n===Bs)return r.COMPRESSED_RGB_S3TC_DXT1_EXT;if(n===zs)return r.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(n===Vs)return r.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(n===Gs)return r.COMPRESSED_RGBA_S3TC_DXT5_EXT}else return null;if(n===ta||n===ea||n===na||n===ia)if(r=t.get("WEBGL_compressed_texture_pvrtc"),r!==null){if(n===ta)return r.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(n===ea)return r.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(n===na)return r.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(n===ia)return r.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}else return null;if(n===sa||n===ra||n===aa)if(r=t.get("WEBGL_compressed_texture_etc"),r!==null){if(n===sa||n===ra)return a===ne?r.COMPRESSED_SRGB8_ETC2:r.COMPRESSED_RGB8_ETC2;if(n===aa)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:r.COMPRESSED_RGBA8_ETC2_EAC}else return null;if(n===oa||n===ca||n===la||n===ha||n===ua||n===fa||n===da||n===pa||n===ma||n===xa||n===ga||n===_a||n===va||n===Ma)if(r=t.get("WEBGL_compressed_texture_astc"),r!==null){if(n===oa)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:r.COMPRESSED_RGBA_ASTC_4x4_KHR;if(n===ca)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:r.COMPRESSED_RGBA_ASTC_5x4_KHR;if(n===la)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:r.COMPRESSED_RGBA_ASTC_5x5_KHR;if(n===ha)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:r.COMPRESSED_RGBA_ASTC_6x5_KHR;if(n===ua)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:r.COMPRESSED_RGBA_ASTC_6x6_KHR;if(n===fa)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:r.COMPRESSED_RGBA_ASTC_8x5_KHR;if(n===da)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:r.COMPRESSED_RGBA_ASTC_8x6_KHR;if(n===pa)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:r.COMPRESSED_RGBA_ASTC_8x8_KHR;if(n===ma)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:r.COMPRESSED_RGBA_ASTC_10x5_KHR;if(n===xa)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:r.COMPRESSED_RGBA_ASTC_10x6_KHR;if(n===ga)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:r.COMPRESSED_RGBA_ASTC_10x8_KHR;if(n===_a)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:r.COMPRESSED_RGBA_ASTC_10x10_KHR;if(n===va)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:r.COMPRESSED_RGBA_ASTC_12x10_KHR;if(n===Ma)return a===ne?r.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:r.COMPRESSED_RGBA_ASTC_12x12_KHR}else return null;if(n===Sa||n===ya||n===ba)if(r=t.get("EXT_texture_compression_bptc"),r!==null){if(n===Sa)return a===ne?r.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:r.COMPRESSED_RGBA_BPTC_UNORM_EXT;if(n===ya)return r.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;if(n===ba)return r.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT}else return null;if(n===Ea||n===Ta||n===Aa||n===wa)if(r=t.get("EXT_texture_compression_rgtc"),r!==null){if(n===Ea)return r.COMPRESSED_RED_RGTC1_EXT;if(n===Ta)return r.COMPRESSED_SIGNED_RED_RGTC1_EXT;if(n===Aa)return r.COMPRESSED_RED_GREEN_RGTC2_EXT;if(n===wa)return r.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT}else return null;return n===ts?i.UNSIGNED_INT_24_8:i[n]!==void 0?i[n]:null}return{convert:e}}const cm=` +void main() { + + gl_Position = vec4( position, 1.0 ); + +}`,lm=` +uniform sampler2DArray depthColor; +uniform float depthWidth; +uniform float depthHeight; + +void main() { + + vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight ); + + if ( coord.x >= 1.0 ) { + + gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r; + + } else { + + gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r; + + } + +}`;class hm{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(t,e){if(this.texture===null){const n=new qc(t.texture);(t.depthNear!==e.depthNear||t.depthFar!==e.depthFar)&&(this.depthNear=t.depthNear,this.depthFar=t.depthFar),this.texture=n}}getMesh(t){if(this.texture!==null&&this.mesh===null){const e=t.cameras[0].viewport,n=new En({vertexShader:cm,fragmentShader:lm,uniforms:{depthColor:{value:this.texture},depthWidth:{value:e.z},depthHeight:{value:e.w}}});this.mesh=new Vt(new Nn(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class um extends ti{constructor(t,e){super();const n=this;let s=null,r=1,a=null,o="local-floor",l=1,c=null,h=null,u=null,d=null,p=null,x=null;const _=typeof XRWebGLBinding<"u",m=new hm,f={},b=e.getContextAttributes();let S=null,T=null;const R=[],w=[],L=new at;let F=null;const E=new ke;E.viewport=new se;const M=new ke;M.viewport=new se;const P=[E,M],O=new wu;let z=null,k=null;this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(K){let J=R[K];return J===void 0&&(J=new Tr,R[K]=J),J.getTargetRaySpace()},this.getControllerGrip=function(K){let J=R[K];return J===void 0&&(J=new Tr,R[K]=J),J.getGripSpace()},this.getHand=function(K){let J=R[K];return J===void 0&&(J=new Tr,R[K]=J),J.getHandSpace()};function W(K){const J=w.indexOf(K.inputSource);if(J===-1)return;const xt=R[J];xt!==void 0&&(xt.update(K.inputSource,K.frame,c||a),xt.dispatchEvent({type:K.type,data:K.inputSource}))}function Y(){s.removeEventListener("select",W),s.removeEventListener("selectstart",W),s.removeEventListener("selectend",W),s.removeEventListener("squeeze",W),s.removeEventListener("squeezestart",W),s.removeEventListener("squeezeend",W),s.removeEventListener("end",Y),s.removeEventListener("inputsourceschange",nt);for(let K=0;K=0&&(w[Rt]=null,R[Rt].disconnect(xt))}for(let J=0;J=w.length){w.push(xt),Rt=kt;break}else if(w[kt]===null){w[kt]=xt,Rt=kt;break}if(Rt===-1)break}const Tt=R[Rt];Tt&&Tt.connect(xt)}}const X=new D,rt=new D;function st(K,J,xt){X.setFromMatrixPosition(J.matrixWorld),rt.setFromMatrixPosition(xt.matrixWorld);const Rt=X.distanceTo(rt),Tt=J.projectionMatrix.elements,kt=xt.projectionMatrix.elements,Qt=Tt[14]/(Tt[10]-1),Ct=Tt[14]/(Tt[10]+1),B=(Tt[9]+1)/Tt[5],y=(Tt[9]-1)/Tt[5],Z=(Tt[8]-1)/Tt[0],Q=(kt[8]+1)/kt[0],ot=Qt*Z,et=Qt*Q,vt=Rt/(-Z+Q),ft=vt*-Z;if(J.matrixWorld.decompose(K.position,K.quaternion,K.scale),K.translateX(ft),K.translateZ(vt),K.matrixWorld.compose(K.position,K.quaternion,K.scale),K.matrixWorldInverse.copy(K.matrixWorld).invert(),Tt[10]===-1)K.projectionMatrix.copy(J.projectionMatrix),K.projectionMatrixInverse.copy(J.projectionMatrixInverse);else{const Mt=Qt+vt,A=Ct+vt,g=ot-ft,N=et+(Rt-ft),q=B*Ct/A*Mt,$=y*Ct/A*Mt;K.projectionMatrix.makePerspective(g,N,q,$,Mt,A),K.projectionMatrixInverse.copy(K.projectionMatrix).invert()}}function St(K,J){J===null?K.matrixWorld.copy(K.matrix):K.matrixWorld.multiplyMatrices(J.matrixWorld,K.matrix),K.matrixWorldInverse.copy(K.matrixWorld).invert()}this.updateCamera=function(K){if(s===null)return;let J=K.near,xt=K.far;m.texture!==null&&(m.depthNear>0&&(J=m.depthNear),m.depthFar>0&&(xt=m.depthFar)),O.near=M.near=E.near=J,O.far=M.far=E.far=xt,(z!==O.near||k!==O.far)&&(s.updateRenderState({depthNear:O.near,depthFar:O.far}),z=O.near,k=O.far),O.layers.mask=K.layers.mask|6,E.layers.mask=O.layers.mask&3,M.layers.mask=O.layers.mask&5;const Rt=K.parent,Tt=O.cameras;St(O,Rt);for(let kt=0;kt0&&(m.alphaTest.value=f.alphaTest);const b=t.get(f),S=b.envMap,T=b.envMapRotation;S&&(m.envMap.value=S,Xn.copy(T),Xn.x*=-1,Xn.y*=-1,Xn.z*=-1,S.isCubeTexture&&S.isRenderTargetTexture===!1&&(Xn.y*=-1,Xn.z*=-1),m.envMapRotation.value.setFromMatrix4(fm.makeRotationFromEuler(Xn)),m.flipEnvMap.value=S.isCubeTexture&&S.isRenderTargetTexture===!1?-1:1,m.reflectivity.value=f.reflectivity,m.ior.value=f.ior,m.refractionRatio.value=f.refractionRatio),f.lightMap&&(m.lightMap.value=f.lightMap,m.lightMapIntensity.value=f.lightMapIntensity,e(f.lightMap,m.lightMapTransform)),f.aoMap&&(m.aoMap.value=f.aoMap,m.aoMapIntensity.value=f.aoMapIntensity,e(f.aoMap,m.aoMapTransform))}function a(m,f){m.diffuse.value.copy(f.color),m.opacity.value=f.opacity,f.map&&(m.map.value=f.map,e(f.map,m.mapTransform))}function o(m,f){m.dashSize.value=f.dashSize,m.totalSize.value=f.dashSize+f.gapSize,m.scale.value=f.scale}function l(m,f,b,S){m.diffuse.value.copy(f.color),m.opacity.value=f.opacity,m.size.value=f.size*b,m.scale.value=S*.5,f.map&&(m.map.value=f.map,e(f.map,m.uvTransform)),f.alphaMap&&(m.alphaMap.value=f.alphaMap,e(f.alphaMap,m.alphaMapTransform)),f.alphaTest>0&&(m.alphaTest.value=f.alphaTest)}function c(m,f){m.diffuse.value.copy(f.color),m.opacity.value=f.opacity,m.rotation.value=f.rotation,f.map&&(m.map.value=f.map,e(f.map,m.mapTransform)),f.alphaMap&&(m.alphaMap.value=f.alphaMap,e(f.alphaMap,m.alphaMapTransform)),f.alphaTest>0&&(m.alphaTest.value=f.alphaTest)}function h(m,f){m.specular.value.copy(f.specular),m.shininess.value=Math.max(f.shininess,1e-4)}function u(m,f){f.gradientMap&&(m.gradientMap.value=f.gradientMap)}function d(m,f){m.metalness.value=f.metalness,f.metalnessMap&&(m.metalnessMap.value=f.metalnessMap,e(f.metalnessMap,m.metalnessMapTransform)),m.roughness.value=f.roughness,f.roughnessMap&&(m.roughnessMap.value=f.roughnessMap,e(f.roughnessMap,m.roughnessMapTransform)),f.envMap&&(m.envMapIntensity.value=f.envMapIntensity)}function p(m,f,b){m.ior.value=f.ior,f.sheen>0&&(m.sheenColor.value.copy(f.sheenColor).multiplyScalar(f.sheen),m.sheenRoughness.value=f.sheenRoughness,f.sheenColorMap&&(m.sheenColorMap.value=f.sheenColorMap,e(f.sheenColorMap,m.sheenColorMapTransform)),f.sheenRoughnessMap&&(m.sheenRoughnessMap.value=f.sheenRoughnessMap,e(f.sheenRoughnessMap,m.sheenRoughnessMapTransform))),f.clearcoat>0&&(m.clearcoat.value=f.clearcoat,m.clearcoatRoughness.value=f.clearcoatRoughness,f.clearcoatMap&&(m.clearcoatMap.value=f.clearcoatMap,e(f.clearcoatMap,m.clearcoatMapTransform)),f.clearcoatRoughnessMap&&(m.clearcoatRoughnessMap.value=f.clearcoatRoughnessMap,e(f.clearcoatRoughnessMap,m.clearcoatRoughnessMapTransform)),f.clearcoatNormalMap&&(m.clearcoatNormalMap.value=f.clearcoatNormalMap,e(f.clearcoatNormalMap,m.clearcoatNormalMapTransform),m.clearcoatNormalScale.value.copy(f.clearcoatNormalScale),f.side===Le&&m.clearcoatNormalScale.value.negate())),f.dispersion>0&&(m.dispersion.value=f.dispersion),f.iridescence>0&&(m.iridescence.value=f.iridescence,m.iridescenceIOR.value=f.iridescenceIOR,m.iridescenceThicknessMinimum.value=f.iridescenceThicknessRange[0],m.iridescenceThicknessMaximum.value=f.iridescenceThicknessRange[1],f.iridescenceMap&&(m.iridescenceMap.value=f.iridescenceMap,e(f.iridescenceMap,m.iridescenceMapTransform)),f.iridescenceThicknessMap&&(m.iridescenceThicknessMap.value=f.iridescenceThicknessMap,e(f.iridescenceThicknessMap,m.iridescenceThicknessMapTransform))),f.transmission>0&&(m.transmission.value=f.transmission,m.transmissionSamplerMap.value=b.texture,m.transmissionSamplerSize.value.set(b.width,b.height),f.transmissionMap&&(m.transmissionMap.value=f.transmissionMap,e(f.transmissionMap,m.transmissionMapTransform)),m.thickness.value=f.thickness,f.thicknessMap&&(m.thicknessMap.value=f.thicknessMap,e(f.thicknessMap,m.thicknessMapTransform)),m.attenuationDistance.value=f.attenuationDistance,m.attenuationColor.value.copy(f.attenuationColor)),f.anisotropy>0&&(m.anisotropyVector.value.set(f.anisotropy*Math.cos(f.anisotropyRotation),f.anisotropy*Math.sin(f.anisotropyRotation)),f.anisotropyMap&&(m.anisotropyMap.value=f.anisotropyMap,e(f.anisotropyMap,m.anisotropyMapTransform))),m.specularIntensity.value=f.specularIntensity,m.specularColor.value.copy(f.specularColor),f.specularColorMap&&(m.specularColorMap.value=f.specularColorMap,e(f.specularColorMap,m.specularColorMapTransform)),f.specularIntensityMap&&(m.specularIntensityMap.value=f.specularIntensityMap,e(f.specularIntensityMap,m.specularIntensityMapTransform))}function x(m,f){f.matcap&&(m.matcap.value=f.matcap)}function _(m,f){const b=t.get(f).light;m.referencePosition.value.setFromMatrixPosition(b.matrixWorld),m.nearDistance.value=b.shadow.camera.near,m.farDistance.value=b.shadow.camera.far}return{refreshFogUniforms:n,refreshMaterialUniforms:s}}function pm(i,t,e,n){let s={},r={},a=[];const o=i.getParameter(i.MAX_UNIFORM_BUFFER_BINDINGS);function l(b,S){const T=S.program;n.uniformBlockBinding(b,T)}function c(b,S){let T=s[b.id];T===void 0&&(x(b),T=h(b),s[b.id]=T,b.addEventListener("dispose",m));const R=S.program;n.updateUBOMapping(b,R);const w=t.render.frame;r[b.id]!==w&&(d(b),r[b.id]=w)}function h(b){const S=u();b.__bindingPointIndex=S;const T=i.createBuffer(),R=b.__size,w=b.usage;return i.bindBuffer(i.UNIFORM_BUFFER,T),i.bufferData(i.UNIFORM_BUFFER,R,w),i.bindBuffer(i.UNIFORM_BUFFER,null),i.bindBufferBase(i.UNIFORM_BUFFER,S,T),T}function u(){for(let b=0;b0&&(T+=R-w),b.__size=T,b.__cache={},this}function _(b){const S={boundary:0,storage:0};return typeof b=="number"||typeof b=="boolean"?(S.boundary=4,S.storage=4):b.isVector2?(S.boundary=8,S.storage=8):b.isVector3||b.isColor?(S.boundary=16,S.storage=12):b.isVector4?(S.boundary=16,S.storage=16):b.isMatrix3?(S.boundary=48,S.storage=48):b.isMatrix4?(S.boundary=64,S.storage=64):b.isTexture?Bt("WebGLRenderer: Texture samplers can not be part of an uniforms group."):Bt("WebGLRenderer: Unsupported uniform value type.",b),S}function m(b){const S=b.target;S.removeEventListener("dispose",m);const T=a.indexOf(S.__bindingPointIndex);a.splice(T,1),i.deleteBuffer(s[S.id]),delete s[S.id],delete r[S.id]}function f(){for(const b in s)i.deleteBuffer(s[b]);a=[],s={},r={}}return{bind:l,update:c,dispose:f}}const mm=new Uint16Array([11481,15204,11534,15171,11808,15015,12385,14843,12894,14716,13396,14600,13693,14483,13976,14366,14237,14171,14405,13961,14511,13770,14605,13598,14687,13444,14760,13305,14822,13066,14876,12857,14923,12675,14963,12517,14997,12379,15025,12230,15049,12023,15070,11843,15086,11687,15100,11551,15111,11433,15120,11330,15127,11217,15132,11060,15135,10922,15138,10801,15139,10695,15139,10600,13012,14923,13020,14917,13064,14886,13176,14800,13349,14666,13513,14526,13724,14398,13960,14230,14200,14020,14383,13827,14488,13651,14583,13491,14667,13348,14740,13132,14803,12908,14856,12713,14901,12542,14938,12394,14968,12241,14992,12017,15010,11822,15024,11654,15034,11507,15041,11380,15044,11269,15044,11081,15042,10913,15037,10764,15031,10635,15023,10520,15014,10419,15003,10330,13657,14676,13658,14673,13670,14660,13698,14622,13750,14547,13834,14442,13956,14317,14112,14093,14291,13889,14407,13704,14499,13538,14586,13389,14664,13201,14733,12966,14792,12758,14842,12577,14882,12418,14915,12272,14940,12033,14959,11826,14972,11646,14980,11490,14983,11355,14983,11212,14979,11008,14971,10830,14961,10675,14950,10540,14936,10420,14923,10315,14909,10204,14894,10041,14089,14460,14090,14459,14096,14452,14112,14431,14141,14388,14186,14305,14252,14130,14341,13941,14399,13756,14467,13585,14539,13430,14610,13272,14677,13026,14737,12808,14790,12617,14833,12449,14869,12303,14896,12065,14916,11845,14929,11655,14937,11490,14939,11347,14936,11184,14930,10970,14921,10783,14912,10621,14900,10480,14885,10356,14867,10247,14848,10062,14827,9894,14805,9745,14400,14208,14400,14206,14402,14198,14406,14174,14415,14122,14427,14035,14444,13913,14469,13767,14504,13613,14548,13463,14598,13324,14651,13082,14704,12858,14752,12658,14795,12483,14831,12330,14860,12106,14881,11875,14895,11675,14903,11501,14905,11351,14903,11178,14900,10953,14892,10757,14880,10589,14865,10442,14847,10313,14827,10162,14805,9965,14782,9792,14757,9642,14731,9507,14562,13883,14562,13883,14563,13877,14566,13862,14570,13830,14576,13773,14584,13689,14595,13582,14613,13461,14637,13336,14668,13120,14704,12897,14741,12695,14776,12516,14808,12358,14835,12150,14856,11910,14870,11701,14878,11519,14882,11361,14884,11187,14880,10951,14871,10748,14858,10572,14842,10418,14823,10286,14801,10099,14777,9897,14751,9722,14725,9567,14696,9430,14666,9309,14702,13604,14702,13604,14702,13600,14703,13591,14705,13570,14707,13533,14709,13477,14712,13400,14718,13305,14727,13106,14743,12907,14762,12716,14784,12539,14807,12380,14827,12190,14844,11943,14855,11727,14863,11539,14870,11376,14871,11204,14868,10960,14858,10748,14845,10565,14829,10406,14809,10269,14786,10058,14761,9852,14734,9671,14705,9512,14674,9374,14641,9253,14608,9076,14821,13366,14821,13365,14821,13364,14821,13358,14821,13344,14821,13320,14819,13252,14817,13145,14815,13011,14814,12858,14817,12698,14823,12539,14832,12389,14841,12214,14850,11968,14856,11750,14861,11558,14866,11390,14867,11226,14862,10972,14853,10754,14840,10565,14823,10401,14803,10259,14780,10032,14754,9820,14725,9635,14694,9473,14661,9333,14627,9203,14593,8988,14557,8798,14923,13014,14922,13014,14922,13012,14922,13004,14920,12987,14919,12957,14915,12907,14909,12834,14902,12738,14894,12623,14888,12498,14883,12370,14880,12203,14878,11970,14875,11759,14873,11569,14874,11401,14872,11243,14865,10986,14855,10762,14842,10568,14825,10401,14804,10255,14781,10017,14754,9799,14725,9611,14692,9445,14658,9301,14623,9139,14587,8920,14548,8729,14509,8562,15008,12672,15008,12672,15008,12671,15007,12667,15005,12656,15001,12637,14997,12605,14989,12556,14978,12490,14966,12407,14953,12313,14940,12136,14927,11934,14914,11742,14903,11563,14896,11401,14889,11247,14879,10992,14866,10767,14851,10570,14833,10400,14812,10252,14789,10007,14761,9784,14731,9592,14698,9424,14663,9279,14627,9088,14588,8868,14548,8676,14508,8508,14467,8360,15080,12386,15080,12386,15079,12385,15078,12383,15076,12378,15072,12367,15066,12347,15057,12315,15045,12253,15030,12138,15012,11998,14993,11845,14972,11685,14951,11530,14935,11383,14920,11228,14904,10981,14887,10762,14870,10567,14850,10397,14827,10248,14803,9997,14774,9771,14743,9578,14710,9407,14674,9259,14637,9048,14596,8826,14555,8632,14514,8464,14471,8317,14427,8182,15139,12008,15139,12008,15138,12008,15137,12007,15135,12003,15130,11990,15124,11969,15115,11929,15102,11872,15086,11794,15064,11693,15041,11581,15013,11459,14987,11336,14966,11170,14944,10944,14921,10738,14898,10552,14875,10387,14850,10239,14824,9983,14794,9758,14762,9563,14728,9392,14692,9244,14653,9014,14611,8791,14569,8597,14526,8427,14481,8281,14436,8110,14391,7885,15188,11617,15188,11617,15187,11617,15186,11618,15183,11617,15179,11612,15173,11601,15163,11581,15150,11546,15133,11495,15110,11427,15083,11346,15051,11246,15024,11057,14996,10868,14967,10687,14938,10517,14911,10362,14882,10206,14853,9956,14821,9737,14787,9543,14752,9375,14715,9228,14675,8980,14632,8760,14589,8565,14544,8395,14498,8248,14451,8049,14404,7824,14357,7630,15228,11298,15228,11298,15227,11299,15226,11301,15223,11303,15219,11302,15213,11299,15204,11290,15191,11271,15174,11217,15150,11129,15119,11015,15087,10886,15057,10744,15024,10599,14990,10455,14957,10318,14924,10143,14891,9911,14856,9701,14820,9516,14782,9352,14744,9200,14703,8946,14659,8725,14615,8533,14568,8366,14521,8220,14472,7992,14423,7770,14374,7578,14315,7408,15260,10819,15260,10819,15259,10822,15258,10826,15256,10832,15251,10836,15246,10841,15237,10838,15225,10821,15207,10788,15183,10734,15151,10660,15120,10571,15087,10469,15049,10359,15012,10249,14974,10041,14937,9837,14900,9647,14860,9475,14820,9320,14779,9147,14736,8902,14691,8688,14646,8499,14598,8335,14549,8189,14499,7940,14448,7720,14397,7529,14347,7363,14256,7218,15285,10410,15285,10411,15285,10413,15284,10418,15282,10425,15278,10434,15272,10442,15264,10449,15252,10445,15235,10433,15210,10403,15179,10358,15149,10301,15113,10218,15073,10059,15033,9894,14991,9726,14951,9565,14909,9413,14865,9273,14822,9073,14777,8845,14730,8641,14682,8459,14633,8300,14583,8129,14531,7883,14479,7670,14426,7482,14373,7321,14305,7176,14201,6939,15305,9939,15305,9940,15305,9945,15304,9955,15302,9967,15298,9989,15293,10010,15286,10033,15274,10044,15258,10045,15233,10022,15205,9975,15174,9903,15136,9808,15095,9697,15053,9578,15009,9451,14965,9327,14918,9198,14871,8973,14825,8766,14775,8579,14725,8408,14675,8259,14622,8058,14569,7821,14515,7615,14460,7435,14405,7276,14350,7108,14256,6866,14149,6653,15321,9444,15321,9445,15321,9448,15320,9458,15317,9470,15314,9490,15310,9515,15302,9540,15292,9562,15276,9579,15251,9577,15226,9559,15195,9519,15156,9463,15116,9389,15071,9304,15025,9208,14978,9023,14927,8838,14878,8661,14827,8496,14774,8344,14722,8206,14667,7973,14612,7749,14556,7555,14499,7382,14443,7229,14385,7025,14322,6791,14210,6588,14100,6409,15333,8920,15333,8921,15332,8927,15332,8943,15329,8965,15326,9002,15322,9048,15316,9106,15307,9162,15291,9204,15267,9221,15244,9221,15212,9196,15175,9134,15133,9043,15088,8930,15040,8801,14990,8665,14938,8526,14886,8391,14830,8261,14775,8087,14719,7866,14661,7664,14603,7482,14544,7322,14485,7178,14426,6936,14367,6713,14281,6517,14166,6348,14054,6198,15341,8360,15341,8361,15341,8366,15341,8379,15339,8399,15336,8431,15332,8473,15326,8527,15318,8585,15302,8632,15281,8670,15258,8690,15227,8690,15191,8664,15149,8612,15104,8543,15055,8456,15001,8360,14948,8259,14892,8122,14834,7923,14776,7734,14716,7558,14656,7397,14595,7250,14534,7070,14472,6835,14410,6628,14350,6443,14243,6283,14125,6135,14010,5889,15348,7715,15348,7717,15348,7725,15347,7745,15345,7780,15343,7836,15339,7905,15334,8e3,15326,8103,15310,8193,15293,8239,15270,8270,15240,8287,15204,8283,15163,8260,15118,8223,15067,8143,15014,8014,14958,7873,14899,7723,14839,7573,14778,7430,14715,7293,14652,7164,14588,6931,14524,6720,14460,6531,14396,6362,14330,6210,14207,6015,14086,5781,13969,5576,15352,7114,15352,7116,15352,7128,15352,7159,15350,7195,15348,7237,15345,7299,15340,7374,15332,7457,15317,7544,15301,7633,15280,7703,15251,7754,15216,7775,15176,7767,15131,7733,15079,7670,15026,7588,14967,7492,14906,7387,14844,7278,14779,7171,14714,6965,14648,6770,14581,6587,14515,6420,14448,6269,14382,6123,14299,5881,14172,5665,14049,5477,13929,5310,15355,6329,15355,6330,15355,6339,15355,6362,15353,6410,15351,6472,15349,6572,15344,6688,15337,6835,15323,6985,15309,7142,15287,7220,15260,7277,15226,7310,15188,7326,15142,7318,15090,7285,15036,7239,14976,7177,14914,7045,14849,6892,14782,6736,14714,6581,14645,6433,14576,6293,14506,6164,14438,5946,14369,5733,14270,5540,14140,5369,14014,5216,13892,5043,15357,5483,15357,5484,15357,5496,15357,5528,15356,5597,15354,5692,15351,5835,15347,6011,15339,6195,15328,6317,15314,6446,15293,6566,15268,6668,15235,6746,15197,6796,15152,6811,15101,6790,15046,6748,14985,6673,14921,6583,14854,6479,14785,6371,14714,6259,14643,6149,14571,5946,14499,5750,14428,5567,14358,5401,14242,5250,14109,5111,13980,4870,13856,4657,15359,4555,15359,4557,15358,4573,15358,4633,15357,4715,15355,4841,15353,5061,15349,5216,15342,5391,15331,5577,15318,5770,15299,5967,15274,6150,15243,6223,15206,6280,15161,6310,15111,6317,15055,6300,14994,6262,14928,6208,14860,6141,14788,5994,14715,5838,14641,5684,14566,5529,14492,5384,14418,5247,14346,5121,14216,4892,14079,4682,13948,4496,13822,4330,15359,3498,15359,3501,15359,3520,15359,3598,15358,3719,15356,3860,15355,4137,15351,4305,15344,4563,15334,4809,15321,5116,15303,5273,15280,5418,15250,5547,15214,5653,15170,5722,15120,5761,15064,5763,15002,5733,14935,5673,14865,5597,14792,5504,14716,5400,14640,5294,14563,5185,14486,5041,14410,4841,14335,4655,14191,4482,14051,4325,13918,4183,13790,4012,15360,2282,15360,2285,15360,2306,15360,2401,15359,2547,15357,2748,15355,3103,15352,3349,15345,3675,15336,4020,15324,4272,15307,4496,15285,4716,15255,4908,15220,5086,15178,5170,15128,5214,15072,5234,15010,5231,14943,5206,14871,5166,14796,5102,14718,4971,14639,4833,14559,4687,14480,4541,14402,4401,14315,4268,14167,4142,14025,3958,13888,3747,13759,3556,15360,923,15360,925,15360,946,15360,1052,15359,1214,15357,1494,15356,1892,15352,2274,15346,2663,15338,3099,15326,3393,15309,3679,15288,3980,15260,4183,15226,4325,15185,4437,15136,4517,15080,4570,15018,4591,14950,4581,14877,4545,14800,4485,14720,4411,14638,4325,14556,4231,14475,4136,14395,3988,14297,3803,14145,3628,13999,3465,13861,3314,13729,3177,15360,263,15360,264,15360,272,15360,325,15359,407,15358,548,15356,780,15352,1144,15347,1580,15339,2099,15328,2425,15312,2795,15292,3133,15264,3329,15232,3517,15191,3689,15143,3819,15088,3923,15025,3978,14956,3999,14882,3979,14804,3931,14722,3855,14639,3756,14554,3645,14470,3529,14388,3409,14279,3289,14124,3173,13975,3055,13834,2848,13701,2658,15360,49,15360,49,15360,52,15360,75,15359,111,15358,201,15356,283,15353,519,15348,726,15340,1045,15329,1415,15314,1795,15295,2173,15269,2410,15237,2649,15197,2866,15150,3054,15095,3140,15032,3196,14963,3228,14888,3236,14808,3224,14725,3191,14639,3146,14553,3088,14466,2976,14382,2836,14262,2692,14103,2549,13952,2409,13808,2278,13674,2154,15360,4,15360,4,15360,4,15360,13,15359,33,15358,59,15357,112,15353,199,15348,302,15341,456,15331,628,15316,827,15297,1082,15272,1332,15241,1601,15202,1851,15156,2069,15101,2172,15039,2256,14970,2314,14894,2348,14813,2358,14728,2344,14640,2311,14551,2263,14463,2203,14376,2133,14247,2059,14084,1915,13930,1761,13784,1609,13648,1464,15360,0,15360,0,15360,0,15360,3,15359,18,15358,26,15357,53,15354,80,15348,97,15341,165,15332,238,15318,326,15299,427,15275,529,15245,654,15207,771,15161,885,15108,994,15046,1089,14976,1170,14900,1229,14817,1266,14731,1284,14641,1282,14550,1260,14460,1223,14370,1174,14232,1116,14066,1050,13909,981,13761,910,13623,839]);let gn=null;function xm(){return gn===null&&(gn=new Hc(mm,32,32,ka,Di),gn.minFilter=Ye,gn.magFilter=Ye,gn.wrapS=Sn,gn.wrapT=Sn,gn.generateMipmaps=!1,gn.needsUpdate=!0),gn}class gm{constructor(t={}){const{canvas:e=sh(),context:n=null,depth:s=!0,stencil:r=!1,alpha:a=!1,antialias:o=!1,premultipliedAlpha:l=!0,preserveDrawingBuffer:c=!1,powerPreference:h="default",failIfMajorPerformanceCaveat:u=!1,reversedDepthBuffer:d=!1}=t;this.isWebGLRenderer=!0;let p;if(n!==null){if(typeof WebGLRenderingContext<"u"&&n instanceof WebGLRenderingContext)throw new Error("THREE.WebGLRenderer: WebGL 1 is not supported since r163.");p=n.getContextAttributes().alpha}else p=a;const x=new Set([Wa,Ha,Ga]),_=new Set([hn,jn,Qi,ts,Ba,za]),m=new Uint32Array(4),f=new Int32Array(4);let b=null,S=null;const T=[],R=[];this.domElement=e,this.debug={checkShaderErrors:!0,onShaderError:null},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this.toneMapping=Un,this.toneMappingExposure=1,this.transmissionResolutionScale=1;const w=this;let L=!1;this._outputColorSpace=De;let F=0,E=0,M=null,P=-1,O=null;const z=new se,k=new se;let W=null;const Y=new Yt(0);let nt=0,X=e.width,rt=e.height,st=1,St=null,Gt=null;const qt=new se(0,0,X,rt),jt=new se(0,0,X,rt);let Kt=!1;const K=new Za;let J=!1,xt=!1;const Rt=new re,Tt=new D,kt=new se,Qt={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0};let Ct=!1;function B(){return M===null?st:1}let y=n;function Z(v,I){return e.getContext(v,I)}try{const v={alpha:!0,depth:s,stencil:r,antialias:o,premultipliedAlpha:l,preserveDrawingBuffer:c,powerPreference:h,failIfMajorPerformanceCaveat:u};if("setAttribute"in e&&e.setAttribute("data-engine",`three.js r${Na}`),e.addEventListener("webglcontextlost",it,!1),e.addEventListener("webglcontextrestored",j,!1),e.addEventListener("webglcontextcreationerror",bt,!1),y===null){const I="webgl2";if(y=Z(I,v),y===null)throw Z(I)?new Error("Error creating WebGL context with your selected attributes."):new Error("Error creating WebGL context.")}}catch(v){throw v("WebGLRenderer: "+v.message),v}let Q,ot,et,vt,ft,Mt,A,g,N,q,$,H,wt,dt,Pt,At,tt,lt,Nt,It,_t,Ot,C,mt;function ht(){Q=new Tp(y),Q.init(),Ot=new om(y,Q),ot=new xp(y,Q,t,Ot),et=new rm(y,Q),ot.reversedDepthBuffer&&d&&et.buffers.depth.setReversed(!0),vt=new Rp(y),ft=new q0,Mt=new am(y,Q,et,ft,ot,Ot,vt),A=new _p(w),g=new Ep(w),N=new Du(y),C=new pp(y,N),q=new Ap(y,N,vt,C),$=new Pp(y,q,N,vt),Nt=new Cp(y,ot,Mt),At=new gp(ft),H=new X0(w,A,g,Q,ot,C,At),wt=new dm(w,ft),dt=new Z0,Pt=new tm(Q),lt=new dp(w,A,g,et,$,p,l),tt=new im(w,$,ot),mt=new pm(y,vt,ot,et),It=new mp(y,Q,vt),_t=new wp(y,Q,vt),vt.programs=H.programs,w.capabilities=ot,w.extensions=Q,w.properties=ft,w.renderLists=dt,w.shadowMap=tt,w.state=et,w.info=vt}ht();const ut=new um(w,y);this.xr=ut,this.getContext=function(){return y},this.getContextAttributes=function(){return y.getContextAttributes()},this.forceContextLoss=function(){const v=Q.get("WEBGL_lose_context");v&&v.loseContext()},this.forceContextRestore=function(){const v=Q.get("WEBGL_lose_context");v&&v.restoreContext()},this.getPixelRatio=function(){return st},this.setPixelRatio=function(v){v!==void 0&&(st=v,this.setSize(X,rt,!1))},this.getSize=function(v){return v.set(X,rt)},this.setSize=function(v,I,V=!0){if(ut.isPresenting){Bt("WebGLRenderer: Can't change size while VR device is presenting.");return}X=v,rt=I,e.width=Math.floor(v*st),e.height=Math.floor(I*st),V===!0&&(e.style.width=v+"px",e.style.height=I+"px"),this.setViewport(0,0,v,I)},this.getDrawingBufferSize=function(v){return v.set(X*st,rt*st).floor()},this.setDrawingBufferSize=function(v,I,V){X=v,rt=I,st=V,e.width=Math.floor(v*V),e.height=Math.floor(I*V),this.setViewport(0,0,v,I)},this.getCurrentViewport=function(v){return v.copy(z)},this.getViewport=function(v){return v.copy(qt)},this.setViewport=function(v,I,V,G){v.isVector4?qt.set(v.x,v.y,v.z,v.w):qt.set(v,I,V,G),et.viewport(z.copy(qt).multiplyScalar(st).round())},this.getScissor=function(v){return v.copy(jt)},this.setScissor=function(v,I,V,G){v.isVector4?jt.set(v.x,v.y,v.z,v.w):jt.set(v,I,V,G),et.scissor(k.copy(jt).multiplyScalar(st).round())},this.getScissorTest=function(){return Kt},this.setScissorTest=function(v){et.setScissorTest(Kt=v)},this.setOpaqueSort=function(v){St=v},this.setTransparentSort=function(v){Gt=v},this.getClearColor=function(v){return v.copy(lt.getClearColor())},this.setClearColor=function(){lt.setClearColor(...arguments)},this.getClearAlpha=function(){return lt.getClearAlpha()},this.setClearAlpha=function(){lt.setClearAlpha(...arguments)},this.clear=function(v=!0,I=!0,V=!0){let G=0;if(v){let U=!1;if(M!==null){const ct=M.texture.format;U=x.has(ct)}if(U){const ct=M.texture.type,gt=_.has(ct),Et=lt.getClearColor(),yt=lt.getClearAlpha(),Ut=Et.r,Ft=Et.g,Dt=Et.b;gt?(m[0]=Ut,m[1]=Ft,m[2]=Dt,m[3]=yt,y.clearBufferuiv(y.COLOR,0,m)):(f[0]=Ut,f[1]=Ft,f[2]=Dt,f[3]=yt,y.clearBufferiv(y.COLOR,0,f))}else G|=y.COLOR_BUFFER_BIT}I&&(G|=y.DEPTH_BUFFER_BIT),V&&(G|=y.STENCIL_BUFFER_BIT,this.state.buffers.stencil.setMask(4294967295)),y.clear(G)},this.clearColor=function(){this.clear(!0,!1,!1)},this.clearDepth=function(){this.clear(!1,!0,!1)},this.clearStencil=function(){this.clear(!1,!1,!0)},this.dispose=function(){e.removeEventListener("webglcontextlost",it,!1),e.removeEventListener("webglcontextrestored",j,!1),e.removeEventListener("webglcontextcreationerror",bt,!1),lt.dispose(),dt.dispose(),Pt.dispose(),ft.dispose(),A.dispose(),g.dispose(),$.dispose(),C.dispose(),mt.dispose(),H.dispose(),ut.dispose(),ut.removeEventListener("sessionstart",to),ut.removeEventListener("sessionend",eo),Bn.stop()};function it(v){v.preventDefault(),go("WebGLRenderer: Context Lost."),L=!0}function j(){go("WebGLRenderer: Context Restored."),L=!1;const v=vt.autoReset,I=tt.enabled,V=tt.autoUpdate,G=tt.needsUpdate,U=tt.type;ht(),vt.autoReset=v,tt.enabled=I,tt.autoUpdate=V,tt.needsUpdate=G,tt.type=U}function bt(v){de("WebGLRenderer: A WebGL context could not be created. Reason: ",v.statusMessage)}function zt(v){const I=v.target;I.removeEventListener("dispose",zt),ce(I)}function ce(v){te(v),ft.remove(v)}function te(v){const I=ft.get(v).programs;I!==void 0&&(I.forEach(function(V){H.releaseProgram(V)}),v.isShaderMaterial&&H.releaseShaderCache(v))}this.renderBufferDirect=function(v,I,V,G,U,ct){I===null&&(I=Qt);const gt=U.isMesh&&U.matrixWorld.determinant()<0,Et=ul(v,I,V,G,U);et.setMaterial(G,gt);let yt=V.index,Ut=1;if(G.wireframe===!0){if(yt=q.getWireframeAttribute(V),yt===void 0)return;Ut=2}const Ft=V.drawRange,Dt=V.attributes.position;let Zt=Ft.start*Ut,ee=(Ft.start+Ft.count)*Ut;ct!==null&&(Zt=Math.max(Zt,ct.start*Ut),ee=Math.min(ee,(ct.start+ct.count)*Ut)),yt!==null?(Zt=Math.max(Zt,0),ee=Math.min(ee,yt.count)):Dt!=null&&(Zt=Math.max(Zt,0),ee=Math.min(ee,Dt.count));const me=ee-Zt;if(me<0||me===1/0)return;C.setup(U,G,Et,V,yt);let xe,ae=It;if(yt!==null&&(xe=N.get(yt),ae=_t,ae.setIndex(xe)),U.isMesh)G.wireframe===!0?(et.setLineWidth(G.wireframeLinewidth*B()),ae.setMode(y.LINES)):ae.setMode(y.TRIANGLES);else if(U.isLine){let Lt=G.linewidth;Lt===void 0&&(Lt=1),et.setLineWidth(Lt*B()),U.isLineSegments?ae.setMode(y.LINES):U.isLineLoop?ae.setMode(y.LINE_LOOP):ae.setMode(y.LINE_STRIP)}else U.isPoints?ae.setMode(y.POINTS):U.isSprite&&ae.setMode(y.TRIANGLES);if(U.isBatchedMesh)if(U._multiDrawInstances!==null)is("WebGLRenderer: renderMultiDrawInstances has been deprecated and will be removed in r184. Append to renderMultiDraw arguments and use indirection."),ae.renderMultiDrawInstances(U._multiDrawStarts,U._multiDrawCounts,U._multiDrawCount,U._multiDrawInstances);else if(Q.get("WEBGL_multi_draw"))ae.renderMultiDraw(U._multiDrawStarts,U._multiDrawCounts,U._multiDrawCount);else{const Lt=U._multiDrawStarts,ue=U._multiDrawCounts,Jt=U._multiDrawCount,Be=yt?N.get(yt).bytesPerElement:1,ni=ft.get(G).currentProgram.getUniforms();for(let ze=0;ze{function ct(){if(G.forEach(function(gt){ft.get(gt).currentProgram.isReady()&&G.delete(gt)}),G.size===0){U(v);return}setTimeout(ct,10)}Q.get("KHR_parallel_shader_compile")!==null?ct():setTimeout(ct,10)})};let Ze=null;function hl(v){Ze&&Ze(v)}function to(){Bn.stop()}function eo(){Bn.start()}const Bn=new il;Bn.setAnimationLoop(hl),typeof self<"u"&&Bn.setContext(self),this.setAnimationLoop=function(v){Ze=v,ut.setAnimationLoop(v),v===null?Bn.stop():Bn.start()},ut.addEventListener("sessionstart",to),ut.addEventListener("sessionend",eo),this.render=function(v,I){if(I!==void 0&&I.isCamera!==!0){de("WebGLRenderer.render: camera is not an instance of THREE.Camera.");return}if(L===!0)return;if(v.matrixWorldAutoUpdate===!0&&v.updateMatrixWorld(),I.parent===null&&I.matrixWorldAutoUpdate===!0&&I.updateMatrixWorld(),ut.enabled===!0&&ut.isPresenting===!0&&(ut.cameraAutoUpdate===!0&&ut.updateCamera(I),I=ut.getCamera()),v.isScene===!0&&v.onBeforeRender(w,v,I,M),S=Pt.get(v,R.length),S.init(I),R.push(S),Rt.multiplyMatrices(I.projectionMatrix,I.matrixWorldInverse),K.setFromProjectionMatrix(Rt,cn,I.reversedDepth),xt=this.localClippingEnabled,J=At.init(this.clippingPlanes,xt),b=dt.get(v,T.length),b.init(),T.push(b),ut.enabled===!0&&ut.isPresenting===!0){const ct=w.xr.getDepthSensingMesh();ct!==null&&er(ct,I,-1/0,w.sortObjects)}er(v,I,0,w.sortObjects),b.finish(),w.sortObjects===!0&&b.sort(St,Gt),Ct=ut.enabled===!1||ut.isPresenting===!1||ut.hasDepthSensing()===!1,Ct&<.addToRenderList(b,v),this.info.render.frame++,J===!0&&At.beginShadows();const V=S.state.shadowsArray;tt.render(V,v,I),J===!0&&At.endShadows(),this.info.autoReset===!0&&this.info.reset();const G=b.opaque,U=b.transmissive;if(S.setupLights(),I.isArrayCamera){const ct=I.cameras;if(U.length>0)for(let gt=0,Et=ct.length;gt0&&io(G,U,v,I),Ct&<.render(v),no(b,v,I);M!==null&&E===0&&(Mt.updateMultisampleRenderTarget(M),Mt.updateRenderTargetMipmap(M)),v.isScene===!0&&v.onAfterRender(w,v,I),C.resetDefaultState(),P=-1,O=null,R.pop(),R.length>0?(S=R[R.length-1],J===!0&&At.setGlobalState(w.clippingPlanes,S.state.camera)):S=null,T.pop(),T.length>0?b=T[T.length-1]:b=null};function er(v,I,V,G){if(v.visible===!1)return;if(v.layers.test(I.layers)){if(v.isGroup)V=v.renderOrder;else if(v.isLOD)v.autoUpdate===!0&&v.update(I);else if(v.isLight)S.pushLight(v),v.castShadow&&S.pushShadow(v);else if(v.isSprite){if(!v.frustumCulled||K.intersectsSprite(v)){G&&kt.setFromMatrixPosition(v.matrixWorld).applyMatrix4(Rt);const gt=$.update(v),Et=v.material;Et.visible&&b.push(v,gt,Et,V,kt.z,null)}}else if((v.isMesh||v.isLine||v.isPoints)&&(!v.frustumCulled||K.intersectsObject(v))){const gt=$.update(v),Et=v.material;if(G&&(v.boundingSphere!==void 0?(v.boundingSphere===null&&v.computeBoundingSphere(),kt.copy(v.boundingSphere.center)):(gt.boundingSphere===null&>.computeBoundingSphere(),kt.copy(gt.boundingSphere.center)),kt.applyMatrix4(v.matrixWorld).applyMatrix4(Rt)),Array.isArray(Et)){const yt=gt.groups;for(let Ut=0,Ft=yt.length;Ut0&&ls(U,I,V),ct.length>0&&ls(ct,I,V),gt.length>0&&ls(gt,I,V),et.buffers.depth.setTest(!0),et.buffers.depth.setMask(!0),et.buffers.color.setMask(!0),et.setPolygonOffset(!1)}function io(v,I,V,G){if((V.isScene===!0?V.overrideMaterial:null)!==null)return;S.state.transmissionRenderTarget[G.id]===void 0&&(S.state.transmissionRenderTarget[G.id]=new $n(1,1,{generateMipmaps:!0,type:Q.has("EXT_color_buffer_half_float")||Q.has("EXT_color_buffer_float")?Di:hn,minFilter:Kn,samples:4,stencilBuffer:r,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:$t.workingColorSpace}));const ct=S.state.transmissionRenderTarget[G.id],gt=G.viewport||z;ct.setSize(gt.z*w.transmissionResolutionScale,gt.w*w.transmissionResolutionScale);const Et=w.getRenderTarget(),yt=w.getActiveCubeFace(),Ut=w.getActiveMipmapLevel();w.setRenderTarget(ct),w.getClearColor(Y),nt=w.getClearAlpha(),nt<1&&w.setClearColor(16777215,.5),w.clear(),Ct&<.render(V);const Ft=w.toneMapping;w.toneMapping=Un;const Dt=G.viewport;if(G.viewport!==void 0&&(G.viewport=void 0),S.setupLightsView(G),J===!0&&At.setGlobalState(w.clippingPlanes,G),ls(v,V,G),Mt.updateMultisampleRenderTarget(ct),Mt.updateRenderTargetMipmap(ct),Q.has("WEBGL_multisampled_render_to_texture")===!1){let Zt=!1;for(let ee=0,me=I.length;ee0),Dt=!!V.morphAttributes.position,Zt=!!V.morphAttributes.normal,ee=!!V.morphAttributes.color;let me=Un;G.toneMapped&&(M===null||M.isXRRenderTarget===!0)&&(me=w.toneMapping);const xe=V.morphAttributes.position||V.morphAttributes.normal||V.morphAttributes.color,ae=xe!==void 0?xe.length:0,Lt=ft.get(G),ue=S.state.lights;if(J===!0&&(xt===!0||v!==O)){const Ce=v===O&&G.id===P;At.setState(G,v,Ce)}let Jt=!1;G.version===Lt.__version?(Lt.needsLights&&Lt.lightsStateVersion!==ue.state.version||Lt.outputColorSpace!==Et||U.isBatchedMesh&&Lt.batching===!1||!U.isBatchedMesh&&Lt.batching===!0||U.isBatchedMesh&&Lt.batchingColor===!0&&U.colorTexture===null||U.isBatchedMesh&&Lt.batchingColor===!1&&U.colorTexture!==null||U.isInstancedMesh&&Lt.instancing===!1||!U.isInstancedMesh&&Lt.instancing===!0||U.isSkinnedMesh&&Lt.skinning===!1||!U.isSkinnedMesh&&Lt.skinning===!0||U.isInstancedMesh&&Lt.instancingColor===!0&&U.instanceColor===null||U.isInstancedMesh&&Lt.instancingColor===!1&&U.instanceColor!==null||U.isInstancedMesh&&Lt.instancingMorph===!0&&U.morphTexture===null||U.isInstancedMesh&&Lt.instancingMorph===!1&&U.morphTexture!==null||Lt.envMap!==yt||G.fog===!0&&Lt.fog!==ct||Lt.numClippingPlanes!==void 0&&(Lt.numClippingPlanes!==At.numPlanes||Lt.numIntersection!==At.numIntersection)||Lt.vertexAlphas!==Ut||Lt.vertexTangents!==Ft||Lt.morphTargets!==Dt||Lt.morphNormals!==Zt||Lt.morphColors!==ee||Lt.toneMapping!==me||Lt.morphTargetsCount!==ae)&&(Jt=!0):(Jt=!0,Lt.__version=G.version);let Be=Lt.currentProgram;Jt===!0&&(Be=hs(G,I,U));let ni=!1,ze=!1,Ni=!1;const fe=Be.getUniforms(),Ue=Lt.uniforms;if(et.useProgram(Be.program)&&(ni=!0,ze=!0,Ni=!0),G.id!==P&&(P=G.id,ze=!0),ni||O!==v){et.buffers.depth.getReversed()&&v.reversedDepth!==!0&&(v._reversedDepth=!0,v.updateProjectionMatrix()),fe.setValue(y,"projectionMatrix",v.projectionMatrix),fe.setValue(y,"viewMatrix",v.matrixWorldInverse);const Ne=fe.map.cameraPosition;Ne!==void 0&&Ne.setValue(y,Tt.setFromMatrixPosition(v.matrixWorld)),ot.logarithmicDepthBuffer&&fe.setValue(y,"logDepthBufFC",2/(Math.log(v.far+1)/Math.LN2)),(G.isMeshPhongMaterial||G.isMeshToonMaterial||G.isMeshLambertMaterial||G.isMeshBasicMaterial||G.isMeshStandardMaterial||G.isShaderMaterial)&&fe.setValue(y,"isOrthographic",v.isOrthographicCamera===!0),O!==v&&(O=v,ze=!0,Ni=!0)}if(U.isSkinnedMesh){fe.setOptional(y,U,"bindMatrix"),fe.setOptional(y,U,"bindMatrixInverse");const Ce=U.skeleton;Ce&&(Ce.boneTexture===null&&Ce.computeBoneTexture(),fe.setValue(y,"boneTexture",Ce.boneTexture,Mt))}U.isBatchedMesh&&(fe.setOptional(y,U,"batchingTexture"),fe.setValue(y,"batchingTexture",U._matricesTexture,Mt),fe.setOptional(y,U,"batchingIdTexture"),fe.setValue(y,"batchingIdTexture",U._indirectTexture,Mt),fe.setOptional(y,U,"batchingColorTexture"),U._colorsTexture!==null&&fe.setValue(y,"batchingColorTexture",U._colorsTexture,Mt));const We=V.morphAttributes;if((We.position!==void 0||We.normal!==void 0||We.color!==void 0)&&Nt.update(U,V,Be),(ze||Lt.receiveShadow!==U.receiveShadow)&&(Lt.receiveShadow=U.receiveShadow,fe.setValue(y,"receiveShadow",U.receiveShadow)),G.isMeshGouraudMaterial&&G.envMap!==null&&(Ue.envMap.value=yt,Ue.flipEnvMap.value=yt.isCubeTexture&&yt.isRenderTargetTexture===!1?-1:1),G.isMeshStandardMaterial&&G.envMap===null&&I.environment!==null&&(Ue.envMapIntensity.value=I.environmentIntensity),Ue.dfgLUT!==void 0&&(Ue.dfgLUT.value=xm()),ze&&(fe.setValue(y,"toneMappingExposure",w.toneMappingExposure),Lt.needsLights&&fl(Ue,Ni),ct&&G.fog===!0&&wt.refreshFogUniforms(Ue,ct),wt.refreshMaterialUniforms(Ue,G,st,rt,S.state.transmissionRenderTarget[v.id]),Hs.upload(y,ro(Lt),Ue,Mt)),G.isShaderMaterial&&G.uniformsNeedUpdate===!0&&(Hs.upload(y,ro(Lt),Ue,Mt),G.uniformsNeedUpdate=!1),G.isSpriteMaterial&&fe.setValue(y,"center",U.center),fe.setValue(y,"modelViewMatrix",U.modelViewMatrix),fe.setValue(y,"normalMatrix",U.normalMatrix),fe.setValue(y,"modelMatrix",U.matrixWorld),G.isShaderMaterial||G.isRawShaderMaterial){const Ce=G.uniformsGroups;for(let Ne=0,nr=Ce.length;Ne0&&Mt.useMultisampledRTT(v)===!1?U=ft.get(v).__webglMultisampledFramebuffer:Array.isArray(Ft)?U=Ft[V]:U=Ft,z.copy(v.viewport),k.copy(v.scissor),W=v.scissorTest}else z.copy(qt).multiplyScalar(st).floor(),k.copy(jt).multiplyScalar(st).floor(),W=Kt;if(V!==0&&(U=pl),et.bindFramebuffer(y.FRAMEBUFFER,U)&&G&&et.drawBuffers(v,U),et.viewport(z),et.scissor(k),et.setScissorTest(W),ct){const yt=ft.get(v.texture);y.framebufferTexture2D(y.FRAMEBUFFER,y.COLOR_ATTACHMENT0,y.TEXTURE_CUBE_MAP_POSITIVE_X+I,yt.__webglTexture,V)}else if(gt){const yt=I;for(let Ut=0;Ut=0&&I<=v.width-G&&V>=0&&V<=v.height-U&&(v.textures.length>1&&y.readBuffer(y.COLOR_ATTACHMENT0+Et),y.readPixels(I,V,G,U,Ot.convert(Ft),Ot.convert(Dt),ct))}finally{const Ut=M!==null?ft.get(M).__webglFramebuffer:null;et.bindFramebuffer(y.FRAMEBUFFER,Ut)}}},this.readRenderTargetPixelsAsync=async function(v,I,V,G,U,ct,gt,Et=0){if(!(v&&v.isWebGLRenderTarget))throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let yt=ft.get(v).__webglFramebuffer;if(v.isWebGLCubeRenderTarget&>!==void 0&&(yt=yt[gt]),yt)if(I>=0&&I<=v.width-G&&V>=0&&V<=v.height-U){et.bindFramebuffer(y.FRAMEBUFFER,yt);const Ut=v.textures[Et],Ft=Ut.format,Dt=Ut.type;if(!ot.textureFormatReadable(Ft))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!ot.textureTypeReadable(Dt))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");const Zt=y.createBuffer();y.bindBuffer(y.PIXEL_PACK_BUFFER,Zt),y.bufferData(y.PIXEL_PACK_BUFFER,ct.byteLength,y.STREAM_READ),v.textures.length>1&&y.readBuffer(y.COLOR_ATTACHMENT0+Et),y.readPixels(I,V,G,U,Ot.convert(Ft),Ot.convert(Dt),0);const ee=M!==null?ft.get(M).__webglFramebuffer:null;et.bindFramebuffer(y.FRAMEBUFFER,ee);const me=y.fenceSync(y.SYNC_GPU_COMMANDS_COMPLETE,0);return y.flush(),await rh(y,me,4),y.bindBuffer(y.PIXEL_PACK_BUFFER,Zt),y.getBufferSubData(y.PIXEL_PACK_BUFFER,0,ct),y.deleteBuffer(Zt),y.deleteSync(me),ct}else throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.")},this.copyFramebufferToTexture=function(v,I=null,V=0){const G=Math.pow(2,-V),U=Math.floor(v.image.width*G),ct=Math.floor(v.image.height*G),gt=I!==null?I.x:0,Et=I!==null?I.y:0;Mt.setTexture2D(v,0),y.copyTexSubImage2D(y.TEXTURE_2D,V,0,0,gt,Et,U,ct),et.unbindTexture()};const ml=y.createFramebuffer(),xl=y.createFramebuffer();this.copyTextureToTexture=function(v,I,V=null,G=null,U=0,ct=null){ct===null&&(U!==0?(is("WebGLRenderer: copyTextureToTexture function signature has changed to support src and dst mipmap levels."),ct=U,U=0):ct=0);let gt,Et,yt,Ut,Ft,Dt,Zt,ee,me;const xe=v.isCompressedTexture?v.mipmaps[ct]:v.image;if(V!==null)gt=V.max.x-V.min.x,Et=V.max.y-V.min.y,yt=V.isBox3?V.max.z-V.min.z:1,Ut=V.min.x,Ft=V.min.y,Dt=V.isBox3?V.min.z:0;else{const We=Math.pow(2,-U);gt=Math.floor(xe.width*We),Et=Math.floor(xe.height*We),v.isDataArrayTexture?yt=xe.depth:v.isData3DTexture?yt=Math.floor(xe.depth*We):yt=1,Ut=0,Ft=0,Dt=0}G!==null?(Zt=G.x,ee=G.y,me=G.z):(Zt=0,ee=0,me=0);const ae=Ot.convert(I.format),Lt=Ot.convert(I.type);let ue;I.isData3DTexture?(Mt.setTexture3D(I,0),ue=y.TEXTURE_3D):I.isDataArrayTexture||I.isCompressedArrayTexture?(Mt.setTexture2DArray(I,0),ue=y.TEXTURE_2D_ARRAY):(Mt.setTexture2D(I,0),ue=y.TEXTURE_2D),y.pixelStorei(y.UNPACK_FLIP_Y_WEBGL,I.flipY),y.pixelStorei(y.UNPACK_PREMULTIPLY_ALPHA_WEBGL,I.premultiplyAlpha),y.pixelStorei(y.UNPACK_ALIGNMENT,I.unpackAlignment);const Jt=y.getParameter(y.UNPACK_ROW_LENGTH),Be=y.getParameter(y.UNPACK_IMAGE_HEIGHT),ni=y.getParameter(y.UNPACK_SKIP_PIXELS),ze=y.getParameter(y.UNPACK_SKIP_ROWS),Ni=y.getParameter(y.UNPACK_SKIP_IMAGES);y.pixelStorei(y.UNPACK_ROW_LENGTH,xe.width),y.pixelStorei(y.UNPACK_IMAGE_HEIGHT,xe.height),y.pixelStorei(y.UNPACK_SKIP_PIXELS,Ut),y.pixelStorei(y.UNPACK_SKIP_ROWS,Ft),y.pixelStorei(y.UNPACK_SKIP_IMAGES,Dt);const fe=v.isDataArrayTexture||v.isData3DTexture,Ue=I.isDataArrayTexture||I.isData3DTexture;if(v.isDepthTexture){const We=ft.get(v),Ce=ft.get(I),Ne=ft.get(We.__renderTarget),nr=ft.get(Ce.__renderTarget);et.bindFramebuffer(y.READ_FRAMEBUFFER,Ne.__webglFramebuffer),et.bindFramebuffer(y.DRAW_FRAMEBUFFER,nr.__webglFramebuffer);for(let zn=0;znMath.PI&&(n-=Oe),s<-Math.PI?s+=Oe:s>Math.PI&&(s-=Oe),n<=s?this._spherical.theta=Math.max(n,Math.min(s,this._spherical.theta)):this._spherical.theta=this._spherical.theta>(n+s)/2?Math.max(n,this._spherical.theta):Math.min(s,this._spherical.theta)),this._spherical.phi=Math.max(this.minPolarAngle,Math.min(this.maxPolarAngle,this._spherical.phi)),this._spherical.makeSafe(),this.enableDamping===!0?this.target.addScaledVector(this._panOffset,this.dampingFactor):this.target.add(this._panOffset),this.target.sub(this.cursor),this.target.clampLength(this.minTargetRadius,this.maxTargetRadius),this.target.add(this.cursor);let r=!1;if(this.zoomToCursor&&this._performCursorZoom||this.object.isOrthographicCamera)this._spherical.radius=this._clampDistance(this._spherical.radius);else{const a=this._spherical.radius;this._spherical.radius=this._clampDistance(this._spherical.radius*this._scale),r=a!=this._spherical.radius}if(_e.setFromSpherical(this._spherical),_e.applyQuaternion(this._quatInverse),e.copy(this.target).add(_e),this.object.lookAt(this.target),this.enableDamping===!0?(this._sphericalDelta.theta*=1-this.dampingFactor,this._sphericalDelta.phi*=1-this.dampingFactor,this._panOffset.multiplyScalar(1-this.dampingFactor)):(this._sphericalDelta.set(0,0,0),this._panOffset.set(0,0,0)),this.zoomToCursor&&this._performCursorZoom){let a=null;if(this.object.isPerspectiveCamera){const o=_e.length();a=this._clampDistance(o*this._scale);const l=o-a;this.object.position.addScaledVector(this._dollyDirection,l),this.object.updateMatrixWorld(),r=!!l}else if(this.object.isOrthographicCamera){const o=new D(this._mouse.x,this._mouse.y,0);o.unproject(this.object);const l=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),this.object.updateProjectionMatrix(),r=l!==this.object.zoom;const c=new D(this._mouse.x,this._mouse.y,0);c.unproject(this.object),this.object.position.sub(c).add(o),this.object.updateMatrixWorld(),a=_e.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),this.zoomToCursor=!1;a!==null&&(this.screenSpacePanning?this.target.set(0,0,-1).transformDirection(this.object.matrix).multiplyScalar(a).add(this.object.position):(Os.origin.copy(this.object.position),Os.direction.set(0,0,-1).transformDirection(this.object.matrix),Math.abs(this.object.up.dot(Os.direction))<_m?this.object.lookAt(this.target):(Sc.setFromNormalAndCoplanarPoint(this.object.up,this.target),Os.intersectPlane(Sc,this.target))))}else if(this.object.isOrthographicCamera){const a=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),a!==this.object.zoom&&(this.object.updateProjectionMatrix(),r=!0)}return this._scale=1,this._performCursorZoom=!1,r||this._lastPosition.distanceToSquared(this.object.position)>Br||8*(1-this._lastQuaternion.dot(this.object.quaternion))>Br||this._lastTargetPosition.distanceToSquared(this.target)>Br?(this.dispatchEvent(Mc),this._lastPosition.copy(this.object.position),this._lastQuaternion.copy(this.object.quaternion),this._lastTargetPosition.copy(this.target),!0):!1}_getAutoRotationAngle(t){return t!==null?Oe/60*this.autoRotateSpeed*t:Oe/60/60*this.autoRotateSpeed}_getZoomScale(t){const e=Math.abs(t*.01);return Math.pow(.95,this.zoomSpeed*e)}_rotateLeft(t){this._sphericalDelta.theta-=t}_rotateUp(t){this._sphericalDelta.phi-=t}_panLeft(t,e){_e.setFromMatrixColumn(e,0),_e.multiplyScalar(-t),this._panOffset.add(_e)}_panUp(t,e){this.screenSpacePanning===!0?_e.setFromMatrixColumn(e,1):(_e.setFromMatrixColumn(e,0),_e.crossVectors(this.object.up,_e)),_e.multiplyScalar(t),this._panOffset.add(_e)}_pan(t,e){const n=this.domElement;if(this.object.isPerspectiveCamera){const s=this.object.position;_e.copy(s).sub(this.target);let r=_e.length();r*=Math.tan(this.object.fov/2*Math.PI/180),this._panLeft(2*t*r/n.clientHeight,this.object.matrix),this._panUp(2*e*r/n.clientHeight,this.object.matrix)}else this.object.isOrthographicCamera?(this._panLeft(t*(this.object.right-this.object.left)/this.object.zoom/n.clientWidth,this.object.matrix),this._panUp(e*(this.object.top-this.object.bottom)/this.object.zoom/n.clientHeight,this.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),this.enablePan=!1)}_dollyOut(t){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale/=t:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_dollyIn(t){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale*=t:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_updateZoomParameters(t,e){if(!this.zoomToCursor)return;this._performCursorZoom=!0;const n=this.domElement.getBoundingClientRect(),s=t-n.left,r=e-n.top,a=n.width,o=n.height;this._mouse.x=s/a*2-1,this._mouse.y=-(r/o)*2+1,this._dollyDirection.set(this._mouse.x,this._mouse.y,1).unproject(this.object).sub(this.object.position).normalize()}_clampDistance(t){return Math.max(this.minDistance,Math.min(this.maxDistance,t))}_handleMouseDownRotate(t){this._rotateStart.set(t.clientX,t.clientY)}_handleMouseDownDolly(t){this._updateZoomParameters(t.clientX,t.clientX),this._dollyStart.set(t.clientX,t.clientY)}_handleMouseDownPan(t){this._panStart.set(t.clientX,t.clientY)}_handleMouseMoveRotate(t){this._rotateEnd.set(t.clientX,t.clientY),this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const e=this.domElement;this._rotateLeft(Oe*this._rotateDelta.x/e.clientHeight),this._rotateUp(Oe*this._rotateDelta.y/e.clientHeight),this._rotateStart.copy(this._rotateEnd),this.update()}_handleMouseMoveDolly(t){this._dollyEnd.set(t.clientX,t.clientY),this._dollyDelta.subVectors(this._dollyEnd,this._dollyStart),this._dollyDelta.y>0?this._dollyOut(this._getZoomScale(this._dollyDelta.y)):this._dollyDelta.y<0&&this._dollyIn(this._getZoomScale(this._dollyDelta.y)),this._dollyStart.copy(this._dollyEnd),this.update()}_handleMouseMovePan(t){this._panEnd.set(t.clientX,t.clientY),this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd),this.update()}_handleMouseWheel(t){this._updateZoomParameters(t.clientX,t.clientY),t.deltaY<0?this._dollyIn(this._getZoomScale(t.deltaY)):t.deltaY>0&&this._dollyOut(this._getZoomScale(t.deltaY)),this.update()}_handleKeyDown(t){let e=!1;switch(t.code){case this.keys.UP:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateUp(Oe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,this.keyPanSpeed),e=!0;break;case this.keys.BOTTOM:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateUp(-Oe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,-this.keyPanSpeed),e=!0;break;case this.keys.LEFT:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateLeft(Oe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(this.keyPanSpeed,0),e=!0;break;case this.keys.RIGHT:t.ctrlKey||t.metaKey||t.shiftKey?this.enableRotate&&this._rotateLeft(-Oe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(-this.keyPanSpeed,0),e=!0;break}e&&(t.preventDefault(),this.update())}_handleTouchStartRotate(t){if(this._pointers.length===1)this._rotateStart.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),n=.5*(t.pageX+e.x),s=.5*(t.pageY+e.y);this._rotateStart.set(n,s)}}_handleTouchStartPan(t){if(this._pointers.length===1)this._panStart.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),n=.5*(t.pageX+e.x),s=.5*(t.pageY+e.y);this._panStart.set(n,s)}}_handleTouchStartDolly(t){const e=this._getSecondPointerPosition(t),n=t.pageX-e.x,s=t.pageY-e.y,r=Math.sqrt(n*n+s*s);this._dollyStart.set(0,r)}_handleTouchStartDollyPan(t){this.enableZoom&&this._handleTouchStartDolly(t),this.enablePan&&this._handleTouchStartPan(t)}_handleTouchStartDollyRotate(t){this.enableZoom&&this._handleTouchStartDolly(t),this.enableRotate&&this._handleTouchStartRotate(t)}_handleTouchMoveRotate(t){if(this._pointers.length==1)this._rotateEnd.set(t.pageX,t.pageY);else{const n=this._getSecondPointerPosition(t),s=.5*(t.pageX+n.x),r=.5*(t.pageY+n.y);this._rotateEnd.set(s,r)}this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const e=this.domElement;this._rotateLeft(Oe*this._rotateDelta.x/e.clientHeight),this._rotateUp(Oe*this._rotateDelta.y/e.clientHeight),this._rotateStart.copy(this._rotateEnd)}_handleTouchMovePan(t){if(this._pointers.length===1)this._panEnd.set(t.pageX,t.pageY);else{const e=this._getSecondPointerPosition(t),n=.5*(t.pageX+e.x),s=.5*(t.pageY+e.y);this._panEnd.set(n,s)}this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd)}_handleTouchMoveDolly(t){const e=this._getSecondPointerPosition(t),n=t.pageX-e.x,s=t.pageY-e.y,r=Math.sqrt(n*n+s*s);this._dollyEnd.set(0,r),this._dollyDelta.set(0,Math.pow(this._dollyEnd.y/this._dollyStart.y,this.zoomSpeed)),this._dollyOut(this._dollyDelta.y),this._dollyStart.copy(this._dollyEnd);const a=(t.pageX+e.x)*.5,o=(t.pageY+e.y)*.5;this._updateZoomParameters(a,o)}_handleTouchMoveDollyPan(t){this.enableZoom&&this._handleTouchMoveDolly(t),this.enablePan&&this._handleTouchMovePan(t)}_handleTouchMoveDollyRotate(t){this.enableZoom&&this._handleTouchMoveDolly(t),this.enableRotate&&this._handleTouchMoveRotate(t)}_addPointer(t){this._pointers.push(t.pointerId)}_removePointer(t){delete this._pointerPositions[t.pointerId];for(let e=0;e{e.isMesh&&(t.add(e.geometry),t.add(e.material))});for(const e of t)e.dispose()}}function _i(i){return new vu({color:0,emissive:16777215,emissiveIntensity:i})}const qi=new D;function qe(i,t,e,n,s,r){const a=2*Math.PI*s/4,o=Math.max(r-2*s,0),l=Math.PI/4;qi.copy(t),qi[n]=0,qi.normalize();const c=.5*a/(a+o),h=1-qi.angleTo(i)/l;return Math.sign(qi[e])===1?h*c:o/(a+o)+c+c*(1-h)}class vn extends oe{constructor(t=1,e=1,n=1,s=2,r=.1){const a=s*2+1;if(r=Math.min(t/2,e/2,n/2,r),super(1,1,1,a,a,a),this.type="RoundedBoxGeometry",this.parameters={width:t,height:e,depth:n,segments:s,radius:r},a===1)return;const o=this.toNonIndexed();this.index=null,this.attributes.position=o.attributes.position,this.attributes.normal=o.attributes.normal,this.attributes.uv=o.attributes.uv;const l=new D,c=new D,h=new D(t,e,n).divideScalar(2).subScalar(r),u=this.attributes.position.array,d=this.attributes.normal.array,p=this.attributes.uv.array,x=u.length/6,_=new D,m=.5/a;for(let f=0,b=0;fe.fillText(c,n/2,n/2+(h-(o.length-1)/2)*l,n*.94));return}e.fillStyle="#5ee7ff";for(const r of[.33,.67])e.beginPath(),e.ellipse(n*r,n*.4,n*.08,n*.12,0,0,Math.PI*2),e.fill();e.strokeStyle="#5ee7ff",e.lineWidth=n*.045,e.lineCap="round",e.beginPath(),e.arc(n/2,n*.55,n*.18,Math.PI*.2,Math.PI*.8),e.stroke(),e.fillStyle="#ffffff",e.font=`bold ${Math.round(n*.11)}px system-ui, sans-serif`,e.textAlign="center",e.fillText("VisuBot",n/2,n*.9)}function zr(i,t,e,n,s){const r=document.createElement("canvas");r.width=t,r.height=e;const a=r.getContext("2d");a&&(s&&(a.fillStyle=s,a.fillRect(0,0,t,e)),a.fillStyle=n,a.textAlign="center",a.textBaseline="middle",i.forEach((l,c)=>{a.font=`${l.bold?"bold ":""}${l.size}px system-ui, sans-serif`,a.fillText(l.text,t/2,e*(c+.5)/i.length)}));const o=new Ka(r);return o.colorSpace=De,o}function Um(){const i=document.createElement("canvas");i.width=i.height=256;const t=i.getContext("2d");if(t){t.fillStyle="#16181b",t.fillRect(0,0,256,256),t.strokeStyle="#2c3036",t.lineWidth=9;for(let n=0;n<6;n++)for(let s=0;s<6;s++){const r=38+n*36,a=38+s*36;t.beginPath(),(n+s)%2?t.arc(r,a,12,0,Math.PI*2):t.rect(r-11,a-11,22,22),t.stroke()}}const e=new Ka(i);return e.colorSpace=De,e}function Nm(){const i=new js;i.moveTo(-7.2,1.4),i.lineTo(4.8,1.4),i.lineTo(9.6,4.6),i.lineTo(8.8,5.9),i.lineTo(4.6,3.6),i.lineTo(4.6,4.7),i.lineTo(-6.6,4.7),i.absarc(-8.4,3.1,1.9,Math.PI*.35,Math.PI*1.55,!1),i.lineTo(-7.2,1.4);const t=(e,n,s)=>{const r=new rs;r.absarc(e,n,s,0,Math.PI*2,!0),i.holes.push(r)};t(-8.4,3.1,.55);for(let e=0;e<8;e++){const n=e/8*Math.PI*2;Math.cos(n)>.6||t(-8.4+Math.cos(n)*1.25,3.1+Math.sin(n)*1.25,.22)}for(let e=0;e<4;e++)for(let n=0;n<3;n++)t(-5.6+e*.95,2.1+n*.95,.25);for(let e=0;e<3;e++)t(6+e*1.05,4+e*.7,.22);return i}function Fm(){const i=new ln,t=new Map,e={},n=(B,y=i)=>{const Z=new ln;return Z.name=B,e[B]=Z,t.set(Z,B),y.add(Z),Z},s=(B,y,Z,Q,ot,et)=>{const vt=new Vt(B,y);return vt.position.set(Z,Q,ot),et.add(vt),vt},r=ve(Im,{metalness:.7,roughness:.3}),a=ve(1776929,{roughness:.6}),o=ve(2764341,{roughness:.45}),l=ve(13225686,{metalness:.9,roughness:.25}),c=ve(1315860,{roughness:.9}),h=ve(10133671,{roughness:.55}),u=ve(15921906,{roughness:.5}),d=ve(1909286,{roughness:.7}),p=new _u({color:2501681,transparent:!0,opacity:.55,roughness:.12,metalness:.1,clearcoat:1,depthWrite:!1}),x=n("chassis"),_=new js;_.moveTo(-4.9,-7.2),_.lineTo(4.9,-7.2),_.lineTo(4.9,4.8),_.lineTo(-4.9,4.8);const m=new rs;m.moveTo(-3.6,-3.4),m.lineTo(-3.6,2.8),m.lineTo(3.6,2.8),m.lineTo(3.6,-3.4),_.holes.push(m);const f=new Ji(_,{depth:.22,bevelEnabled:!1});f.rotateX(Math.PI/2),s(f,r,0,1.62,0,x);const b=new Ji(Nm(),{depth:.22,bevelEnabled:!1,curveSegments:16});b.rotateY(-Math.PI/2);for(const B of[-1,1])s(b,r,B*4.9+(B>0?.22:0),0,0,x);s(new oe(9.8,3.3,.22),r,0,3.05,-7.2,x);const S=new Vt(new Si(1.1,.16,6,20,Math.PI*.8),a);S.rotation.z=Math.PI*1.1,S.position.set(0,2.9,-7.33),x.add(S);const T=new js;T.moveTo(-4.9,0),T.lineTo(4.9,0),T.lineTo(4.9,3.4),T.lineTo(-4.9,3.4);const R=new rs;R.moveTo(-1.1,.6),R.lineTo(-1.1,2.6),R.lineTo(-.5,2.6),R.lineTo(0,1.9),R.lineTo(.5,2.6),R.lineTo(1.1,2.6),R.lineTo(1.1,.6),R.lineTo(.6,.6),R.lineTo(.6,1.8),R.lineTo(0,1.1),R.lineTo(-.6,1.8),R.lineTo(-.6,.6),T.holes.push(R);const w=new Vt(new Ji(T,{depth:.22,bevelEnabled:!1}),r);w.rotation.x=-.35,w.position.set(0,1.5,4.8),x.add(w);const L=n("motors"),F=ve(9225450,{roughness:.55});for(const B of[-1,1]){s(new vn(2,2.8,3,2,.2),F,B*3.7,3.3,0,L);const y=s(new Ee(.75,.75,2.8,20),l,B*1.55,3,B*.8,L);y.rotation.z=Math.PI/2;const Z=s(new Ee(.8,.8,.5,20),F,B*2.6,3,B*.8,L);Z.rotation.z=Math.PI/2}const E=n("wheels"),M=ve(16777215,{map:Um(),roughness:.6});for(const B of[-1,1]){const y=new ln,Z=new Vt(new Ee(3.3,3.3,2.2,44),c);Z.rotation.z=Math.PI/2,y.add(Z);const Q=new Vt(new Si(2.75,.32,10,44),c);Q.rotation.y=Math.PI/2,Q.position.x=B*1.1,y.add(Q);const ot=new Vt(new ss(2.6,40),M);ot.rotation.y=B*Math.PI/2,ot.position.x=B*1,y.add(ot);const et=new Vt(new Ee(.3,.3,.3,12),l);et.rotation.z=Math.PI/2,et.position.x=B*1.05,y.add(et),y.position.set(B*6.45,3.3,0),y.name=B<0?"wheelLeft":"wheelRight",E.add(y)}const P=n("caster");s(new $i(1.3,20,10,0,Math.PI*2,0,Math.PI/2),a,0,.75,-4.6,P).scale.set(1.3,.7,1),s(new $i(.75,20,14),a,0,.75,-4.6,P);for(const B of[-.9,.9])s(new Ee(.25,.25,.2,12),l,B,1.28,-5.6,P);const z=n("lineSensor");s(new vn(8,.3,2.4,2,.1),d,0,1.25,-8,z);for(let B=0;B<4;B++){const y=-3.3+B*2.2;s(new oe(.6,.12,.6),ve(16119285,{emissive:16777215,emissiveIntensity:.5}),y,1.06,-8.3,z),s(new $i(.13,8,6),ve(16728128,{emissive:16722474,emissiveIntensity:1.4}),y,1.06,-7.6,z)}const k=n("shield"),W=new Vt(new vn(9.4,3.4,11.2,3,.5),p);W.position.set(0,6.5,-1.4),W.renderOrder=1,k.add(W),s(new oe(9,.16,10.8),d,0,5.1,-1.4,k);for(const[B,y]of[[-2,-4],[1.5,-3.6],[-1.6,-2.2],[1.8,-2.4]])s(new Ee(.45,.45,.4,14),a,B,5.35,y,k);const Y=zr([{text:"makeblock",size:56,bold:!0},{text:"mBot2 One Robot Per Child",size:30}],512,160,"#e9edf0","#777d84"),nt=new Vt(new Ee(1.05,1.05,7,28),new Te({map:Y,roughness:.4,metalness:.3}));nt.rotation.z=Math.PI/2,nt.rotation.x=-Math.PI/2,nt.position.set(0,6.3,.6),k.add(nt);for(const B of[-3.2,-2.3])s(new oe(.6,.5,.3),u,B,5.6,4.25,k);for(const B of[.4,2.2]){s(new oe(1.5,.45,.35),u,B,5.6,4.25,k);const y=s(new Si(.7,.12,6,12,Math.PI),a,B,5,4.5,k);y.rotation.y=Math.PI/2}const X=n("powerSwitch");s(new oe(.2,.5,1.2),o,-4.72,5.8,-3.4,X),s(new oe(.3,.38,.45),u,-4.8,5.8,-3.6,X);const rt=new Vt(new Nn(1.4,.4),new Ys({map:zr([{text:"ON/OFF",size:44,bold:!0}],256,72,"#e9edf0",void 0),transparent:!0}));rt.rotation.y=-Math.PI/2,rt.position.set(-4.76,5.25,-3.4),X.add(rt);for(const B of[-1.9,-.9])s(new oe(.3,.45,.7),u,-4.6,5.8,B,k);const st=new ln;i.add(st);const St=n("cyberpi",st),Gt=new Vt(new vn(7.9,1,3.1,3,.25),p);Gt.renderOrder=1,St.add(Gt),s(new oe(7.6,.12,2.9),d,0,-.1,0,St);const qt=new Vt(new Nn(1.6,.4),new Ys({map:zr([{text:"CyberPi",size:44}],256,64,"#c9d1d8",void 0),transparent:!0}));qt.position.set(-2.6,0,1.56),St.add(qt),s(new oe(.12,.3,.9),a,3.98,.05,-.7,St);const jt=n("screen",st),Kt=document.createElement("canvas");Kt.width=Kt.height=256,ll(Kt);const K=new Ka(Kt);K.colorSpace=De,s(new oe(3,.08,2.6),ve(14672870),.1,.47,0,jt);const J=new Vt(new Nn(2.7,2.3),new Te({map:K,emissive:16777215,emissiveMap:K,emissiveIntensity:.9,roughness:.15}));J.rotation.x=-Math.PI/2,J.position.set(.1,.52,0),jt.add(J);const xt=n("joystick",st);s(new Ee(.75,.75,.12,24),ve(9080982),-2.75,.52,0,xt),s(new Ee(.22,.22,.5,12),ve(7107192),-2.75,.75,0,xt),s(new Ee(.55,.6,.32,24),h,-2.75,1.05,0,xt);const Rt=n("buttons",st);s(new vn(.85,.3,.85,2,.15),h,2.6,.58,-.62,Rt);const Tt=s(new Ee(.55,.55,.3,3),h,2.6,.58,.68,Rt);Tt.rotation.y=Math.PI/2,s(new Ee(.24,.24,.22,14).rotateZ(Math.PI/2),h,3.98,.05,.5,Rt);const kt=n("leds",st);s(new oe(6.6,.3,.06),ve(15658734,{transparent:!0,opacity:.3,roughness:.2}),0,-.12,1.68,kt);const Qt=[];for(let B=0;B<5;B++){const y=new Te({color:14540253,emissiveIntensity:1,roughness:.3,toneMapped:!1});Qt.push(y),s(new oe(.7,.22,.08),y,-2.8+B*1.4,-.12,1.63,kt)}for(const[B,y]of[[-1.75,"lightSensor"],[-1.75,"microphone"]]){const Z=y==="lightSensor"?-1.05:1.05;s(new Ee(.14,.14,.08,10),ve(657930,{roughness:.2}),B,.52,Z,n(y,st))}st.position.set(0,8.55,3.15);const Ct=n("ultrasonic");s(new vn(6.4,2.8,1.3,3,.4),a,0,0,0,Ct);for(const B of[-1,1]){const y=s(new Ee(1.2,1.2,1.3,32),a,B*1.6,0,-1.1,Ct);y.rotation.x=Math.PI/2;const Z=s(new Si(.98,.17,10,32),ve(10396842,{metalness:.5,roughness:.35}),B*1.6,0,-1.76,Ct);Z.name="sonarRing";const Q=s(new ss(.85,28),ve(3817285,{roughness:.9}),B*1.6,0,-1.7,Ct);Q.rotation.y=Math.PI}s(new vn(2.6,1.5,.3,2,.12),a,0,-1.6,-.3,Ct);for(const B of[-.7,.7])s(new Ee(.28,.28,.2,12).rotateX(Math.PI/2),l,B,-1.75,-.5,Ct);return Ct.position.set(0,6.4,-8),i.traverse(B=>{const y=B;if(!y.isMesh)return;const Z=y.material.transparent;y.castShadow=!Z,y.receiveShadow=!0;const Q=y.material;Qt.includes(Q)||(y.material=Q.clone())}),{group:i,parts:t,partGroups:e,leds:Qt,screen:{canvas:Kt,texture:K}}}const $e=(i,t=0)=>new D(i.x,t,-i.y),Vr=i=>i*Math.PI/180,qn={floor:16052714,grid:14078148,wall:13214827,tape:2236962,trail:15227148},Om=12.9,yc=3.3;class Vm{constructor(t){le(this,"canvas");le(this,"renderer");le(this,"scene",new kc);le(this,"camera",new ke(45,1,1,2e3));le(this,"controls");le(this,"model");le(this,"robot");le(this,"trailGroup",new ln);le(this,"trailPiece",new oe(1,.15,1.4));le(this,"trailMaterial",new Te({color:qn.trail}));le(this,"liveSegment");le(this,"worldGroup",new ln);le(this,"frame");le(this,"sun");le(this,"resize");le(this,"shown",{x:0,y:0,heading:0});le(this,"anim");le(this,"trail",[]);le(this,"wasShown",!1);le(this,"wheelPose");le(this,"flight");le(this,"shownScreen");le(this,"loop",()=>{if(this.canvas.isConnected)this.wasShown=!0;else if(this.wasShown)return this.dispose();this.frame=requestAnimationFrame(this.loop);let t=this.shown;if(this.anim){const n=Math.min(1,(performance.now()-this.anim.start)/this.anim.ms),s=n<.5?2*n*n:1-(-2*n+2)**2/2,{from:r,to:a}=this.anim;t={x:r.x+(a.x-r.x)*s,y:r.y+(a.y-r.y)*s,heading:r.heading+(a.heading-r.heading)*s},n>=1&&(this.shown={...a},this.anim=void 0)}this.applyPose(t);const e=!!this.flight;if(this.flight){const n=Math.min(1,(performance.now()-this.flight.start)/this.flight.ms),s=n<.5?4*n*n*n:1-(-2*n+2)**3/2,{from:r,to:a}=this.flight;this.controls.target.lerpVectors(r.target,a.target,s);const o=r.pos.clone().sub(r.target),l=a.pos.clone().sub(a.target),c=o.clone().normalize().lerp(l.clone().normalize(),s);c.lengthSq()<1e-4&&c.set(-1,0,0),c.normalize();const h=o.length()+(l.length()-o.length())*s;this.camera.position.copy(this.controls.target).addScaledVector(c,h),n>=1&&(this.flight=void 0)}(e||this.controls.autoRotate)&&this.controls.update(),this.renderer.render(this.scene,this.camera)});this.host=t,this.canvas=document.createElement("canvas"),this.canvas.className="visubot-canvas",t.append(this.canvas),this.renderer=new gm({canvas:this.canvas,antialias:!0,alpha:!0}),this.renderer.setPixelRatio(Math.min(2,window.devicePixelRatio)),this.renderer.toneMapping=Tc,this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=Ec;const e=new Ia(this.renderer);this.scene.environment=e.fromScene(new Lm,.04).texture,this.scene.environmentIntensity=.7,e.dispose(),this.scene.add(new yu(16777215,9077104,.9));const n=new Au(16777215,1.8);n.position.set(-40,90,50),n.castShadow=!0,n.shadow.mapSize.set(1024,1024),n.shadow.camera.left=n.shadow.camera.bottom=-30,n.shadow.camera.right=n.shadow.camera.top=30,n.shadow.camera.far=300,n.shadow.bias=-5e-4,this.sun=n,this.scene.add(n,n.target),this.scene.add(this.worldGroup),this.model=Fm(),this.robot=this.model.group,this.scene.add(this.robot),this.scene.add(this.trailGroup),this.liveSegment=new Vt(this.trailPiece,this.trailMaterial),this.scene.add(this.liveSegment),this.camera.position.set(0,75,95),this.controls=new vm(this.camera,this.canvas),this.controls.target.set(0,0,-15),this.controls.maxPolarAngle=Math.PI-.05,this.controls.minDistance=12,this.controls.maxDistance=600,this.controls.update(),this.controls.addEventListener("start",()=>{this.flight=void 0,this.controls.autoRotate=!1}),this.resize=new ResizeObserver(()=>this.fit()),this.resize.observe(t),this.fit(),this.loop()}dispose(){this.frame!==void 0&&cancelAnimationFrame(this.frame),this.resize.disconnect(),this.controls.dispose(),this.renderer.dispose(),this.renderer.forceContextLoss(),this.canvas.remove()}setWorld(t){this.worldGroup.clear();const e=Math.max(t.width,t.depth,80);this.flight=void 0,this.controls.autoRotate=!1,this.controls.target.set(0,0,0),this.camera.position.set(0,e*.95,e*.5),this.controls.update();const n=new Vt(new Nn(t.width,t.depth),new Te({color:qn.floor,roughness:.9}));n.rotation.x=-Math.PI/2,n.receiveShadow=!0,this.worldGroup.add(n);const s=[];for(let b=-t.width/2;b<=t.width/2+1e-6;b+=10)s.push(b,.05,-t.depth/2,b,.05,t.depth/2);for(let b=-t.depth/2;b<=t.depth/2+1e-6;b+=10)s.push(-t.width/2,.05,b,t.width/2,.05,b);const r=new Ie;r.setAttribute("position",new he(s,3)),this.worldGroup.add(new Bh(r,new Wc({color:qn.grid})));const a=[{from:{x:-t.width/2,y:-t.depth/2},to:{x:t.width/2,y:-t.depth/2}},{from:{x:t.width/2,y:-t.depth/2},to:{x:t.width/2,y:t.depth/2}},{from:{x:t.width/2,y:t.depth/2},to:{x:-t.width/2,y:t.depth/2}},{from:{x:-t.width/2,y:t.depth/2},to:{x:-t.width/2,y:-t.depth/2}}],o=new Te({color:qn.wall});for(const b of[...a.map(S=>({...S,low:!0})),...t.walls.map(S=>({...S,low:!1}))]){const S=Math.hypot(b.to.x-b.from.x,b.to.y-b.from.y),T=b.low?4:15,R=new Vt(new oe(S,T,2),o);R.position.copy($e({x:(b.from.x+b.to.x)/2,y:(b.from.y+b.to.y)/2},T/2)),R.rotation.y=Math.atan2(b.to.y-b.from.y,b.to.x-b.from.x),this.worldGroup.add(R)}const l=new oe(rn,12,rn);for(const b of t.blocks??[]){const S=new Vt(l,o);S.position.copy($e(b,6)),S.castShadow=S.receiveShadow=!0,this.worldGroup.add(S)}const c=new oe(rn,.1,rn),h=new Te({color:qn.tape});for(const b of t.marks??[]){const S=new Vt(c,h);S.position.copy($e(b,.1)),this.worldGroup.add(S)}const u=new Te({color:qn.tape}),d=new Te({color:3126084,emissive:1800748,emissiveIntensity:.4}),p=t.goals??[],x=(b,S)=>p.some(T=>Math.abs(T.x-b)<1e-6&&Math.abs(T.y-S)<1e-6);for(const b of p){const S=new Vt(c,u);if(S.position.copy($e(b,.1)),this.worldGroup.add(S),x(b.x+rn,b.y)||x(b.x,b.y+rn))continue;const T=new Vt(new Ee(.25,.25,9,8),new Te({color:14540253}));T.position.copy($e({x:b.x+rn/2-1,y:b.y+rn/2-1},4.5));const R=new Vt(new oe(4,2.6,.2),d);R.position.copy($e({x:b.x+rn/2-3,y:b.y+rn/2-1},7.6)),this.worldGroup.add(T,R)}const _={red:14692657,green:3126084,blue:1867478,yellow:16429061};for(const b of t.colors??[]){const S=new Vt(c,new Te({color:_[b.color]}));S.position.copy($e(b.at,.1)),this.worldGroup.add(S)}const m=new Te({color:3126084,transparent:!0,opacity:.3,depthWrite:!1});for(const b of t.targets??[]){const S=new Vt(c,m);S.position.copy($e(b,.12)),this.worldGroup.add(S)}const f=new Te({color:qn.tape});for(const b of t.lines)for(let S=0;S+1({...n})),this.trailGroup.clear(),this.applyPose(this.shown)}moveTo(t,e,n){this.anim&&(this.shown={...this.anim.to}),this.trail=e.map(a=>({...a}));let s={...t};const r=s.heading-this.shown.heading;r>180?s={...s,heading:s.heading-360}:r<-180&&(s={...s,heading:s.heading+360}),this.anim={from:{...this.shown},to:s,start:performance.now(),ms:Math.max(1,n)}}showcase(){this.worldGroup.clear();const t=new Vt(new ss(16,48),new Te({color:15328474,roughness:.95}));t.rotation.x=-Math.PI/2,t.receiveShadow=!0,this.worldGroup.add(t),this.place({x:0,y:0,heading:0},[{x:0,y:0}]),this.controls.target.set(0,5,-2),this.camera.position.set(-20,18,-24),this.controls.update()}highlight(t){const e=new Set(t===void 0?[]:Array.isArray(t)?t:[t]);for(const[n,s]of Object.entries(this.model.partGroups))s.traverse(r=>{var c;const a=r;if(!a.isMesh)return;const o=a.material;if(!o.emissive)return;(c=o.userData).baseEmissive??(c.baseEmissive={color:o.emissive.getHex(),intensity:o.emissiveIntensity});const l=o.userData.baseEmissive;e.has(n)?(o.emissive.setHex(16756736),o.emissiveIntensity=Math.max(l.intensity,.22)):(o.emissive.setHex(l.color),o.emissiveIntensity=l.intensity)})}focusOn(t,e="",n=!1,s=900){const r=new On;this.robot.updateMatrixWorld(!0);for(const u of t)r.expandByObject(this.model.partGroups[u]);r.isEmpty()&&r.setFromObject(this.robot);const a=r.getCenter(new D),o=r.getSize(new D).length(),l=new D(...{vorn:[0,.35,-1],front:[0,.35,-1],hinten:[0,.55,1],back:[0,.55,1],oben:[0,1,.12],top:[0,1,.12],unten:[.05,-1,-.3],bottom:[.05,-1,-.3],seite:[-1,.5,.15],side:[-1,.5,.15]}[e]??[-.75,.6,-.85]).normalize(),c=Math.max(14,o*(t.length?1.8:1.35)+6),h=a.clone().addScaledVector(l,c);this.flight={from:{pos:this.camera.position.clone(),target:this.controls.target.clone()},to:{pos:h,target:a},start:performance.now(),ms:s},this.controls.autoRotate=n,this.controls.autoRotateSpeed=1.2}setScreen(t){t!==this.shownScreen&&(this.shownScreen=t,ll(this.model.screen.canvas,t),this.model.screen.texture.needsUpdate=!0)}setLed(t){this.setLeds(this.model.leds.map(()=>t))}setLeds(t){for(const[e,n]of this.model.leds.entries()){const s=t[e];s?(n.emissive.setRGB(s[0]/255,s[1]/255,s[2]/255),n.color.setRGB(s[0]/255,s[1]/255,s[2]/255)):(n.emissive.setRGB(0,0,0),n.color.set(14540253))}}partAt(t,e){const n=this.canvas.getBoundingClientRect(),s=new Ru;s.setFromCamera(new at((t-n.left)/n.width*2-1,-((e-n.top)/n.height)*2+1),this.camera);for(const r of s.intersectObject(this.robot,!0))for(let a=r.object;a;a=a.parent){const o=this.model.parts.get(a);if(o)return o}}fit(){const t=Math.max(1,this.host.clientWidth),e=Math.max(1,this.host.clientHeight);this.renderer.setSize(t,e,!1),this.camera.aspect=t/e,this.camera.updateProjectionMatrix()}applyPose(t){this.turnWheels(t),this.robot.position.copy($e(t)),this.robot.rotation.y=-Vr(t.heading),this.sun.target.position.copy(this.robot.position),this.sun.position.copy(this.robot.position).add(new D(-40,90,50));const e=this.anim?this.trail.length-2:this.trail.length-1;for(;this.trailGroup.children.length>Math.max(0,e);)this.trailGroup.remove(this.trailGroup.children[this.trailGroup.children.length-1]);for(let s=this.trailGroup.children.length;s.01,t.scale.set(s+1.4,1,1),t.position.copy($e({x:(e.x+n.x)/2,y:(e.y+n.y)/2},.2)),t.rotation.y=Math.atan2(n.y-e.y,n.x-e.x)}}export{Vm as Robot3D}; diff --git a/website/app/assets/ru-B4vTuE57.js b/website/app/assets/ru-B4vTuE57.js new file mode 100644 index 00000000..a3d3cb73 --- /dev/null +++ b/website/app/assets/ru-B4vTuE57.js @@ -0,0 +1,180 @@ +const e=`/* Тексты, которые есть только в веб-версии. Все остальные берутся из Localizable.strings приложения. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "Структурная схема VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Экспорт…"; +"web_export_title" = "Сохранить как изображение или PDF либо распечатать"; +"web_export_png" = "Изображение (PNG)"; +"web_export_svg" = "Векторная графика (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "Файл VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "Ошибка экспорта: %@"; +"web_print_hint" = "Через «Экспорт… → PDF» можно сохранить схему и затем распечатать её."; +"web_delete" = "Удалить"; +"web_language_title" = "Язык интерфейса"; +"web_simulation_start" = "Запустить симуляцию"; +"web_simulation_end" = "Завершить симуляцию"; +"web_simulation_start_title" = "Выполнить схему шаг за шагом"; +"web_simulation_end_title" = "Завершить симуляцию и продолжить редактирование"; +"web_palette_hint" = "Перетащите в схему"; +"web_tabs_label" = "Схемы"; +"web_status_modified" = "изменено"; +"web_inspector_title" = "Свойства"; +"web_inspector_help_drop" = "Перетаскивайте элементы из палитры на плитку: сверху = перед, снизу = после, на «ø» = заменить. Существующие элементы можно перемещать мышью."; +"web_inspector_help_files" = "Файлы также можно перетащить в окно."; +"web_case_name" = "Имя варианта"; +"web_case_name_placeholder" = "напр. 1, ok, default"; +"web_copied" = "Элемент скопирован."; +"web_discard_message_fmt" = "Изменения в «%@» будут потеряны."; +"web_err_unreadable_fmt" = "«%@» не является читаемым файлом VisuStruct (%@)."; +"web_saved_fmt" = "«%@» сохранён."; +"web_saved_txt_fmt" = "Сохранено как «%@». Удалите расширение .txt, чтобы использовать файл."; +"web_drop_impossible" = "Сюда нельзя поместить"; +"web_sim_delay" = "Пауза на шаг"; +"web_sim_delay_value_fmt" = "%@ с"; +"web_codegen_language" = "Язык"; +"web_codegen_comments" = "Текст схемы как комментарии"; +"web_codegen_empty_else" = "Выводить пустую ветку else в коде"; +"web_copied_check" = "Скопировано ✓"; +"web_copy_manual" = "Выделено, нажмите Ctrl+C для копирования"; +"web_run_stopped_loop" = "Выполнение остановлено: возможен бесконечный цикл."; +"web_run_cancelled" = "Выполнение отменено."; +"web_run_error" = "Ошибка при выполнении."; +"web_run_dropped_fmt" = "… скрыто более ранних строк: %d"; +"web_sim_call_arguments_fmt" = "Вызов не соответствует заголовку %@. Проверь значения в скобках."; +"web_sim_missing_return_fmt" = "%@ завершилась, не вернув значение через return."; +"web_sim_file_not_found_fmt" = "Файла с именем %@ нет."; +"web_sim_end_of_file_fmt" = "В файле %@ больше нет строк."; +"web_sim_null_value_fmt" = "%@ равно null."; +"web_sim_written_file_fmt" = "%@ (сохранён)"; +"web_site_home" = "Главная страница"; +"web_site_imprint" = "Выходные данные"; +"web_site_privacy" = "Конфиденциальность"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Программирование"; +"web_live_hide" = "Скрыть программирование"; +"web_scale_canvas" = "Размер текста: структурная схема"; +"web_scale_code" = "Размер текста: программирование"; +"web_live_indent" = "Отступы"; +"web_live_indent_title" = "Расставить отступы: четыре пробела на уровень (выделенные строки, иначе всё)"; +"web_live_show" = "Показать программирование"; +"web_live_resize" = "Изменить ширину области кода (двойной щелчок: сбросить)"; +"web_live_hint" = "Код растёт вместе с диаграммой. Серый = заполнитель: пиши в инспекторе, и текст появится здесь. Щёлкни строку, чтобы выбрать элемент."; +"web_live_ph_selector" = "переменная"; +"web_live_ph_code" = "Твой код"; +"web_live_ph_end" = "конец"; +"web_live_language" = "Язык программирования"; +"web_live_java_class" = "Как класс"; +"web_live_java_class_hint" = "Имя класса = заголовок диаграммы"; +"web_live_java_main" = "С методом main"; +"web_settings_display" = "Отображение"; +"web_live_swing" = "Настоящая Java (со Swing)"; +"web_live_swing_hint" = "Настоящая Java с окнами (CheerpJ). При первом запуске однократно загружает около 40 МБ."; +"web_live_swing_windows" = "Окна Java"; +"web_live_swing_hide" = "Закрыть окна Java"; +"web_live_swing_loading" = "Загрузка Java (в первый раз около 40 МБ) …"; +"web_live_swing_compiling" = "Компиляция …"; +"web_live_swing_running" = "Программа выполняется."; +"web_live_swing_compile_failed" = "Ошибка компиляции, см. выше."; +"web_live_swing_failed" = "Не удалось загрузить Java. Проверь подключение к интернету."; +"web_live_hint_edit" = "Набери здесь код Java, и диаграмма построится сама. Или работай в диаграмме, и код будет расти вместе с ней. Серый = заполнитель, просто пиши поверх."; +"web_live_edit_label" = "Код Java"; +"web_parse_line_fmt" = "Строка %d: %@"; +"web_parse_missing" = "Здесь ещё не хватает: %@"; +"web_parse_extra" = "Лишнее: %@"; +"web_parse_unclosed_string" = "Не хватает закрывающей %@."; +"web_parse_else_without_if" = "У этого «else» нет «if»."; +"web_parse_case_outside_switch" = "«case» и «default» должны быть внутри «switch»."; +"web_parse_missing_do_while" = "После «do { … }» не хватает «while (условие);»."; +"web_parse_more_methods" = "Пока здесь учитывается только один метод. Создай другие подпрограммы в отдельных вкладках."; +"web_parse_missing_import" = "В самом начале не хватает %@ Без этой строки Java не знает Scanner."; +"web_parse_missing_scanner" = "Сначала не хватает %@ Без этой строки Scanner не существует."; +"web_parse_unknown_type" = "Java не знает такого типа данных. Может быть, %@?"; +"web_editor_title" = "Диаграмма"; +"web_editor_show" = "Показать диаграмму"; +"web_editor_hide" = "Скрыть диаграмму"; +"web_keywords_title" = "Ключевые слова кода"; +"web_keywords_hint" = "if, while, for вместо названий элементов"; +"web_palette_compact" = "Элементы всегда компактно"; +"web_palette_compact_hint" = "Значок с маленьким названием под ним, иначе только при узкой колонке"; +"web_about_version_fmt" = "Версия %@"; +"web_about_software" = "Используемое ПО"; +"web_about_software_text" = "Редактор кода использует CodeMirror и Lezer (лицензия MIT). С поддержкой Swing VisuStruct загружает CheerpJ от Leaning Technologies (лицензия Community) и javac из OpenJDK."; +"web_about_licenses" = "Тексты лицензий"; +"web_live_run" = "Запустить"; +"web_live_run_title" = "Запустить программу: вывод и ввод появятся ниже"; +"web_live_run_finished" = "Программа завершена."; +"web_live_run_stopped" = "Остановлено."; +"web_console" = "Консоль"; +"web_console_hide" = "Скрыть консоль"; +"web_console_resize" = "Изменить высоту консоли"; +"web_diagram_tools" = "Инструменты диаграммы"; +"web_files_title" = "Файлы"; +"web_files_show" = "Показать файлы"; +"web_files_hide" = "Скрыть файлы"; +"web_files_resize" = "Изменить ширину файлов"; +"web_files_new_folder" = "Новая папка"; +"web_files_switch" = "Выбрать другую папку"; +"web_files_delete" = "Удалить"; +"web_files_in_browser" = "В хранилище этого браузера"; +"web_files_save_hint_fmt" = "При сохранении программа попадает в %@."; +"web_files_empty" = "Пока ничего не сохранено. При сохранении VisuStruct создаёт здесь папку с сегодняшней датой."; +"web_files_reconnect_hint" = "После перезагрузки браузер ещё раз спросит, может ли VisuStruct использовать твою папку."; +"web_files_reconnect_fmt" = "Открыть папку «%@»"; +"web_files_connect_hint" = "Выбери папку как рабочее пространство. VisuStruct создаёт в ней папку для каждого дня и сохраняет диаграмму и код."; +"web_files_connect" = "Выбрать папку"; +"web_files_browser_hint" = "Этот браузер не может открывать папки на устройстве (напр. на iPad). Твои файлы остаются в хранилище этого браузера."; +"web_files_browser" = "Сохранять в браузере"; +"web_files_delete_confirm_fmt" = "Действительно удалить «%@»?"; +"web_files_folder_prompt" = "Имя новой папки:"; +"web_files_default_name" = "Программа"; +"web_files_saved_fmt" = "Сохранено: %@"; +"web_files_create" = "Создать"; +"web_learn_ludwig_tip" = "Совет Людвига"; +"web_game_title" = "Игра: Истина или ложь?"; +"web_game_intro" = "Людвиг показывает значения и условие. Условие истинно (true) или ложно (false)? Десять раундов, всё сложнее."; +"web_game_start" = "Начать игру"; +"web_game_round_fmt" = "Раунд %@ из %@"; +"web_game_score_fmt" = "Очки: %@"; +"web_game_true" = "истина (true)"; +"web_game_false" = "ложь (false)"; +"web_game_right" = "Верно!"; +"web_game_wrong" = "Не совсем. Вот как это вычисляется:"; +"web_game_next" = "Дальше"; +"web_game_finish" = "Результат"; +"web_game_done_fmt" = "%@ из %@ верно."; +"web_game_perfect" = "Всё верно – Людвиг впечатлён!"; +"web_game_good" = "Отлично! Посмотри на ошибки и попробуй ещё раз."; +"web_game_practice" = "Повторение – мать учения. Перечитай таблицу истинности и сыграй ещё раз."; +"web_game_again" = "Играть снова"; +"web_game_wrong_short" = "К сожалению, неверно."; +"web_game_practice_short" = "Повторение — мать учения. Перечитай объяснения и сыграй ещё раунд."; +"web_game_clicks" = "Клики:"; +"web_game_nobody" = "Никто не слушает — ничего не происходит."; +"web_game_event_fmt" = "Клик по «%@»: слушатель слышит это и выполняет свой код."; +"web_game_try" = "Теперь попробуй кнопки в окне сам."; +"web_game_time_fmt" = "Осталось %@ с"; +"web_game_defused" = "✂️ Обезврежено! Ты нашёл ошибку."; +"web_game_boom_time" = "💥 Бум! Время вышло."; +"web_game_boom_wrong" = "💥 Бум! Это была не та строка."; +"web_game_fix" = "Правильная строка:"; +"web_game_order_hint" = "Нажимай на шаги в правильном порядке."; +"web_debug_step" = "Шаг"; +"web_debug_step_title" = "Шаг: выполнить одну инструкцию и снова остановиться"; +"web_debug_continue" = "Продолжить до следующей точки останова"; +"web_debug_paused_fmt" = "Остановлено перед строкой %d."; +"web_debug_gutter_title" = "Нажми на номер строки, чтобы поставить или убрать точку останова"; +"web_swap_to_code" = "Программирование крупно"; +"web_swap_to_editor" = "Структограмма крупно"; +"web_editor_resize" = "Изменить ширину структограммы"; +"web_palette_resize" = "Изменить ширину элементов"; +"web_palette_hide" = "Скрыть элементы"; +"web_palette_show" = "Показать элементы"; +"web_code_scopes" = "Цветные блоки кода"; +"web_code_scopes_hint" = "Класс, метод, цикл, ветвление в отдельных рамках"; +"web_pseudocode" = "Псевдокод"; +`;export{e as default}; diff --git a/website/app/assets/schiffe-versenken-CXt1SF0S.svg b/website/app/assets/schiffe-versenken-CXt1SF0S.svg new file mode 100644 index 00000000..289e2fd5 --- /dev/null +++ b/website/app/assets/schiffe-versenken-CXt1SF0S.svg @@ -0,0 +1,55 @@ + + +A +0 +B +1 +C +2 +D +3 +E +4 +1 +0 + + + + + +2 +1 + + + + + +3 +2 + + + + + +4 +3 + + + + + +5 +4 + + + + + + + + + + + +Index + diff --git a/website/app/assets/schiffe-versenken-iEBDHIxD.svg b/website/app/assets/schiffe-versenken-iEBDHIxD.svg new file mode 100644 index 00000000..8aeefaab --- /dev/null +++ b/website/app/assets/schiffe-versenken-iEBDHIxD.svg @@ -0,0 +1,55 @@ + + +A +0 +B +1 +C +2 +D +3 +E +4 +1 +0 + + + + + +2 +1 + + + + + +3 +2 + + + + + +4 +3 + + + + + +5 +4 + + + + + + + + + + + +Índice + diff --git a/website/app/assets/ss-binaere-suche-CPsLGldq.svg b/website/app/assets/ss-binaere-suche-CPsLGldq.svg new file mode 100644 index 00000000..c05c4a47 --- /dev/null +++ b/website/app/assets/ss-binaere-suche-CPsLGldq.svg @@ -0,0 +1,67 @@ + + +Gesucht: die 27. Die Karten sind sortiert. +1. Mitte: 13 < 27, links fällt weg +2♦ +3♣ +5♠ +7♣ +8♥ +10♦ +12♥ +13♠ +15♣ +18♦ +20♥ +21♠ +24♥ +27♣ +30♦ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +2. Mitte: 21 < 27, links fällt weg +2♦ +3♣ +5♠ +7♣ +8♥ +10♦ +12♥ +13♠ +15♣ +18♦ +20♥ +21♠ +24♥ +27♣ +30♦ +3. Mitte: gefunden nach 3 Vergleichen +2♦ +3♣ +5♠ +7♣ +8♥ +10♦ +12♥ +13♠ +15♣ +18♦ +20♥ +21♠ +24♥ +27♣ +30♦ + diff --git a/website/app/assets/ss-binaere-suche-D02W1TH_.svg b/website/app/assets/ss-binaere-suche-D02W1TH_.svg new file mode 100644 index 00000000..e5250f36 --- /dev/null +++ b/website/app/assets/ss-binaere-suche-D02W1TH_.svg @@ -0,0 +1,67 @@ + + +Looking for the 27. The cards are sorted. +1st middle: 13 < 27, drop the left +2♦ +3♣ +5♠ +7♣ +8♥ +10♦ +12♥ +13♠ +15♣ +18♦ +20♥ +21♠ +24♥ +27♣ +30♦ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +2nd middle: 21 < 27, drop the left +2♦ +3♣ +5♠ +7♣ +8♥ +10♦ +12♥ +13♠ +15♣ +18♦ +20♥ +21♠ +24♥ +27♣ +30♦ +3rd middle: found after 3 comparisons +2♦ +3♣ +5♠ +7♣ +8♥ +10♦ +12♥ +13♠ +15♣ +18♦ +20♥ +21♠ +24♥ +27♣ +30♦ + diff --git a/website/app/assets/ss-binaere-suche-DVVS2SNc.svg b/website/app/assets/ss-binaere-suche-DVVS2SNc.svg new file mode 100644 index 00000000..8caadd8c --- /dev/null +++ b/website/app/assets/ss-binaere-suche-DVVS2SNc.svg @@ -0,0 +1,67 @@ + + +Procura-se o 27. As cartas estão ordenadas. +1.º meio: 13 < 27, a esquerda sai +2♦ +3♣ +5♠ +7♣ +8♥ +10♦ +12♥ +13♠ +15♣ +18♦ +20♥ +21♠ +24♥ +27♣ +30♦ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +2.º meio: 21 < 27, a esquerda sai +2♦ +3♣ +5♠ +7♣ +8♥ +10♦ +12♥ +13♠ +15♣ +18♦ +20♥ +21♠ +24♥ +27♣ +30♦ +3.º meio: encontrado após 3 comparações +2♦ +3♣ +5♠ +7♣ +8♥ +10♦ +12♥ +13♠ +15♣ +18♦ +20♥ +21♠ +24♥ +27♣ +30♦ + diff --git a/website/app/assets/ss-bubblesort-AFDcFDah.svg b/website/app/assets/ss-bubblesort-AFDcFDah.svg new file mode 100644 index 00000000..9b13f206 --- /dev/null +++ b/website/app/assets/ss-bubblesort-AFDcFDah.svg @@ -0,0 +1,35 @@ + + +Uma ronda: comparar vizinhos +7♥ +3♠ +10♦ +5♣ +2♥ +Início +3♠ +7♥ +10♦ +5♣ +2♥ +7 > 3: trocar +3♠ +7♥ +10♦ +5♣ +2♥ +7 < 10: certo +3♠ +7♥ +5♣ +10♦ +2♥ +10 > 5: trocar +3♠ +7♥ +5♣ +2♥ +10♦ +10 > 2: trocar +A carta maior sobe para a direita como uma bolha. + diff --git a/website/app/assets/ss-bubblesort-CmKEoNfO.svg b/website/app/assets/ss-bubblesort-CmKEoNfO.svg new file mode 100644 index 00000000..a584b009 --- /dev/null +++ b/website/app/assets/ss-bubblesort-CmKEoNfO.svg @@ -0,0 +1,35 @@ + + +One round: compare neighbours +7♥ +3♠ +10♦ +5♣ +2♥ +Start +3♠ +7♥ +10♦ +5♣ +2♥ +7 > 3: swap +3♠ +7♥ +10♦ +5♣ +2♥ +7 < 10: fine +3♠ +7♥ +5♣ +10♦ +2♥ +10 > 5: swap +3♠ +7♥ +5♣ +2♥ +10♦ +10 > 2: swap +The largest card rises to the right like a bubble. + diff --git a/website/app/assets/ss-bubblesort-Dic2ZfaT.svg b/website/app/assets/ss-bubblesort-Dic2ZfaT.svg new file mode 100644 index 00000000..6c47eef5 --- /dev/null +++ b/website/app/assets/ss-bubblesort-Dic2ZfaT.svg @@ -0,0 +1,35 @@ + + +Ein Durchgang: Nachbarn vergleichen +7♥ +3♠ +10♦ +5♣ +2♥ +Start +3♠ +7♥ +10♦ +5♣ +2♥ +7 > 3: tauschen +3♠ +7♥ +10♦ +5♣ +2♥ +7 < 10: passt +3♠ +7♥ +5♣ +10♦ +2♥ +10 > 5: tauschen +3♠ +7♥ +5♣ +2♥ +10♦ +10 > 2: tauschen +Die größte Karte steigt wie eine Blase nach rechts. + diff --git a/website/app/assets/ss-vergleiche-DRqzU2TZ.svg b/website/app/assets/ss-vergleiche-DRqzU2TZ.svg new file mode 100644 index 00000000..1cf631a0 --- /dev/null +++ b/website/app/assets/ss-vergleiche-DRqzU2TZ.svg @@ -0,0 +1,22 @@ + + +Vergleiche im schlimmsten Fall +Lineare SucheBinäre Suche +0 +25 +50 +75 +100 +0 +25 +50 +75 +100 + +Anzahl der Karten +Vergleiche + + +100 Vergleiche +7 Vergleiche + diff --git a/website/app/assets/ss-vergleiche-DWgkIvLr.svg b/website/app/assets/ss-vergleiche-DWgkIvLr.svg new file mode 100644 index 00000000..672279b3 --- /dev/null +++ b/website/app/assets/ss-vergleiche-DWgkIvLr.svg @@ -0,0 +1,22 @@ + + +Comparações no pior caso +Pesquisa linearPesquisa binária +0 +25 +50 +75 +100 +0 +25 +50 +75 +100 + +Número de cartas +Comparações + + +100comparações +7 comparações + diff --git a/website/app/assets/ss-vergleiche-UczNldcC.svg b/website/app/assets/ss-vergleiche-UczNldcC.svg new file mode 100644 index 00000000..57a87c8a --- /dev/null +++ b/website/app/assets/ss-vergleiche-UczNldcC.svg @@ -0,0 +1,22 @@ + + +Comparisons in the worst case +Linear searchBinary search +0 +25 +50 +75 +100 +0 +25 +50 +75 +100 + +Number of cards +Comparisons + + +100 comparisons +7 comparisons + diff --git a/website/app/assets/sv-Dau75zUV.js b/website/app/assets/sv-Dau75zUV.js new file mode 100644 index 00000000..a13be35d --- /dev/null +++ b/website/app/assets/sv-Dau75zUV.js @@ -0,0 +1,180 @@ +const e=`/* Texter som bara finns i webbversionen. Allt annat kommer från appens Localizable.strings. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct-struktogram"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Exportera…"; +"web_export_title" = "Spara som bild eller PDF, eller skriv ut"; +"web_export_png" = "Bild (PNG)"; +"web_export_svg" = "Vektorgrafik (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "VisuStruct-fil (.visustruct)"; +"web_export_failed_fmt" = "Exporten misslyckades: %@"; +"web_print_hint" = "Använd ”Exportera… → PDF” för att spara diagrammet och skriva ut det därifrån."; +"web_delete" = "Radera"; +"web_language_title" = "Gränssnittets språk"; +"web_simulation_start" = "Starta simulering"; +"web_simulation_end" = "Avsluta simulering"; +"web_simulation_start_title" = "Kör struktogrammet steg för steg"; +"web_simulation_end_title" = "Avsluta simuleringen och fortsätt redigera"; +"web_palette_hint" = "Dra in i struktogrammet"; +"web_tabs_label" = "Diagram"; +"web_status_modified" = "ändrad"; +"web_inspector_title" = "Egenskaper"; +"web_inspector_help_drop" = "Dra element från paletten till en ruta: överst = före, nederst = efter, på ”ø” = ersätt. Befintliga element kan flyttas med musen."; +"web_inspector_help_files" = "Du kan också släppa filer i fönstret."; +"web_case_name" = "Namn på case"; +"web_case_name_placeholder" = "t.ex. 1, ok, default"; +"web_copied" = "Elementet kopierat."; +"web_discard_message_fmt" = "Ändringarna i ”%@” går förlorade."; +"web_err_unreadable_fmt" = "”%@” är inte en läsbar VisuStruct-fil (%@)."; +"web_saved_fmt" = "”%@” sparad."; +"web_saved_txt_fmt" = "Sparad som ”%@”. Ta bort filändelsen .txt för att använda den."; +"web_drop_impossible" = "Kan inte släppas här"; +"web_sim_delay" = "Paus per steg"; +"web_sim_delay_value_fmt" = "%@ s"; +"web_codegen_language" = "Språk"; +"web_codegen_comments" = "Diagramtext som kommentarer"; +"web_codegen_empty_else" = "Skriv ut tom else-gren i koden"; +"web_copied_check" = "Kopierat ✓"; +"web_copy_manual" = "Markerat, tryck Ctrl+C för att kopiera"; +"web_run_stopped_loop" = "Körningen stoppades: möjlig oändlig loop."; +"web_run_cancelled" = "Körningen avbröts."; +"web_run_error" = "Fel vid körning."; +"web_run_dropped_fmt" = "… %d tidigare rader dolda"; +"web_sim_call_arguments_fmt" = "Anropet passar inte till huvudet i %@. Kontrollera värdena inom parentes."; +"web_sim_missing_return_fmt" = "%@ avslutades utan att returnera ett värde med return."; +"web_sim_file_not_found_fmt" = "Det finns ingen fil som heter %@."; +"web_sim_end_of_file_fmt" = "Filen %@ har inga fler rader."; +"web_sim_null_value_fmt" = "%@ är null."; +"web_sim_written_file_fmt" = "%@ (sparad)"; +"web_site_home" = "Startsida"; +"web_site_imprint" = "Kontaktuppgifter"; +"web_site_privacy" = "Integritet"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Programmering"; +"web_live_hide" = "Dölj programmering"; +"web_scale_canvas" = "Textstorlek: strukturdiagram"; +"web_scale_code" = "Textstorlek: programmering"; +"web_live_indent" = "Indrag"; +"web_live_indent_title" = "Gör indrag i koden: fyra blanksteg per nivå (markerade rader, annars allt)"; +"web_live_show" = "Visa programmering"; +"web_live_resize" = "Ändra kodområdets bredd (dubbelklick: återställ)"; +"web_live_hint" = "Koden växer med ditt diagram. Grått = platshållare: skriv i inspektören så visas texten här. Klicka på en rad för att markera elementet."; +"web_live_ph_selector" = "variabel"; +"web_live_ph_code" = "Din kod"; +"web_live_ph_end" = "slut"; +"web_live_language" = "Programmeringsspråk"; +"web_live_java_class" = "Som klass"; +"web_live_java_class_hint" = "Klassnamn = diagrammets titel"; +"web_live_java_main" = "Med main-metod"; +"web_settings_display" = "Visning"; +"web_live_swing" = "Riktig Java (med Swing)"; +"web_live_swing_hint" = "Riktig Java med fönster (CheerpJ). Laddar ner ca 40 MB en gång vid första körningen."; +"web_live_swing_windows" = "Java-fönster"; +"web_live_swing_hide" = "Stäng Java-fönster"; +"web_live_swing_loading" = "Java laddas (första gången ca 40 MB) …"; +"web_live_swing_compiling" = "Kompilerar …"; +"web_live_swing_running" = "Programmet körs."; +"web_live_swing_compile_failed" = "Kompileringsfel, se ovan."; +"web_live_swing_failed" = "Java kunde inte laddas. Kontrollera internetanslutningen."; +"web_live_hint_edit" = "Skriv Java-kod här så bygger diagrammet sig självt. Eller arbeta i diagrammet så växer koden med. Grått = platshållare, skriv bara över."; +"web_live_edit_label" = "Java-kod"; +"web_parse_line_fmt" = "Rad %d: %@"; +"web_parse_missing" = "Här saknas ännu: %@"; +"web_parse_extra" = "För mycket: %@"; +"web_parse_unclosed_string" = "Det avslutande %@ saknas."; +"web_parse_else_without_if" = "Denna ”else” har ingen ”if”."; +"web_parse_case_outside_switch" = "”case” och ”default” hör hemma i en ”switch”."; +"web_parse_missing_do_while" = "Efter ”do { … }” saknas ”while (villkor);”."; +"web_parse_more_methods" = "För tillfället räknas bara en metod här. Skapa andra underprogram i egna flikar."; +"web_parse_missing_import" = "Högst upp saknas %@ Utan den raden känner Java inte till Scanner."; +"web_parse_missing_scanner" = "Innan saknas %@ Utan den raden finns ingen Scanner."; +"web_parse_unknown_type" = "Java känner inte till den här datatypen. Menade du %@?"; +"web_editor_title" = "Strukturdiagram"; +"web_editor_show" = "Visa strukturdiagram"; +"web_editor_hide" = "Dölj strukturdiagram"; +"web_keywords_title" = "Kodnyckelord"; +"web_keywords_hint" = "if, while, for i stället för elementnamn"; +"web_palette_compact" = "Element alltid kompakta"; +"web_palette_compact_hint" = "Symbol med litet namn under, annars bara när kolumnen är smal"; +"web_about_version_fmt" = "Version %@"; +"web_about_software" = "Programvara som används"; +"web_about_software_text" = "Kodredigeraren använder CodeMirror och Lezer (MIT-licens). Med Swing-stöd laddar VisuStruct CheerpJ från Leaning Technologies (Community-licens) och javac från OpenJDK."; +"web_about_licenses" = "Licenstexter"; +"web_live_run" = "Kör"; +"web_live_run_title" = "Kör programmet: utdata och indata visas nedanför"; +"web_live_run_finished" = "Programmet är klart."; +"web_live_run_stopped" = "Stoppat."; +"web_console" = "Konsol"; +"web_console_hide" = "Dölj konsolen"; +"web_console_resize" = "Ändra konsolens höjd"; +"web_diagram_tools" = "Diagramverktyg"; +"web_files_title" = "Filer"; +"web_files_show" = "Visa filer"; +"web_files_hide" = "Dölj filer"; +"web_files_resize" = "Ändra bredd på filer"; +"web_files_new_folder" = "Ny mapp"; +"web_files_switch" = "Välj en annan mapp"; +"web_files_delete" = "Ta bort"; +"web_files_in_browser" = "I den här webbläsarens lagring"; +"web_files_save_hint_fmt" = "Sparandet lägger programmet i %@."; +"web_files_empty" = "Inget sparat ännu. När du sparar skapar VisuStruct en mapp med dagens datum här."; +"web_files_reconnect_hint" = "Efter omladdning frågar webbläsaren igen om VisuStruct får använda din mapp."; +"web_files_reconnect_fmt" = "Öppna mappen ”%@”"; +"web_files_connect_hint" = "Välj en mapp som arbetsyta. VisuStruct skapar en mapp för varje dag där och sparar diagram och kod."; +"web_files_connect" = "Välj mapp"; +"web_files_browser_hint" = "Den här webbläsaren kan inte öppna mappar på enheten (t.ex. på iPad). Dina filer stannar i webbläsarens lagring."; +"web_files_browser" = "Spara i webbläsaren"; +"web_files_delete_confirm_fmt" = "Vill du verkligen ta bort ”%@”?"; +"web_files_folder_prompt" = "Namn på den nya mappen:"; +"web_files_default_name" = "Program"; +"web_files_saved_fmt" = "Sparat: %@"; +"web_files_create" = "Skapa"; +"web_learn_ludwig_tip" = "Ludwigs tips"; +"web_game_title" = "Spel: Sant eller falskt?"; +"web_game_intro" = "Ludwig visar värden och ett villkor. Är villkoret sant (true) eller falskt (false)? Tio rundor, allt svårare."; +"web_game_start" = "Starta spelet"; +"web_game_round_fmt" = "Runda %@ av %@"; +"web_game_score_fmt" = "Poäng: %@"; +"web_game_true" = "sant (true)"; +"web_game_false" = "falskt (false)"; +"web_game_right" = "Rätt!"; +"web_game_wrong" = "Inte riktigt. Så räknar man:"; +"web_game_next" = "Nästa"; +"web_game_finish" = "Resultat"; +"web_game_done_fmt" = "%@ av %@ rätt."; +"web_game_perfect" = "Allt rätt – Ludwig är imponerad!"; +"web_game_good" = "Snyggt! Titta på dina misstag och försök igen."; +"web_game_practice" = "Övning ger färdighet. Läs sanningstabellen igen och spela en runda till."; +"web_game_again" = "Spela igen"; +"web_game_wrong_short" = "Tyvärr fel."; +"web_game_practice_short" = "Övning ger färdighet. Läs förklaringarna igen och spela en runda till."; +"web_game_clicks" = "Klick:"; +"web_game_nobody" = "Ingen lyssnar – ingenting händer."; +"web_game_event_fmt" = "Klick på ”%@”: lyssnaren hör det och kör sin kod."; +"web_game_try" = "Prova nu själv knapparna i fönstret."; +"web_game_time_fmt" = "%@ s kvar"; +"web_game_defused" = "✂️ Desarmerad! Du hittade felet."; +"web_game_boom_time" = "💥 Pang! Tiden är ute."; +"web_game_boom_wrong" = "💥 Pang! Det var fel rad."; +"web_game_fix" = "Rätt rad:"; +"web_game_order_hint" = "Tryck på stegen i rätt ordning."; +"web_debug_step" = "Steg"; +"web_debug_step_title" = "Steg: kör en sats och pausa igen"; +"web_debug_continue" = "Fortsätt till nästa brytpunkt"; +"web_debug_paused_fmt" = "Pausad före rad %d."; +"web_debug_gutter_title" = "Klicka på ett radnummer för att sätta eller ta bort en brytpunkt"; +"web_swap_to_code" = "Programmering stor"; +"web_swap_to_editor" = "Struktogram stort"; +"web_editor_resize" = "Ändra bredd på struktogrammet"; +"web_palette_resize" = "Ändra bredd på elementen"; +"web_palette_hide" = "Dölj elementen"; +"web_palette_show" = "Visa elementen"; +"web_code_scopes" = "Färgade kodblock"; +"web_code_scopes_hint" = "Klass, metod, loop, förgrening i egna rutor"; +"web_pseudocode" = "Pseudokod"; +`;export{e as default}; diff --git a/website/app/assets/tr-DrZsTe-O.js b/website/app/assets/tr-DrZsTe-O.js new file mode 100644 index 00000000..3cc2459f --- /dev/null +++ b/website/app/assets/tr-DrZsTe-O.js @@ -0,0 +1,180 @@ +const e=`/* Yalnızca web sürümünde bulunan metinler. Geri kalan her şey uygulamanın Localizable.strings dosyalarından gelir. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct yapı şeması"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Dışa aktar…"; +"web_export_title" = "Görsel veya PDF olarak kaydet ya da yazdır"; +"web_export_png" = "Görsel (PNG)"; +"web_export_svg" = "Vektör grafik (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "VisuStruct dosyası (.visustruct)"; +"web_export_failed_fmt" = "Dışa aktarma başarısız: %@"; +"web_print_hint" = "Diyagramı kaydetmek için “Dışa aktar… → PDF” seçeneğini kullanın ve oradan yazdırın."; +"web_delete" = "Sil"; +"web_language_title" = "Arayüz dili"; +"web_simulation_start" = "Simülasyonu başlat"; +"web_simulation_end" = "Simülasyonu bitir"; +"web_simulation_start_title" = "Yapı şemasını adım adım çalıştır"; +"web_simulation_end_title" = "Simülasyonu bitir ve düzenlemeye devam et"; +"web_palette_hint" = "Yapı şemasına sürükleyin"; +"web_tabs_label" = "Diyagramlar"; +"web_status_modified" = "değiştirildi"; +"web_inspector_title" = "Özellikler"; +"web_inspector_help_drop" = "Paletteki öğeleri bir kutucuğa sürükleyin: üst = önce, alt = sonra, “ø” üzerine = değiştir. Mevcut öğeler fareyle taşınabilir."; +"web_inspector_help_files" = "Dosyaları pencereye de bırakabilirsiniz."; +"web_case_name" = "Durum adı"; +"web_case_name_placeholder" = "ör. 1, ok, default"; +"web_copied" = "Öğe kopyalandı."; +"web_discard_message_fmt" = "“%@” üzerindeki değişiklikler kaybolacak."; +"web_err_unreadable_fmt" = "“%@” okunabilir bir VisuStruct dosyası değil (%@)."; +"web_saved_fmt" = "“%@” kaydedildi."; +"web_saved_txt_fmt" = "“%@” olarak kaydedildi. Kullanmak için .txt uzantısını kaldırın."; +"web_drop_impossible" = "Buraya bırakılamaz"; +"web_sim_delay" = "Adım başına duraklama"; +"web_sim_delay_value_fmt" = "%@ sn"; +"web_codegen_language" = "Dil"; +"web_codegen_comments" = "Diyagram metni yorum olarak"; +"web_codegen_empty_else" = "Kodda boş else dalı oluştur"; +"web_copied_check" = "Kopyalandı ✓"; +"web_copy_manual" = "Seçildi, kopyalamak için Ctrl+C tuşlarına basın"; +"web_run_stopped_loop" = "Çalıştırma durduruldu: olası sonsuz döngü."; +"web_run_cancelled" = "Çalıştırma iptal edildi."; +"web_run_error" = "Çalıştırma sırasında hata."; +"web_run_dropped_fmt" = "… önceki %d satır gizlendi"; +"web_sim_call_arguments_fmt" = "Çağrı %@ başlığıyla eşleşmiyor. Parantez içindeki değerleri kontrol et."; +"web_sim_missing_return_fmt" = "%@ return ile bir değer döndürmeden bitti."; +"web_sim_file_not_found_fmt" = "%@ adında bir dosya yok."; +"web_sim_end_of_file_fmt" = "%@ dosyasında başka satır yok."; +"web_sim_null_value_fmt" = "%@ null."; +"web_sim_written_file_fmt" = "%@ (kaydedildi)"; +"web_site_home" = "Ana sayfa"; +"web_site_imprint" = "Künye"; +"web_site_privacy" = "Gizlilik"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Programlama"; +"web_live_hide" = "Programlamayı gizle"; +"web_scale_canvas" = "Yazı boyutu: yapı diyagramı"; +"web_scale_code" = "Yazı boyutu: programlama"; +"web_live_indent" = "Girinti"; +"web_live_indent_title" = "Kodu girintile: her seviye için dört boşluk (seçili satırlar, yoksa tümü)"; +"web_live_show" = "Programlamayı göster"; +"web_live_resize" = "Kod alanının genişliğini değiştir (çift tıklama: sıfırla)"; +"web_live_hint" = "Kod diyagramınla birlikte büyür. Gri = yer tutucu: denetçiye yaz, metnin burada görünür. Öğesini seçmek için bir satıra tıkla."; +"web_live_ph_selector" = "değişken"; +"web_live_ph_code" = "Kodun"; +"web_live_ph_end" = "bitiş"; +"web_live_language" = "Programlama dili"; +"web_live_java_class" = "Sınıf olarak"; +"web_live_java_class_hint" = "Sınıf adı = diyagram başlığı"; +"web_live_java_main" = "main metoduyla"; +"web_settings_display" = "Görünüm"; +"web_live_swing" = "Gerçek Java (Swing ile)"; +"web_live_swing_hint" = "Pencereli gerçek Java (CheerpJ). İlk çalıştırmada bir kez yaklaşık 40 MB indirir."; +"web_live_swing_windows" = "Java pencereleri"; +"web_live_swing_hide" = "Java pencerelerini kapat"; +"web_live_swing_loading" = "Java yükleniyor (ilk seferde yaklaşık 40 MB) …"; +"web_live_swing_compiling" = "Derleniyor …"; +"web_live_swing_running" = "Program çalışıyor."; +"web_live_swing_compile_failed" = "Derleme hatası, yukarıya bak."; +"web_live_swing_failed" = "Java yüklenemedi. İnternet bağlantını kontrol et."; +"web_live_hint_edit" = "Buraya Java kodu yaz, diyagram kendiliğinden oluşsun. Ya da diyagramda çalış, kod onunla büyüsün. Gri = yer tutucu, üzerine yazman yeterli."; +"web_live_edit_label" = "Java kodu"; +"web_parse_line_fmt" = "Satır %d: %@"; +"web_parse_missing" = "Burada hâlâ eksik: %@"; +"web_parse_extra" = "Fazla: %@"; +"web_parse_unclosed_string" = "Kapanış %@ eksik."; +"web_parse_else_without_if" = "Bu “else” için bir “if” yok."; +"web_parse_case_outside_switch" = "“case” ve “default” bir “switch” içinde olmalı."; +"web_parse_missing_do_while" = "“do { … }” sonrasında “while (koşul);” eksik."; +"web_parse_more_methods" = "Şimdilik burada yalnızca bir metot sayılır. Diğer alt programları ayrı sekmelerde oluştur."; +"web_parse_missing_import" = "En üstte %@ eksik. Bu satır olmadan Java Scanner’ı tanımaz."; +"web_parse_missing_scanner" = "Önce %@ eksik. Bu satır olmadan Scanner yoktur."; +"web_parse_unknown_type" = "Java bu veri türünü tanımıyor. %@ mı demek istedin?"; +"web_editor_title" = "Diyagram"; +"web_editor_show" = "Diyagramı göster"; +"web_editor_hide" = "Diyagramı gizle"; +"web_keywords_title" = "Kod anahtar sözcükleri"; +"web_keywords_hint" = "Öğe adları yerine if, while, for"; +"web_palette_compact" = "Öğeler her zaman kompakt"; +"web_palette_compact_hint" = "Simgenin altında küçük ad; aksi halde yalnızca sütun dar olduğunda"; +"web_about_version_fmt" = "Sürüm %@"; +"web_about_software" = "Kullanılan yazılımlar"; +"web_about_software_text" = "Kod düzenleyici CodeMirror ve Lezer kullanır (MIT lisansı). Swing desteğiyle VisuStruct, Leaning Technologies’in CheerpJ’sini (Community lisansı) ve OpenJDK’dan javac’ı yükler."; +"web_about_licenses" = "Lisans metinleri"; +"web_live_run" = "Çalıştır"; +"web_live_run_title" = "Programı çalıştır: çıktı ve girdi aşağıda görünür"; +"web_live_run_finished" = "Program bitti."; +"web_live_run_stopped" = "Durduruldu."; +"web_console" = "Konsol"; +"web_console_hide" = "Konsolu gizle"; +"web_console_resize" = "Konsolu yeniden boyutlandır"; +"web_diagram_tools" = "Diyagram araçları"; +"web_files_title" = "Dosyalar"; +"web_files_show" = "Dosyaları göster"; +"web_files_hide" = "Dosyaları gizle"; +"web_files_resize" = "Dosyaların genişliğini değiştir"; +"web_files_new_folder" = "Yeni klasör"; +"web_files_switch" = "Başka bir klasör seç"; +"web_files_delete" = "Sil"; +"web_files_in_browser" = "Bu tarayıcının belleğinde"; +"web_files_save_hint_fmt" = "Kaydetme programı %@ içine koyar."; +"web_files_empty" = "Henüz bir şey kaydedilmedi. Kaydettiğinde VisuStruct burada bugünün tarihiyle bir klasör oluşturur."; +"web_files_reconnect_hint" = "Yeniden yüklemeden sonra tarayıcı, VisuStruct’ın klasörünü kullanıp kullanamayacağını bir kez daha sorar."; +"web_files_reconnect_fmt" = "“%@” klasörünü aç"; +"web_files_connect_hint" = "Çalışma alanı olarak bir klasör seç. VisuStruct içinde her gün için bir klasör oluşturur, diyagramı ve kodu kaydeder."; +"web_files_connect" = "Klasör seç"; +"web_files_browser_hint" = "Bu tarayıcı cihazdaki klasörleri açamaz (ör. iPad’de). Dosyaların bu tarayıcının belleğinde kalır."; +"web_files_browser" = "Tarayıcıya kaydet"; +"web_files_delete_confirm_fmt" = "“%@” gerçekten silinsin mi?"; +"web_files_folder_prompt" = "Yeni klasörün adı:"; +"web_files_default_name" = "Program"; +"web_files_saved_fmt" = "Kaydedildi: %@"; +"web_files_create" = "Oluştur"; +"web_learn_ludwig_tip" = "Ludwig’in ipucu"; +"web_game_title" = "Oyun: Doğru mu yanlış mı?"; +"web_game_intro" = "Ludwig sana değerler ve bir koşul gösterir. Koşul doğru (true) mu yanlış (false) mı? On tur, giderek zorlaşır."; +"web_game_start" = "Oyunu başlat"; +"web_game_round_fmt" = "Tur %@ / %@"; +"web_game_score_fmt" = "Puan: %@"; +"web_game_true" = "doğru (true)"; +"web_game_false" = "yanlış (false)"; +"web_game_right" = "Doğru!"; +"web_game_wrong" = "Maalesef yanlış. Şöyle hesaplanır:"; +"web_game_next" = "İleri"; +"web_game_finish" = "Sonuç"; +"web_game_done_fmt" = "%@ / %@ doğru."; +"web_game_perfect" = "Hepsi doğru – Ludwig çok etkilendi!"; +"web_game_good" = "Harika! Hatalarına bir daha bak ve yeniden dene."; +"web_game_practice" = "Pratik mükemmelleştirir. Yukarıdaki doğruluk tablosunu tekrar oku ve bir tur daha oyna."; +"web_game_again" = "Tekrar oyna"; +"web_game_wrong_short" = "Maalesef yanlış."; +"web_game_practice_short" = "Pratik mükemmelleştirir. Açıklamaları tekrar oku ve bir tur daha oyna."; +"web_game_clicks" = "Tıklamalar:"; +"web_game_nobody" = "Kimse dinlemiyor – hiçbir şey olmuyor."; +"web_game_event_fmt" = "“%@” tıklandı: dinleyici bunu duyar ve kodunu çalıştırır."; +"web_game_try" = "Şimdi penceredeki düğmeleri kendin dene."; +"web_game_time_fmt" = "%@ sn kaldı"; +"web_game_defused" = "✂️ Etkisiz hâle getirildi! Hatayı buldun."; +"web_game_boom_time" = "💥 Bum! Süre doldu."; +"web_game_boom_wrong" = "💥 Bum! Yanlış satırdı."; +"web_game_fix" = "Doğru satır:"; +"web_game_order_hint" = "Adımlara doğru sırayla dokun."; +"web_debug_step" = "Adım"; +"web_debug_step_title" = "Adım: bir komutu çalıştır ve yeniden dur"; +"web_debug_continue" = "Bir sonraki kesme noktasına kadar devam et"; +"web_debug_paused_fmt" = "%d. satırdan önce duraklatıldı."; +"web_debug_gutter_title" = "Kesme noktası koymak veya kaldırmak için satır numarasına tıkla"; +"web_swap_to_code" = "Programlama büyük"; +"web_swap_to_editor" = "Yapı diyagramı büyük"; +"web_editor_resize" = "Diyagram genişliğini değiştir"; +"web_palette_resize" = "Öğelerin genişliğini değiştir"; +"web_palette_hide" = "Öğeleri gizle"; +"web_palette_show" = "Öğeleri göster"; +"web_code_scopes" = "Renkli kod blokları"; +"web_code_scopes_hint" = "Sınıf, metot, döngü, dallanma kendi kutularında"; +"web_pseudocode" = "Sözde kod"; +`;export{e as default}; diff --git a/website/app/assets/uk-DQrOpK2W.js b/website/app/assets/uk-DQrOpK2W.js new file mode 100644 index 00000000..4836970c --- /dev/null +++ b/website/app/assets/uk-DQrOpK2W.js @@ -0,0 +1,180 @@ +const e=`/* Тексти, які є лише у веб-версії. Усі інші беруться з Localizable.strings застосунку. */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "Структурна схема VisuStruct"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "Експорт…"; +"web_export_title" = "Зберегти як зображення або PDF чи надрукувати"; +"web_export_png" = "Зображення (PNG)"; +"web_export_svg" = "Векторна графіка (SVG)"; +"web_export_pdf" = "PDF (A4)"; +"web_export_visustruct" = "Файл VisuStruct (.visustruct)"; +"web_export_failed_fmt" = "Помилка експорту: %@"; +"web_print_hint" = "Через «Експорт… → PDF» можна зберегти схему, а потім надрукувати її."; +"web_delete" = "Видалити"; +"web_language_title" = "Мова інтерфейсу"; +"web_simulation_start" = "Запустити симуляцію"; +"web_simulation_end" = "Завершити симуляцію"; +"web_simulation_start_title" = "Виконати схему крок за кроком"; +"web_simulation_end_title" = "Завершити симуляцію та продовжити редагування"; +"web_palette_hint" = "Перетягніть у схему"; +"web_tabs_label" = "Схеми"; +"web_status_modified" = "змінено"; +"web_inspector_title" = "Властивості"; +"web_inspector_help_drop" = "Перетягуйте елементи з палітри на плитку: зверху = перед, знизу = після, на «ø» = замінити. Наявні елементи можна переміщувати мишею."; +"web_inspector_help_files" = "Файли також можна перетягнути у вікно."; +"web_case_name" = "Назва випадку"; +"web_case_name_placeholder" = "напр. 1, ok, default"; +"web_copied" = "Елемент скопійовано."; +"web_discard_message_fmt" = "Зміни в «%@» буде втрачено."; +"web_err_unreadable_fmt" = "«%@» не є придатним для читання файлом VisuStruct (%@)."; +"web_saved_fmt" = "«%@» збережено."; +"web_saved_txt_fmt" = "Збережено як «%@». Видаліть розширення .txt, щоб використати файл."; +"web_drop_impossible" = "Сюди не можна помістити"; +"web_sim_delay" = "Пауза на крок"; +"web_sim_delay_value_fmt" = "%@ с"; +"web_codegen_language" = "Мова"; +"web_codegen_comments" = "Текст схеми як коментарі"; +"web_codegen_empty_else" = "Виводити порожню гілку else в коді"; +"web_copied_check" = "Скопійовано ✓"; +"web_copy_manual" = "Виділено, натисніть Ctrl+C, щоб скопіювати"; +"web_run_stopped_loop" = "Виконання зупинено: можливий нескінченний цикл."; +"web_run_cancelled" = "Виконання скасовано."; +"web_run_error" = "Помилка під час виконання."; +"web_run_dropped_fmt" = "… приховано попередніх рядків: %d"; +"web_sim_call_arguments_fmt" = "Виклик не відповідає заголовку %@. Перевір значення в дужках."; +"web_sim_missing_return_fmt" = "%@ завершилася, не повернувши значення через return."; +"web_sim_file_not_found_fmt" = "Файлу з назвою %@ немає."; +"web_sim_end_of_file_fmt" = "У файлі %@ більше немає рядків."; +"web_sim_null_value_fmt" = "%@ дорівнює null."; +"web_sim_written_file_fmt" = "%@ (збережено)"; +"web_site_home" = "Головна сторінка"; +"web_site_imprint" = "Вихідні дані"; +"web_site_privacy" = "Конфіденційність"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "Програмування"; +"web_live_hide" = "Сховати програмування"; +"web_scale_canvas" = "Розмір тексту: структурна схема"; +"web_scale_code" = "Розмір тексту: програмування"; +"web_live_indent" = "Відступи"; +"web_live_indent_title" = "Розставити відступи: чотири пробіли на рівень (виділені рядки, інакше все)"; +"web_live_show" = "Показати програмування"; +"web_live_resize" = "Змінити ширину області коду (подвійний клік: скинути)"; +"web_live_hint" = "Код росте разом із діаграмою. Сірий = заповнювач: пиши в інспекторі, і текст з’явиться тут. Клацни рядок, щоб вибрати елемент."; +"web_live_ph_selector" = "змінна"; +"web_live_ph_code" = "Твій код"; +"web_live_ph_end" = "кінець"; +"web_live_language" = "Мова програмування"; +"web_live_java_class" = "Як клас"; +"web_live_java_class_hint" = "Назва класу = заголовок діаграми"; +"web_live_java_main" = "З методом main"; +"web_settings_display" = "Вигляд"; +"web_live_swing" = "Справжня Java (зі Swing)"; +"web_live_swing_hint" = "Справжня Java з вікнами (CheerpJ). Під час першого запуску одноразово завантажує близько 40 МБ."; +"web_live_swing_windows" = "Вікна Java"; +"web_live_swing_hide" = "Закрити вікна Java"; +"web_live_swing_loading" = "Завантаження Java (уперше близько 40 МБ) …"; +"web_live_swing_compiling" = "Компіляція …"; +"web_live_swing_running" = "Програма виконується."; +"web_live_swing_compile_failed" = "Помилка компіляції, див. вище."; +"web_live_swing_failed" = "Не вдалося завантажити Java. Перевір підключення до інтернету."; +"web_live_hint_edit" = "Набери тут код Java, і діаграма будується сама. Або працюй у діаграмі, і код росте разом із нею. Сірий = заповнювач, просто пиши поверх."; +"web_live_edit_label" = "Код Java"; +"web_parse_line_fmt" = "Рядок %d: %@"; +"web_parse_missing" = "Тут ще бракує: %@"; +"web_parse_extra" = "Зайве: %@"; +"web_parse_unclosed_string" = "Бракує закривного %@."; +"web_parse_else_without_if" = "Цей «else» не має «if»."; +"web_parse_case_outside_switch" = "«case» і «default» мають бути всередині «switch»."; +"web_parse_missing_do_while" = "Після «do { … }» бракує «while (умова);»."; +"web_parse_more_methods" = "Поки що тут враховується лише один метод. Інші підпрограми створи в окремих вкладках."; +"web_parse_missing_import" = "На самому початку бракує %@ Без цього рядка Java не знає Scanner."; +"web_parse_missing_scanner" = "Спочатку бракує %@ Без цього рядка Scanner не існує."; +"web_parse_unknown_type" = "Java не знає такого типу даних. Можливо, %@?"; +"web_editor_title" = "Діаграма"; +"web_editor_show" = "Показати діаграму"; +"web_editor_hide" = "Сховати діаграму"; +"web_keywords_title" = "Ключові слова коду"; +"web_keywords_hint" = "if, while, for замість назв елементів"; +"web_palette_compact" = "Елементи завжди компактно"; +"web_palette_compact_hint" = "Значок із маленькою назвою під ним, інакше лише за вузької колонки"; +"web_about_version_fmt" = "Версія %@"; +"web_about_software" = "Використане програмне забезпечення"; +"web_about_software_text" = "Редактор коду використовує CodeMirror і Lezer (ліцензія MIT). З підтримкою Swing VisuStruct завантажує CheerpJ від Leaning Technologies (ліцензія Community) і javac з OpenJDK."; +"web_about_licenses" = "Тексти ліцензій"; +"web_live_run" = "Запустити"; +"web_live_run_title" = "Запустити програму: виведення і введення з’являться нижче"; +"web_live_run_finished" = "Програму завершено."; +"web_live_run_stopped" = "Зупинено."; +"web_console" = "Консоль"; +"web_console_hide" = "Сховати консоль"; +"web_console_resize" = "Змінити висоту консолі"; +"web_diagram_tools" = "Інструменти діаграми"; +"web_files_title" = "Файли"; +"web_files_show" = "Показати файли"; +"web_files_hide" = "Сховати файли"; +"web_files_resize" = "Змінити ширину файлів"; +"web_files_new_folder" = "Нова тека"; +"web_files_switch" = "Вибрати іншу теку"; +"web_files_delete" = "Видалити"; +"web_files_in_browser" = "У сховищі цього браузера"; +"web_files_save_hint_fmt" = "Під час збереження програма потрапляє в %@."; +"web_files_empty" = "Ще нічого не збережено. Під час збереження VisuStruct створює тут теку з сьогоднішньою датою."; +"web_files_reconnect_hint" = "Після перезавантаження браузер ще раз запитає, чи може VisuStruct використовувати твою теку."; +"web_files_reconnect_fmt" = "Відкрити теку «%@»"; +"web_files_connect_hint" = "Вибери теку як робочий простір. VisuStruct створює в ній теку для кожного дня і зберігає діаграму та код."; +"web_files_connect" = "Вибрати теку"; +"web_files_browser_hint" = "Цей браузер не може відкривати теки на пристрої (напр. на iPad). Твої файли залишаються у сховищі цього браузера."; +"web_files_browser" = "Зберегти в браузері"; +"web_files_delete_confirm_fmt" = "Справді видалити «%@»?"; +"web_files_folder_prompt" = "Назва нової теки:"; +"web_files_default_name" = "Програма"; +"web_files_saved_fmt" = "Збережено: %@"; +"web_files_create" = "Створити"; +"web_learn_ludwig_tip" = "Порада Людвіга"; +"web_game_title" = "Гра: Істина чи хиба?"; +"web_game_intro" = "Людвіг показує значення й умову. Умова істинна (true) чи хибна (false)? Десять раундів, щоразу складніше."; +"web_game_start" = "Почати гру"; +"web_game_round_fmt" = "Раунд %@ з %@"; +"web_game_score_fmt" = "Бали: %@"; +"web_game_true" = "істина (true)"; +"web_game_false" = "хиба (false)"; +"web_game_right" = "Правильно!"; +"web_game_wrong" = "Не зовсім. Ось як це обчислюється:"; +"web_game_next" = "Далі"; +"web_game_finish" = "Результат"; +"web_game_done_fmt" = "%@ з %@ правильно."; +"web_game_perfect" = "Усе правильно – Людвіг вражений!"; +"web_game_good" = "Чудово! Переглянь помилки й спробуй ще раз."; +"web_game_practice" = "Практика робить майстра. Перечитай таблицю істинності й зіграй ще раз."; +"web_game_again" = "Грати ще"; +"web_game_wrong_short" = "На жаль, неправильно."; +"web_game_practice_short" = "Повторення — мати навчання. Перечитай пояснення і зіграй ще раунд."; +"web_game_clicks" = "Кліки:"; +"web_game_nobody" = "Ніхто не слухає — нічого не відбувається."; +"web_game_event_fmt" = "Клік по «%@»: слухач чує це і виконує свій код."; +"web_game_try" = "Тепер спробуй кнопки у вікні сам."; +"web_game_time_fmt" = "Залишилось %@ с"; +"web_game_defused" = "✂️ Знешкоджено! Ти знайшов помилку."; +"web_game_boom_time" = "💥 Бум! Час вийшов."; +"web_game_boom_wrong" = "💥 Бум! Це був не той рядок."; +"web_game_fix" = "Правильний рядок:"; +"web_game_order_hint" = "Натискай на кроки в правильному порядку."; +"web_debug_step" = "Крок"; +"web_debug_step_title" = "Крок: виконати одну інструкцію й знову зупинитися"; +"web_debug_continue" = "Далі до наступної точки зупинки"; +"web_debug_paused_fmt" = "Зупинено перед рядком %d."; +"web_debug_gutter_title" = "Клацни номер рядка, щоб поставити або прибрати точку зупинки"; +"web_swap_to_code" = "Програмування великим"; +"web_swap_to_editor" = "Структурограма великою"; +"web_editor_resize" = "Змінити ширину структурограми"; +"web_palette_resize" = "Змінити ширину елементів"; +"web_palette_hide" = "Сховати елементи"; +"web_palette_show" = "Показати елементи"; +"web_code_scopes" = "Кольорові блоки коду"; +"web_code_scopes_hint" = "Клас, метод, цикл, розгалуження в окремих рамках"; +"web_pseudocode" = "Псевдокод"; +`;export{e as default}; diff --git a/website/app/assets/visubot-CyGFOI9V.webp b/website/app/assets/visubot-CyGFOI9V.webp new file mode 100644 index 0000000000000000000000000000000000000000..7dc5b040a8fa4d79dade3909766fb21dcb77d090 GIT binary patch literal 9042 zcmV-YBdy$0Nk&FWBLDzbMM6+kP&il$0000G0001^003VA06|PpNX88S00HkO5FqfM zE+8TjcX`ca!eJx1al<__?}_~vOjfdi$VTsNI#M89jHeew!OUlfx-X}M>;b9LZLqXd%lEWYN?qv`W z6F`qGA92x_){t#)@MC$VuxLFDs?5qJ<+vr?$hKYE${1gpKP5yubf6f63m~nv*MBq(7ysfvhtjzQL z{-+*#vy~ya5ua`0LLW};LP)n-}A&lK-JtYNNU{nhVQr-a#ulU z(P=azB*5%558QL_Ng#3a3yr4vmj8Sy#6kifv?L7rWa4%r79Su<7gD za#zJ!pym!{l0kfC-bEe0Uh&1;rVZV_P$vNdO=Wb{7fDx zl(`**#g3*a9NhQmCu$H@KDA%E>os2gELU?2$1EhU|BjE|=>%Wdg1zP+tu6_#n-2nJ zn!rPE`}7#1E1B~f9ut7grz)eN-`DtWMxu@X>@StRN#ybEW55q2@l~Q%;KEkgf?W= zJ1KM}Qa&ElL4W{HZFVf!jr-P{u0VvR-~6R) z_8^cmw0gyFnl4ycE`{X+7OIFZJwQSNc~0zyDp3|DbaxL_(!`dFFmss1=20$$oRk3i+(UTam7WrB-6J)_JD@r$}sxMaaI-fHV<6+I!o}X(AL^ z#?`%rZ9jc9)|Ux5Q~RcLp^~;T9@`K(EuEF_&MYZsK`FHl{lJxzXUB>{q^5gHE@RK; zQ_BWQJoY5Pk6drbld+@S8*kaYc6GUbZEzRc_Pza=B+txLqe)!1*^T1|&e}2w5NkZS zZ`xih*^Kg~qdnjAp+Eo5&GOdo={fgAJuUiHm#<#)%*i|wlj{QL<4+a&au9<{Z@O}8 z2d2l`Y9h@e$-nn~Sz7A2<*i%#ht}NigID#cB%N++2D~~O~8fWdYMB=8G4z?`=>DhZ@ z5^IQ}9B=0_neX+3smb&x*~X6H!x}HTvO9#*kbB9_4A=7D8+zSJ*Q{wvmYT~{nQ9Cv z&2u9hwgn`z1&B=EOy?N`YZ1HnlFrgn5)sk(K?t-O z0^yZ|?rDi5MiC`+RiGU5$pY4vC%paAHYc@1v(@0;TM+Bm)m>gPnkZ24q5DfFGFMDv z6zEJ7pFC!q{K`8HLd?otn}-ZMpDcvVwvl>zX-~uP$(mVdmw>G9F6(Oq0n+ZlRmqRl zl@=Wwq*-#?%_Yqy|NMJD1W+xv4_;DnAFVpzNynKy-8l%sk4;xeOWOn(>M4a+5QXdh z_)E_o8$SNoqvB0m0EuaGwIQ-MO@Ps_{OtrG7(SJCZMiI?c635Abq{@K>E5$hMbo1b zHKb!JF7ys2`U=J`zyB)p{~cn$+1+9)Y6|1e-ShQ(s{n}^ZDGrI)~f0A&rOV`hh zFH#Z*N!-04nt*oJQz6UUB$(k8oK zYdm>xIyzYowD0aWjRv@eTqCsv@T@Og0-9~+A3hrbFTOuLjUuL9-2%)aNkY53fV;{imoJ}7 zofi!7As!7t5Zo1^xr+l7nH+r^HEHX)YE#LQp6SB0YgKQW(T5amZaRr#1D2hA2`)UjGxf{>n zlMqwa=HkDTO`jc!p4UUEbFG(LJgrnc7S*Y9F5rxwtNI*EVCZ-nX|PFaX33(w@bGm3lnq%LO~vrm>Q#7;6H{#VQr-~dv54( zoUwW|^ZH1ZILO%k*_^xCWoWaUW%9Z~?7Nan@Ne5_>Uh?E$txphT0b^bm>0FlZV}Lf z&n?=f^+>Z_y_bMY?Nk6o+s&xqX?pAKs)Xr>pBtZ@$zv>H>Y(QzJT_Bbq@5kHwR`~S zT*H_&#Gz2YxeXjhsI0EO_{5#hkLA_eV$vaCdgR`bYQ9()EzA9o5W=tNhhc!56Ec9a>#?EfE2wOQGihH&gO*B z6cGX3t+gSVI=c;Waz*BH*8$Uwga)7<&CBJk4W}~&eARuntqTxT@W|W}+-aTWRAwR%Gz6}T*Rr@+1-;RctO*i^*cAOZX0>xu@?ae?$*#wqd>JJ(^%{Q z0_0T_5TUa*ZR@$=cEv?YoimrOssiZHmaRK>ZeP19&^Y=0gLgmlA|Oc+vL;PkDv+1X zQ{XVKY~b}4CCJHVOSx9oZQrwN>y~vrG+J~(QsDg458m^?#{rcl-mod7Ko8x*GdPXb znroKt5ylTsoQ^mB%B2I=NMWENG<7#gfypQT=w>LINRwKrP{t;D>8?{_y{)TLdTV3H zMu#`P?DvCxAF-R2jkcXr;R27cue*q4frI)7^B|0 z90KMK#qj^3MoW;3b|`9-btj<2`<{t>6X9@*jB+&`7*?Mj&H!0v2&n(ZnnF)GO)h^P z-H*)?IBVw7Xx(Mu9AA(Ck$U&PAe>eJ3lD{i547-HI7^d4wIz^N9LF6;R27wZ1cV?- z{-&44uwbD9x%`QJ=)4y7A0Nr6i%KhiySpHw%G_R^%A?Owfjo-y$Kou~^?2Y+>MaG% zJe>ZGn}6mP_fQuVz|9d2%$-k7Opcu$K67sP?CA99U!^8Z0vUry>(}3EVc|-U_Xtzp zAhsl+0nzW!__nt1`I)Q03<&^!eqwa&%*g3eXGX`yCabhK{ev_ESvK~vm{-5`6gX=MEho86BUdRTTl;QLebO&}Pg1%Z?OT1P8*r5k$H3nP3ZI z>4|R;qiBSl^<6%5e3a%Y0**UQi_YbV8{n*fxBq^$cST_lg{j;WN&NdRE_6OFXnozU z5peKRZ;YR%C=Lr1QZvPo2HePa&!5~)QR22Dmi;OV8H%4Bib`{pip$RN)0FBi4epx4 z(|`LxE-Qf74Aic_xUSNgI7ReZ> zeU=MmK|2Q>@`pkMdV0$g0Kqh5A})*LdgK8_i8NKUoR8v{<7^OJ4EN~euP!u- z03MACrAXhMw?JV*7Q{VD1{~PCap4uhx4+?~Tc9x2*4&LmVe<9e6`$zlV@xQv?>Ha$Z-~U1RXYL#G@9-2ad=a89V{_kNdMe2t* zm$LO>E!&}H9`OZh%p~)bI8i?Ly-AFS!uXX>FSWK%UuvZ{HWR%k}&IGI3Dr45$;ivWy6Yq)SEpWf(gKNqD(9!^vD^To-A z`8sKhb4xxdQ|UwYWlZK^-VjEJ?F|Dhh%DIDaPLgW9jWp;vAoQi(R;^{=W3QI#pkT* zs{Wl#y+~hsUpKc}3GtnM{ODPfhVX21Sg%r|N+cP(8(Z)q=@n;8aeKB}x{-L6&G^ht z*48{5KMWyvLdHkvqAz|K5VESzL+k(I|1J03*>{eJfkyBl_FbPr1;fas9%^M|%KxD85%F+hha+K-JsevOy@5+;0RI22 zW}yG(U0?w0hM!!4;qxI%9gd?M{};#X=LXsAg_Z~MWbP-8YAKtHNzK}rvKw_I z@$^uZhXl}zxbp0db?(zSgXHtN&e1v^58e1|LlIz9oA@uw= zcRHV|OKDZ&GMdQa0Ff$=hq`G0xN@ou`-EJHn#WqB_?#vMyaJuyD^00z6qMUi8e(o% zcih&p{M-F~ey-V`bJ~EL1t@VPxl|#<08j;>jZ<^do&YP}6jVA=klVs9kWelevPFSD4))_dckCRq9HsiMT3j<}iuh=cq^)6U|IAu17 z44+JemNL&|>7b&h`v$_a5Sh|+yXqcio?uL%yIGPpVNuRTtTenF71%Cl)^E#{d=Gum zIncmoPV~0Bd-S;{;#@2J`W|IP#gw4JFWinX$Z-V)gf&Mcw;l7JK%8j$Nb2AIEtn}y z_zA99{n{4gHC&-Vu5qi)D)y%5@#a~7^kUxthuMVvGwIOaZtb_%;Pe0Gr@fvhW-%ba zIU>}hA_Rq5QLg!BMxw-xjG{>B8&E+;^<~7L*~c);p-pk7<{KLY?PCPHIt|hl-RFQH z>Xw$GOspoWqLSsW{u+UWLWlqhEMc;e*@rc^?zY6{lsbRgktnfB2j}{-ah0tM7nUw- zL%jk=gV+gVAf_Gu0tD$#TIc9Ibz~S7l%LHx`sbR$zUp@PO#K6WrI6jGao_w?$`{4@ zmquHcj+pE!7}>eL7;ZKS*2&m)$53&@w5Yy_ckLEj;w9dH!K#t-08W9I(S*g=zy!)K z$rye>g=75T`}rk!MvLULR41de0)Q%+J&iAwi-7Nx|rYh)n5V9;KS~y2vs^Vki z9Vy9Ij{GpX$Tc1TqDiH4OhHNLTBWu6nav<&_*U5r*BttLT=J|zV`9(jH~+`<2-90V zC8Tg|*Z5#LgDc;pIE9>CCgtFF+yCpB`%(w3Ndy3(Eo{BN3=rf(nif+VjoKPYuB~Pp zUFPW1o?W(KdZDvXv~%!QL-Zstmd0<;j_itLp|(U{p26I|56E6OF9FjyD=?!n*A!fq zJ!|b(&K8UfLl&BIZ9SK$AqdAGzHXia(qJea51scw_C~t-IO}c%N4rM2ht`q$DB&tF z|MF)Ff=xvn3BBV&R#vxYu9G)EIG%@~9#HVqXXetM6H>%R#jlSdty;lhlx^#~08?NzX)!(2S zR6{5V1~)4o`Ng0Q|Lpm^7{ratC6IP<2Q-S=^mu<8w6jK_*K_D&kb21gjzyiZ6xFu! zA&&;Z*|qbqP|5Va! zNpf%$ek_Pv(F7Yl)dax|hjW5g5gFHH1GVK=1aG*n9%;VJgD10VHFjy5r|h$Pf;-GM z6cvn~JkRR;X+n=&G|)5;WX7+2MEQgdzeauG4|PRKo;u>i-lemb|F>;>$KLW_J&^?S=pZ;L{p|) z1TXpf?m7M$u2Uk;_xep2%eH&hWVJ{3L%r9)PnkH+f5TPWr?QMLJBmW_`T?+v zVf>k(x39_>!i)!>r{!1egGb~0v;QV_+%UDYx@wJyE$pD&6lPQW$T4ItqJ=)Wg zjyZ0H%Fw@&hzd=1r3T-^I<@ZVA(7dQJ_YqTJ!kj%ih7qQTl2)KVmm4M@JTNfw68T= zO=nsu5+xL*fz+19J#HZy`0&?Cby(1P@mWPX0Yq4GoG3?nPb9W+{>C;MDSG@O!_F~4 z`DGJ?U4()q zwKH}ZN+h+|3|T*A1*qf!58Q;j8|cV%oe<*54DY4arZi$2SswrZ;MDsK-n4eS3r#cn zxhhOa3y}qEEF4iwr2qUbY2d0 zCu#lBG4AbFJ=^c#aCrF{wno@{NFN|n1a&yM2MQc7pD}Q*g#@AD!cQ_7^a%H=EQjcO zs_4ePiG5WL#$Fm_1uK#IVT~PMT<~0@=U)%mY3IZ-0<)<40C@4?ZW|Iq*ZkUxB4OveKh~D zy?A66b9>03e2gp%7Hrz&!cR(T4^-p&XGC_yj5k0&2Y0|Reo=^j<&#VKI=q)pe-#T= z1j2v7&6LSw3Cue*yq1Z$xj^NDbK-*5`^-U!cF#>Vv>i9y2@T~Dr2~28yNybZ<1+i@ zh^)uSTEA6kQ(XvYlHds>w{w8Rl1rIxM%lg0$1wJd zjT}zd=D@9RlAf~m7Rerm=tLas4;0B+4H65CYg|7!V}pn$ga<;F zFRam0YEi%-ECI45v zYyPI{a@*eON|>bijl?06pzZnC>|$6tygQg-#XToL?baDVSm60xvr@RF#+hb5!UUa~ zI=9Jz*jpi~ScBaZBkft8{~^pCcsjpheLl49ut%;Iwjg%!o}-MA%piOoHDM>H5}-5U zbWRD|0@=fe;B;#Mf6=z*|J_OX@KS(V;VflE{+%t0YoMzOn@PM;_T8iNEFMcZ1M(Q3 zrzs!zM&N8IdH`GXd~W6|HG8^YP}_L~q(2Z=qwO31`|V=A{P8lgeJ^|}Xi~2t^QzI` zItmMhb%wT6>-B^!=^*a6;ZIUG82M8O`a*+zHW$Fl?1CNKFzU62C85QCEM!pAzlO<6 zkpj;^dl3&Wi_fuTY&BM`VZ!#Kt{y2>fsgcJUMlIx;&h+<%6RFemddpdJAC}nf6mdL zzW(2?10HrYt}&~F43`6jHJ2?X#R}_{R_~6PZ}<-|%RvjxA701`@?Y9G4?{)4*4?-Q_}yr0F_AZ>GL6fetbe&!q(_TM@_K z{kL}v719j95y10D0eCSW57FzrdA|EVlHBAp^@tGdeNo!7x*+}XLr_e?inHK%MCpvd zB1)&E!l>ij>PMbTS(X*%7m1K-#oq~1ZQZ9snv0b}+veu*%b4;d?g}8PlE#Xi>aM&J z(-yvu7heb87-^@QvGt^um{8C=a~x$n+_c<3B?4t5f3E9mXL$0k)odlM!)eEKl2fQe zI@}r@sAAN+egx?S4ElmrreXm8!c10q&U$2fL7iWPh&vL`Rq8Yp^gJ4gOKYkG1XHi5 z&q>6-1EJoH<-rBj&q>zxt6=F6XcNq7DW{S3xZe4dmOa$V4ap7|sBMNj$xdf8lqC$g z|LIfTN3B?hiQzpn#0uRURYv%RB;u@YBo~GPeVQWAd~5=;7({{fV?zJwxQ1B)fH#k! zvY>ZBWHPa^VGHt}0&UT;n%k&2F$`17p;AA5fc_QeDL>Q#ZrApKJ#yJB%JNw!yxFy` z!iw9CKp)ccZG*oJaRl-6lLT%q1tB=Q4sYbcM_m?MvjYy(j?cMz)=GK!9N~bebCnls zmow75b8;POx`DQ;AHUP18c@5+^Yd8$K0ObalVbl;u!t_933BS3o_beTab4w?B?zL( z;)_%paVM55MoA>#A-Dts41|_q1iH*z=f-9){mOD?S$`tRa>oS98F7O0vu9P#Yj{@5 z#+gapLiV!1luqqAEphPR+*SWfQPnqGB}oay?0DCLl;nj&FmPI^!H;ueOutfC&{4E+ zn1lQo#`W^fA1xgta}t$(YKK0(_ah&NuVAN;o)C_CtLKKT)eo&{_R!ltAYX*|;mzCg z-a`i9g+`02skNP1r|ay+o9$ug_h1;BfP(O0qyc_;+b0lGEXfAS{gySS zWrnTLaFw4wvZrJ+*hATLntCH)$?Z>U57-Y;kk5l~o|s8aGT&x*^FQh_$wHo!f7Kzy zKgCSw17tD$_So3BdJGIO+JHrrM6`T1)2!+oH82m>sg-4q$Xyd-VO1V$SVP&7b|*hw z$)tdc{uG1d@!+&s=7~Z-upcoe6}*y6bNyyvt5T>8s^E;RLchX;GA+*CZIN_9!-(p0 zW>yCbQKQ502YU6^)%HJcal%FmlDoFCRf10!@D@9Dg@$DV0e@eSx!M*2{(_USJHBN% zB5Y@i>W6`EpGlh!8$A8&#a8(o4@;Qd$xLqD^t&$-ii01Kmr;Wr;!cj`tG>zIn@=pKpKNHQ?MIQ2qww zkZ@orEMO%u8|GmZwdJ)@uj8ks_Yk3gP zALgRK>N@6 z;OhQqe#Yr$2^2*$Q8N3zZ}1pdJr7*VBbdTGix^LyD?7|OHm#@jAZB(qND!7PAXmpsnAO`H8ao&x^9u- z5!hzGMF8$GReM5z+3Y6-c5KL@9c%wT(rwq26o6?|Xu^ZP&qx!i&x5#_gs2U9*Iyd%IKp|yAX`$b!&_^wu z5kA6{ISDW}aNhtI$znvsJp|)$3!@Oq;9pwRHPd-MGO_=>tO5e=0e}E(oQhiy@!$Y0 zl&r(tP=D91uyH7O*e)X66NM-KixJtbiR|(b;wPplY&CCKo5^oeEVvD9-x$zX`GbEAI9lwqv!@@&vG!DUMZgc}hD}7d-&`JNU?WT7v@kn` zP|Z}}SNqCd5_%zoZ8sZmZxL3Zi8`5d{@>61U<0`c{7qlj+!<_dJ@*;xq2#uE$}o*} zj?5H~b|nljjlPp$1y%MKE}lpHdhk=U^;N2d*b<7RM&kOOfThX(f4D@YRN#@jEP8+d E04ZhEH2?qr literal 0 HcmV?d00001 diff --git a/website/app/assets/zh-Hans-CeIYjS3N.js b/website/app/assets/zh-Hans-CeIYjS3N.js new file mode 100644 index 00000000..3c763aeb --- /dev/null +++ b/website/app/assets/zh-Hans-CeIYjS3N.js @@ -0,0 +1,180 @@ +const e=`/* 仅存在于网页版中的文本。其他所有文本均来自应用的 Localizable.strings。 */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct 结构图"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "导出…"; +"web_export_title" = "保存为图片或 PDF,或打印"; +"web_export_png" = "图片(PNG)"; +"web_export_svg" = "矢量图(SVG)"; +"web_export_pdf" = "PDF(A4)"; +"web_export_visustruct" = "VisuStruct 文件(.visustruct)"; +"web_export_failed_fmt" = "导出失败:%@"; +"web_print_hint" = "请通过“导出… → PDF”保存图表,然后从那里打印。"; +"web_delete" = "删除"; +"web_language_title" = "界面语言"; +"web_simulation_start" = "开始模拟"; +"web_simulation_end" = "结束模拟"; +"web_simulation_start_title" = "逐步运行结构图"; +"web_simulation_end_title" = "结束模拟并继续编辑"; +"web_palette_hint" = "拖入结构图"; +"web_tabs_label" = "图表"; +"web_status_modified" = "已修改"; +"web_inspector_title" = "属性"; +"web_inspector_help_drop" = "将元素从面板拖到块上:上部 = 插入到前面,下部 = 插入到后面,拖到“ø”上 = 替换。已有元素可用鼠标移动。"; +"web_inspector_help_files" = "也可以直接将文件拖入窗口。"; +"web_case_name" = "分支名称"; +"web_case_name_placeholder" = "例如 1, ok, default"; +"web_copied" = "已复制元素。"; +"web_discard_message_fmt" = "对“%@”的更改将会丢失。"; +"web_err_unreadable_fmt" = "“%@”不是可读取的 VisuStruct 文件(%@)。"; +"web_saved_fmt" = "已保存“%@”。"; +"web_saved_txt_fmt" = "已另存为“%@”。去掉 .txt 扩展名后即可使用。"; +"web_drop_impossible" = "无法放置在此处"; +"web_sim_delay" = "每步暂停"; +"web_sim_delay_value_fmt" = "%@ 秒"; +"web_codegen_language" = "语言"; +"web_codegen_comments" = "将图表文字作为注释"; +"web_codegen_empty_else" = "在代码中输出空的 else 分支"; +"web_copied_check" = "已复制 ✓"; +"web_copy_manual" = "已选中,按 Ctrl+C 复制"; +"web_run_stopped_loop" = "执行已停止:可能存在无限循环。"; +"web_run_cancelled" = "执行已取消。"; +"web_run_error" = "运行时出错。"; +"web_run_dropped_fmt" = "… 已隐藏之前的 %d 行"; +"web_sim_call_arguments_fmt" = "调用与 %@ 的首行不匹配。请检查括号中的值。"; +"web_sim_missing_return_fmt" = "%@ 结束时没有用 return 返回值。"; +"web_sim_file_not_found_fmt" = "没有名为 %@ 的文件。"; +"web_sim_end_of_file_fmt" = "文件 %@ 没有更多行了。"; +"web_sim_null_value_fmt" = "%@ 是 null。"; +"web_sim_written_file_fmt" = "%@(已保存)"; +"web_site_home" = "主页"; +"web_site_imprint" = "版权信息"; +"web_site_privacy" = "隐私"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "编程"; +"web_live_hide" = "隐藏编程"; +"web_scale_canvas" = "文字大小:结构图"; +"web_scale_code" = "文字大小:编程"; +"web_live_indent" = "缩进"; +"web_live_indent_title" = "缩进代码:每层四个空格(选中的行,否则全部)"; +"web_live_show" = "显示编程"; +"web_live_resize" = "更改代码区宽度(双击:重置)"; +"web_live_hint" = "代码随图一起生成。灰色 = 占位符:在检查器中输入,文字就会出现在这里。点击某行可选中对应元素。"; +"web_live_ph_selector" = "变量"; +"web_live_ph_code" = "你的代码"; +"web_live_ph_end" = "结束"; +"web_live_language" = "编程语言"; +"web_live_java_class" = "作为类"; +"web_live_java_class_hint" = "类名 = 结构图标题"; +"web_live_java_main" = "包含 main 方法"; +"web_settings_display" = "显示"; +"web_live_swing" = "真正的 Java(含 Swing)"; +"web_live_swing_hint" = "带窗口的真正 Java(CheerpJ)。首次运行时一次性下载约 40 MB。"; +"web_live_swing_windows" = "Java 窗口"; +"web_live_swing_hide" = "关闭 Java 窗口"; +"web_live_swing_loading" = "正在加载 Java(首次约 40 MB)…"; +"web_live_swing_compiling" = "正在编译…"; +"web_live_swing_running" = "程序正在运行。"; +"web_live_swing_compile_failed" = "编译错误,见上方。"; +"web_live_swing_failed" = "无法加载 Java。请检查网络连接。"; +"web_live_hint_edit" = "在这里输入 Java 代码,结构图会随之生成。或者在结构图中操作,代码也会一起增长。灰色 = 占位符,直接覆盖输入即可。"; +"web_live_edit_label" = "Java 代码"; +"web_parse_line_fmt" = "第 %d 行:%@"; +"web_parse_missing" = "这里还缺少:%@"; +"web_parse_extra" = "多余:%@"; +"web_parse_unclosed_string" = "这里缺少结尾的 %@。"; +"web_parse_else_without_if" = "这个“else”没有对应的“if”。"; +"web_parse_case_outside_switch" = "“case”和“default”应写在“switch”里面。"; +"web_parse_missing_do_while" = "“do { … }”之后还缺少“while (条件);”。"; +"web_parse_more_methods" = "目前这里只计入一个方法。请在单独的标签页中创建其他子程序。"; +"web_parse_missing_import" = "最上面缺少 %@ 没有这一行,Java 不认识 Scanner。"; +"web_parse_missing_scanner" = "前面缺少 %@ 没有这一行就没有 Scanner。"; +"web_parse_unknown_type" = "Java 不认识这个数据类型。你是想写 %@ 吗?"; +"web_editor_title" = "结构图"; +"web_editor_show" = "显示结构图"; +"web_editor_hide" = "隐藏结构图"; +"web_keywords_title" = "代码关键字"; +"web_keywords_hint" = "用 if、while、for 代替元素名称"; +"web_palette_compact" = "元素始终紧凑显示"; +"web_palette_compact_hint" = "图标下方显示小字名称;否则仅在栏较窄时"; +"web_about_version_fmt" = "版本 %@"; +"web_about_software" = "使用的软件"; +"web_about_software_text" = "代码编辑器使用 CodeMirror 和 Lezer(MIT 许可证)。启用 Swing 支持后,VisuStruct 会加载 Leaning Technologies 的 CheerpJ(Community 许可证)和 OpenJDK 的 javac。"; +"web_about_licenses" = "许可证文本"; +"web_live_run" = "运行"; +"web_live_run_title" = "运行程序:输出和输入显示在下方"; +"web_live_run_finished" = "程序已结束。"; +"web_live_run_stopped" = "已停止。"; +"web_console" = "控制台"; +"web_console_hide" = "隐藏控制台"; +"web_console_resize" = "调整控制台高度"; +"web_diagram_tools" = "图表工具"; +"web_files_title" = "文件"; +"web_files_show" = "显示文件"; +"web_files_hide" = "隐藏文件"; +"web_files_resize" = "调整文件栏宽度"; +"web_files_new_folder" = "新建文件夹"; +"web_files_switch" = "选择其他文件夹"; +"web_files_delete" = "删除"; +"web_files_in_browser" = "在此浏览器的存储中"; +"web_files_save_hint_fmt" = "保存时程序将放入 %@。"; +"web_files_empty" = "还没有保存任何内容。保存时,VisuStruct 会在这里创建一个以今天日期命名的文件夹。"; +"web_files_reconnect_hint" = "重新加载后,浏览器会再次询问 VisuStruct 是否可以使用你的文件夹。"; +"web_files_reconnect_fmt" = "打开文件夹“%@”"; +"web_files_connect_hint" = "选择一个文件夹作为工作区。VisuStruct 会在其中为每一天创建文件夹,并保存图和代码。"; +"web_files_connect" = "选择文件夹"; +"web_files_browser_hint" = "此浏览器无法打开设备上的文件夹(例如 iPad)。你的文件会保留在此浏览器的存储中。"; +"web_files_browser" = "保存在浏览器中"; +"web_files_delete_confirm_fmt" = "确定删除“%@”?"; +"web_files_folder_prompt" = "新文件夹名称:"; +"web_files_default_name" = "程序"; +"web_files_saved_fmt" = "已保存:%@"; +"web_files_create" = "新建"; +"web_learn_ludwig_tip" = "路德维希的提示"; +"web_game_title" = "游戏:真还是假?"; +"web_game_intro" = "路德维希给你看一些值和一个条件。这个条件是真(true)还是假(false)?共十轮,越来越难。"; +"web_game_start" = "开始游戏"; +"web_game_round_fmt" = "第 %@ 轮,共 %@ 轮"; +"web_game_score_fmt" = "得分:%@"; +"web_game_true" = "真 (true)"; +"web_game_false" = "假 (false)"; +"web_game_right" = "答对了!"; +"web_game_wrong" = "不太对。是这样计算的:"; +"web_game_next" = "下一轮"; +"web_game_finish" = "结果"; +"web_game_done_fmt" = "答对 %@ / %@。"; +"web_game_perfect" = "全部正确——路德维希被你折服了!"; +"web_game_good" = "很棒!再看看错题,然后再试一次。"; +"web_game_practice" = "熟能生巧。再读一遍上面的真值表,再玩一轮吧。"; +"web_game_again" = "再玩一次"; +"web_game_wrong_short" = "很遗憾,答错了。"; +"web_game_practice_short" = "熟能生巧。再读一遍解释,再玩一轮吧。"; +"web_game_clicks" = "点击:"; +"web_game_nobody" = "没有人在监听——什么也不会发生。"; +"web_game_event_fmt" = "点击“%@”:监听器听到后执行它的代码。"; +"web_game_try" = "现在自己试试窗口里的按钮吧。"; +"web_game_time_fmt" = "还剩 %@ 秒"; +"web_game_defused" = "✂️ 拆除成功!你找到了错误。"; +"web_game_boom_time" = "💥 嘭!时间到了。"; +"web_game_boom_wrong" = "💥 嘭!这不是出错的那一行。"; +"web_game_fix" = "正确的写法:"; +"web_game_order_hint" = "按正确的顺序点击各个步骤。"; +"web_debug_step" = "单步"; +"web_debug_step_title" = "单步:执行一条语句后再次暂停"; +"web_debug_continue" = "继续运行到下一个断点"; +"web_debug_paused_fmt" = "在第 %d 行之前暂停。"; +"web_debug_gutter_title" = "点击行号可设置或删除断点"; +"web_swap_to_code" = "编程放大"; +"web_swap_to_editor" = "结构图放大"; +"web_editor_resize" = "调整结构图宽度"; +"web_palette_resize" = "调整元素宽度"; +"web_palette_hide" = "隐藏元素"; +"web_palette_show" = "显示元素"; +"web_code_scopes" = "代码块彩色显示"; +"web_code_scopes_hint" = "类、方法、循环、分支各有自己的框"; +"web_pseudocode" = "伪代码"; +`;export{e as default}; diff --git a/website/app/assets/zh-Hant-7-ScZHAu.js b/website/app/assets/zh-Hant-7-ScZHAu.js new file mode 100644 index 00000000..cbcbdc06 --- /dev/null +++ b/website/app/assets/zh-Hant-7-ScZHAu.js @@ -0,0 +1,180 @@ +const e=`/* 僅存在於網頁版的文字。其他所有文字皆來自 App 的 Localizable.strings。 */ + +"web_brand_suffix" = "Web"; +"web_file_type" = "VisuStruct 結構圖"; +"web_key_ctrl" = "Ctrl"; +"web_key_delete" = "Del"; +"web_key_shift" = "Shift"; +"web_export" = "匯出…"; +"web_export_title" = "儲存為圖片或 PDF,或列印"; +"web_export_png" = "圖片(PNG)"; +"web_export_svg" = "向量圖形(SVG)"; +"web_export_pdf" = "PDF(A4)"; +"web_export_visustruct" = "VisuStruct 檔案(.visustruct)"; +"web_export_failed_fmt" = "匯出失敗:%@"; +"web_print_hint" = "請透過「匯出… → PDF」儲存圖表,再從那裡列印。"; +"web_delete" = "刪除"; +"web_language_title" = "介面語言"; +"web_simulation_start" = "開始模擬"; +"web_simulation_end" = "結束模擬"; +"web_simulation_start_title" = "逐步執行結構圖"; +"web_simulation_end_title" = "結束模擬並繼續編輯"; +"web_palette_hint" = "拖曳到結構圖中"; +"web_tabs_label" = "圖表"; +"web_status_modified" = "已修改"; +"web_inspector_title" = "屬性"; +"web_inspector_help_drop" = "將元素從面板拖曳到區塊上:上方 = 插入在前,下方 = 插入在後,拖到「ø」上 = 取代。現有元素可用滑鼠移動。"; +"web_inspector_help_files" = "也可以直接將檔案拖曳到視窗中。"; +"web_case_name" = "分支名稱"; +"web_case_name_placeholder" = "例如 1, ok, default"; +"web_copied" = "已複製元素。"; +"web_discard_message_fmt" = "對「%@」所做的變更將會遺失。"; +"web_err_unreadable_fmt" = "「%@」不是可讀取的 VisuStruct 檔案(%@)。"; +"web_saved_fmt" = "已儲存「%@」。"; +"web_saved_txt_fmt" = "已儲存為「%@」。移除 .txt 副檔名後即可使用。"; +"web_drop_impossible" = "無法放置在此處"; +"web_sim_delay" = "每步暫停"; +"web_sim_delay_value_fmt" = "%@ 秒"; +"web_codegen_language" = "語言"; +"web_codegen_comments" = "將圖表文字作為註解"; +"web_codegen_empty_else" = "在程式碼中輸出空的 else 分支"; +"web_copied_check" = "已複製 ✓"; +"web_copy_manual" = "已選取,按 Ctrl+C 複製"; +"web_run_stopped_loop" = "執行已停止:可能是無限迴圈。"; +"web_run_cancelled" = "執行已取消。"; +"web_run_error" = "執行時發生錯誤。"; +"web_run_dropped_fmt" = "… 已隱藏先前的 %d 行"; +"web_sim_call_arguments_fmt" = "呼叫與 %@ 的首行不相符。請檢查括號中的值。"; +"web_sim_missing_return_fmt" = "%@ 結束時沒有用 return 傳回值。"; +"web_sim_file_not_found_fmt" = "沒有名為 %@ 的檔案。"; +"web_sim_end_of_file_fmt" = "檔案 %@ 沒有更多行了。"; +"web_sim_null_value_fmt" = "%@ 是 null。"; +"web_sim_written_file_fmt" = "%@(已儲存)"; +"web_site_home" = "首頁"; +"web_site_imprint" = "版權資訊"; +"web_site_privacy" = "隱私"; + +/* Programmieren (früher „Code live“) */ +"web_live_title" = "程式設計"; +"web_live_hide" = "隱藏程式設計"; +"web_scale_canvas" = "文字大小:結構圖"; +"web_scale_code" = "文字大小:程式設計"; +"web_live_indent" = "縮排"; +"web_live_indent_title" = "縮排程式碼:每層四個空格(選取的行,否則全部)"; +"web_live_show" = "顯示程式設計"; +"web_live_resize" = "變更程式碼區寬度(按兩下:重設)"; +"web_live_hint" = "程式碼會隨圖一起產生。灰色 = 預留位置:在檢閱器中輸入,文字就會出現在這裡。點一下某行可選取對應元素。"; +"web_live_ph_selector" = "變數"; +"web_live_ph_code" = "你的程式碼"; +"web_live_ph_end" = "結束"; +"web_live_language" = "程式語言"; +"web_live_java_class" = "作為類別"; +"web_live_java_class_hint" = "類別名稱 = 結構圖標題"; +"web_live_java_main" = "包含 main 方法"; +"web_settings_display" = "顯示"; +"web_live_swing" = "真正的 Java(含 Swing)"; +"web_live_swing_hint" = "帶視窗的真正 Java(CheerpJ)。首次執行時一次性下載約 40 MB。"; +"web_live_swing_windows" = "Java 視窗"; +"web_live_swing_hide" = "關閉 Java 視窗"; +"web_live_swing_loading" = "正在載入 Java(首次約 40 MB)…"; +"web_live_swing_compiling" = "正在編譯…"; +"web_live_swing_running" = "程式執行中。"; +"web_live_swing_compile_failed" = "編譯錯誤,見上方。"; +"web_live_swing_failed" = "無法載入 Java。請檢查網路連線。"; +"web_live_hint_edit" = "在這裡輸入 Java 程式碼,結構圖會隨之產生。或者在結構圖中操作,程式碼也會一起成長。灰色 = 預留位置,直接覆寫輸入即可。"; +"web_live_edit_label" = "Java 程式碼"; +"web_parse_line_fmt" = "第 %d 行:%@"; +"web_parse_missing" = "這裡還缺少:%@"; +"web_parse_extra" = "多餘:%@"; +"web_parse_unclosed_string" = "這裡缺少結尾的 %@。"; +"web_parse_else_without_if" = "這個「else」沒有對應的「if」。"; +"web_parse_case_outside_switch" = "「case」和「default」應寫在「switch」裡面。"; +"web_parse_missing_do_while" = "「do { … }」之後還缺少「while (條件);」。"; +"web_parse_more_methods" = "目前這裡只計入一個方法。請在單獨的分頁中建立其他子程式。"; +"web_parse_missing_import" = "最上面缺少 %@ 沒有這一行,Java 不認識 Scanner。"; +"web_parse_missing_scanner" = "前面缺少 %@ 沒有這一行就沒有 Scanner。"; +"web_parse_unknown_type" = "Java 不認識這個資料型別。你是想寫 %@ 嗎?"; +"web_editor_title" = "結構圖"; +"web_editor_show" = "顯示結構圖"; +"web_editor_hide" = "隱藏結構圖"; +"web_keywords_title" = "程式碼關鍵字"; +"web_keywords_hint" = "用 if、while、for 取代元素名稱"; +"web_palette_compact" = "元素一律精簡顯示"; +"web_palette_compact_hint" = "圖示下方顯示小字名稱;否則僅在欄位較窄時"; +"web_about_version_fmt" = "版本 %@"; +"web_about_software" = "使用的軟體"; +"web_about_software_text" = "程式碼編輯器使用 CodeMirror 與 Lezer(MIT 授權)。啟用 Swing 支援後,VisuStruct 會載入 Leaning Technologies 的 CheerpJ(Community 授權)與 OpenJDK 的 javac。"; +"web_about_licenses" = "授權條款全文"; +"web_live_run" = "執行"; +"web_live_run_title" = "執行程式:輸出與輸入顯示在下方"; +"web_live_run_finished" = "程式已結束。"; +"web_live_run_stopped" = "已停止。"; +"web_console" = "主控台"; +"web_console_hide" = "隱藏主控台"; +"web_console_resize" = "調整主控台高度"; +"web_diagram_tools" = "圖表工具"; +"web_files_title" = "檔案"; +"web_files_show" = "顯示檔案"; +"web_files_hide" = "隱藏檔案"; +"web_files_resize" = "調整檔案欄寬度"; +"web_files_new_folder" = "新增資料夾"; +"web_files_switch" = "選擇其他資料夾"; +"web_files_delete" = "刪除"; +"web_files_in_browser" = "在此瀏覽器的儲存空間中"; +"web_files_save_hint_fmt" = "儲存時程式會放入 %@。"; +"web_files_empty" = "還沒有儲存任何內容。儲存時,VisuStruct 會在這裡建立一個以今天日期命名的資料夾。"; +"web_files_reconnect_hint" = "重新載入後,瀏覽器會再次詢問 VisuStruct 是否可以使用你的資料夾。"; +"web_files_reconnect_fmt" = "開啟資料夾「%@」"; +"web_files_connect_hint" = "選擇一個資料夾作為工作區。VisuStruct 會在其中為每一天建立資料夾,並儲存圖與程式碼。"; +"web_files_connect" = "選擇資料夾"; +"web_files_browser_hint" = "此瀏覽器無法開啟裝置上的資料夾(例如 iPad)。你的檔案會保留在此瀏覽器的儲存空間中。"; +"web_files_browser" = "儲存在瀏覽器中"; +"web_files_delete_confirm_fmt" = "確定刪除「%@」?"; +"web_files_folder_prompt" = "新資料夾名稱:"; +"web_files_default_name" = "程式"; +"web_files_saved_fmt" = "已儲存:%@"; +"web_files_create" = "新增"; +"web_learn_ludwig_tip" = "路德維希的提示"; +"web_game_title" = "遊戲:真還是假?"; +"web_game_intro" = "路德維希給你看一些值和一個條件。這個條件是真(true)還是假(false)?共十輪,越來越難。"; +"web_game_start" = "開始遊戲"; +"web_game_round_fmt" = "第 %@ 輪,共 %@ 輪"; +"web_game_score_fmt" = "得分:%@"; +"web_game_true" = "真 (true)"; +"web_game_false" = "假 (false)"; +"web_game_right" = "答對了!"; +"web_game_wrong" = "不太對。是這樣計算的:"; +"web_game_next" = "下一輪"; +"web_game_finish" = "結果"; +"web_game_done_fmt" = "答對 %@ / %@。"; +"web_game_perfect" = "全部正確——路德維希被你折服了!"; +"web_game_good" = "很棒!再看看錯題,然後再試一次。"; +"web_game_practice" = "熟能生巧。再讀一遍上面的真值表,再玩一輪吧。"; +"web_game_again" = "再玩一次"; +"web_game_wrong_short" = "很可惜,答錯了。"; +"web_game_practice_short" = "熟能生巧。再讀一遍說明,再玩一輪吧。"; +"web_game_clicks" = "點擊:"; +"web_game_nobody" = "沒有人在監聽——什麼也不會發生。"; +"web_game_event_fmt" = "點擊「%@」:監聽器聽到後執行它的程式碼。"; +"web_game_try" = "現在自己試試視窗裡的按鈕吧。"; +"web_game_time_fmt" = "還剩 %@ 秒"; +"web_game_defused" = "✂️ 拆除成功!你找到了錯誤。"; +"web_game_boom_time" = "💥 砰!時間到了。"; +"web_game_boom_wrong" = "💥 砰!這不是出錯的那一行。"; +"web_game_fix" = "正確的寫法:"; +"web_game_order_hint" = "按正確的順序點擊各個步驟。"; +"web_debug_step" = "單步"; +"web_debug_step_title" = "單步:執行一條敘述後再次暫停"; +"web_debug_continue" = "繼續執行到下一個中斷點"; +"web_debug_paused_fmt" = "在第 %d 行之前暫停。"; +"web_debug_gutter_title" = "點擊行號可設定或刪除中斷點"; +"web_swap_to_code" = "程式設計放大"; +"web_swap_to_editor" = "結構圖放大"; +"web_editor_resize" = "調整結構圖寬度"; +"web_palette_resize" = "調整元素寬度"; +"web_palette_hide" = "隱藏元素"; +"web_palette_show" = "顯示元素"; +"web_code_scopes" = "程式碼區塊彩色顯示"; +"web_code_scopes_hint" = "類別、方法、迴圈、分支各有自己的框"; +"web_pseudocode" = "虛擬碼"; +`;export{e as default}; diff --git a/website/app/assets/zk-zeichen-8efNmpGx.svg b/website/app/assets/zk-zeichen-8efNmpGx.svg new file mode 100644 index 00000000..eac69023 --- /dev/null +++ b/website/app/assets/zk-zeichen-8efNmpGx.svg @@ -0,0 +1,31 @@ + + +String palavra = "Passatempo" +0 +P +1 +a +2 +s +3 +s +4 +a +5 +t +6 +e +7 +m +8 +p +9 +o +substring(0, 5) +→ "Passa" +substring(5) +→ "tempo" +charAt(0) → 'P'length() → 10 +indexOf("tempo") → 5 +O fim de substring não está incluído. + diff --git a/website/app/assets/zk-zeichen-CgUEhNoK.svg b/website/app/assets/zk-zeichen-CgUEhNoK.svg new file mode 100644 index 00000000..0eb01ebf --- /dev/null +++ b/website/app/assets/zk-zeichen-CgUEhNoK.svg @@ -0,0 +1,29 @@ + + +String word = "Billygoat" +0 +B +1 +i +2 +l +3 +l +4 +y +5 +g +6 +o +7 +a +8 +t +substring(0, 5) +→ "Billy" +substring(5) +→ "goat" +charAt(0) → 'B'length() → 9 +indexOf("goat") → 5 +The end of substring is not included. + diff --git a/website/app/assets/zk-zeichen-vYvc3iJg.svg b/website/app/assets/zk-zeichen-vYvc3iJg.svg new file mode 100644 index 00000000..030e9d81 --- /dev/null +++ b/website/app/assets/zk-zeichen-vYvc3iJg.svg @@ -0,0 +1,27 @@ + + +String wort = "Geißbock" +0 +G +1 +e +2 +i +3 +ß +4 +b +5 +o +6 +c +7 +k +substring(0, 4) +→ "Geiß" +substring(4) +→ "bock" +charAt(0) → 'G'length() → 8 +indexOf("bock") → 4 +Das Ende von substring gehört nicht dazu. + diff --git a/website/app/index.html b/website/app/index.html index 217e3492..fb0df971 100644 --- a/website/app/index.html +++ b/website/app/index.html @@ -6,13 +6,8 @@ VisuStruct Web -<<<<<<< HEAD - - -======= - - ->>>>>>> origin/main + +
    From a354f905cf830332adee6883cc562f83ae78ecdf Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 31 Oct 2026 02:19:57 +0000 Subject: [PATCH 3/3] =?UTF-8?q?main=20=C3=BCbernommen,=20Version=200.14.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Ugz28WsFncnVqF96ZZJzbu --- CHANGELOG.md | 2 +- web/lessons/README.md | 2 +- web/src/ui/app.ts | 9 +++++++-- .../{flowApp-RE0WoNHh.js => flowApp-CwdCTHJe.js} | 2 +- .../assets/{index-UBfMpaby.js => index-L2QtAwwh.js} | 10 +++++----- .../{objectApp-DuUC9Wrs.js => objectApp-BFz3uIYn.js} | 6 +++--- .../{projectZip-BjgFtmAO.js => projectZip-ovwyC9wk.js} | 2 +- .../{robot3d-PhMH2w0K.js => robot3d-uruuREju.js} | 2 +- website/app/index.html | 2 +- 9 files changed, 21 insertions(+), 16 deletions(-) rename website/app/assets/{flowApp-RE0WoNHh.js => flowApp-CwdCTHJe.js} (99%) rename website/app/assets/{index-UBfMpaby.js => index-L2QtAwwh.js} (99%) rename website/app/assets/{objectApp-DuUC9Wrs.js => objectApp-BFz3uIYn.js} (99%) rename website/app/assets/{projectZip-BjgFtmAO.js => projectZip-ovwyC9wk.js} (99%) rename website/app/assets/{robot3d-PhMH2w0K.js => robot3d-uruuREju.js} (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dac41b5..7a00bd70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ The format is loosely inspired by Keep a Changelog. ### Added -- **Web 0.14.4, area „Code“ and area colours:** the area „Programmieren“ is now called „Code“ (en „Code“, pt „Código“) in the app, all lessons, VisuBot lessons, tasks and glossary. Struktogramm and Code each have a colour (blue #007aff, violet #7c3aed): a coloured top edge, the slim strip when collapsed, and the area names on the exercise card („Löse diese Übung im Struktogramm und im Code.“). New exercise key `bereich: struktogramm | code | beide`: the card names the area(s) and „Im Editor öffnen“ opens exactly those (nothing is closed). Lesson 20 „Countdown“ and „Fakultät aus Java“ use `beide` (de/en/pt). +- **Web 0.14.4, area „Code“ and area colours:** the area „Programmieren“ is now called „Code“ (en „Code“, pt „Código“) in the app, all lessons, VisuBot lessons, tasks and glossary. Struktogramm and Code each have a colour (blue #007aff, violet #7c3aed): a coloured top edge, the slim strip when collapsed, and the area names on the exercise card („Löse diese Übung im Struktogramm und im Code.“). New exercise key `bereich: struktogramm | code | beide`: the card names the area(s) and „Im Editor öffnen“ shows exactly those: the lessons stay open, everything else (files, mBot2 live, the other area) is closed. Lesson 20 „Countdown“ and „Fakultät aus Java“ use `beide` (de/en/pt). - **Web 0.14.3, Grace Hopper with photo:** lesson 7's Angeberwissen about the moth („bug“) now says who Grace Hopper was (one of the first compilers in 1952, the idea behind COBOL, admiral in the US Navy), followed by her portrait (U.S. Navy, public domain, Commons „Commodore Grace M. Hopper, USN (covered).jpg“, 300×400). Lesson 20 gets an Angeberwissen box: she built one of the first compilers although many said computers could only do arithmetic (de/en/pt). - **Web 0.14.2, Java in the console:** lesson 20 step „Wie Java auf jedem Computer läuft“ has a new Angeberwissen box on `java -version`, `javac Einmaleins.java` and `java Einmaleins`, plus the hint that a missing `javac -version` means only a JRE is installed (de/en/pt). Fix: the two diagrams in that step were missing their closing `:::`, so in 0.14.1 the text after the first diagram showed up as its caption; they now have short captions, and a new test flags overly long captions. - **Web 0.14.1, how Java runs on every computer:** lesson 20 has a new step „Wie Java auf jedem Computer läuft“ after „Snippet oder Class“: source code → compiler `javac` → bytecode (`.class`) → JVM on Windows/macOS/Linux, platform independence („Write once, run anywhere“), the JVM pictured as a small computer made of software (but a virtual machine, not an operating system), a table JRE vs. JDK, the JVM translating bytecode into machine code (JIT compiler), and a comparison with C++ (compiled directly to machine code, so once per system; second diagram l20-cpp.svg and a C++/Java table). New self-drawn diagram l20-jvm.svg (de/en/pt), the CAFEBABE Angeberwissen moved into the new step, three competences, three checklist lines and three quiz questions. Lesson 4 „Jetzt in Java“ points to lesson 20. New glossary entries Quellcode, Compiler, Bytecode, Maschinencode, JIT-Compiler, JVM, JRE, JDK, plattformunabhängig and Nachschlagen section „Java › Vom Code zum Programm“ (de/en/pt). diff --git a/web/lessons/README.md b/web/lessons/README.md index 3447de91..5a188619 100644 --- a/web/lessons/README.md +++ b/web/lessons/README.md @@ -78,7 +78,7 @@ lösung: l2-hallo-loesung.visustruct - `datei:` (optional, nach einem `test:`) Diese Datei soll das Programm in diesem Test speichern, zum Beispiel `datei: einkauf-neu.txt -> Heu | Äpfel | Kuchen`. Verglichen wird Zeile für Zeile wie bei den Ausgaben. - `code: java` (optional) Die Übung wird im Bereich Code in Java gelöst. „Im Editor öffnen“ öffnet die Spalte gleich mit und stellt sie auf Java. Geprüft wird wie sonst das Struktogramm, das beim Tippen entsteht. Eine Musterlösung ist Pflicht, der Test tippt sie als Java und prüft sie. -- `bereich: struktogramm | code | beide` (optional) Wo man die Übung löst. Die Karte zeigt es farbig an (Struktogramm blau, Code violett), und „Im Editor öffnen“ öffnet genau diese Bereiche (geschlossen wird nichts). Ohne Angabe gilt `code` bei `code: java`, sonst `struktogramm`. Für Übungen, bei denen man Code tippt und das Struktogramm liest (oder umgekehrt), `beide` nehmen. +- `bereich: struktogramm | code | beide` (optional) Wo man die Übung löst. Die Karte zeigt es farbig an (Struktogramm blau, Code violett), und „Im Editor öffnen“ zeigt genau diese Bereiche: Lektionen bleiben offen, alles andere (Dateien, mBot2 live, bei `struktogramm` der Code, bei `code` das Struktogramm) wird geschlossen. Ohne Angabe gilt `code` bei `code: java`, sonst `struktogramm`. Für Übungen, bei denen man Code tippt und das Struktogramm liest (oder umgekehrt), `beide` nehmen. - Die Kennung (`l2-hallo`) muss überall eindeutig sein, denn unter ihr wird der Fortschritt gespeichert. Eine Checkliste zum Abhaken: diff --git a/web/src/ui/app.ts b/web/src/ui/app.ts index a28bd498..36921599 100644 --- a/web/src/ui/app.ts +++ b/web/src/ui/app.ts @@ -1231,11 +1231,16 @@ export class App { }, reveal: (areas) => this.revealAreas(areas), openExercise: (ex: Exercise, doc: VSDocument) => { - // Die Übung sagt, wo man sie löst (`bereich:`), und genau diese Bereiche gehen auf. - // Geschlossen wird nichts, so wächst das Struktogramm beim Tippen sichtbar mit. + // Die Übung sagt, wo man sie löst (`bereich:`). Holger 2026-10-31: Lektionen bleiben offen, sonst ist nur + // dieser Bereich zu sehen (bei `beide` Struktogramm und Code); Dateien, mBot2 live usw. gehen zu. const area = exerciseArea(ex) if (area !== 'code') this.setEditorHidden(false) if (area !== 'struktogramm') this.openJavaColumn() + if (this.coding) this.setCoding(false) + if (this.shell.classList.contains('files-open')) this.setFilesOpen(false) + if (this.previewOpen) this.setPreviewOpen(false) + if (area === 'struktogramm' && this.liveCoding) this.setLiveCoding(false) + if (area === 'code' && !this.editorHidden) this.setEditorHidden(true) const existing = this.tabs.findIndex((tab) => tab.exerciseId === ex.id) if (existing >= 0) { this.switchTab(existing) diff --git a/website/app/assets/flowApp-RE0WoNHh.js b/website/app/assets/flowApp-CwdCTHJe.js similarity index 99% rename from website/app/assets/flowApp-RE0WoNHh.js rename to website/app/assets/flowApp-CwdCTHJe.js index 9c9dea86..a27b09ff 100644 --- a/website/app/assets/flowApp-RE0WoNHh.js +++ b/website/app/assets/flowApp-CwdCTHJe.js @@ -1,4 +1,4 @@ -var dt=Object.defineProperty;var lt=(n,t,e)=>t in n?dt(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var y=(n,t,e)=>lt(n,typeof t!="symbol"?t+"":t,e);import{t as h,g as ct,i as I,w as ht,n as ut,f as ft,o as G,q as pt,u as gt,v as wt,x as vt,y as mt,l as xt}from"./index-UBfMpaby.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,yt=170;function bt(n,t,e){const i=[];for(const s of n.split(` +var dt=Object.defineProperty;var lt=(n,t,e)=>t in n?dt(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var y=(n,t,e)=>lt(n,typeof t!="symbol"?t+"":t,e);import{t as h,g as ct,i as I,w as ht,n as ut,f as ft,o as G,q as pt,u as gt,v as wt,x as vt,y as mt,l as xt}from"./index-L2QtAwwh.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,yt=170;function bt(n,t,e){const i=[];for(const s of n.split(` `)){let o="";for(const r of s.split(/\s+/).filter(Boolean)){const a=o?`${o} ${r}`:r;o&&e(a)>t?(i.push(o),o=r):o=a}i.push(o)}return i.length?i:[""]}const q=n=>Math.round(n/m)*m;function C(n,t){const e=bt(n.text,yt,t),i=Math.max(0,...e.map(t)),s=e.length*H;let o,r;if(n.shape==="verzweigung")o=Math.max(140,i*1.7+30),r=Math.max(80,s*1.8+24);else{const a=n.shape==="ein"?44:n.shape==="unterprogramm"?40:n.shape==="anweisung"?24:36;o=Math.max(n.shape==="start"||n.shape==="ende"?100:120,i+a),r=Math.max(40,s+18)}return{x:n.x,y:n.y,w:Math.ceil(o/m)*m,h:Math.ceil(r/m)*m,lines:e}}function V(n){return n==="ende"?[]:n==="verzweigung"?["ja","nein"]:["out"]}const D=n=>n!=="start";function P(n,t,e){var s;if(e==="out")return"bottom";const i=((s=n.yesRight)==null?void 0:s.includes(t.id))??!1;return e==="ja"===i?"right":"bottom"}function F(n,t){return t==="bottom"?[n.x,n.y+n.h/2]:[n.x+n.w/2,n.y]}const _t=n=>[n.x,n.y-n.h/2];function $t(n,t,e,i=0){const[s,o]=F(n,t),[r,a]=_t(e),d=m,u=Math.max(n.x+n.w/2,e.x+e.w/2)+d*(1.5+i);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(n=""){return{title:n,nodes:[],edges:[]}}function it(n,t){const e=new Set([...n.nodes.map(s=>s.id),...n.edges.map(s=>s.id)]);let i=1;for(;e.has(`${t}${i}`);)i++;return`${t}${i}`}function O(n,t,e,i,s){const o=it(n,"n");return{doc:{...n,nodes:[...n.nodes,{id:o,shape:t,x:q(e),y:q(i),text:s}]},id:o}}function J(n,t,e,i){return{...n,nodes:n.nodes.map(s=>s.id===t?{...s,x:Math.max(m*4,q(e)),y:Math.max(m*2,q(i))}:s)}}function Lt(n,t,e){return{...n,nodes:n.nodes.map(i=>i.id===t?{...i,text:e}:i)}}function _(n,t,e,i){const s=n.nodes.find(a=>a.id===t),o=n.nodes.find(a=>a.id===i);if(!s||!o||t===i||!V(s.shape).includes(e)||!D(o.shape))return n;const r=n.edges.filter(a=>!(a.from===t&&a.port===e));return{...n,edges:[...r,{id:it(n,"e"),from:t,port:e,to:i}]}}function Et(n,t){return V(t.shape).find(e=>!n.edges.some(i=>i.from===t.id&&i.port===e))}function kt(n,t){var e;return{...n,nodes:n.nodes.filter(i=>i.id!==t),edges:n.edges.filter(i=>i.from!==t&&i.to!==t),yesRight:(e=n.yesRight)==null?void 0:e.filter(i=>i!==t)}}function St(n,t){return{...n,edges:n.edges.filter(e=>e.id!==t)}}function ot(n,t){const e=new Set(n.yesRight??[]);return e.has(t)?e.delete(t):e.add(t),{...n,yesRight:[...e]}}function b(n){return JSON.stringify({format:"visuflow",version:1,...n},null,2)}function W(n){let t;try{t=JSON.parse(n)}catch{return}if(!t||typeof t!="object")return;const e=t;if(!Array.isArray(e.nodes)||!Array.isArray(e.edges))return;const i=[];for(const o of e.nodes)!o||typeof o.id!="string"||!et.includes(o.shape)||!Number.isFinite(o.x)||!Number.isFinite(o.y)||i.some(r=>r.id===o.id)||i.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:i,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"&&i.some(r=>r.id===o))),s}const z="http://www.w3.org/2000/svg",X="visuflow.doc",Mt=100,Y=14,rt=`${Y}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`,T="#1c1c1e",w=n=>n.replace(/[&<>"]/g,t=>({"&":"&","<":"<",">":">",'"':"""})[t]);function At(n){try{return localStorage.getItem(n)}catch{return null}}function Z(n,t){try{localStorage.setItem(n,t)}catch{}}function It(){const n=xt(),t=n==="pt-PT"?"pt":n==="de"?"de":"en";return`${/\/app\/(index\.html)?$/.test(location.pathname)?"../":"https://visustruct.org/"}${t}/index.html`}function j(n,t,e){const i=URL.createObjectURL(new Blob([t],{type:e})),s=document.createElement("a");s.href=i,s.download=n,s.click(),setTimeout(()=>URL.revokeObjectURL(i),1e3)}function v(n,t={}){const e=document.createElementNS(z,n);for(const[i,s]of Object.entries(t))e.setAttribute(i,String(s));return e}let N;function R(n){return N===void 0&&(N=document.createElement("canvas").getContext("2d")),N?(N.font=rt,N.measureText(n).width):n.length*Y*.55}const Ct=n=>h(`web_visuflow_shape_${n}`),B=n=>h(`web_visuflow_text_${n}`);function at(n,t){const e=t.x-t.w/2,i=t.x+t.w/2,s=t.y-t.h/2,o=t.y+t.h/2;return n==="verzweigung"?v("path",{d:`M${t.x} ${s} L${i} ${t.y} L${t.x} ${o} L${e} ${t.y} Z`}):n==="ein"?v("path",{d:`M${e+14} ${s} L${i} ${s} L${i-14} ${o} L${e} ${o} Z`}):n==="unterprogramm"?v("path",{d:`M${e} ${s} H${i} V${o} H${e} Z M${e+10} ${s} V${o} M${i-10} ${s} V${o}`}):v("rect",{x:e,y:s,width:t.w,height:t.h,rx:n==="anweisung"?2:t.h/2})}function Rt(n){const t=v("text",{"text-anchor":"middle","font-size":Y,fill:T});return n.lines.forEach((e,i)=>{const s=v("tspan",{x:n.x,y:n.y+5+(i-(n.lines.length-1)/2)*H});s.textContent=e,t.append(s)}),t}function Q(n){const t=v("svg",{viewBox:"0 0 64 36",width:64,height:36,"aria-hidden":"true"}),e=at(n,{x:32,y:18,w:n==="verzweigung"?54:56,h:n==="verzweigung"?32:26});return e.setAttribute("fill",st[n]),e.setAttribute("stroke",T),e.setAttribute("stroke-width","1.5"),t.append(e),t.outerHTML}function tt(){let n=nt(h("web_visuflow_example_title"));const t=[],e=(p,f,l,c)=>{const g=O(n,p,f,l,c);n=g.doc,t.push(g.id)};e("start",240,60,B("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,B("ende"));const[i,s,o,r,a,d,u]=t;return n=_(n,i,"out",s),n=_(n,s,"out",o),n=_(n,o,"out",r),n=ot(n,r),n=_(n,r,"ja",a),n=_(n,a,"out",r),n=_(n,r,"nein",d),n=_(n,d,"out",u),n}function Tt(){return O(nt(),"start",240,60,B("start")).doc}class Pt{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(At(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"))} diff --git a/website/app/assets/index-UBfMpaby.js b/website/app/assets/index-L2QtAwwh.js similarity index 99% rename from website/app/assets/index-UBfMpaby.js rename to website/app/assets/index-L2QtAwwh.js index 0cf62d51..91132961 100644 --- a/website/app/assets/index-UBfMpaby.js +++ b/website/app/assets/index-L2QtAwwh.js @@ -64320,7 +64320,7 @@ ${l}`)}Na=rM(((o=e.find(([l])=>l==="begriffe.md"))==null?void 0:o[1])??"")}const

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

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

    ${Me(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,Ku(Xu,this.highlightMode)});const n=e("[data-sim=delay]");n.value=this.delay,n.addEventListener("change",()=>{this.delay=n.value,Ku(Ir,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=`

    ${Me(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),c=l.insertCell();u.kind==="grid"?c.append(rg(u)):c.textContent=Ce(u)}this.variables.replaceChildren(r)}e.outputLines.length===0&&e.files.size===0?this.output.innerHTML=`

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

    `:(this.output.replaceChildren(...e.outputLines.map(r=>{const o=document.createElement("div");return o.textContent=r,o}),...sg(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=`

    ${Me(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?t1(r):"",o.hidden=!r}}function rg(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 x1=Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),Gn=360/x1.length,YM="http://www.w3.org/2000/svg";function Fe(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 xt(i,e={},t){const n=document.createElementNS(YM,i);for(const[a,s]of Object.entries(e))n.setAttribute(a,String(s));return t!==void 0&&(n.textContent=t),n}function XM(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 ec(i,e){const t=xt("g",{class:e}),n=x1.map((a,s)=>{const r=xt("g",{transform:`rotate(${s*Gn})`});return r.append(xt("text",{x:0,y:-i,"text-anchor":"middle","dominant-baseline":"central"},a)),t.append(r),r});return{group:t,cells:n}}function KM(i,e){let t=i,n=!1,a=-t*Gn;const s=Fe("section",{class:"learn-game learn-caesar"});s.append(Fe("div",{class:"learn-game-head"},Fe("strong",{},p("web_learn_caesar_title")))),s.append(Fe("p",{class:"learn-game-status"},p("web_learn_caesar_hint")));const r=xt("svg",{viewBox:"-200 -200 400 400",class:"learn-caesar-disc",role:"img"});r.append(xt("circle",{r:196,class:"outer-disc"})),r.append(xt("path",{d:eZ(196,92,Gn/2),class:"window"}));const o=ec(168,"outer-letters");r.append(o.group);for(let j=0;j{o.cells.forEach((B,E)=>B.classList.toggle("marked",E===j)),u.cells.forEach((B,E)=>B.classList.toggle("marked",j!==void 0&&E===(j+t)%26))},T=()=>{c.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),I.textContent=XM(v.value,n?-t:t)||" ";const j=Array.from(v.value.toUpperCase()).reverse().find(E=>x1.includes(E));if(j===void 0)return k();const B=x1.indexOf(j);k(n?(B-t+26)%26:B)},_=j=>{t=(j%26+26)%26,a=-t*Gn,T()};m.addEventListener("click",()=>_(t-1)),d.addEventListener("click",()=>_(t+1)),f.addEventListener("click",()=>{var j;n&&(v.value=((j=I.textContent)==null?void 0:j.trim())??""),n=!1,T()}),b.addEventListener("click",()=>{var j;n||(v.value=((j=I.textContent)==null?void 0:j.trim())??""),n=!0,T()}),v.addEventListener("input",T),o.cells.forEach((j,B)=>j.addEventListener("click",()=>k(B)));let D;const P=j=>{const B=r.getBoundingClientRect();return Math.atan2(j.clientY-(B.top+B.height/2),j.clientX-(B.left+B.width/2))*180/Math.PI};l.addEventListener("pointerdown",j=>{const B=j;D=P(B)-a,l.classList.add("dragging"),r.setPointerCapture(B.pointerId),B.preventDefault()}),r.addEventListener("pointermove",j=>{if(D===void 0)return;a=P(j)-D,l.setAttribute("transform",`rotate(${a})`);const B=Math.round(-a/Gn);if((B%26+26)%26!==t){t=(B%26+26)%26;const E=a;T(),a=E,l.setAttribute("transform",`rotate(${a})`)}});const O=()=>{D!==void 0&&(D=void 0,l.classList.remove("dragging"),_(t))};return r.addEventListener("pointerup",O),r.addEventListener("pointercancel",O),T(),s}function eZ(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 l0=i=>p(`web_visubot_part_${i}`),og=new WeakMap;function lg(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=(m,d,h)=>{r.hidden=!1,r.textContent=l0(m),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=K(async()=>{const{Robot3D:m}=await import("./robot3d-PhMH2w0K.js");return{Robot3D:m}},[],import.meta.url).then(({Robot3D:m})=>{const d=new m(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(m=>{console.error(m),s.textContent=p("web_visubot_no_3d")}),c={box:a,ready:u,focus:i,view:e};return og.set(a,c),c}function tZ(i,e,t=!1){return lg(i,e,t).box}function nZ(i){const e=i.querySelector(".visubot-model"),t=e&&og.get(e);for(const n of i.querySelectorAll("[data-robot-part]")){const a=(n.dataset.robotPart??"").split(",").filter(Boolean);if(n.title=a.map(l0).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 iZ(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=Tn(`**${t+1}/${i.length}** ${i[t].question}`)},r=lg([],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",l0(l));return}t++,a.className="visubot-quiz-feedback right",t{u.forEach(v=>{window.clearTimeout(v),window.clearInterval(v)}),u=[]},m=()=>{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,I=$("div",{class:"learn-bomb-fuse"},$("span",{})),z=$("span",{class:"learn-bomb-time"}),k=$("div",{class:"learn-bomb","aria-live":"polite"},$("span",{class:"learn-bomb-icon","aria-hidden":"true"},"💣"),z,I),T=$("div",{class:"learn-game-feedback",role:"status"}),_=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,Ku(Xu,this.highlightMode)});const n=e("[data-sim=delay]");n.value=this.delay,n.addEventListener("change",()=>{this.delay=n.value,Ku(Ir,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=`

    ${Me(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),c=l.insertCell();u.kind==="grid"?c.append(rg(u)):c.textContent=Ce(u)}this.variables.replaceChildren(r)}e.outputLines.length===0&&e.files.size===0?this.output.innerHTML=`

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

    `:(this.output.replaceChildren(...e.outputLines.map(r=>{const o=document.createElement("div");return o.textContent=r,o}),...sg(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=`

    ${Me(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?t1(r):"",o.hidden=!r}}function rg(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 x1=Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),Gn=360/x1.length,YM="http://www.w3.org/2000/svg";function Fe(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 xt(i,e={},t){const n=document.createElementNS(YM,i);for(const[a,s]of Object.entries(e))n.setAttribute(a,String(s));return t!==void 0&&(n.textContent=t),n}function XM(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 ec(i,e){const t=xt("g",{class:e}),n=x1.map((a,s)=>{const r=xt("g",{transform:`rotate(${s*Gn})`});return r.append(xt("text",{x:0,y:-i,"text-anchor":"middle","dominant-baseline":"central"},a)),t.append(r),r});return{group:t,cells:n}}function KM(i,e){let t=i,n=!1,a=-t*Gn;const s=Fe("section",{class:"learn-game learn-caesar"});s.append(Fe("div",{class:"learn-game-head"},Fe("strong",{},p("web_learn_caesar_title")))),s.append(Fe("p",{class:"learn-game-status"},p("web_learn_caesar_hint")));const r=xt("svg",{viewBox:"-200 -200 400 400",class:"learn-caesar-disc",role:"img"});r.append(xt("circle",{r:196,class:"outer-disc"})),r.append(xt("path",{d:eZ(196,92,Gn/2),class:"window"}));const o=ec(168,"outer-letters");r.append(o.group);for(let j=0;j{o.cells.forEach((B,E)=>B.classList.toggle("marked",E===j)),u.cells.forEach((B,E)=>B.classList.toggle("marked",j!==void 0&&E===(j+t)%26))},T=()=>{c.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),I.textContent=XM(v.value,n?-t:t)||" ";const j=Array.from(v.value.toUpperCase()).reverse().find(E=>x1.includes(E));if(j===void 0)return k();const B=x1.indexOf(j);k(n?(B-t+26)%26:B)},_=j=>{t=(j%26+26)%26,a=-t*Gn,T()};m.addEventListener("click",()=>_(t-1)),d.addEventListener("click",()=>_(t+1)),f.addEventListener("click",()=>{var j;n&&(v.value=((j=I.textContent)==null?void 0:j.trim())??""),n=!1,T()}),b.addEventListener("click",()=>{var j;n||(v.value=((j=I.textContent)==null?void 0:j.trim())??""),n=!0,T()}),v.addEventListener("input",T),o.cells.forEach((j,B)=>j.addEventListener("click",()=>k(B)));let D;const P=j=>{const B=r.getBoundingClientRect();return Math.atan2(j.clientY-(B.top+B.height/2),j.clientX-(B.left+B.width/2))*180/Math.PI};l.addEventListener("pointerdown",j=>{const B=j;D=P(B)-a,l.classList.add("dragging"),r.setPointerCapture(B.pointerId),B.preventDefault()}),r.addEventListener("pointermove",j=>{if(D===void 0)return;a=P(j)-D,l.setAttribute("transform",`rotate(${a})`);const B=Math.round(-a/Gn);if((B%26+26)%26!==t){t=(B%26+26)%26;const E=a;T(),a=E,l.setAttribute("transform",`rotate(${a})`)}});const O=()=>{D!==void 0&&(D=void 0,l.classList.remove("dragging"),_(t))};return r.addEventListener("pointerup",O),r.addEventListener("pointercancel",O),T(),s}function eZ(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 l0=i=>p(`web_visubot_part_${i}`),og=new WeakMap;function lg(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=(m,d,h)=>{r.hidden=!1,r.textContent=l0(m),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=K(async()=>{const{Robot3D:m}=await import("./robot3d-uruuREju.js");return{Robot3D:m}},[],import.meta.url).then(({Robot3D:m})=>{const d=new m(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(m=>{console.error(m),s.textContent=p("web_visubot_no_3d")}),c={box:a,ready:u,focus:i,view:e};return og.set(a,c),c}function tZ(i,e,t=!1){return lg(i,e,t).box}function nZ(i){const e=i.querySelector(".visubot-model"),t=e&&og.get(e);for(const n of i.querySelectorAll("[data-robot-part]")){const a=(n.dataset.robotPart??"").split(",").filter(Boolean);if(n.title=a.map(l0).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 iZ(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=Tn(`**${t+1}/${i.length}** ${i[t].question}`)},r=lg([],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",l0(l));return}t++,a.className="visubot-quiz-feedback right",t{u.forEach(v=>{window.clearTimeout(v),window.clearInterval(v)}),u=[]},m=()=>{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,I=$("div",{class:"learn-bomb-fuse"},$("span",{})),z=$("span",{class:"learn-bomb-time"}),k=$("div",{class:"learn-bomb","aria-live":"polite"},$("span",{class:"learn-bomb-icon","aria-hidden":"true"},"💣"),z,I),T=$("div",{class:"learn-game-feedback",role:"status"}),_=v.code.split(` `).map((E,U)=>{const ee=$("button",{class:"ln",type:"button"},E||" ");return ee.disabled=!E.trim(),ee.addEventListener("click",()=>j(U+1===v.wrongLine?"right":"wrong",ee)),ee}),D=$("div",{class:"learn-game-code learn-bomb-code mono",dir:"ltr"},..._),P=Date.now(),O=()=>{if(!t.isConnected&&Date.now()-P>1e3)return c();const E=Math.max(0,w-(Date.now()-P)/1e3);z.textContent=p("web_game_time_fmt",Math.ceil(E)),I.firstChild.style.width=`${E/w*100}%`,k.classList.toggle("hurry",E<=5),E<=0&&j("time")},j=(E,U)=>{c(),_.forEach((Ie,fe)=>{Ie.disabled=!0,fe+1===v.wrongLine&&Ie.classList.add("right")}),U&&E==="wrong"&&U.classList.add("wrong");const ee=E==="right";ee&&l++,m(),k.classList.add(ee?"defused":"boom"),k.firstChild.textContent=ee?"✂️":"💥",T.className=`learn-game-feedback ${ee?"right":"wrong"}`;const he=d();T.replaceChildren($("p",{},p(ee?"web_game_defused":E==="time"?"web_game_boom_time":"web_game_boom_wrong")),Fn("div",{class:"learn-game-explain"},v.explanation),$("p",{class:"learn-bomb-fix"},`${p("web_game_fix")} `,$("code",{},v.fix.trim())),he),he.focus({preventScroll:!0})};s.replaceChildren(k,Fn("p",{class:"learn-game-question"},v.question),D,T),O();const B=window.setInterval(O,200);u.push(B)},g=()=>{const v=i.rounds[o],w=[];v.code.trim()&&w.push(nc(v.code).element),w.push(Fn("p",{class:"learn-game-question"},v.question),$("p",{class:"learn-order-hint"},p("web_game_order_hint")));const I=$("div",{class:"learn-game-options learn-order"}),z=$("div",{class:"learn-game-feedback",role:"status"});let k=0;const T=sZ(v.options.length).map(D=>{const P=$("span",{class:"learn-order-badge","aria-hidden":"true"}),O=$("span",{});O.innerHTML=Oe(v.options[D].text);const j=$("button",{},P,O);return j.addEventListener("click",()=>{if(D!==k)return j.classList.add("wrong"),_(!1);j.classList.add("right"),P.textContent=String(++k),j.disabled=!0,k===v.options.length&&_(!0)}),I.append(j),{k:D,b:j,badge:P}}),_=D=>{for(const{k:O,b:j,badge:B}of[...T].sort((E,U)=>E.k-U.k))j.disabled=!0,B.textContent=String(O+1),I.append(j);D&&l++,m(),z.className=`learn-game-feedback ${D?"right":"wrong"}`;const P=d();z.replaceChildren($("p",{},p(D?"web_game_right":"web_game_wrong_short")),Fn("div",{class:"learn-game-explain"},v.explanation),P),P.focus({preventScroll:!0})};s.replaceChildren(...w,I,z)},f=()=>{if(c(),i.kind==="bombe"||i.kind==="reihenfolge"){m(),i.kind==="bombe"?h():g();return}const v=i.rounds[o];m();const w=nc(v.code),I=[];let z;i.kind==="zuhoerer"?(z=rZ(Gh(v.code),w),I.push($("div",{class:"learn-swing-row"},w.element,z.element)),v.clicks.length&&I.push($("p",{class:"learn-swing-clicks"},`${p("web_game_clicks")} `,...v.clicks.flatMap((P,O)=>[...O?[" → "]:[],$("code",{},P)])))):v.code.trim()&&I.push(w.element),I.push(Fn("p",{class:"learn-game-question"},v.question));const k=$("div",{class:`learn-game-options ${i.kind==="layout"?"pictures":""}`}),T=$("div",{class:"learn-game-feedback",role:"status"}),_=v.options.map(P=>{const O=$("button",{});return i.kind==="layout"?O.append(lZ(P.text)):P.text.includes(` `)?O.append(oZ(P.text)):O.innerHTML=Oe(P.text),O.addEventListener("click",()=>D(P.right,O)),k.append(O),O}),D=(P,O)=>{_.forEach((B,E)=>{B.disabled=!0,v.options[E].right&&B.classList.add("right")}),P||O.classList.add("wrong"),P&&l++,m(),T.className=`learn-game-feedback ${P?"right":"wrong"}`;const j=d();T.replaceChildren($("p",{},p(P?"web_game_right":"web_game_wrong_short")),Fn("div",{class:"learn-game-explain"},v.explanation)),T.append(j),z&&(u=z.replay(v.clicks,()=>j.before($("p",{class:"learn-swing-try"},p("web_game_try"))))),j.focus({preventScroll:!0})};s.replaceChildren(...I,k,T)},b=()=>{c(),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(Fn("p",{},i.intro),x),t}function sZ(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 nc(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 rZ(i,e){const t=Hh(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 m of i.labels){const d=$("div",{class:"learn-swing-label"},t.texts[m.name]);s.set(m.name,d),a.append(d)}const r=i.buttons.map(m=>{const d=$("button",{class:"learn-swing-button",disabled:""},t.texts[m.name]);return s.set(m.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=m=>{var h,g;const d=s.get(m.button);d.classList.add("pressed"),window.setTimeout(()=>d.classList.remove("pressed"),350),e.highlight((h=m.listener)==null?void 0:h.from,(g=m.listener)==null?void 0:g.to),o.textContent=m.listener?p("web_game_event_fmt",d.textContent??""):p("web_game_nobody"),o.className=`learn-swing-event ${m.listener?"heard":"nobody"}`;for(const[f,b]of Object.entries(m.texts)){const x=s.get(f);x&&x.textContent!==b&&(x.textContent=b,x.classList.remove("changed"),x.offsetWidth,x.classList.add("changed"))}m.console.length&&(l.hidden=!1,l.textContent+=m.console.map(f=>`${f} @@ -64335,7 +64335,7 @@ ${l}`)}Na=rM(((o=e.find(([l])=>l==="begriffe.md"))==null?void 0:o[1])??"")}const ${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=C("details",{class:"reference-group"});r.open=n.includes(s);const o=C("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(){be.setView({tab:this.tab,lesson:this.lessonId,task:this.taskId})}openLesson(e){this.tab="lessons",this.lessonId=e,this.returnTo=void 0,this.persist(),this.render(),this.body.scrollTop=0}renderLessonList(){this.body.append(C("p",{class:"hint"},p("web_learn_intro")));for(const e of SZ()){this.body.append(C("h3",{class:"learn-section"},e.name));const t=C("ol",{class:"learn-list"});for(const n of e.lessons){const a=be.lesson(n.id),s=a.done?"✓":a.step>0?p("web_learn_step_of_fmt",a.step+1,n.steps.length):"",r=C("button",{class:"learn-item"+(a.done?" done":""),"data-lesson":n.id},C("span",{class:"learn-num"},String(n.number)),C("span",{class:"learn-item-text"},C("strong",{},n.robot?`🤖 ${n.title}`:n.title),C("small",{},n.summary)),C("span",{class:"learn-status"},s));r.addEventListener("click",()=>this.openLesson(n.id)),t.append(C("li",{},r))}this.body.append(t)}this.body.append(this.renderTeacherBox())}renderLesson(e){var u;const t=be.lesson(e.id),n=Math.min(t.step,e.steps.length-1),a=e.steps[n],s=C("button",{class:"learn-back"},`← ${p("web_learn_all_lessons")}`);s.addEventListener("click",()=>this.openLesson(void 0));const r=C("nav",{class:"learn-progress","aria-label":p("web_learn_step_of_fmt",n+1,e.steps.length)});r.append(...e.steps.map((c,m)=>{const d=p("web_learn_step_fmt",m+1,c.title),h=mthis.goToStep(e,m)),g})),this.body.append(C("div",{class:"learn-lesson-head"},C("div",{class:"learn-head-row"},s,this.stepNav(e,n,t.done,"learn-nav learn-nav-top")),C("p",{class:"learn-kicker"},`${p("web_learn_lesson_fmt",e.number)} · ${e.section}${e.robot?" · 🤖 VisuBot":""}`),C("h2",{class:"learn-title"},C("span",{class:"learn-num","aria-hidden":"true"},String(e.number)),e.title),r,C("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 c=C("button",{class:"learn-return"},`↩ ${p("web_learn_back_to_checklist")}`);return c.addEventListener("click",()=>{this.returnTo=void 0,this.goToStep(e,o.step),this.body.scrollTop=o.scroll}),c};o&&this.body.append(l()),a.blocks.forEach((c,m)=>this.body.append(this.renderBlock(c,`${n}-${m}`,e))),lc(this.body),nZ(this.body),this.openNeededColumns(a.blocks),rc(this.body,Na),this.body.append(this.stepNav(e,n,t.done,"learn-nav")),o&&this.body.append(l())}stepNav(e,t,n,a){const s=C("div",{class:a}),r=C("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=C("button",{class:"primary"},n?`✓ ${p("web_learn_done")}`:p("web_learn_finish"));o.addEventListener("click",()=>{be.updateLesson(e.id,{done:!0});const l=Ot.find(u=>u.number===e.number+1);this.openLesson(l==null?void 0:l.id)}),s.append(o)}return s}goToStep(e,t){be.updateLesson(e.id,{step:t}),this.render(),this.body.scrollTop=0}openNeededColumns(e){const t=e.flatMap(n=>n.kind==="exercise"?[n.exercise]:[]);zZ(this.body)?(this.host.showEditor(),yZ(this.body)&&this.host.reveal(["palette"])):wZ(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(),IZ(this.body)&&this.host.showLiveCode()}renderTaskList(){this.body.append(C("p",{class:"hint"},p("web_learn_tasks_intro")));const e=C("ul",{class:"learn-list"});for(const t of jn){const n=this.taskExercises(t),a=n.length>0&&n.every(o=>be.exercise(o.id).done),s=Ot.find(o=>o.number===t.after),r=C("button",{class:"learn-item"+(a?" done":""),"data-task":t.id},C("span",{class:"learn-num","aria-label":p("web_learn_level_fmt",t.level)},"★".repeat(t.level)),C("span",{class:"learn-item-text"},C("strong",{},t.title),C("small",{},s?p("web_learn_after_fmt",s.number,s.title):"")),C("span",{class:"learn-status"},a?"✓":""));r.addEventListener("click",()=>{this.taskId=t.id,this.persist(),this.render(),this.body.scrollTop=0}),e.append(C("li",{},r))}this.body.append(e,this.renderTeacherBox())}renderTeacherBox(){const e=C("details",{class:"learn-teacher"},C("summary",{},p("web_learn_teacher")));if($u()){e.setAttribute("open","");const s=C("button",{},p("web_learn_teacher_off"));return s.addEventListener("click",()=>{qM(),this.render()}),e.append(C("p",{},p("web_learn_teacher_on")),s),e}const t=C("input",{type:"password",autocomplete:"off","aria-label":p("web_learn_teacher_code"),placeholder:p("web_learn_teacher_code")}),n=C("p",{class:"learn-result",role:"status"}),a=C("form",{class:"group"},t,C("button",{type:"submit"},p("web_learn_teacher_unlock")));return a.addEventListener("submit",async s=>{s.preventDefault(),await QM(t.value)?this.render():(n.className="learn-result info",n.textContent=p("web_learn_teacher_wrong"))}),e.append(C("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=C("button",{class:"learn-back"},`← ${p("web_learn_all_tasks")}`);t.addEventListener("click",()=>{this.taskId=void 0,this.persist(),this.render()});const n=Ot.find(a=>a.number===e.after);if(this.body.append(t,C("h2",{class:"learn-title"},e.title)),n){const a=C("button",{class:"link-button"},p("web_learn_after_fmt",n.number,n.title));a.addEventListener("click",()=>this.openLesson(n.id)),this.body.append(C("p",{class:"learn-kicker"},a))}e.blocks.forEach((a,s)=>this.body.append(this.renderBlock(a,`task-${s}`))),lc(this.body),this.openNeededColumns(e.blocks),rc(this.body,Na)}renderBlock(e,t,n){switch(e.kind){case"markdown":return this.withOpenButtons(tt("div",{class:"learn-text"},Tn(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 this.renderGraphic(e.file,e.caption,e.labeled);case"game":return this.renderGame(e.game);case"roundGame":return aZ(e.game,ra);case"rescueGame":return uZ(e.game,ra);case"caesar":return KM(e.key,e.text);case"cloze":return mZ(e.cloze);case"pap":return bZ(e.pap);case"textFile":return ag(e.name,e.content);case"robotModel":return tZ(e.focus,e.view,e.spin);case"robotQuiz":return iZ(e.tasks,e.done)}}renderBrag(e,t=!1){const n=C("aside",{class:"learn-brag"});n.append(C("img",{src:ra,alt:"",width:"48",height:"48"}));const a=C("div",{},C("p",{class:"learn-brag-title"},p(t?"web_learn_ludwig_tip":"web_learn_brag")));return a.append(tt("div",{class:"learn-text"},Tn(e))),n.append(a),n}renderGame(e){const n=C("section",{class:"learn-game"}),a=C("div",{class:"learn-game-head"});a.append(C("img",{src:ra,alt:"",width:"40",height:"40"}),C("strong",{},p("web_game_title")));const s=C("p",{class:"learn-game-status"}),r=C("div",{class:"learn-game-stage"});n.append(a,s,r);let o=0,l=0;const u=()=>{const d=dx(e,o,10);s.textContent=`${p("web_game_round_fmt",o+1,10)} · ${p("web_game_score_fmt",l)}`;const h=C("div",{class:"learn-game-values mono"});for(const[w,I]of hx(d))h.append(C("code",{},`${w} = ${I}`));const g=C("div",{class:"group learn-game-answers"}),f=C("button",{class:"learn-game-true"},`✓ ${p("web_game_true")}`),b=C("button",{class:"learn-game-false"},`✗ ${p("web_game_false")}`);g.append(f,b);const x=C("div",{class:"learn-game-feedback",role:"status"}),v=w=>{f.disabled=b.disabled=!0;const I=w===d.answer;I&&l++,s.textContent=`${p("web_game_round_fmt",o+1,10)} · ${p("web_game_score_fmt",l)}`,x.className=`learn-game-feedback ${I?"right":"wrong"}`;const z=C("div",{class:"learn-game-steps mono"});cx(d.condition,d.values).forEach((T,_)=>z.append(C("div",{},`${_?"→ ":""}${T}`)));const k=C("button",{class:"primary"},o+1<10?p("web_game_next"):p("web_game_finish"));k.addEventListener("click",()=>{o++,o<10?u():c()}),x.replaceChildren(C("p",{},p(I?"web_game_right":"web_game_wrong")),z,k),k.focus()};f.addEventListener("click",()=>v(!0)),b.addEventListener("click",()=>v(!1)),r.replaceChildren(h,C("div",{class:"learn-game-condition mono"},d.condition),g,x)},c=()=>{s.textContent="";const d=C("button",{class:"primary"},p("web_game_again"));d.addEventListener("click",()=>{o=l=0,u()}),r.replaceChildren(C("p",{class:"learn-game-result"},p("web_game_done_fmt",l,10)),C("p",{},p(l===10?"web_game_perfect":l>=10*.7?"web_game_good":"web_game_practice")),d)},m=C("button",{class:"primary"},p("web_game_start"));return m.addEventListener("click",u),r.append(C("p",{},p("web_game_intro")),m),n}renderImages(e,t){const n=C("figure",{class:"learn-figure"}),a=C("div",{class:"learn-images"});for(const s of e){const r=zr(s);r&&a.append(C("img",{src:r,alt:"",loading:"lazy"}))}return n.append(a),t&&n.append(tt("figcaption",{},Oe(t))),n}renderGraphic(e,t,n){const a=C("figure",{class:"learn-figure"}),s=zr(e),r=n?zr(n):void 0;if(s&&r){const o=C("img",{class:"learn-graphic",src:s,alt:"",loading:"lazy"}),l=C("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,C("p",{class:"learn-graphic-hint"},p("web_learn_graphic_labels")))}else s&&a.append(C("img",{class:"learn-graphic",src:s,alt:"",loading:"lazy"}));return t&&a.append(tt("figcaption",{},Oe(t))),a}withOpenButtons(e){for(const t of e.querySelectorAll("pre.lesson-code[data-open=editor]")){const n=t.textContent??"",a=C("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=ti(e),a=C("figure",{class:"learn-figure"});if(!n)return a;const s=this.host.preview(n);s&&a.append(C("div",{class:"learn-preview",dir:"ltr"},s)),t&&a.append(tt("figcaption",{},Oe(t)));const r=C("button",{},p("web_learn_open_in_editor"));return r.addEventListener("click",()=>this.host.openDiagram(n,e)),a.append(r),a}renderExercise(e){const t=C("section",{class:"learn-exercise","data-exercise":e.id}),n=()=>be.exercise(e.id),a=C("span",{class:"learn-badge"},`✓ ${p("web_learn_solved")}`);a.hidden=!n().done,t.append(C("h4",{},`${p("web_learn_exercise")}: ${e.title}`,a),jZ(e),tt("div",{class:"learn-text"},Tn(e.task)));const s=C("div",{class:"learn-result",role:"status"}),r=C("div",{class:"learn-hints"}),o=C("div",{class:"group"}),l=C("button",{class:"primary"},p("web_learn_open_exercise"));l.addEventListener("click",()=>{const m=n().xml;let d=uc(e);if(m)try{d=Nl(m)}catch{}this.host.openExercise(e,d)});const u=C("button",{},p("web_learn_check"));if(u.addEventListener("click",()=>{const m=this.host.exerciseDocument(e.id);if(!m){s.className="learn-result info",s.textContent=p("web_learn_open_first");return}if(m.elements.every(Bl)){s.className="learn-result info",s.textContent=p("web_learn_empty");return}this.host.stopSimulation();const d=sx(m,e.tests,this.host.subprogramsFor(e.id),Ja),h=rx(m),g=e.requires.map(x=>x==="forZaehlSchleife"?"forSchleife":x).filter(x=>x in S&&!h.has(S[x])),f=e.loopDepth!==void 0&&Do(m.elements)x.passed)&&g.length===0&&!f;this.showResult(s,d,g,b,f),b&&(be.updateExercise(e.id,{done:!0}),a.hidden=!1)}),o.append(l,u),e.hints.length>0){const m=C("button",{},p("web_learn_hint"));m.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(tt("aside",{class:"lesson-note"},Tn(h+e.hints[d]))),m.textContent=p("web_learn_hint_more"),m.toggleAttribute("disabled",d+1>=e.hints.length)}),o.append(m)}const c=C("button",{class:"danger-text"},p("web_learn_reset"));if(c.addEventListener("click",()=>{if(c.dataset.confirm!=="1"){c.dataset.confirm="1",c.textContent=p("web_learn_reset_confirm"),setTimeout(()=>{c.dataset.confirm="",c.textContent=p("web_learn_reset")},4e3);return}be.resetExercise(e.id),this.host.resetExercise(e.id,uc(e)),a.hidden=!0,s.replaceChildren(),s.className="learn-result",c.dataset.confirm="",c.textContent=p("web_learn_reset")}),o.append(c),t.append(o,r,s),$u()&&e.solution){const m=ti(e.solution);if(m){const d=C("details",{class:"learn-solution"},C("summary",{},p("web_learn_solution")));d.addEventListener("toggle",()=>{if(!d.open||d.querySelector(".learn-preview"))return;const h=this.host.preview(m);h&&d.append(C("div",{class:"learn-preview",dir:"ltr"},h));const g=C("button",{},p("web_learn_open_in_editor"));g.addEventListener("click",()=>{this.host.openDiagram(m,e.solution);for(const f of e.subprograms){const b=ti(f);b&&this.host.openDiagram(b,f)}});for(const f of e.subprograms){const b=ti(f),x=b&&this.host.preview(b);x&&d.append(C("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,c,m;e.className="learn-result "+(a?"ok":"fail"),e.replaceChildren(C("p",{class:"learn-result-head"},a?`🎉 ${p("web_learn_passed")}`:p("web_learn_failed")));for(const d of n)e.append(C("p",{},`✗ ${p("web_learn_missing_fmt",TZ(S[d]))}`));s&&e.append(C("p",{},`✗ ${p("web_visubot_depth_fmt",s)}`));const r=C("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=C("div",{class:"learn-test-detail"});if(d.test.drive&&b.append(C("span",{},`${p("web_learn_expected")}: `,C("code",{},X1(d.test.drive)||"–")),C("span",{},`${p("web_learn_actual")}: `,C("code",{},X1(d.result.drive??[])||"–"))),d.test.actions&&b.append(C("span",{},`${p("web_learn_expected")}: `,C("code",{},X1(d.test.actions)||"–")),C("span",{},`${p("web_learn_actual")}: `,C("code",{},X1(d.result.actions??[])||"–"))),d.test.led!==void 0){const x=v=>p(v?"web_visubot_led_on":"web_visubot_led_off");b.append(C("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(C("span",{},`🔊 ${p("web_learn_expected")}: ${x(d.test.tone)} · ${p("web_learn_actual")}: ${x(d.result.tone)}`))}d.test.screen!==void 0&&b.append(C("span",{},`📺 ${p("web_learn_expected")}: `,C("code",{},d.test.screen),` · ${p("web_learn_actual")}: `,C("code",{},d.result.screen??"–"))),d.test.world&&(((l=(o=Ja(d.test.world))==null?void 0:o.goals)!=null&&l.length||(c=(u=Ja(d.test.world))==null?void 0:u.targets)!=null&&c.length)&&b.append(C("span",{},d.result.atGoal?`✓ ${p("web_visubot_goal_reached")}`:`✗ ${p("web_visubot_goal_missed")}`)),d.result.bumps&&b.append(C("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(C("span",{},`${p("web_learn_expected")}: `,C("code",{},d.test.expected.join(" | ")||"–")),C("span",{},`${p("web_learn_actual")}: `,C("code",{},d.result.outputs.join(" | ")||"–")));for(const x of d.test.files??[])b.append(C("span",{},`📄 ${x.name}, ${p("web_learn_expected")}: `,C("code",{},x.lines.join(" | ")||"–")),C("span",{},`📄 ${x.name}, ${p("web_learn_actual")}: `,C("code",{},Fh((m=d.result.files)==null?void 0:m.get(x.name)).join(" | ")||"–")));d.result.error&&b.append(C("span",{class:"learn-error"},t1(d.result.error))),d.result.missingInput&&b.append(C("span",{class:"learn-error"},p("web_learn_missing_input"))),d.result.tooManySteps&&b.append(C("span",{class:"learn-error"},p("web_learn_too_many_steps"))),!d.passed&&d.result.unusedInputs&&b.append(C("span",{class:"learn-error"},p("web_learn_unused_input"))),r.append(C("li",{class:d.passed?"ok":"fail"},...f,b))}e.append(r)}renderCompetences(e){const t=C("aside",{class:"learn-competences"},C("p",{class:"learn-competences-title"},p("web_learn_competences_intro"))),n=C("ul",{});for(const a of e)n.append(tt("li",{},Oe(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=C("div",{class:"learn-checklist-wrap"}),r=C("p",{class:"learn-rating-legend"});for(const l of a)r.append(C("span",{},`${l.icon} ${l.label}`));const o=C("ul",{class:"learn-checklist"});return s.append(r,o),e.forEach((l,u)=>{var v;const c=`${t}-${u}`,m=n?(v=be.lesson(n.id).checks)==null?void 0:v[c]:void 0;let d=m===!0?"sun":m||void 0;const h=tt("span",{class:"learn-check-text"},Oe(l.text)),g=C("span",{class:"learn-rating",role:"group","aria-label":h.textContent??""}),f=a.map(w=>{const I=C("button",{class:"learn-rating-button",title:w.label,"aria-label":w.label},w.icon);return I.addEventListener("click",()=>{if(d=d===w.value?void 0:w.value,b(),!n)return;const z={...be.lesson(n.id).checks??{}};d?z[c]=d:delete z[c],be.updateLesson(n.id,{checks:Object.keys(z).length?z:void 0})}),I}),b=()=>{f.forEach((w,I)=>w.setAttribute("aria-pressed",String(a[I].value===d))),x.dataset.rating=d??""};g.append(...f);const x=C("li",{},h,g);if(n&&l.step!==void 0){const w=l.step,I=p("web_learn_step_fmt",w+1,n.steps[w].title),z=C("button",{class:"link-button learn-check-link",title:I,"aria-label":`${p("web_learn_review")}: ${I}`},p("web_learn_review"));z.addEventListener("click",()=>{this.returnTo={lesson:n.id,step:be.lesson(n.id).step,scroll:this.body.scrollTop},this.goToStep(n,w)}),x.append(z)}b(),o.append(x)}),s}renderQuiz(e,t,n){const a=C("div",{class:"learn-quiz"}),s=C("p",{class:"learn-score",role:"status"}),r=()=>n?be.lesson(n.id).quiz??{}:{},o=C("div",{class:"learn-review"}),l=()=>{const u=r(),c=(f,b)=>f.pairs?f.pairs.every((x,v)=>u[`${t}-${b}-${v}`]!==void 0):u[`${t}-${b}`]!==void 0,m=(f,b)=>{var x;return!!(f.pairs?f.pairs.every((v,w)=>cc(f)[u[`${t}-${b}-${w}`]]===f.pairs[w].right):(x=f.options[u[`${t}-${b}`]])!=null&&x.correct)},d=e.filter(c).length,h=e.filter(m).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=>m(e[f],f))};return e.forEach((u,c)=>{const m=`${t}-${c}`,d=C("fieldset",{},tt("legend",{},Oe(u.question))),h=tt("p",{class:"learn-explanation"},Oe(u.explanation??""));if(u.pairs){d.append(this.renderMatch(u,m,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=tt("button",{class:"learn-option"},Oe(f.text));x.addEventListener("click",()=>{n&&be.updateLesson(n.id,{quiz:{...r(),[m]:b}}),g(b),l()}),d.append(x)}),d.append(h),g(r()[m]),a.append(d)}),a.append(s,o),l(),a}fillChecklistReview(e,t,n,a){const s={sun:"☀️",cloud:"⛅",umbrella:"☂️"},r=be.lesson(t.id).checks??{},o=[];let l=0;t.steps.forEach((u,c)=>u.blocks.forEach((m,d)=>{m.kind==="checklist"&&m.items.forEach((h,g)=>{const f=r[`${c}-${d}-${g}`],b=f===!0?"sun":f||void 0,x=h.step===void 0?[]:n.map((k,T)=>k.step===h.step?T:-1).filter(k=>k>=0),v=x.filter(k=>!a(k));let w="";b==="sun"&&v.length?w=p("web_learn_review_overrated_fmt",v.map(k=>k+1).join(", ")):b&&b!=="sun"&&x.length&&!v.length&&(w=p("web_learn_review_underrated")),w&&l++;const I=C("li",{class:w?"learn-review-deviation":""}),z=tt("span",{class:"learn-check-text"},Oe(h.text));if(w&&z.append(C("br",{}),C("em",{},w)),I.append(z,C("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 k=h.step,T=C("button",{class:"link-button learn-check-link"},p("web_learn_review"));T.addEventListener("click",()=>{this.returnTo={lesson:t.id,step:be.lesson(t.id).step,scroll:this.body.scrollTop},this.goToStep(t,k)}),I.append(T)}o.push(I)})})),o.length&&e.append(C("p",{class:"learn-review-title"},`📋 ${p("web_learn_review_title")}`),C("p",{},p(l?"web_learn_review_hint":"web_learn_review_match")),C("ul",{class:"learn-checklist"},...o))}renderMatch(e,t,n,a,s,r){const o=e.pairs,l=cc(e),u=C("div",{class:"learn-match"});let c={};const m=()=>a?n():c,d=b=>a?be.updateLesson(a.id,{quiz:b}):c=b,h=b=>m()[`${t}-${b}`],g=o.map(b=>{const x=C("select",{class:"learn-match-select"});x.append(C("option",{value:""},"–")),l.forEach((w,I)=>x.append(C("option",{value:String(I)},w)));const v=tt("label",{class:"learn-match-left"},Oe(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={...m()};b.value===""?delete v[`${t}-${x}`]:v[`${t}-${x}`]=Number(b.value),d(v),f(),r()})),f(),u}}function cc(i){return(i.pairs??[]).map(e=>e.right).sort((e,t)=>e.localeCompare(t,"de"))}function jZ(i){const e=$h(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=C("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(C("span",{class:`area-name area-${o}`},n[o]))}else r&&s.append(r);return s}const AZ=""+new URL("visubot-CyGFOI9V.webp",import.meta.url).href,Us="visustruct.visubot";function $s(){try{return localStorage.getItem(Us)}catch{return null}}function ui(){const i=$s();return i==="1"||i==="kurs"?"on":"off"}const hg=()=>$s()==="2";function gg(){try{localStorage.setItem(Us,"2")}catch{}}const pg=()=>$s()==="3";function fg(){try{localStorage.setItem(Us,"3")}catch{}}const OZ=()=>$s()!==null;function Sr(i){try{localStorage.setItem(Us,i==="on"?"1":"0")}catch{}}const PZ=`VisuBot`,Hn=()=>ui()!=="off",mc=i=>i.replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]);function Lo(){const i=hg()?"object":pg()?"flow":ui(),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")}
    - ${mc(p(t))}`}class DZ{constructor(e=Ii){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 ds(e),this.element=document.createElement("section"),this.element.className="visubot",this.element.innerHTML=`

    ${p("web_visubot_world")}

    ${p("web_visubot_world_in_preview")}

    ${MZ()}${ZZ()}`,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=ge.listen(()=>this.updateLive()),this.setupControls(),this.check=this.element.querySelector(".visubot-check"),this.setupCheck(),this.updateLive(),this.updateStatus()}show(){this.loading??(this.loading=K(async()=>{const{Robot3D:e}=await import("./robot3d-PhMH2w0K.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]??Ii,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 ds(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;ge.run(e.dataset.py).then(()=>t?new Promise(a=>setTimeout(a,Number(n))).then(()=>ge.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&&ge.connected;){for(const e of this.check.querySelectorAll("[data-sensor]")){if(!this.check.open||!ge.connected)break;const t=e.dataset.sensor,n=await ge.ask(_t[t].python).catch(()=>{});n!==void 0&&(e.textContent=typeof _t[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 ge.connected}async prepareLive(e,t=[]){const n={};for(const a of new Set(["getDistance","getLine",...t])){const s=await ge.ask(_t[a].python);typeof _t[a].simulated=="boolean"?n[a]=s===!0||typeof s=="number"&&s!==0:typeof _t[a].simulated=="string"?n[a]=typeof s=="string"?s:String(_t[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){ge.disconnect(e instanceof Error?e.message:String(e))}updateLive(){this.liveStatus.textContent=xg(),this.liveStatus.classList.toggle("connected",ge.connected),this.check.hidden=!ge.connected,ge.connected||(this.check.open=!1),this.updateStatus()}follow(e,t){var a,s,r,o;for(;this.appliedl!==0);this.world.tick(s0),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&&ge.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 H1;function bg(i,e){try{H1??(H1=new AudioContext);const t=H1.createOscillator(),n=H1.createGain();t.type="square",t.frequency.value=Math.max(20,Math.min(2e4,i)),n.gain.value=.05,t.connect(n).connect(H1.destination);const a=H1.currentTime+Math.min(Math.max(e,0),5e3)/1e3;t.start(),t.stop(a)}catch{}}function MZ(){const i=(t,n,a,s,r)=>``,e=(t,n,a)=>``;return`
    🎛 ${p("web_visubot_controls")} + ${mc(p(t))}`}class DZ{constructor(e=Ii){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 ds(e),this.element=document.createElement("section"),this.element.className="visubot",this.element.innerHTML=`

    ${p("web_visubot_world")}

    ${p("web_visubot_world_in_preview")}

    ${MZ()}${ZZ()}`,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=ge.listen(()=>this.updateLive()),this.setupControls(),this.check=this.element.querySelector(".visubot-check"),this.setupCheck(),this.updateLive(),this.updateStatus()}show(){this.loading??(this.loading=K(async()=>{const{Robot3D:e}=await import("./robot3d-uruuREju.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]??Ii,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 ds(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;ge.run(e.dataset.py).then(()=>t?new Promise(a=>setTimeout(a,Number(n))).then(()=>ge.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&&ge.connected;){for(const e of this.check.querySelectorAll("[data-sensor]")){if(!this.check.open||!ge.connected)break;const t=e.dataset.sensor,n=await ge.ask(_t[t].python).catch(()=>{});n!==void 0&&(e.textContent=typeof _t[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 ge.connected}async prepareLive(e,t=[]){const n={};for(const a of new Set(["getDistance","getLine",...t])){const s=await ge.ask(_t[a].python);typeof _t[a].simulated=="boolean"?n[a]=s===!0||typeof s=="number"&&s!==0:typeof _t[a].simulated=="string"?n[a]=typeof s=="string"?s:String(_t[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){ge.disconnect(e instanceof Error?e.message:String(e))}updateLive(){this.liveStatus.textContent=xg(),this.liveStatus.classList.toggle("connected",ge.connected),this.check.hidden=!ge.connected,ge.connected||(this.check.open=!1),this.updateStatus()}follow(e,t){var a,s,r,o;for(;this.appliedl!==0);this.world.tick(s0),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&&ge.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 H1;function bg(i,e){try{H1??(H1=new AudioContext);const t=H1.createOscillator(),n=H1.createGain();t.type="square",t.frequency.value=Math.max(20,Math.min(2e4,i)),n.gain.value=.05,t.connect(n).connect(H1.destination);const a=H1.currentTime+Math.min(Math.max(e,0),5e3)/1e3;t.start(),t.stop(a)}catch{}}function MZ(){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)} @@ -64564,7 +64564,7 @@ ${i}

    ${yn(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=`${Ct}🤖 ${yn(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=K(async()=>{const{Robot3D:e}=await import("./robot3d-PhMH2w0K.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=`${Ct}🤖 ${yn(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=K(async()=>{const{Robot3D:e}=await import("./robot3d-uruuREju.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]??Ii)}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=YF(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=se.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&&bg(s.tone[0],s.tone[1]),this.showFrame(s,io-30),this.playTimer=window.setTimeout(n,io)};this.playTimer=window.setTimeout(n,io)}stopPlaying(e){var t;this.playTimer!==void 0&&window.clearTimeout(this.playTimer),this.playTimer=void 0,this.playButton.innerHTML=se.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(`⚠︎ ${t1(e.notice)}`),this.status.textContent=t.join(" · ")}pause(){window.clearTimeout(this.pending),this.pending=void 0,this.lastKey=void 0,this.stopPlaying(!1)}}const KF={left:12,top:10},eR=8,Es=8e3,xi=16,ao=12,a2="#fafafa";function s2(i){const e=i.caption.trim();return e===""?p("diagram_title_placeholder"):e}function od(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 ld(i,e){return od(i.caption)||od(e)||"VisuStruct"}function tR(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,xi,"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+"…",xi,"bold")>e;)r=r.slice(0,-1);return[a[0],r+"…"]}return a}function ud(i,e,t,n=320){const a={...i,elements:i.elements.map(Xa)},s=new Vd(e,t).layout(a,KF),r=Math.min(Es,Math.max(n,s.canvasSize.width)),o=Math.min(Es,Math.max(n,s.canvasSize.height));if(r<=2||o<=2)return;const l=tR(s2(i),r-2*ao,t),u=Math.ceil(xi*1.2),c=Math.min(56,l.length*u+2),m=c+o,d=new $d(e,t).render(s,{width:r,height:o},void 0,eR);d.setAttribute("y",String(c)),d.removeAttribute("class");const h=Se("svg",{xmlns:"http://www.w3.org/2000/svg",width:r,height:m,viewBox:`0 0 ${r} ${m}`});h.append(Se("rect",{x:0,y:0,width:r,height:m,fill:a2}));const g=Se("text",{x:ao,y:0,"font-family":Ns,"font-size":xi,"font-weight":600,fill:"black"});return l.forEach((f,b)=>{const x=Se("tspan",{x:ao,y:b*u+xi});x.textContent=f,g.append(x)}),h.append(g,d),{svg:h,width:r,height:m}}function r2(i){return` `+new XMLSerializer().serializeToString(i.svg)}async function cd(i,e){const t=Math.max(1,Math.min(e,Es/i.width,Es/i.height)),n=URL.createObjectURL(new Blob([r2(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=a2,r.fillRect(0,0,s.width,s.height),r.drawImage(a,0,0,s.width,s.height),s}finally{URL.revokeObjectURL(n)}}function nR(i){return new Promise((e,t)=>i.toBlob(n=>n?e(n):t(new Error("PNG konnte nicht erzeugt werden.")),"image/png"))}function iR(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),c=r(l),[m,d]=c.s>u.s?[l,c]:[o,u],h=a*d.s,g=s*d.s;return{page:m,draw:{x:32+(d.cw-h)/2,y:32+(d.ch-g)/2,width:h,height:g}}}async function aR(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 sR(i,e,t,n,a){const{page:s,draw:r}=iR(n.width,n.height),o=await aR(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`,c=new TextEncoder,m=[["<< /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 @@ -64863,7 +64863,7 @@ ${m}

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

    ${W(p("web_about_software_text"))} ${W(p("web_about_licenses"))}

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

    - `,t.querySelector("[data-action=about-done]").addEventListener("click",()=>t.close()),t.addEventListener("click",n=>n.target===t&&t.close()),t.addEventListener("close",()=>t.remove()),document.body.append(t),t.showModal()}setupSettingsMenu(e,t){const n=a=>{t.hidden=!a,e.setAttribute("aria-expanded",String(a))};e.addEventListener("click",()=>n(t.hidden)),this.closeSettings&&document.removeEventListener("pointerdown",this.closeSettings),this.escapeSettings&&document.removeEventListener("keydown",this.escapeSettings),this.closeSettings=a=>{!t.hidden&&!e.parentElement.contains(a.target)&&n(!1)},document.addEventListener("pointerdown",this.closeSettings),this.escapeSettings=a=>{a.key!=="Escape"||t.hidden||(n(!1),e.focus())},document.addEventListener("keydown",this.escapeSettings)}learnRail(){return this.railButton=me("button",{class:"learn-rail"}),this.labelLearnRail(),this.railButton.addEventListener("click",()=>this.setLearning(!0)),this.railButton}liveRail(){return this.liveRailButton=me("button",{class:"learn-rail live-rail"}),this.labelLiveRail(),this.liveRailButton.addEventListener("click",()=>this.setLiveCoding(!0)),this.liveRailButton}labelLiveRail(){this.liveRailButton&&(this.liveRailButton.title=p("web_live_show"),this.liveRailButton.innerHTML=`${Ct}</> ${W(p("web_live_title"))}`)}labelLearnRail(){this.railButton&&(this.railButton.title=p("web_learn_show"),this.railButton.innerHTML=`${Ct}🎓 ${W(p("web_learn_title"))}`)}learnHost(){return{collapse:()=>this.setLearning(!1),showEditor:()=>{this.editorHidden&&this.setEditorHidden(!1)},showLiveCode:()=>{this.liveCoding||this.setLiveCoding(!0)},showJava:()=>this.openJavaColumn(),showFiles:()=>{this.shell.classList.contains("files-open")||this.setFilesOpen(!0)},reveal:e=>this.revealAreas(e),openExercise:(e,t)=>{const n=$h(e);n!=="code"&&this.setEditorHidden(!1),n!=="struktogramm"&&this.openJavaColumn();const a=this.tabs.findIndex(r=>r.exerciseId===e.id);if(a>=0){this.switchTab(a),this.setSimulating(!1);return}const s=this.makeTab();s.doc=t,s.exerciseId=e.id,s.selected=t.elements.length>0?[0]:void 0,this.isPristine(this.tab)?this.tabs[this.tabIndex]=s:this.tabs.push(s),this.tabIndex=this.tabs.indexOf(s),this.setSimulating(!1),this.render()},openJavaCode:e=>{this.openJavaColumn();const t=this.makeTab();t.doc=this.live.documentFromJavaText(e),this.isPristine(this.tab)?this.tabs[this.tabIndex]=t:this.tabs.push(t),this.tabIndex=this.tabs.indexOf(t),this.setSimulating(!1),this.live.adoptJava(t.doc,e),this.render()},openDiagram:(e,t)=>{this.setEditorHidden(!1),this.loadXML(u1(e),e.caption.trim()?`${e.caption.trim()}.visustruct`:t)},exerciseDocument:e=>{const t=this.tabs.find(a=>a.exerciseId===e);if(t)return t.doc;const n=this.tab;if(!(n.exerciseId||this.isPristine(n)))return n.exerciseId=e,be.updateExercise(e,{xml:u1(n.doc)}),n.doc},subprogramsFor:e=>{const t=this.tabs.find(n=>n.exerciseId===e);return n=>this.findSubprogram(n,t)},stopSimulation:()=>this.setSimulating(!1),resetExercise:(e,t)=>{const n=this.tabs.find(a=>a.exerciseId===e);n&&(n.undoStack.push(n.doc),n.doc=t,n.redoStack=[],n.selected=[0],n===this.tab&&this.render())},preview:e=>{const t=ud(e,this.metrics,this.measure,0);if(!t)return;const n=t.svg.getAttribute("width");return n&&(t.svg.style.maxWidth=`${n}px`),t.svg.removeAttribute("width"),t.svg.removeAttribute("height"),t.svg}}}isPristine(e){return!e.dirty&&!e.fileName&&!e.exerciseId&&e.undoStack.length===0}rememberExercise(){const e=this.tab;e.exerciseId&&(clearTimeout(this.exerciseSaveTimer),this.exerciseSaveTimer=window.setTimeout(()=>{e.exerciseId&&be.updateExercise(e.exerciseId,{xml:u1(e.doc)})},300))}paletteIcon(e){const t=Se("svg",{viewBox:"0 0 28 20",width:28,height:20,class:"icon"}),n={fill:"none",stroke:"currentColor","stroke-width":1.5};t.append(Se("rect",{x:1,y:1,width:26,height:18,...n}));const a=s=>t.append(Se("path",{d:s,...n}));switch(e){case"verzweigung":a("M1 1 L14 10 L27 1 M14 10 V19");break;case"fallauswahl":a("M1 1 L20 10 L27 1 M1 10 H27 M10 10 V19 M20 10 V19");break;case"forZaehlSchleife":case"whileSchleife":a("M7 7 H27 M7 7 V19");break;case"doUntilSchleife":a("M7 1 V13 H27");break;case"endlosschleife":a("M7 6 H27 M7 6 V14 H27");break;case"aufruf":a("M5 1 V19 M23 1 V19");break;case"aussprung":a("M6 1 L1 10 L6 19");break}return t}render(){const e={...this.doc,elements:this.doc.elements.map(Xa)};this.layout=this.engine.layout(e),this.flat=H2(this.layout.elements),this.selected&&!Ft(this.doc,this.selected)&&(this.selected=void 0);const t=this.zoom,n=this.canvasHost;this.renderedHostSize={width:n.clientWidth,height:n.clientHeight};const a={width:Math.max(320,this.layout.canvasSize.width,Math.floor(n.clientWidth/t)),height:Math.max(240,this.layout.canvasSize.height+60,Math.floor(n.clientHeight/t))};this.pseudocodeBox.checked=!!this.doc.pseudocode,this.renderer.usesSimulationHighlight=this.simulating,this.renderer.fillsSelection=this.liveCoding,this.svg=this.renderer.render(this.layout,a,this.simulating?this.simPath:this.selected),this.svg.setAttribute("width",String(Math.floor(a.width*t))),this.svg.setAttribute("height",String(Math.floor(a.height*t))),this.overlay=Se("g",{class:"drop-overlay"}),this.svg.append(this.overlay),this.canvasHost.replaceChildren(this.svg),document.activeElement!==this.captionInput&&(this.captionInput.value=this.doc.caption),this.undoButton.disabled=this.simulating||this.undoStack.length===0,this.redoButton.disabled=this.simulating||this.redoStack.length===0,this.deleteButton.disabled=this.simulating||!this.selected||!dr(this.doc,this.selected),this.captionInput.readOnly=this.simulating,this.codeButton.disabled=this.simulating,this.exportButton.disabled=this.simulating,this.coding&&this.code.refresh(),this.refreshLive(),this.refreshPreview(),this.renderTabs(),this.renderInspector(),this.updateStatus()}refreshLive(){this.liveCoding&&this.live.refresh(this.doc,this.simulating?this.simPath:this.selected,{owner:this.tab,subprograms:new Set(this.tabs.filter(e=>e!==this.tab).flatMap(e=>{var t;return((t=zt(e.doc.caption))==null?void 0:t.name)??[]})),editable:!this.simulating,resolve:e=>this.findSubprogram(e)})}updateStatus(){this.rememberExercise(),document.title=`${this.dirty?"• ":""}${this.fileName} – VisuStruct Web`,this.statusLine.textContent=`${this.fileName}${this.dirty?` (${p("web_status_modified")})`:""}`}renderInspector(){const e=this.selected,t=e?Ft(this.doc,e):void 0,n=this.inspector;if(!e||!t){n.replaceChildren(me("h2",{},p("web_inspector_title")),me("p",{class:"hint"},p("inspector_no_selection")),me("p",{class:"hint"},p("web_inspector_help_drop")),me("p",{class:"hint"},p("web_inspector_help_files")));return}if(n.replaceChildren(me("h2",{},`${p("web_inspector_title")} · ${so(t.type)}`)),t.type===S.anweisung){const a=$a(t.textLines.join(` + `,t.querySelector("[data-action=about-done]").addEventListener("click",()=>t.close()),t.addEventListener("click",n=>n.target===t&&t.close()),t.addEventListener("close",()=>t.remove()),document.body.append(t),t.showModal()}setupSettingsMenu(e,t){const n=a=>{t.hidden=!a,e.setAttribute("aria-expanded",String(a))};e.addEventListener("click",()=>n(t.hidden)),this.closeSettings&&document.removeEventListener("pointerdown",this.closeSettings),this.escapeSettings&&document.removeEventListener("keydown",this.escapeSettings),this.closeSettings=a=>{!t.hidden&&!e.parentElement.contains(a.target)&&n(!1)},document.addEventListener("pointerdown",this.closeSettings),this.escapeSettings=a=>{a.key!=="Escape"||t.hidden||(n(!1),e.focus())},document.addEventListener("keydown",this.escapeSettings)}learnRail(){return this.railButton=me("button",{class:"learn-rail"}),this.labelLearnRail(),this.railButton.addEventListener("click",()=>this.setLearning(!0)),this.railButton}liveRail(){return this.liveRailButton=me("button",{class:"learn-rail live-rail"}),this.labelLiveRail(),this.liveRailButton.addEventListener("click",()=>this.setLiveCoding(!0)),this.liveRailButton}labelLiveRail(){this.liveRailButton&&(this.liveRailButton.title=p("web_live_show"),this.liveRailButton.innerHTML=`${Ct}</> ${W(p("web_live_title"))}`)}labelLearnRail(){this.railButton&&(this.railButton.title=p("web_learn_show"),this.railButton.innerHTML=`${Ct}🎓 ${W(p("web_learn_title"))}`)}learnHost(){return{collapse:()=>this.setLearning(!1),showEditor:()=>{this.editorHidden&&this.setEditorHidden(!1)},showLiveCode:()=>{this.liveCoding||this.setLiveCoding(!0)},showJava:()=>this.openJavaColumn(),showFiles:()=>{this.shell.classList.contains("files-open")||this.setFilesOpen(!0)},reveal:e=>this.revealAreas(e),openExercise:(e,t)=>{const n=$h(e);n!=="code"&&this.setEditorHidden(!1),n!=="struktogramm"&&this.openJavaColumn(),this.coding&&this.setCoding(!1),this.shell.classList.contains("files-open")&&this.setFilesOpen(!1),this.previewOpen&&this.setPreviewOpen(!1),n==="struktogramm"&&this.liveCoding&&this.setLiveCoding(!1),n==="code"&&!this.editorHidden&&this.setEditorHidden(!0);const a=this.tabs.findIndex(r=>r.exerciseId===e.id);if(a>=0){this.switchTab(a),this.setSimulating(!1);return}const s=this.makeTab();s.doc=t,s.exerciseId=e.id,s.selected=t.elements.length>0?[0]:void 0,this.isPristine(this.tab)?this.tabs[this.tabIndex]=s:this.tabs.push(s),this.tabIndex=this.tabs.indexOf(s),this.setSimulating(!1),this.render()},openJavaCode:e=>{this.openJavaColumn();const t=this.makeTab();t.doc=this.live.documentFromJavaText(e),this.isPristine(this.tab)?this.tabs[this.tabIndex]=t:this.tabs.push(t),this.tabIndex=this.tabs.indexOf(t),this.setSimulating(!1),this.live.adoptJava(t.doc,e),this.render()},openDiagram:(e,t)=>{this.setEditorHidden(!1),this.loadXML(u1(e),e.caption.trim()?`${e.caption.trim()}.visustruct`:t)},exerciseDocument:e=>{const t=this.tabs.find(a=>a.exerciseId===e);if(t)return t.doc;const n=this.tab;if(!(n.exerciseId||this.isPristine(n)))return n.exerciseId=e,be.updateExercise(e,{xml:u1(n.doc)}),n.doc},subprogramsFor:e=>{const t=this.tabs.find(n=>n.exerciseId===e);return n=>this.findSubprogram(n,t)},stopSimulation:()=>this.setSimulating(!1),resetExercise:(e,t)=>{const n=this.tabs.find(a=>a.exerciseId===e);n&&(n.undoStack.push(n.doc),n.doc=t,n.redoStack=[],n.selected=[0],n===this.tab&&this.render())},preview:e=>{const t=ud(e,this.metrics,this.measure,0);if(!t)return;const n=t.svg.getAttribute("width");return n&&(t.svg.style.maxWidth=`${n}px`),t.svg.removeAttribute("width"),t.svg.removeAttribute("height"),t.svg}}}isPristine(e){return!e.dirty&&!e.fileName&&!e.exerciseId&&e.undoStack.length===0}rememberExercise(){const e=this.tab;e.exerciseId&&(clearTimeout(this.exerciseSaveTimer),this.exerciseSaveTimer=window.setTimeout(()=>{e.exerciseId&&be.updateExercise(e.exerciseId,{xml:u1(e.doc)})},300))}paletteIcon(e){const t=Se("svg",{viewBox:"0 0 28 20",width:28,height:20,class:"icon"}),n={fill:"none",stroke:"currentColor","stroke-width":1.5};t.append(Se("rect",{x:1,y:1,width:26,height:18,...n}));const a=s=>t.append(Se("path",{d:s,...n}));switch(e){case"verzweigung":a("M1 1 L14 10 L27 1 M14 10 V19");break;case"fallauswahl":a("M1 1 L20 10 L27 1 M1 10 H27 M10 10 V19 M20 10 V19");break;case"forZaehlSchleife":case"whileSchleife":a("M7 7 H27 M7 7 V19");break;case"doUntilSchleife":a("M7 1 V13 H27");break;case"endlosschleife":a("M7 6 H27 M7 6 V14 H27");break;case"aufruf":a("M5 1 V19 M23 1 V19");break;case"aussprung":a("M6 1 L1 10 L6 19");break}return t}render(){const e={...this.doc,elements:this.doc.elements.map(Xa)};this.layout=this.engine.layout(e),this.flat=H2(this.layout.elements),this.selected&&!Ft(this.doc,this.selected)&&(this.selected=void 0);const t=this.zoom,n=this.canvasHost;this.renderedHostSize={width:n.clientWidth,height:n.clientHeight};const a={width:Math.max(320,this.layout.canvasSize.width,Math.floor(n.clientWidth/t)),height:Math.max(240,this.layout.canvasSize.height+60,Math.floor(n.clientHeight/t))};this.pseudocodeBox.checked=!!this.doc.pseudocode,this.renderer.usesSimulationHighlight=this.simulating,this.renderer.fillsSelection=this.liveCoding,this.svg=this.renderer.render(this.layout,a,this.simulating?this.simPath:this.selected),this.svg.setAttribute("width",String(Math.floor(a.width*t))),this.svg.setAttribute("height",String(Math.floor(a.height*t))),this.overlay=Se("g",{class:"drop-overlay"}),this.svg.append(this.overlay),this.canvasHost.replaceChildren(this.svg),document.activeElement!==this.captionInput&&(this.captionInput.value=this.doc.caption),this.undoButton.disabled=this.simulating||this.undoStack.length===0,this.redoButton.disabled=this.simulating||this.redoStack.length===0,this.deleteButton.disabled=this.simulating||!this.selected||!dr(this.doc,this.selected),this.captionInput.readOnly=this.simulating,this.codeButton.disabled=this.simulating,this.exportButton.disabled=this.simulating,this.coding&&this.code.refresh(),this.refreshLive(),this.refreshPreview(),this.renderTabs(),this.renderInspector(),this.updateStatus()}refreshLive(){this.liveCoding&&this.live.refresh(this.doc,this.simulating?this.simPath:this.selected,{owner:this.tab,subprograms:new Set(this.tabs.filter(e=>e!==this.tab).flatMap(e=>{var t;return((t=zt(e.doc.caption))==null?void 0:t.name)??[]})),editable:!this.simulating,resolve:e=>this.findSubprogram(e)})}updateStatus(){this.rememberExercise(),document.title=`${this.dirty?"• ":""}${this.fileName} – VisuStruct Web`,this.statusLine.textContent=`${this.fileName}${this.dirty?` (${p("web_status_modified")})`:""}`}renderInspector(){const e=this.selected,t=e?Ft(this.doc,e):void 0,n=this.inspector;if(!e||!t){n.replaceChildren(me("h2",{},p("web_inspector_title")),me("p",{class:"hint"},p("inspector_no_selection")),me("p",{class:"hint"},p("web_inspector_help_drop")),me("p",{class:"hint"},p("web_inspector_help_files")));return}if(n.replaceChildren(me("h2",{},`${p("web_inspector_title")} · ${so(t.type)}`)),t.type===S.anweisung){const a=$a(t.textLines.join(` `)),s=me("div",{class:"segmented",role:"group","aria-label":p("inspector_io_mode_title")});for(const[r,o]of[["statement",p("inspector_io_mode_statement")],["input",p("inspector_io_mode_input")],["output",p("inspector_io_mode_output")]]){const l=me("button",{"aria-pressed":String(r===a)},o);l.addEventListener("click",()=>{var m,d;const u=((m=Ft(this.doc,e))==null?void 0:m.textLines.join(` `))??"";if(r===$a(u))return;const c=O2(r,u);this.commit(N1(this.doc,e,c.split(` `))),(d=this.inspector.querySelector("textarea"))==null||d.focus()}),s.append(l)}n.append(s,me("p",{class:"hint mono-hint"},fR[a]))}if(t.type===S.forSchleife){const a=me("div",{class:"for-fields"}),s=K0(t.textLines);[[p("inspector_for_init"),p("inspector_for_placeholder_init")],[p("inspector_for_condition"),p("inspector_for_placeholder_condition")],[p("inspector_for_step"),p("inspector_for_placeholder_step")]].forEach(([o,l],u)=>{const c=me("input",{placeholder:l,spellcheck:"false",autocomplete:"off"});c.value=s[u],this.liveEdit(c,m=>{const d=Ft(this.doc,e);if(!d)return;const h=K0(d.textLines);return h[u]=M2(m),N1(this.doc,e,h)}),a.append(me("label",{},o,c))}),n.append(a)}else if(t.type!==S.leerElement){const a=pR[t.type];a&&n.append(me("p",{class:"hint mono-hint"},a));const s=fd(t),r=me("textarea",{rows:"3",spellcheck:"false"}),o=t.textLines.join(` @@ -64872,4 +64872,4 @@ ${m}

    ${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=Nl(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:pd()}),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([u1(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:pd()}),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=ld(this.doc,un(this.tab));return this.offerDownload(`${s}.visustruct`,new Blob([u1(this.doc)],{type:"application/xml"}))}const t=ud(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=ld(this.doc,un(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([r2(t)],{type:"image/svg+xml"}));break}case"png":{const s=await cd(t,a);await this.offerDownload(`${n}.png`,await nR(s));break}case"pdf":{const s=await cd(t,Math.max(a,3)),r=await sR(rR(s),s.width,s.height,t,s2(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==="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&&fo(n.idPath,this.selected);this.selected=n==null?void 0:n.idPath,this.render(),n&&e.pointerType!=="touch"&&!(In(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=Pt(this.doc,e.path);t.textContent=`${so(n.type)}: ${Zl(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||In(this.doc,s.idPath)?void 0:gd.includes(Pt(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 c=u.frame.y+u.frame.height;return t>c?n.kind==="move"&&n.path.length===1&&n.path[0]===a.length-1?void 0:{kind:"rootAppend",frame:{x:u.frame.x,y:c,width:u.frame.width,height:0}}:t=n.path.length&&n.path.every((u,c)=>r[c]===u)?void 0:In(this.doc,r)?{kind:"replace",path:r,frame:s.frame}:{kind:t"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e])}function Zd(i){if(!i)return[];for(const e of[...Ot.flatMap(t=>t.steps.flatMap(n=>n.blocks)),...jn.flatMap(t=>t.blocks)])if(!(e.kind!=="exercise"||e.exercise.id!==i))return e.exercise.tests.flatMap(t=>{const n=t.world?Ja(t.world):void 0;return n?[n]:[]});return[]}let Jt,Pl,Dl;function Bd(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!==Dl&&(uo(),e&&(Dl=e,Pl=window.setTimeout(()=>Bd(e),350)))}),document.addEventListener("focusin",i=>{const e=i.target.closest("[data-tip]");uo(),e!=null&&e.matches(":focus-visible")&&Bd(e)});for(const i of["pointerdown","focusout","scroll","keydown"])document.addEventListener(i,uo,!0)}const Ml="visustruct.reloadedAfterError";function c2(){try{const i=Number(sessionStorage.getItem(Ml));if(i&&Date.now()-i<3e4)return!1;sessionStorage.setItem(Ml,String(Date.now()))}catch{return!1}return location.reload(),!0}function _R(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=>{c2()&&i.preventDefault()});const jR=K2();Promise.all([ah(jR,!1),ih(Y2(),!1)]).then(()=>{u2(),CR();const i=new URLSearchParams(location.search);i.has("visuobject")&&gg(),i.has("visuflow")&&fg();const e=document.getElementById("app"),t=!i.has("visustruct")&&!i.has("visubot");if(hg()&&t)return K(async()=>{const{ObjectApp:n}=await import("./objectApp-DuUC9Wrs.js").then(a=>a.g);return{ObjectApp:n}},[],import.meta.url).then(({ObjectApp:n})=>void new n(e));if(pg()&&t)return K(async()=>{const{FlowApp:n}=await import("./flowApp-RE0WoNHh.js");return{FlowApp:n}},[],import.meta.url).then(({FlowApp:n})=>void new n(e));new kR(e)}).then(()=>{try{sessionStorage.removeItem(Ml)}catch{}}).catch(i=>{/dynamically imported module|Importing a module script failed|error loading dynamically/i.test(String(i))&&c2()||_R(i)});export{qn as C,AF as J,qb as L,K as _,fF as a,EF as b,Xf as c,ZR as d,fg as e,Sr as f,zR as g,la as h,se as i,JZ as j,NZ as k,s1 as l,MR as m,gg as n,od as o,MF as p,r2 as q,hc as r,VZ as s,p as t,cd as u,nR as v,Lo as w,sR as x,rR as y}; + `,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=Nl(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:pd()}),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([u1(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:pd()}),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=ld(this.doc,un(this.tab));return this.offerDownload(`${s}.visustruct`,new Blob([u1(this.doc)],{type:"application/xml"}))}const t=ud(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=ld(this.doc,un(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([r2(t)],{type:"image/svg+xml"}));break}case"png":{const s=await cd(t,a);await this.offerDownload(`${n}.png`,await nR(s));break}case"pdf":{const s=await cd(t,Math.max(a,3)),r=await sR(rR(s),s.width,s.height,t,s2(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==="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&&fo(n.idPath,this.selected);this.selected=n==null?void 0:n.idPath,this.render(),n&&e.pointerType!=="touch"&&!(In(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=Pt(this.doc,e.path);t.textContent=`${so(n.type)}: ${Zl(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||In(this.doc,s.idPath)?void 0:gd.includes(Pt(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 c=u.frame.y+u.frame.height;return t>c?n.kind==="move"&&n.path.length===1&&n.path[0]===a.length-1?void 0:{kind:"rootAppend",frame:{x:u.frame.x,y:c,width:u.frame.width,height:0}}:t=n.path.length&&n.path.every((u,c)=>r[c]===u)?void 0:In(this.doc,r)?{kind:"replace",path:r,frame:s.frame}:{kind:t"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e])}function Zd(i){if(!i)return[];for(const e of[...Ot.flatMap(t=>t.steps.flatMap(n=>n.blocks)),...jn.flatMap(t=>t.blocks)])if(!(e.kind!=="exercise"||e.exercise.id!==i))return e.exercise.tests.flatMap(t=>{const n=t.world?Ja(t.world):void 0;return n?[n]:[]});return[]}let Jt,Pl,Dl;function Bd(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!==Dl&&(uo(),e&&(Dl=e,Pl=window.setTimeout(()=>Bd(e),350)))}),document.addEventListener("focusin",i=>{const e=i.target.closest("[data-tip]");uo(),e!=null&&e.matches(":focus-visible")&&Bd(e)});for(const i of["pointerdown","focusout","scroll","keydown"])document.addEventListener(i,uo,!0)}const Ml="visustruct.reloadedAfterError";function c2(){try{const i=Number(sessionStorage.getItem(Ml));if(i&&Date.now()-i<3e4)return!1;sessionStorage.setItem(Ml,String(Date.now()))}catch{return!1}return location.reload(),!0}function _R(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=>{c2()&&i.preventDefault()});const jR=K2();Promise.all([ah(jR,!1),ih(Y2(),!1)]).then(()=>{u2(),CR();const i=new URLSearchParams(location.search);i.has("visuobject")&&gg(),i.has("visuflow")&&fg();const e=document.getElementById("app"),t=!i.has("visustruct")&&!i.has("visubot");if(hg()&&t)return K(async()=>{const{ObjectApp:n}=await import("./objectApp-BFz3uIYn.js").then(a=>a.g);return{ObjectApp:n}},[],import.meta.url).then(({ObjectApp:n})=>void new n(e));if(pg()&&t)return K(async()=>{const{FlowApp:n}=await import("./flowApp-CwdCTHJe.js");return{FlowApp:n}},[],import.meta.url).then(({FlowApp:n})=>void new n(e));new kR(e)}).then(()=>{try{sessionStorage.removeItem(Ml)}catch{}}).catch(i=>{/dynamically imported module|Importing a module script failed|error loading dynamically/i.test(String(i))&&c2()||_R(i)});export{qn as C,AF as J,qb as L,K as _,fF as a,EF as b,Xf as c,ZR as d,fg as e,Sr as f,zR as g,la as h,se as i,JZ as j,NZ as k,s1 as l,MR as m,gg as n,od as o,MF as p,r2 as q,hc as r,VZ as s,p as t,cd as u,nR as v,Lo as w,sR as x,rR as y}; diff --git a/website/app/assets/objectApp-DuUC9Wrs.js b/website/app/assets/objectApp-BFz3uIYn.js similarity index 99% rename from website/app/assets/objectApp-DuUC9Wrs.js rename to website/app/assets/objectApp-BFz3uIYn.js index 939cc2f3..13807eea 100644 --- a/website/app/assets/objectApp-DuUC9Wrs.js +++ b/website/app/assets/objectApp-BFz3uIYn.js @@ -1,5 +1,5 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./projectZip-BjgFtmAO.js","./index-UBfMpaby.js","./index-DaVEKYYQ.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 ct}from"./index-UBfMpaby.js";function Ys(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 ct}from"./index-L2QtAwwh.js";function Ys(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 Zs(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=Ys(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=Zs(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 Qs(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 ei=/^[\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 ti={"+":"public ","-":"private ","#":"protected ","~":""};function si(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?"":ti[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(;ns.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}=Ti(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>kn&&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 Ji([...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-BjgFtmAO.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-BjgFtmAO.js");return{projectToZip:s}},__vite__mapDeps([0,1,2]),import.meta.url),t=e(this.project);Sn(`${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 yn(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 _n(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 on(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(bi(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(fi(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(sn(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>kn&&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 Ji([...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-ovwyC9wk.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-ovwyC9wk.js");return{projectToZip:s}},__vite__mapDeps([0,1,2]),import.meta.url),t=e(this.project);Sn(`${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 yn(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 _n(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 on(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(bi(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(fi(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(sn(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-BjgFtmAO.js b/website/app/assets/projectZip-ovwyC9wk.js similarity index 99% rename from website/app/assets/projectZip-BjgFtmAO.js rename to website/app/assets/projectZip-ovwyC9wk.js index cda3c651..8d2b588c 100644 --- a/website/app/assets/projectZip-BjgFtmAO.js +++ b/website/app/assets/projectZip-ovwyC9wk.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-DuUC9Wrs.js";import"./index-UBfMpaby.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-BFz3uIYn.js";import"./index-L2QtAwwh.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-PhMH2w0K.js b/website/app/assets/robot3d-uruuREju.js similarity index 99% rename from website/app/assets/robot3d-PhMH2w0K.js rename to website/app/assets/robot3d-uruuREju.js index 3c82cdba..2170f3d1 100644 --- a/website/app/assets/robot3d-PhMH2w0K.js +++ b/website/app/assets/robot3d-uruuREju.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-UBfMpaby.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-L2QtAwwh.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 503cdebf..b5215088 100644 --- a/website/app/index.html +++ b/website/app/index.html @@ -6,7 +6,7 @@ VisuStruct Web - +